[libc-commits] [libc] [libc] Implement IPv6 (AF_INET6) support in inet_pton (PR #226550)

Aman Maurya via libc-commits libc-commits at lists.llvm.org
Mon Sep 28 11:52:12 PDT 2026


================
@@ -67,6 +67,107 @@ namespace net {
   return true;
 }
 
+namespace {
+
+LIBC_INLINE constexpr bool is_hex_char(char c) {
+  return internal::isalnum(c) && internal::b36_char_to_int(c) < 16;
+}
+
+} // anonymous namespace
+
+[[nodiscard]] bool str_to_ipv6(cpp::string_view src, struct in6_addr &dst) {
+  if (src.empty())
+    return false;
+
+  uint8_t bytes[16] = {0};
+  size_t cur_byte = 0;
+  int double_colon_byte = -1;
+
+  if (src.starts_with("::")) {
+    double_colon_byte = 0;
+    src.remove_prefix(2);
+    if (src.empty()) {
+      inline_memcpy(&dst.s6_addr, bytes, 16);
+      return true;
+    }
+  } else if (src[0] == ':') {
+    return false;
+  }
+
+  uint32_t val = 0;
+  size_t num_digits = 0;
+  size_t token_start = 0;
+
+  for (size_t i = 0; i < src.size(); ++i) {
+    char c = src[i];
+    if (is_hex_char(c)) {
+      if (++num_digits > 4)
+        return false;
+      if (num_digits == 1)
+        token_start = i;
+      val = (val << 4) | static_cast<uint32_t>(internal::b36_char_to_int(c));
+    } else if (c == ':') {
+      if (num_digits == 0) {
+        if (double_colon_byte != -1)
+          return false;
+        double_colon_byte = static_cast<int>(cur_byte);
+        continue;
+      }
+      if (i + 1 == src.size())
+        return false; // Trailing single colon
+
+      if (cur_byte + 2 > 16)
+        return false;
+
+      bytes[cur_byte++] = static_cast<uint8_t>(val >> 8);
+      bytes[cur_byte++] = static_cast<uint8_t>(val & 0xff);
+      val = 0;
+      num_digits = 0;
+    } else if (c == '.') {
+      if (num_digits == 0 || cur_byte + 4 > 16)
+        return false;
+
+      cpp::string_view ipv4_str = src.substr(token_start);
+      struct in_addr in4;
+      if (!str_to_ipv4(ipv4_str, in4))
+        return false;
+
+      inline_memcpy(&bytes[cur_byte], &in4.s_addr, 4);
+      cur_byte += 4;
+      num_digits = 0;
+      break;
+    } else {
+      return false;
+    }
+  }
+
+  if (num_digits > 0) {
+    if (cur_byte + 2 > 16)
+      return false;
+    bytes[cur_byte++] = static_cast<uint8_t>(val >> 8);
----------------
amanmaurya92 wrote:

Done. I switched to storing `uint16_t` words directly with `Endian::to_big_endian(result.value)` into `s6_addr16`, which completely eliminates the manual byte splitting from investigation.


https://github.com/llvm/llvm-project/pull/226550


More information about the libc-commits mailing list