[libc-commits] [libc] [libc][wctype] Implement internal UTF8 wctype classification functions (PR #174607)

Marcell Leleszi via libc-commits libc-commits at lists.llvm.org
Fri Feb 6 01:53:03 PST 2026


================
@@ -125,255 +132,473 @@ LIBC_INLINE static constexpr bool isdigit(wchar_t wch) {
   }
 }
 
-LIBC_INLINE static constexpr wchar_t tolower(wchar_t wch) {
+LIBC_INLINE constexpr bool isalpha(wchar_t wch) {
   switch (wch) {
+  case L'a':
+  case L'b':
+  case L'c':
+  case L'd':
+  case L'e':
+  case L'f':
+  case L'g':
+  case L'h':
+  case L'i':
+  case L'j':
+  case L'k':
+  case L'l':
+  case L'm':
+  case L'n':
+  case L'o':
+  case L'p':
+  case L'q':
+  case L'r':
+  case L's':
+  case L't':
+  case L'u':
+  case L'v':
+  case L'w':
+  case L'x':
+  case L'y':
+  case L'z':
   case L'A':
-    return L'a';
   case L'B':
-    return L'b';
   case L'C':
-    return L'c';
   case L'D':
-    return L'd';
   case L'E':
-    return L'e';
   case L'F':
-    return L'f';
   case L'G':
-    return L'g';
   case L'H':
-    return L'h';
   case L'I':
-    return L'i';
   case L'J':
-    return L'j';
   case L'K':
-    return L'k';
   case L'L':
-    return L'l';
   case L'M':
-    return L'm';
   case L'N':
-    return L'n';
   case L'O':
-    return L'o';
   case L'P':
-    return L'p';
   case L'Q':
-    return L'q';
   case L'R':
-    return L'r';
   case L'S':
-    return L's';
   case L'T':
-    return L't';
   case L'U':
-    return L'u';
   case L'V':
-    return L'v';
   case L'W':
-    return L'w';
   case L'X':
-    return L'x';
   case L'Y':
-    return L'y';
   case L'Z':
-    return L'z';
+    return true;
   default:
-    return wch;
+    return false;
   }
 }
 
-LIBC_INLINE static constexpr wchar_t toupper(wchar_t wch) {
+LIBC_INLINE constexpr bool isalnum(wchar_t wch) {
   switch (wch) {
   case L'a':
-    return L'A';
   case L'b':
-    return L'B';
   case L'c':
-    return L'C';
   case L'd':
-    return L'D';
   case L'e':
-    return L'E';
   case L'f':
-    return L'F';
   case L'g':
-    return L'G';
   case L'h':
-    return L'H';
   case L'i':
-    return L'I';
   case L'j':
-    return L'J';
   case L'k':
-    return L'K';
   case L'l':
-    return L'L';
   case L'm':
-    return L'M';
   case L'n':
-    return L'N';
   case L'o':
-    return L'O';
   case L'p':
-    return L'P';
   case L'q':
-    return L'Q';
   case L'r':
-    return L'R';
   case L's':
-    return L'S';
   case L't':
-    return L'T';
   case L'u':
-    return L'U';
   case L'v':
-    return L'V';
   case L'w':
-    return L'W';
   case L'x':
-    return L'X';
   case L'y':
-    return L'Y';
   case L'z':
-    return L'Z';
+  case L'A':
+  case L'B':
+  case L'C':
+  case L'D':
+  case L'E':
+  case L'F':
+  case L'G':
+  case L'H':
+  case L'I':
+  case L'J':
+  case L'K':
+  case L'L':
+  case L'M':
+  case L'N':
+  case L'O':
+  case L'P':
+  case L'Q':
+  case L'R':
+  case L'S':
+  case L'T':
+  case L'U':
+  case L'V':
+  case L'W':
+  case L'X':
+  case L'Y':
+  case L'Z':
+  case L'0':
+  case L'1':
+  case L'2':
+  case L'3':
+  case L'4':
+  case L'5':
+  case L'6':
+  case L'7':
+  case L'8':
+  case L'9':
+    return true;
   default:
-    return wch;
+    return false;
+  }
+}
+
+LIBC_INLINE constexpr bool isspace(wchar_t wch) {
+  switch (wch) {
+  case L' ':
+  case L'\t':
+  case L'\n':
+  case L'\v':
+  case L'\f':
+  case L'\r':
+    return true;
+  default:
+    return false;
+  }
+}
+
+LIBC_INLINE constexpr bool isblank(wchar_t wch) {
+  switch (wch) {
+  case L' ':
+  case L'\t':
+    return true;
+  default:
+    return false;
   }
 }
 
-LIBC_INLINE static constexpr bool isalpha(wchar_t wch) {
+LIBC_INLINE constexpr bool isgraph(wchar_t wch) {
+  return 0x20 < wch && wch < 0x7f;
+}
+
+LIBC_INLINE constexpr bool isprint(wchar_t wch) {
+  return (static_cast<unsigned>(wch) - ' ') < 95;
+}
+
+LIBC_INLINE constexpr bool isxdigit(wchar_t wch) {
   switch (wch) {
   case L'a':
   case L'b':
   case L'c':
   case L'd':
   case L'e':
   case L'f':
-  case L'g':
-  case L'h':
-  case L'i':
-  case L'j':
-  case L'k':
-  case L'l':
-  case L'm':
-  case L'n':
-  case L'o':
-  case L'p':
-  case L'q':
-  case L'r':
-  case L's':
-  case L't':
-  case L'u':
-  case L'v':
-  case L'w':
-  case L'x':
-  case L'y':
-  case L'z':
   case L'A':
   case L'B':
   case L'C':
   case L'D':
   case L'E':
   case L'F':
+  case L'0':
+  case L'1':
+  case L'2':
+  case L'3':
+  case L'4':
+  case L'5':
+  case L'6':
+  case L'7':
+  case L'8':
+  case L'9':
+    return true;
+  default:
+    return false;
+  }
+}
+
+LIBC_INLINE constexpr bool iscntrl(wchar_t wch) {
+  return (wch < 0x20 || wch == 0x7f);
+}
+
+LIBC_INLINE constexpr bool ispunct(wchar_t wch) {
+  return !isalnum(wch) && isgraph(wch);
+}
+
+LIBC_INLINE constexpr wchar_t tolower(wchar_t wch) {
+  switch (wch) {
+  case L'A':
+    return L'a';
+  case L'B':
+    return L'b';
+  case L'C':
+    return L'c';
+  case L'D':
+    return L'd';
+  case L'E':
+    return L'e';
+  case L'F':
+    return L'f';
   case L'G':
+    return L'g';
   case L'H':
+    return L'h';
   case L'I':
+    return L'i';
   case L'J':
+    return L'j';
   case L'K':
+    return L'k';
   case L'L':
+    return L'l';
   case L'M':
+    return L'm';
   case L'N':
+    return L'n';
   case L'O':
+    return L'o';
   case L'P':
+    return L'p';
   case L'Q':
+    return L'q';
   case L'R':
+    return L'r';
   case L'S':
+    return L's';
   case L'T':
+    return L't';
   case L'U':
+    return L'u';
   case L'V':
+    return L'v';
   case L'W':
+    return L'w';
   case L'X':
+    return L'x';
   case L'Y':
+    return L'y';
   case L'Z':
-    return true;
+    return L'z';
   default:
-    return false;
+    return wch;
   }
 }
 
-LIBC_INLINE static constexpr bool isalnum(wchar_t wch) {
+LIBC_INLINE constexpr wchar_t toupper(wchar_t wch) {
   switch (wch) {
   case L'a':
+    return L'A';
   case L'b':
+    return L'B';
   case L'c':
+    return L'C';
   case L'd':
+    return L'D';
   case L'e':
+    return L'E';
   case L'f':
+    return L'F';
   case L'g':
+    return L'G';
   case L'h':
+    return L'H';
   case L'i':
+    return L'I';
   case L'j':
+    return L'J';
   case L'k':
+    return L'K';
   case L'l':
+    return L'L';
   case L'm':
+    return L'M';
   case L'n':
+    return L'N';
   case L'o':
+    return L'O';
   case L'p':
+    return L'P';
   case L'q':
+    return L'Q';
   case L'r':
+    return L'R';
   case L's':
+    return L'S';
   case L't':
+    return L'T';
   case L'u':
+    return L'U';
   case L'v':
+    return L'V';
   case L'w':
+    return L'W';
   case L'x':
+    return L'X';
   case L'y':
+    return L'Y';
   case L'z':
-  case L'A':
-  case L'B':
-  case L'C':
-  case L'D':
-  case L'E':
-  case L'F':
-  case L'G':
-  case L'H':
-  case L'I':
-  case L'J':
-  case L'K':
-  case L'L':
-  case L'M':
-  case L'N':
-  case L'O':
-  case L'P':
-  case L'Q':
-  case L'R':
-  case L'S':
-  case L'T':
-  case L'U':
-  case L'V':
-  case L'W':
-  case L'X':
-  case L'Y':
-  case L'Z':
-  case L'0':
-  case L'1':
-  case L'2':
-  case L'3':
-  case L'4':
-  case L'5':
-  case L'6':
-  case L'7':
-  case L'8':
-  case L'9':
-    return true;
+    return L'Z';
   default:
-    return false;
+    return wch;
+  }
+}
+
+} // namespace ascii
+
+LIBC_INLINE constexpr bool islower(wchar_t wch) {
+#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
+  return ascii::islower(wch);
+#else
+  if (static_cast<uint32_t>(wch) < 128) {
+    return ascii::islower(wch);
+  }
+  return lookup_properties(wch) & PropertyFlag::LOWER;
+#endif
+}
+
+LIBC_INLINE constexpr bool isupper(wchar_t wch) {
+#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
+  return ascii::isupper(wch);
+#else
+  if (static_cast<uint32_t>(wch) < 128) {
+    return ascii::isupper(wch);
+  }
+  return lookup_properties(wch) & PropertyFlag::UPPER;
+#endif
+}
+
+LIBC_INLINE constexpr bool isdigit(wchar_t wch) {
+  // In C.UT8, only ASCII digits are considered digits
+  return ascii::isdigit(wch);
+}
+
+LIBC_INLINE constexpr bool isalpha(wchar_t wch) {
+#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
+  return ascii::isalpha(wch);
+#else
+  if (static_cast<uint32_t>(wch) < 128) {
+    return ascii::isalpha(wch);
+  }
+  return lookup_properties(wch) & PropertyFlag::ALPHA;
+#endif
+}
+
+LIBC_INLINE constexpr bool isalnum(wchar_t wch) {
+#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
+  return ascii::isalnum(wch);
+#else
+  if (static_cast<uint32_t>(wch) < 128) {
+    return ascii::isalnum(wch);
+  }
+  // Only need to check ALPHA, digit cases are covered by ASCII path
+  return lookup_properties(wch) & PropertyFlag::ALPHA;
+#endif
+}
+
+LIBC_INLINE constexpr bool isspace(wchar_t wch) {
+#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
+  return ascii::isspace(wch);
+#else
+  if (static_cast<uint32_t>(wch) < 128) {
+    return ascii::isspace(wch);
+  }
+  return lookup_properties(wch) & PropertyFlag::SPACE;
+#endif
+}
+
+LIBC_INLINE constexpr bool isblank(wchar_t wch) {
+#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
+  return ascii::isblank(wch);
+#else
+  if (static_cast<uint32_t>(wch) < 128) {
+    return ascii::isblank(wch);
+  }
+  return lookup_properties(wch) & PropertyFlag::BLANK;
+#endif
+}
+
+LIBC_INLINE constexpr bool isgraph(wchar_t wch) {
+#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
+  return ascii::isgraph(wch);
+#else
+  if (static_cast<uint32_t>(wch) < 128) {
+    return ascii::isgraph(wch);
+  }
+  // print && !space
+  return (lookup_properties(wch) &
+          (PropertyFlag::PRINT | PropertyFlag::SPACE)) == PropertyFlag::PRINT;
+#endif
+}
+
+LIBC_INLINE constexpr bool isprint(wchar_t wch) {
+#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
+  return ascii::isprint(wch);
+#else
+  if (static_cast<uint32_t>(wch) < 128) {
+    return ascii::isprint(wch);
   }
+  return lookup_properties(wch) & PropertyFlag::PRINT;
+#endif
 }
 
-LIBC_INLINE static constexpr int b36_char_to_int(wchar_t wch) {
+LIBC_INLINE constexpr bool isxdigit(wchar_t wch) {
----------------
mleleszi wrote:

Done

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


More information about the libc-commits mailing list