[libc-commits] [libc] [libc] Add wchar support to File (PR #189504)
Jeff Bailey via libc-commits
libc-commits at lists.llvm.org
Fri May 1 09:37:19 PDT 2026
================
@@ -509,4 +550,132 @@ File::ModeFlags File::mode_flags(const char *mode) {
return flags;
}
+FileIOResult File::write_unlocked(const wchar_t *ws, size_t len) {
+ switch (orientation) {
+ case Orientation::BYTE:
+ err = true;
+ return {0, EINVAL};
+ case Orientation::UNORIENTED:
+ orientation = Orientation::WIDE;
+ break;
+ case Orientation::WIDE:
+ break;
+ }
+
+ size_t written = 0;
+ for (size_t i = 0; i < len; ++i) {
+ internal::CharacterConverter cr(&mbstate);
+ int push_err = cr.push(static_cast<char32_t>(ws[i]));
+ if (push_err != 0) {
+ err = true;
+ return {written, push_err};
+ }
+ // buffer the whole wchar to save on calls to write.
+ char buffer[4];
+ size_t char_size = 0;
+ while (!cr.isEmpty()) {
+ auto pop_res = cr.pop<char8_t>();
+ if (!pop_res.has_value()) {
+ err = true;
+ return {written, pop_res.error()};
+ }
+ char8_t byte = pop_res.value();
+ buffer[char_size] = byte;
+ ++char_size;
+ }
+ auto write_res = write_unlocked_impl(buffer, char_size);
+ if (write_res.has_error())
+ return {written, write_res.error};
+ if (write_res.value < 1)
+ return {written, 0};
+ ++written;
+ }
+ return {written, 0};
+}
+
+FileIOResult File::read_unlocked(wchar_t *ws, size_t len) {
+ switch (orientation) {
+ case Orientation::BYTE:
+ err = true;
+ return {0, EINVAL};
+ case Orientation::UNORIENTED:
+ orientation = Orientation::WIDE;
+ break;
+ case Orientation::WIDE:
+ break;
+ }
+
+ size_t read_count = 0;
+ for (size_t i = 0; i < len; ++i) {
+ internal::CharacterConverter cr(&mbstate);
+ while (!cr.isFull()) {
+ uint8_t byte;
+ auto read_res = read_unlocked_impl(&byte, 1);
+ if (read_res.has_error())
+ return {read_count, read_res.error};
+ if (read_res.value == 0) { // EOF
+ if (cr.isEmpty())
+ return {read_count, 0};
+ err = true;
+ return {read_count, EILSEQ}; // Incomplete character at EOF
+ }
+ int push_err = cr.push(static_cast<char8_t>(byte));
+ if (push_err != 0) {
+ err = true;
+ return {read_count, push_err};
+ }
+ }
+ auto pop_res = cr.pop<char32_t>();
+ if (!pop_res.has_value()) {
+ err = true;
+ return {read_count, pop_res.error()};
+ }
+ ws[i] = static_cast<wchar_t>(pop_res.value());
+ ++read_count;
+ }
+ return {read_count, 0};
+}
+
+wint_t File::ungetwc_unlocked(wint_t wc) {
+ if (wc == WEOF)
----------------
kaladron wrote:
ungetc_unlocked has a guard:
```
if (c == EOF || !read_allowed() || (prev_op == FileOp::WRITE))
return EOF;
```
Does read_allowed need to be checked here too?
https://github.com/llvm/llvm-project/pull/189504
More information about the libc-commits
mailing list