aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--meson/suppressions/meson.build1
-rw-r--r--src/.clang-tidy6
-rw-r--r--src/byte_source.c15
-rw-r--r--src/byte_source.h7
-rw-r--r--test/.clang-tidy2
-rw-r--r--test/test_node.c4
-rw-r--r--test/test_reader.c103
-rw-r--r--test/test_uri.c102
9 files changed, 118 insertions, 125 deletions
diff --git a/NEWS b/NEWS
index 3e9c71d3..8ccb7568 100644
--- a/NEWS
+++ b/NEWS
@@ -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