diff --git a/Userland/Libraries/LibC/bits/stdio_file_implementation.h b/Userland/Libraries/LibC/bits/stdio_file_implementation.h index abd6eaf3a6..46e9a8cec5 100644 --- a/Userland/Libraries/LibC/bits/stdio_file_implementation.h +++ b/Userland/Libraries/LibC/bits/stdio_file_implementation.h @@ -40,7 +40,9 @@ public: size_t read(u8*, size_t); size_t write(const u8*, size_t); - bool gets(u8*, size_t); + template + bool gets(CharType*, size_t); + bool ungetc(u8 byte) { return m_buffer.enqueue_front(byte); } int seek(off_t offset, int whence); diff --git a/Userland/Libraries/LibC/stdio.cpp b/Userland/Libraries/LibC/stdio.cpp index 92a3039d90..84017cf5b5 100644 --- a/Userland/Libraries/LibC/stdio.cpp +++ b/Userland/Libraries/LibC/stdio.cpp @@ -232,7 +232,8 @@ size_t FILE::write(const u8* data, size_t size) return total_written; } -bool FILE::gets(u8* data, size_t size) +template +bool FILE::gets(T* data, size_t size) { // gets() is a lot like read(), but it is different enough in how it // processes newlines and null-terminates the buffer that it deserves a @@ -249,7 +250,8 @@ bool FILE::gets(u8* data, size_t size) if (m_buffer.may_use()) { // Let's see if the buffer has something queued for us. size_t queued_size; - const u8* queued_data = m_buffer.begin_dequeue(queued_size); + const T* queued_data = bit_cast(m_buffer.begin_dequeue(queued_size)); + queued_size /= sizeof(T); if (queued_size == 0) { // Nothing buffered; we're going to have to read some. bool read_some_more = read_into_buffer(); @@ -261,11 +263,17 @@ bool FILE::gets(u8* data, size_t size) return total_read > 0; } size_t actual_size = min(size - 1, queued_size); - u8* newline = reinterpret_cast(memchr(queued_data, '\n', actual_size)); - if (newline) - actual_size = newline - queued_data + 1; - memcpy(data, queued_data, actual_size); - m_buffer.did_dequeue(actual_size); + T const* newline = nullptr; + for (size_t i = 0; i < actual_size; ++i) { + if (queued_data[i] != '\n') + continue; + + newline = &queued_data[i]; + actual_size = i + 1; + break; + } + memcpy(data, queued_data, actual_size * sizeof(T)); + m_buffer.did_dequeue(actual_size * sizeof(T)); total_read += actual_size; data += actual_size; size -= actual_size; @@ -273,18 +281,18 @@ bool FILE::gets(u8* data, size_t size) break; } else { // Sadly, we have to actually read these characters one by one. - u8 byte; - ssize_t nread = do_read(&byte, 1); + T value; + ssize_t nread = do_read(bit_cast(&value), sizeof(T)); if (nread <= 0) { *data = 0; return total_read > 0; } - VERIFY(nread == 1); - *data = byte; + VERIFY(nread == sizeof(T)); + *data = value; total_read++; data++; size--; - if (byte == '\n') + if (value == '\n') break; } } @@ -1204,3 +1212,6 @@ void __fpurge(FILE* stream) stream->purge(); } } + +template bool FILE::gets(u8*, size_t); +template bool FILE::gets(u32*, size_t); diff --git a/Userland/Libraries/LibC/wchar.h b/Userland/Libraries/LibC/wchar.h index 6b2d2f767a..d17b432180 100644 --- a/Userland/Libraries/LibC/wchar.h +++ b/Userland/Libraries/LibC/wchar.h @@ -77,6 +77,8 @@ wint_t getwchar(void); wint_t fputwc(wchar_t wc, FILE* stream); wint_t putwc(wchar_t wc, FILE* stream); wint_t putwchar(wchar_t wc); +wchar_t* fgetws(wchar_t* __restrict ws, int n, FILE* __restrict stream); +int fputws(const wchar_t* __restrict ws, FILE* __restrict stream); int fwide(FILE* stream, int mode); __END_DECLS diff --git a/Userland/Libraries/LibC/wstdio.cpp b/Userland/Libraries/LibC/wstdio.cpp index b4f4df488a..521551a208 100644 --- a/Userland/Libraries/LibC/wstdio.cpp +++ b/Userland/Libraries/LibC/wstdio.cpp @@ -98,4 +98,24 @@ wint_t putwchar(wchar_t wc) { return fputwc(wc, stdout); } + +wchar_t* fgetws(wchar_t* __restrict buffer, int size, FILE* __restrict stream) +{ + VERIFY(stream); + ScopedFileLock lock(stream); + bool ok = stream->gets(bit_cast(buffer), size); + return ok ? buffer : nullptr; +} + +int fputws(wchar_t const* __restrict ws, FILE* __restrict stream) +{ + VERIFY(stream); + ScopedFileLock lock(stream); + int size = 0; + for (auto const* p = ws; *p != 0; ++p, ++size) { + if (putwc(*p, stream) == WEOF) + return WEOF; + } + return size; +} }