Skip to content

Commit c8b33ae

Browse files
authored
feat: Filesystem::getline() (AcademySoftwareFoundation#4569)
Convenience function to safely read one line of text from an open FILE* and return it as a string. Signed-off-by: Larry Gritz <[email protected]>
1 parent 3663310 commit c8b33ae

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

src/include/OpenImageIO/filesystem.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,16 @@ OIIO_UTIL_API int fseek (FILE *file, int64_t offset, int whence);
223223
/// Version of ftell that works with 64 bit offsets on all systems.
224224
OIIO_UTIL_API int64_t ftell (FILE *file);
225225

226+
/// Read one line of text from an open text file file until the hitting a
227+
/// newline, reaching `maxlen` characters without encountering a newline, or
228+
/// reaching the end of the file, and return the characters read as a
229+
/// std::string. The newline will be included in the returned string, unless
230+
/// the line was too long, in which case the string returned will be the
231+
/// partial result with no newline at the end. If an error occurs or if the
232+
/// end of the file is encountered before either a newline is reached or
233+
/// maxlen characters are read, an empty string will be returned.
234+
OIIO_UTIL_API std::string getline(FILE* file, size_t maxlen = 4096);
235+
226236
/// Return the current (".") directory path.
227237
///
228238
OIIO_UTIL_API std::string current_path ();

src/libutil/filesystem.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,24 @@ Filesystem::ftell(FILE* file)
541541

542542

543543

544+
std::string
545+
Filesystem::getline(FILE* file, size_t maxlen)
546+
{
547+
std::string result;
548+
char* buf;
549+
OIIO_ALLOCATE_STACK_OR_HEAP(buf, char, maxlen + 1);
550+
if (fgets(buf, int(maxlen + 1), file)) {
551+
buf[maxlen] = 0; // be sure it is terminated
552+
if (!feof(file))
553+
result.assign(buf);
554+
} else {
555+
result.assign("");
556+
}
557+
return result;
558+
}
559+
560+
561+
544562
void
545563
Filesystem::open(OIIO::ifstream& stream, string_view path,
546564
std::ios_base::openmode mode)

src/libutil/filesystem_test.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,44 @@ test_last_write_time()
607607

608608

609609

610+
void
611+
test_getline()
612+
{
613+
const char* contents = "Line 1\n"
614+
"Line 2\n"
615+
"Really really really long long line line 3\n"
616+
"Line 4\n"
617+
"Line 5 no newline";
618+
const char* tmpfilename = "getline.txt";
619+
Filesystem::write_text_file(tmpfilename, contents);
620+
621+
FILE* in = Filesystem::fopen(tmpfilename, "r");
622+
OIIO_CHECK_ASSERT(in != nullptr);
623+
OIIO_CHECK_EQUAL(Filesystem::getline(in, 30), "Line 1\n");
624+
OIIO_CHECK_EQUAL(Filesystem::getline(in, 30), "Line 2\n");
625+
OIIO_CHECK_EQUAL(Filesystem::getline(in, 30),
626+
"Really really really long long");
627+
OIIO_CHECK_EQUAL(Filesystem::getline(in, 30), " line line 3\n");
628+
OIIO_CHECK_EQUAL(Filesystem::getline(in, 30), "Line 4\n");
629+
OIIO_CHECK_EQUAL(Filesystem::getline(in, 30), ""); // EOF before \n
630+
fclose(in);
631+
632+
// Again, with a complete line at the end to be sure we read it
633+
Filesystem::write_text_file(tmpfilename, "Line 1\n"
634+
"Line 2\n");
635+
in = Filesystem::fopen(tmpfilename, "r");
636+
OIIO_CHECK_ASSERT(in != nullptr);
637+
OIIO_CHECK_EQUAL(Filesystem::getline(in, 30), "Line 1\n");
638+
OIIO_CHECK_EQUAL(Filesystem::getline(in, 30), "Line 2\n");
639+
OIIO_CHECK_EQUAL(Filesystem::getline(in, 30), "");
640+
OIIO_CHECK_ASSERT(feof(in));
641+
fclose(in);
642+
643+
Filesystem::remove(tmpfilename);
644+
}
645+
646+
647+
610648
int
611649
main(int /*argc*/, char* /*argv*/[])
612650
{
@@ -617,6 +655,7 @@ main(int /*argc*/, char* /*argv*/[])
617655
test_scan_sequences();
618656
test_mem_proxies();
619657
test_last_write_time();
658+
test_getline();
620659

621660
return unit_test_failures;
622661
}

0 commit comments

Comments
 (0)