LibC: Add some missing wchar.h functions
isw* functions are just wrappers to is* tow* functions are just wrappers to to*
This commit is contained in:
102
userspace/libraries/LibC/wchar-stdio.cpp
Normal file
102
userspace/libraries/LibC/wchar-stdio.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#include <BAN/UTF8.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <wchar.h>
|
||||
|
||||
struct FILEScopeLock
|
||||
{
|
||||
FILEScopeLock(FILE* stream)
|
||||
: m_stream(stream)
|
||||
{
|
||||
flockfile(m_stream);
|
||||
}
|
||||
~FILEScopeLock()
|
||||
{
|
||||
funlockfile(m_stream);
|
||||
}
|
||||
FILE* m_stream;
|
||||
};
|
||||
|
||||
wint_t getwc(FILE* stream)
|
||||
{
|
||||
return fgetwc(stream);
|
||||
}
|
||||
|
||||
wint_t fgetwc(FILE* stream)
|
||||
{
|
||||
FILEScopeLock _(stream);
|
||||
|
||||
char buffer[4];
|
||||
|
||||
buffer[0] = getc_unlocked(stream);
|
||||
if (buffer[0] == EOF)
|
||||
return WEOF;
|
||||
|
||||
const auto length = BAN::UTF8::byte_length(buffer[0]);
|
||||
if (length == BAN::UTF8::invalid)
|
||||
{
|
||||
errno = EILSEQ;
|
||||
return WEOF;
|
||||
}
|
||||
|
||||
for (uint32_t i = 1; i < length; i++)
|
||||
if ((buffer[i] = getc_unlocked(stream)) == EOF)
|
||||
return WEOF;
|
||||
|
||||
const auto ret = BAN::UTF8::to_codepoint(buffer);
|
||||
if (ret == BAN::UTF8::invalid)
|
||||
{
|
||||
errno = EILSEQ;
|
||||
return WEOF;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
wint_t putwc(wchar_t wc, FILE* stream)
|
||||
{
|
||||
return fputwc(wc, stream);
|
||||
}
|
||||
|
||||
wint_t fputwc(wchar_t wc, FILE* stream)
|
||||
{
|
||||
char buffer[4];
|
||||
if (!BAN::UTF8::from_codepoints(&wc, 1, buffer))
|
||||
{
|
||||
errno = EILSEQ;
|
||||
return WEOF;
|
||||
}
|
||||
|
||||
FILEScopeLock _(stream);
|
||||
|
||||
const auto bytes = BAN::UTF8::byte_length(buffer[0]);
|
||||
for (uint32_t i = 0; i < bytes; i++)
|
||||
if (putc_unlocked(buffer[i], stream) == EOF)
|
||||
return WEOF;
|
||||
|
||||
return wc;
|
||||
}
|
||||
|
||||
wint_t ungetwc(wint_t wc, FILE* stream)
|
||||
{
|
||||
char buffer[4];
|
||||
if (!BAN::UTF8::from_codepoints(&wc, 1, buffer))
|
||||
{
|
||||
errno = EILSEQ;
|
||||
return WEOF;
|
||||
}
|
||||
|
||||
FILEScopeLock _(stream);
|
||||
|
||||
const auto bytes = BAN::UTF8::byte_length(buffer[0]);
|
||||
for (uint32_t i = 0; i < bytes; i++)
|
||||
{
|
||||
if (ungetc(buffer[i], stream) != EOF)
|
||||
continue;
|
||||
for (uint32_t j = 0; j < i; j++)
|
||||
fgetc(stream);
|
||||
return WEOF;
|
||||
}
|
||||
|
||||
return wc;
|
||||
}
|
||||
Reference in New Issue
Block a user