mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 15:27:35 +00:00
LibC: Implement f{get,put}ws()
This commit is contained in:
parent
bd9a22e7e7
commit
db7a6d6e74
4 changed files with 48 additions and 13 deletions
|
@ -40,7 +40,9 @@ public:
|
|||
size_t read(u8*, size_t);
|
||||
size_t write(const u8*, size_t);
|
||||
|
||||
bool gets(u8*, size_t);
|
||||
template<typename CharType>
|
||||
bool gets(CharType*, size_t);
|
||||
|
||||
bool ungetc(u8 byte) { return m_buffer.enqueue_front(byte); }
|
||||
|
||||
int seek(off_t offset, int whence);
|
||||
|
|
|
@ -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<typename T>
|
||||
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<const T*>(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<u8*>(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<u8*>(&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>(u8*, size_t);
|
||||
template bool FILE::gets<u32>(u32*, size_t);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<u32*>(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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue