diff --git a/code/logic/fossil/io/input.h b/code/logic/fossil/io/input.h index 400def4..889b120 100644 --- a/code/logic/fossil/io/input.h +++ b/code/logic/fossil/io/input.h @@ -22,6 +22,14 @@ extern "C" { #endif +/** + * Reads a single character from the input stream. + * + * @param input_stream Pointer to the input stream to read from. + * @return The character read as an unsigned char cast to an int, or EOF on end-of-file or error. + */ +int fossil_io_getc(FILE *input_stream); + /** * Reads a line from the input stream and stores it into the buffer pointed to by 'buf'. * @@ -171,6 +179,16 @@ namespace fossil { */ class Input { public: + /** + * Reads a single character from the input stream. + * + * @param input_stream Pointer to the input stream to read from. + * @return The character read as an unsigned char cast to an int, or EOF on end-of-file or error. + */ + static int getc(FILE *input_stream) { + return fossil_io_getc(input_stream); + } + /** * Reads a line from the input stream and stores it into the buffer pointed to by 'buf'. * diff --git a/code/logic/input.c b/code/logic/input.c index 7d2744c..774b6b1 100644 --- a/code/logic/input.c +++ b/code/logic/input.c @@ -88,6 +88,20 @@ void fossil_io_show_progress(int progress) { fflush(stdout); } +int fossil_io_getc(FILE *input_stream) { + if (input_stream == NULL) { + fprintf(stderr, "Error: Invalid input stream.\n"); + return EOF; + } + + int c = fgetc(input_stream); + if (c == EOF && ferror(input_stream)) { + fprintf(stderr, "Error: Failed to read from input stream.\n"); + } + + return c; +} + // Function to get a sanitized line of input from a provided stream (or stdin by default) char *fossil_io_gets_from_stream(char *buf, size_t size, FILE *input_stream) { if (buf == NULL || size == 0 || input_stream == NULL) { diff --git a/code/tests/cases/test_input.c b/code/tests/cases/test_input.c index 4e75e1a..ffcf7dc 100644 --- a/code/tests/cases/test_input.c +++ b/code/tests/cases/test_input.c @@ -208,14 +208,15 @@ FOSSIL_TEST_CASE(c_test_io_validate_is_length_invalid) { ASSUME_ITS_FALSE(result); } -FOSSIL_TEST_CASE(c_test_io_show_progress) { - // This test assumes the progress bar function doesn't return anything. - // We'll just check that the progress is shown correctly. +FOSSIL_TEST_CASE(c_test_io_getc) { + const char *input_data = "test input\n"; + FILE *input_stream = tmpfile(); + fwrite(input_data, 1, strlen(input_data), input_stream); + rewind(input_stream); - // Test with various progress values (0%, 50%, 100%) - fossil_io_show_progress(0); - fossil_io_show_progress(50); - fossil_io_show_progress(100); + int ch = fossil_io_getc(input_stream); + ASSUME_ITS_EQUAL_I32('t', ch); + fclose(input_stream); } // * * * * * * * * * * * * * * * * * * * * * * * * @@ -240,7 +241,7 @@ FOSSIL_TEST_GROUP(c_input_tests) { FOSSIL_TEST_ADD(c_input_suite, c_test_io_validate_is_email_invalid); FOSSIL_TEST_ADD(c_input_suite, c_test_io_validate_is_length_valid); FOSSIL_TEST_ADD(c_input_suite, c_test_io_validate_is_length_invalid); - FOSSIL_TEST_ADD(c_input_suite, c_test_io_show_progress); + FOSSIL_TEST_ADD(c_input_suite, c_test_io_getc); FOSSIL_TEST_REGISTER(c_input_suite); } diff --git a/code/tests/cases/test_input.cpp b/code/tests/cases/test_input.cpp index 76980cc..3f6452a 100644 --- a/code/tests/cases/test_input.cpp +++ b/code/tests/cases/test_input.cpp @@ -335,6 +335,17 @@ FOSSIL_TEST_CASE(cpp_test_io_input_class_gets_from_stream_whitespace_only) { fclose(input_stream); } +FOSSIL_TEST_CASE(cpp_test_io_getc) { + const char *input_data = "test input\n"; + FILE *input_stream = tmpfile(); + fwrite(input_data, 1, strlen(input_data), input_stream); + rewind(input_stream); + + int ch = fossil::io::Input::getc(input_stream); + ASSUME_ITS_EQUAL_I32('t', ch); + fclose(input_stream); +} + // * * * * * * * * * * * * * * * * * * * * * * * * // * Fossil Logic Test Pool // * * * * * * * * * * * * * * * * * * * * * * * * @@ -369,6 +380,7 @@ FOSSIL_TEST_GROUP(cpp_input_tests) { FOSSIL_TEST_ADD(cpp_input_suite, cpp_test_io_input_class_gets_utf8_valid); FOSSIL_TEST_ADD(cpp_input_suite, cpp_test_io_input_class_gets_from_stream_empty); FOSSIL_TEST_ADD(cpp_input_suite, cpp_test_io_input_class_gets_from_stream_whitespace_only); + FOSSIL_TEST_ADD(cpp_input_suite, cpp_test_io_getc); FOSSIL_TEST_REGISTER(cpp_input_suite); }