c++實現ipv6轉std::size_t數組

 

 int inet6_pton(const char* src, std::uint8_t* dst) {
            if (src == nullptr) {
                return 0;
            }

            constexpr  char  xdigits_l[] = "0123456789abcdef";
            constexpr  char  xdigits_u[] = "0123456789ABCDEF";
            const      char* xdigits = nullptr;
            const      char* curtok = nullptr;
            constexpr  int  NS_IN6ADDRSZ = 16;
            constexpr   int NS_INT16SZ = 2;
            std::uint8_t tmp[NS_IN6ADDRSZ] = { 0 };
            std::uint8_t* tp = tmp;
            std::uint8_t* endp = nullptr;
            std::uint8_t* colonp = nullptr;
            endp = tp + NS_IN6ADDRSZ;

            /* Leading :: requires some special handling. */
            if (*src == ':') {
                if (*++src != ':') {
                    return 0;
                }
            }

            int              seen_xdigits = 0;
            std::size_t    val = 0;
            char  ch = 0;
            while ((ch = *src++) != '\0') {
                const char* pch = nullptr;

                if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) {
                    pch = strchr((xdigits = xdigits_u), ch);
                }

                if (pch != NULL) {
                    val <<= 4;
                    val |= (pch - xdigits);
                    if (++seen_xdigits > 4) {
                        return 0;
                    }

                    continue;
                }

                if (ch == ':') {
                    curtok = src;
                    if (!seen_xdigits) {
                        if (colonp != nullptr) {
                            return 0;
                        }

                        colonp = tp;
                        continue;
                    }
                    else if (*src == 0) {
                        return 0;
                    }

                    if (tp + NS_INT16SZ > endp) {
                        return 0;
                    }

                    *tp++ = (u_char)(val >> 8) & 0xff;    //放在高位上
                    *tp++ = (u_char)val & 0xff; //放在低位上
                    seen_xdigits = 0;
                    val = 0;
                    continue;
                }

                if (ch == '.' && ((tp + 4) <= endp)) {
                    std::size_t value = 0;

                   //自己實現
                    if (inet4_pton(curtok, value)) {
                        unsigned char* buf = (unsigned char*)&value;
                        memcpy(tp, buf, 4);
                        tp += 4;
                        seen_xdigits = 0;
                        break;  /*%< '\\' was seen by inet_pton4(). */
                    }
                }

                return 0;
            }

            if (seen_xdigits) {
                if (tp + NS_INT16SZ > endp) {
                    return 0;
                }

                *tp++ = (u_char)(val >> 8) & 0xff;
                *tp++ = (u_char)val & 0xff;
            }

            if (colonp != NULL) {
                const int n = tp - colonp;
                if (tp == endp) {
                    return 0;
                }

                for (int i = 1; i <= n; i++) {
                    endp[-i] = colonp[n - i];
                    colonp[n - i] = 0;
                }

                tp = endp;
            }

            if (tp != endp) {
                return 0;
            }

            memcpy(dst, tmp, NS_IN6ADDRSZ);

            return 1;
        }

        void inet6_ntop(const u_char* src, std::string& dst) {
            constexpr  int  NS_IN6ADDRSZ = 16;
            constexpr   int NS_INT16SZ = 2;
            char tmp[100] = { 0 };
            char* tp = nullptr;
            struct { int base, len; } best, cur;
            std::size_t words[NS_IN6ADDRSZ / NS_INT16SZ] = { 0 };

            memset(words, '\0', sizeof words);
            for (int i = 0; i < NS_IN6ADDRSZ; i += 2) {
                words[i / 2] = (src[i] << 8) | src[i + 1];
            }

            best.base = -1;
            cur.base = -1;
            best.len = 0;
            cur.len = 0;
            for (int i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
                if (words[i] == 0) {
                    if (cur.base == -1) {
                        cur.base = i, cur.len = 1;
                    }
                    else {
                        cur.len++;
                    }
                }
                else {
                    if (cur.base != -1) {
                        if (best.base == -1 || cur.len > best.len) {
                            best = cur;
                        }

                        cur.base = -1;
                    }
                }
            }
            if (cur.base != -1) {
                if (best.base == -1 || cur.len > best.len) {
                    best = cur;
                }
            }
            if (best.base != -1 && best.len < 2) {
                best.base = -1;
            }

            /*
             * Format the result.
             */
            tp = tmp;
            for (int i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
                /* Are we inside the best run of 0x00's? */
                if (best.base != -1 && i >= best.base &&
                    i < (best.base + best.len)) {
                    if (i == best.base) {
                        *tp++ = ':';
                    }

                    continue;
                }
                /* Are we following an initial run of 0x00s or any real hex? */
                if (i != 0) {
                    *tp++ = ':';
                }

                /* Is this address an encapsulated IPv4? */
                if (i == 6 && best.base == 0 &&
                    (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
                    std::string temp;
                    temp.resize(20);
                    memcpy(&temp[0], (char*)src + 12,4);

                    std::size_t value = 0;
                    std::size_t* ptr = (std::size_t*)temp.data();
                    value = *ptr;

                    inet4_ntop(value, temp);
                    int len = strlen(temp.c_str());
                    memcpy(tp, temp.c_str(),len);
                    tp += len;
                    break;
                }
                
                std::stringstream sstream;
                sstream << std::hex << words[i];
                int len = strlen(sstream.str().c_str());
                memcpy(tp, sstream.str().c_str(), len);
                tp +=len;
            }
            /* Was it a trailing run of 0x00's? */
            if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ)) {
                *tp++ = ':';
            }

            *tp++ = '\0';

            int len = strlen(tmp);
            dst.resize(len);
            memcpy(&dst[0], tmp, len);
        }
 

int main(){

    //std::string str = "3FFE:2900:D005:0:2AA:FF:FE28:9C5A";

    //std::string str = "ffee:198:603:0:396e:4789:8e99:890f";
    //std::string str = "0:0:0:0:0:ffff:192.1.56.10";
    std::string str = "2a01:198:603:0::";
    std::uint8_t data[16] = { 0 };
    wheel::unit::inet6_pton(str.c_str(), data);
    std::string sss;
    net6_ntop(data, sss);

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章