diff options
author | David Robillard <d@drobilla.net> | 2019-12-08 23:21:23 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2019-12-08 23:21:23 +0100 |
commit | 2efb107eb4d4381198de51bd4f092ae1ead02e31 (patch) | |
tree | ee89c919e80d041d6eae2b08abfd247c2fc67be2 | |
parent | 41a5903cc5350b9e90ebfbeea66a3a1eabe7f663 (diff) | |
download | serd-2efb107eb4d4381198de51bd4f092ae1ead02e31.tar.gz serd-2efb107eb4d4381198de51bd4f092ae1ead02e31.tar.bz2 serd-2efb107eb4d4381198de51bd4f092ae1ead02e31.zip |
Fix reading from a null-delimited socket
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | src/reader.c | 6 | ||||
-rw-r--r-- | tests/serd_test.c | 61 | ||||
-rw-r--r-- | wscript | 2 |
4 files changed, 70 insertions, 2 deletions
@@ -2,8 +2,9 @@ serd (0.30.3) unstable; * Fix EOF handling while reading in bulk or from strings * Fix lax handling of string errors + * Fix reading from a null-delimited socket - -- David Robillard <d@drobilla.net> Sun, 27 Oct 2019 21:41:05 +0000 + -- David Robillard <d@drobilla.net> Sun, 08 Dec 2019 22:20:08 +0000 serd (0.30.2) stable; diff --git a/src/reader.c b/src/reader.c index 68a5f886..ef393ec7 100644 --- a/src/reader.c +++ b/src/reader.c @@ -14,6 +14,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "reader.h" #include "serd_internal.h" #include <ctype.h> @@ -343,6 +344,11 @@ serd_reader_read_chunk(SerdReader* reader) st = serd_byte_source_advance(&reader->source); } + if (peek_byte(reader) == 0) { + // Skip leading null byte, for reading from a null-delimited socket + eat_byte_safe(reader, 0); + } + return st ? st : read_statement(reader) ? SERD_SUCCESS : SERD_FAILURE; } diff --git a/tests/serd_test.c b/tests/serd_test.c index bb05a586..0a89247b 100644 --- a/tests/serd_test.c +++ b/tests/serd_test.c @@ -111,6 +111,64 @@ test_file_uri(const char* hostname, serd_node_free(&node); } +static void +test_read_chunks() +{ + ReaderTest* const rt = (ReaderTest*)calloc(1, sizeof(ReaderTest)); + FILE* const f = tmpfile(); + static const char null = 0; + SerdReader* const reader = + serd_reader_new(SERD_TURTLE, rt, free, NULL, NULL, test_sink, NULL); + + assert(reader); + assert(serd_reader_get_handle(reader) == rt); + assert(f); + + SerdStatus st = serd_reader_start_stream(reader, f, NULL, false); + assert(st == SERD_SUCCESS); + + // Write two statement separated by null characters + fprintf(f, "@prefix eg: <http://example.org/> .\n"); + fprintf(f, "eg:s eg:p eg:o1 .\n"); + fwrite(&null, sizeof(null), 1, f); + fprintf(f, "eg:s eg:p eg:o2 .\n"); + fwrite(&null, sizeof(null), 1, f); + fseek(f, 0, SEEK_SET); + + // Read prefix + st = serd_reader_read_chunk(reader); + assert(st == SERD_SUCCESS); + assert(rt->n_statements == 0); + + // Read first statement + st = serd_reader_read_chunk(reader); + assert(st == SERD_SUCCESS); + assert(rt->n_statements == 1); + + // Read terminator + st = serd_reader_read_chunk(reader); + assert(st == SERD_SUCCESS); // FIXME: return SERD_FAILURE? + assert(rt->n_statements == 1); + + // Read second statement (after null terminator) + st = serd_reader_read_chunk(reader); + assert(st == SERD_SUCCESS); + assert(rt->n_statements == 2); + + // Read terminator + st = serd_reader_read_chunk(reader); + assert(st == SERD_SUCCESS); // FIXME: return SERD_FAILURE? + assert(rt->n_statements == 2); + + // EOF + st = serd_reader_read_chunk(reader); + assert(st == SERD_SUCCESS); // FIXME: return SERD_FAILURE? + assert(rt->n_statements == 2); + + serd_reader_free(reader); + fclose(f); +} + int main(void) { @@ -490,6 +548,9 @@ main(void) assert(!strcmp((const char*)out, "@base <http://example.org/base> .\n")); serd_free(out); + // Test reading a series of chunks (like from a socket) + test_read_chunks(); + // Rewind and test reader fseek(fd, 0, SEEK_SET); @@ -12,7 +12,7 @@ from waflib.extras import autowaf # major increment <=> incompatible changes # minor increment <=> compatible changes (additions) # micro increment <=> no interface changes -SERD_VERSION = '0.30.2' +SERD_VERSION = '0.30.3' SERD_MAJOR_VERSION = '0' # Mandatory waf variables |