[libc-commits] [libc] [libc] Implemented CharacterConverter push/pop for utf32->utf8 conversions (PR #143971)

Brooks Moses via libc-commits libc-commits at lists.llvm.org
Fri Jun 13 16:27:04 PDT 2025


================
@@ -22,13 +24,61 @@ bool CharacterConverter::isComplete() {
   return state->bytes_processed == state->total_bytes;
 }
 
-int CharacterConverter::push(char8_t utf8_byte) {}
+int CharacterConverter::push(char32_t utf32) {
+  state->partial = utf32;
+  state->bytes_processed = 0;
+  state->total_bytes = 0;
 
-int CharacterConverter::push(char32_t utf32) {}
+  // determine number of utf-8 bytes needed to represent this utf32 value
+  constexpr char32_t ranges[] = {0x7f, 0x7ff, 0xffff, 0x10ffff};
+  constexpr int num_ranges = 4;
+  for (uint8_t i = 0; i < num_ranges; i++) {
+    if (state->partial <= ranges[i]) {
+      state->total_bytes = i + 1;
+      break;
+    }
+  }
+  if (state->total_bytes == 0)
+    return -1;
 
-utf_ret<char8_t> CharacterConverter::pop_utf8() {}
+  return 0;
+}
+
+ErrorOr<char8_t> CharacterConverter::pop_utf8() {
+  if (state->bytes_processed >= state->total_bytes)
+    return Error(-1);
+
+  constexpr char8_t FIRST_BYTE_HEADERS[] = {0, 0xC0, 0xE0, 0xF0};
+  constexpr char8_t CONTINUING_BYTE_HEADER = 0x80;
+
+  // the number of bits per utf-8 byte that actually encode character
+  // information not metadata (# of bits excluding the byte headers)
+  constexpr size_t ENCODED_BITS_PER_UTF8 = 6;
----------------
brooksmoses wrote:

After landing these two CLs, it would be good to do a refactoring followup to move these constants to a central location, since you're both defining the same ones.

(Also, this one is really ENCODED_BITS_PER_UTF8_FOLLOWING_BYTE or something like that.  Does the standard have a word it uses for "not-first byte"?)

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


More information about the libc-commits mailing list