feat(libc): implement rewind

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Adrià Franch 2026-10-11 02:54:24 +02:00
parent 06da117642
commit e7605c8fd6
2 changed files with 38 additions and 0 deletions

View File

@ -246,6 +246,12 @@ int APS5_VABI fsetpos_nid_postfix(FileStream* stream, const std::int64_t* positi
return fseeko_nid_postfix(stream, *position, SEEK_SET);
}
void APS5_VABI rewind_nid_postfix(FileStream* stream) {
const int saved = errno;
if (fseeko_nid_postfix(stream, 0, SEEK_SET) == 0) errno = saved;
stream->ClearError();
}
int APS5_VABI fputs_nid_postfix(const char* str, FileStream* stream) {
if (!str) throw std::runtime_error("fputs: null string");
const int result = std::fputs(str, GetNativeStream(stream));

View File

@ -41,8 +41,10 @@ int APS5_VABI __swbuf_nid_postfix(int, FileStream*);
int APS5_VABI ungetc_nid_postfix(int, FileStream*);
char* APS5_VABI fgets_nid_postfix(char*, int, FileStream*);
int APS5_VABI feof_nid_postfix(FileStream*);
int APS5_VABI ferror_nid_postfix(FileStream*);
int APS5_VABI fileno_nid_postfix(FileStream*);
void APS5_VABI clearerr_nid_postfix(FileStream*);
void APS5_VABI rewind_nid_postfix(FileStream*);
int APS5_VABI setvbuf_nid_postfix(FileStream*, char*, int, std::size_t);
void APS5_VABI setbuf_nid_postfix(FileStream*, char*);
FileStream* APS5_VABI fdopen_nid_postfix(int, const char*);
@ -93,6 +95,35 @@ static bool CheckFileBytes(const std::string& filename, const std::string& expec
return false;
}
static void CheckRewind() {
FileStream stream(std::tmpfile());
Require(fwrite_nid_postfix("ab", 1, 2, &stream) == 2);
*__error_nid_postfix() = 7;
rewind_nid_postfix(&stream);
Require(*__error_nid_postfix() == 7 && ftello_nid_postfix(&stream) == 0);
Require(fgetc_nid_postfix(&stream) == 'a' && ungetc_nid_postfix('z', &stream) == 'z');
rewind_nid_postfix(&stream);
Require(fgetc_nid_postfix(&stream) == 'a' && fgetc_nid_postfix(&stream) == 'b' && fgetc_nid_postfix(&stream) == EOF);
Require(feof_nid_postfix(&stream) != 0);
stream.SetEncodingError();
Require(ferror_nid_postfix(&stream) != 0);
rewind_nid_postfix(&stream);
Require(feof_nid_postfix(&stream) == 0 && ferror_nid_postfix(&stream) == 0 && fgetc_nid_postfix(&stream) == 'a');
stream.Close();
#ifndef _WIN32
int pipeEnds[2];
Require(::pipe(pipeEnds) == 0);
Require(::write(pipeEnds[1], "p", 1) == 1);
::close(pipeEnds[1]);
FileStream pipe(::fdopen(pipeEnds[0], "r"));
Require(fgetc_nid_postfix(&pipe) == 'p' && fgetc_nid_postfix(&pipe) == EOF && feof_nid_postfix(&pipe) != 0);
*__error_nid_postfix() = 0;
rewind_nid_postfix(&pipe);
Require(*__error_nid_postfix() == 29 && feof_nid_postfix(&pipe) == 0 && ferror_nid_postfix(&pipe) == 0);
pipe.Close();
#endif
}
static bool CheckBinaryModes() {
const auto directory = "anyps5-byte-stream-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count());
Require(std::filesystem::create_directory(directory));
@ -333,5 +364,6 @@ int main() {
Require(lockedWrite && fseeko_nid_postfix(&locked, 0, SEEK_SET) == 0);
Require(fgetc_nid_postfix(&locked) == 'A' && fgetc_nid_postfix(&locked) == 'B');
locked.Close();
CheckRewind();
return CheckBinaryModes() ? 0 : 1;
}