diff options
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | meson/suppressions/meson.build | 1 | ||||
-rw-r--r-- | src/.clang-tidy | 6 | ||||
-rw-r--r-- | src/byte_source.c | 15 | ||||
-rw-r--r-- | src/byte_source.h | 7 | ||||
-rw-r--r-- | test/.clang-tidy | 2 | ||||
-rw-r--r-- | test/test_node.c | 4 | ||||
-rw-r--r-- | test/test_reader.c | 103 | ||||
-rw-r--r-- | test/test_uri.c | 102 |
9 files changed, 118 insertions, 125 deletions
@@ -4,6 +4,7 @@ serd (0.32.3) unstable; urgency=medium * Fix library current_version on MacOS * Fix overly permissive parsing of syntax names on the command line * Fix parsing NQuads lines with no space before the final dot + * Fix reading chunks from files without trailing newlines * Fix rewriting special literals when datatype URIs are prefixed names * Gracefully handle errors while writing the end of anonymous nodes * Improve test suite coverage @@ -12,7 +13,7 @@ serd (0.32.3) unstable; urgency=medium * Treat out of range unicode characters as errors * Write blank lines between graphs and statements in TriG - -- David Robillard <d@drobilla.net> Tue, 25 Jun 2024 22:38:16 +0000 + -- David Robillard <d@drobilla.net> Sat, 03 Aug 2024 15:50:39 +0000 serd (0.32.2) stable; urgency=medium diff --git a/meson/suppressions/meson.build b/meson/suppressions/meson.build index 94ca305d..461a7128 100644 --- a/meson/suppressions/meson.build +++ b/meson/suppressions/meson.build @@ -22,6 +22,7 @@ if is_variable('cc') '-Wno-double-promotion', '-Wno-format-nonliteral', '-Wno-padded', + '-Wno-switch-default', '-Wno-unsafe-buffer-usage', ] diff --git a/src/.clang-tidy b/src/.clang-tidy index 52862fe4..18cba92e 100644 --- a/src/.clang-tidy +++ b/src/.clang-tidy @@ -2,9 +2,13 @@ # SPDX-License-Identifier: 0BSD OR ISC Checks: > + -*-macro-to-enum, -*-magic-numbers, -bugprone-easily-swappable-parameters, + -bugprone-inc-dec-in-conditions, + -bugprone-multi-level-implicit-pointer-conversion, -cert-err33-c, + -clang-analyzer-optin.core.EnumCastOutOfRange, -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling, -concurrency-mt-unsafe, -google-readability-todo, @@ -12,7 +16,7 @@ Checks: > -hicpp-signed-bitwise, -llvm-header-guard, -misc-no-recursion, - -modernize-macro-to-enum, + -readability-avoid-nested-conditional-operator, CheckOptions: - key: readability-function-cognitive-complexity.IgnoreMacros value: 'true' diff --git a/src/byte_source.c b/src/byte_source.c index 5443f4dd..122dc0f9 100644 --- a/src/byte_source.c +++ b/src/byte_source.c @@ -19,18 +19,17 @@ serd_byte_source_page(SerdByteSource* const source) const size_t n_read = source->read_func(source->file_buf, 1, source->page_size, source->stream); + source->buf_size = n_read; + if (n_read < source->page_size) { + source->file_buf[n_read] = '\0'; + } + if (n_read == 0) { - source->file_buf[0] = '\0'; - source->eof = true; + source->eof = true; return (source->error_func(source->stream) ? SERD_ERR_UNKNOWN : SERD_FAILURE); } - if (n_read < source->page_size) { - source->file_buf[n_read] = '\0'; - source->buf_size = n_read; - } - return SERD_SUCCESS; } @@ -52,7 +51,7 @@ serd_byte_source_open_source(SerdByteSource* const source, source->stream = stream; source->from_stream = true; source->page_size = page_size; - source->buf_size = page_size; + source->buf_size = 0U; source->cur = cur; source->error_func = error_func; source->read_func = read_func; diff --git a/src/byte_source.h b/src/byte_source.h index 02aab663..afd9ccb9 100644 --- a/src/byte_source.h +++ b/src/byte_source.h @@ -69,10 +69,11 @@ serd_byte_source_advance(SerdByteSource* source) { SerdStatus st = SERD_SUCCESS; - if (serd_byte_source_peek(source) == '\n') { + const uint8_t c = serd_byte_source_peek(source); + if (c == '\n') { ++source->cur.line; source->cur.col = 0; - } else { + } else if (c) { ++source->cur.col; } @@ -82,7 +83,7 @@ serd_byte_source_advance(SerdByteSource* source) if (source->page_size > 1) { if (++source->read_head == source->page_size) { st = serd_byte_source_page(source); - } else if (source->read_head == source->buf_size) { + } else if (source->read_head >= source->buf_size) { source->eof = true; } } else { diff --git a/test/.clang-tidy b/test/.clang-tidy index 457abcaf..99a3264a 100644 --- a/test/.clang-tidy +++ b/test/.clang-tidy @@ -8,9 +8,11 @@ Checks: > -bugprone-easily-swappable-parameters, -cert-err33-c, -clang-analyzer-nullability.NullableDereferenced, + -clang-analyzer-optin.core.EnumCastOutOfRange, -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling, -concurrency-mt-unsafe, -hicpp-signed-bitwise, + -readability-redundant-casting, CheckOptions: - key: readability-function-cognitive-complexity.IgnoreMacros value: 'true' diff --git a/test/test_node.c b/test/test_node.c index af14171b..09e9dfff 100644 --- a/test/test_node.c +++ b/test/test_node.c @@ -24,7 +24,7 @@ #endif static void -test_strtod(double dbl, double max_delta) +check_strtod(double dbl, double max_delta) { char buf[1024]; snprintf(buf, sizeof(buf), "%f", dbl); @@ -56,7 +56,7 @@ test_string_to_double(void) const double delta = fabs(num - expt_test_nums[i]); assert(delta <= DBL_EPSILON); - test_strtod(expt_test_nums[i], DBL_EPSILON); + check_strtod(expt_test_nums[i], DBL_EPSILON); } } diff --git a/test/test_reader.c b/test/test_reader.c index b102f8a6..9e2edd17 100644 --- a/test/test_reader.c +++ b/test/test_reader.c @@ -26,7 +26,7 @@ typedef struct { } ReaderTest; static SerdStatus -test_base_sink(void* const handle, const SerdNode* const uri) +base_sink(void* const handle, const SerdNode* const uri) { (void)uri; @@ -36,9 +36,9 @@ test_base_sink(void* const handle, const SerdNode* const uri) } static SerdStatus -test_prefix_sink(void* const handle, - const SerdNode* const name, - const SerdNode* const uri) +prefix_sink(void* const handle, + const SerdNode* const name, + const SerdNode* const uri) { (void)name; (void)uri; @@ -49,14 +49,14 @@ test_prefix_sink(void* const handle, } static SerdStatus -test_statement_sink(void* const handle, - SerdStatementFlags flags, - const SerdNode* const graph, - const SerdNode* const subject, - const SerdNode* const predicate, - const SerdNode* const object, - const SerdNode* const object_datatype, - const SerdNode* const object_lang) +statement_sink(void* const handle, + SerdStatementFlags flags, + const SerdNode* const graph, + const SerdNode* const subject, + const SerdNode* const predicate, + const SerdNode* const object, + const SerdNode* const object_datatype, + const SerdNode* const object_lang) { (void)flags; (void)graph; @@ -72,7 +72,7 @@ test_statement_sink(void* const handle, } static SerdStatus -test_end_sink(void* const handle, const SerdNode* const node) +end_sink(void* const handle, const SerdNode* const node) { (void)node; @@ -85,13 +85,8 @@ static void test_read_string(void) { ReaderTest rt = {0, 0, 0, 0}; - SerdReader* const reader = serd_reader_new(SERD_TURTLE, - &rt, - NULL, - test_base_sink, - test_prefix_sink, - test_statement_sink, - test_end_sink); + SerdReader* const reader = serd_reader_new( + SERD_TURTLE, &rt, NULL, base_sink, prefix_sink, statement_sink, end_sink); assert(reader); assert(serd_reader_get_handle(reader) == &rt); @@ -155,9 +150,9 @@ eof_test_error(void* stream) return 0; } -/// A read of a big page hits EOF then fails to read chunks immediately +/// A read of a file stream hits EOF then fails to read chunks immediately static void -test_read_eof_by_page(const char* const path) +test_read_eof_file(const char* const path) { FILE* const f = fopen(path, "w+b"); assert(f); @@ -167,21 +162,23 @@ test_read_eof_by_page(const char* const path) fseek(f, 0L, SEEK_SET); ReaderTest rt = {0, 0, 0, 0}; - SerdReader* const reader = serd_reader_new(SERD_TURTLE, - &rt, - NULL, - test_base_sink, - test_prefix_sink, - test_statement_sink, - test_end_sink); + SerdReader* const reader = serd_reader_new( + SERD_TURTLE, &rt, NULL, base_sink, prefix_sink, statement_sink, end_sink); + fseek(f, 0L, SEEK_SET); serd_reader_start_stream(reader, f, (const uint8_t*)"test", true); - assert(serd_reader_read_chunk(reader) == SERD_SUCCESS); assert(serd_reader_read_chunk(reader) == SERD_FAILURE); assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + serd_reader_end_stream(reader); + fseek(f, 0L, SEEK_SET); + serd_reader_start_stream(reader, f, (const uint8_t*)"test", false); + assert(serd_reader_read_chunk(reader) == SERD_SUCCESS); + assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + assert(serd_reader_read_chunk(reader) == SERD_FAILURE); serd_reader_end_stream(reader); + serd_reader_free(reader); fclose(f); } @@ -191,13 +188,8 @@ static void test_read_eof_by_byte(void) { ReaderTest rt = {0, 0, 0, 0}; - SerdReader* const reader = serd_reader_new(SERD_TURTLE, - &rt, - NULL, - test_base_sink, - test_prefix_sink, - test_statement_sink, - test_end_sink); + SerdReader* const reader = serd_reader_new( + SERD_TURTLE, &rt, NULL, base_sink, prefix_sink, statement_sink, end_sink); size_t n_reads = 0U; serd_reader_start_source_stream(reader, @@ -212,6 +204,7 @@ test_read_eof_by_byte(void) assert(serd_reader_read_chunk(reader) == SERD_SUCCESS); assert(serd_reader_read_chunk(reader) == SERD_FAILURE); + serd_reader_end_stream(reader); serd_reader_free(reader); } @@ -236,24 +229,21 @@ test_read_nquads_chunks(const char* const path) fprintf(f, "<http://example.org/s> <http://example.org/p3> " - "<http://example.org/o3> .\n"); + "<http://example.org/o3> ."); fseek(f, 0, SEEK_SET); ReaderTest rt = {0, 0, 0, 0}; - SerdReader* const reader = serd_reader_new(SERD_NQUADS, - &rt, - NULL, - test_base_sink, - test_prefix_sink, - test_statement_sink, - test_end_sink); + SerdReader* const reader = serd_reader_new( + SERD_NQUADS, &rt, NULL, base_sink, prefix_sink, statement_sink, end_sink); assert(reader); assert(serd_reader_get_handle(reader) == &rt); assert(f); - SerdStatus st = serd_reader_start_stream(reader, f, NULL, false); + SerdStatus st = serd_reader_start_source_stream( + reader, (SerdSource)fread, (SerdStreamErrorFunc)ferror, f, NULL, 32U); + assert(st == SERD_SUCCESS); // Read first statement @@ -297,7 +287,7 @@ test_read_nquads_chunks(const char* const path) assert(rt.n_end == 0); assert(serd_reader_read_chunk(reader) == SERD_FAILURE); - + serd_reader_end_stream(reader); serd_reader_free(reader); fclose(f); remove(path); @@ -316,24 +306,19 @@ test_read_turtle_chunks(const char* const path) fprintf(f, "eg:s eg:p1 eg:o1 ;\n"); fprintf(f, " eg:p2 eg:o2 .\n"); fwrite(&null, sizeof(null), 1, f); - fprintf(f, "eg:s eg:p [ eg:sp eg:so ] .\n"); - fwrite(&null, sizeof(null), 1, f); + fprintf(f, "eg:s eg:p [ eg:sp eg:so ] ."); fseek(f, 0, SEEK_SET); ReaderTest rt = {0, 0, 0, 0}; - SerdReader* const reader = serd_reader_new(SERD_TURTLE, - &rt, - NULL, - test_base_sink, - test_prefix_sink, - test_statement_sink, - test_end_sink); + SerdReader* const reader = serd_reader_new( + SERD_TURTLE, &rt, NULL, base_sink, prefix_sink, statement_sink, end_sink); assert(reader); assert(serd_reader_get_handle(reader) == &rt); assert(f); - SerdStatus st = serd_reader_start_stream(reader, f, NULL, false); + SerdStatus st = serd_reader_start_source_stream( + reader, (SerdSource)fread, (SerdStreamErrorFunc)ferror, f, NULL, 32U); assert(st == SERD_SUCCESS); // Read base @@ -393,7 +378,7 @@ test_read_turtle_chunks(const char* const path) assert(rt.n_end == 1); assert(serd_reader_read_chunk(reader) == SERD_FAILURE); - + serd_reader_end_stream(reader); serd_reader_free(reader); fclose(f); remove(path); @@ -428,7 +413,7 @@ main(void) test_read_turtle_chunks(path); test_read_string(); - test_read_eof_by_page(path); + test_read_eof_file(path); test_read_eof_by_byte(); assert(!remove(path)); diff --git a/test/test_uri.c b/test/test_uri.c index fc5eab71..94669ad5 100644 --- a/test/test_uri.c +++ b/test/test_uri.c @@ -37,11 +37,11 @@ test_uri_string_has_scheme(void) } static void -test_file_uri(const char* const hostname, - const char* const path, - const bool escape, - const char* const expected_uri, - const char* expected_path) +check_file_uri(const char* const hostname, + const char* const path, + const bool escape, + const char* const expected_uri, + const char* expected_path) { if (!expected_path) { expected_path = path; @@ -112,62 +112,62 @@ test_uri_to_path(void) static void test_uri_parsing(void) { - test_file_uri(NULL, "C:/My 100%", true, "file:///C:/My%20100%%", NULL); - test_file_uri(NULL, "/foo/bar", true, "file:///foo/bar", NULL); - test_file_uri("bhost", "/foo/bar", true, "file://bhost/foo/bar", NULL); - test_file_uri(NULL, "a/relative path", false, "a/relative path", NULL); - test_file_uri( + check_file_uri(NULL, "C:/My 100%", true, "file:///C:/My%20100%%", NULL); + check_file_uri(NULL, "/foo/bar", true, "file:///foo/bar", NULL); + check_file_uri("bhost", "/foo/bar", true, "file://bhost/foo/bar", NULL); + check_file_uri(NULL, "a/relative path", false, "a/relative path", NULL); + check_file_uri( NULL, "a/relative <path>", true, "a/relative%20%3Cpath%3E", NULL); #ifdef _WIN32 - test_file_uri( + check_file_uri( NULL, "C:\\My 100%", true, "file:///C:/My%20100%%", "C:/My 100%"); - test_file_uri(NULL, - "\\drive\\relative", - true, - "file:///drive/relative", - "/drive/relative"); - - test_file_uri(NULL, - "C:\\Program Files\\Serd", - true, - "file:///C:/Program%20Files/Serd", - "C:/Program Files/Serd"); - - test_file_uri("ahost", - "C:\\Pointless Space", - true, - "file://ahost/C:/Pointless%20Space", - "C:/Pointless Space"); + check_file_uri(NULL, + "\\drive\\relative", + true, + "file:///drive/relative", + "/drive/relative"); + + check_file_uri(NULL, + "C:\\Program Files\\Serd", + true, + "file:///C:/Program%20Files/Serd", + "C:/Program Files/Serd"); + + check_file_uri("ahost", + "C:\\Pointless Space", + true, + "file://ahost/C:/Pointless%20Space", + "C:/Pointless Space"); #else /* What happens with Windows paths on other platforms is a bit weird, but more or less unavoidable. It doesn't work to interpret backslashes as path separators on any other platform. */ - test_file_uri("ahost", - "C:\\Pointless Space", - true, - "file://ahost/C:%5CPointless%20Space", - "/C:\\Pointless Space"); - - test_file_uri(NULL, - "\\drive\\relative", - true, - "%5Cdrive%5Crelative", - "\\drive\\relative"); - - test_file_uri(NULL, - "C:\\Program Files\\Serd", - true, - "file:///C:%5CProgram%20Files%5CSerd", - "/C:\\Program Files\\Serd"); - - test_file_uri("ahost", - "C:\\Pointless Space", - true, - "file://ahost/C:%5CPointless%20Space", - "/C:\\Pointless Space"); + check_file_uri("ahost", + "C:\\Pointless Space", + true, + "file://ahost/C:%5CPointless%20Space", + "/C:\\Pointless Space"); + + check_file_uri(NULL, + "\\drive\\relative", + true, + "%5Cdrive%5Crelative", + "\\drive\\relative"); + + check_file_uri(NULL, + "C:\\Program Files\\Serd", + true, + "file:///C:%5CProgram%20Files%5CSerd", + "/C:\\Program Files\\Serd"); + + check_file_uri("ahost", + "C:\\Pointless Space", + true, + "file://ahost/C:%5CPointless%20Space", + "/C:\\Pointless Space"); #endif // Test tolerance of NULL hostname parameter |