aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2021-01-13 14:31:00 +0100
committerDavid Robillard <d@drobilla.net>2022-01-13 15:33:54 -0500
commitf078026b3c5d63c494381d3573a8107ddd7d78f7 (patch)
tree1aec4cd71120f9c3ab92542780c9d9d10d210965
parent1644a72d32fec7833c9f487e9ed9b99e303fc015 (diff)
downloadserd-f078026b3c5d63c494381d3573a8107ddd7d78f7.tar.gz
serd-f078026b3c5d63c494381d3573a8107ddd7d78f7.tar.bz2
serd-f078026b3c5d63c494381d3573a8107ddd7d78f7.zip
Add SerdBuffer type for mutable buffers
This avoids const violations from abusing SerdChunk as a mutable buffer for string sinks.
-rw-r--r--NEWS1
-rw-r--r--include/serd/serd.h22
-rw-r--r--meson.build2
-rw-r--r--src/node.c18
-rw-r--r--src/serd_config.h2
-rw-r--r--src/uri.c12
-rw-r--r--src/writer.c15
-rw-r--r--test/test_reader_writer.c10
-rw-r--r--test/test_writer.c6
9 files changed, 47 insertions, 41 deletions
diff --git a/NEWS b/NEWS
index 67ccdac4..1cc734bc 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,6 @@
serd (1.0.1) unstable;
+ * Add SerdBuffer for mutable buffers to keep SerdChunk const-correct
* Remove serd_uri_to_path()
* Remove support for Turtle named inline nodes extension
* Remove useless character counting from API
diff --git a/include/serd/serd.h b/include/serd/serd.h
index 0d9a4444..db89e275 100644
--- a/include/serd/serd.h
+++ b/include/serd/serd.h
@@ -97,6 +97,12 @@ typedef struct {
size_t len; ///< Length of chunk in bytes
} SerdChunk;
+/// A mutable buffer in memory
+typedef struct {
+ void* SERD_NULLABLE buf; ///< Buffer
+ size_t len; ///< Size of buffer in bytes
+} SerdBuffer;
+
/**
Free memory allocated by Serd.
@@ -900,26 +906,26 @@ serd_file_sink(const void* SERD_NONNULL buf,
/**
A convenience sink function for writing to a string.
- This function can be used as a SerdSink to write to a SerdChunk which is
+ This function can be used as a SerdSink to write to a SerdBuffer which is
resized as necessary with realloc(). The `stream` parameter must point to
- an initialized SerdChunk. When the write is finished, the string should be
- retrieved with serd_chunk_sink_finish().
+ an initialized SerdBuffer. When the write is finished, the string should be
+ retrieved with serd_buffer_sink_finish().
*/
SERD_API
size_t
-serd_chunk_sink(const void* SERD_NONNULL buf,
- size_t len,
- void* SERD_NONNULL stream);
+serd_buffer_sink(const void* SERD_NONNULL buf,
+ size_t len,
+ void* SERD_NONNULL stream);
/**
- Finish a serialisation to a chunk with serd_chunk_sink().
+ Finish a serialisation to a chunk with serd_buffer_sink().
The returned string is the result of the serialisation, which is null
terminated (by this function) and owned by the caller.
*/
SERD_API
uint8_t* SERD_NULLABLE
-serd_chunk_sink_finish(SerdChunk* SERD_NONNULL stream);
+serd_buffer_sink_finish(SerdBuffer* SERD_NONNULL stream);
/**
Set a function to be called when errors occur during writing.
diff --git a/meson.build b/meson.build
index 890c8894..7073a76c 100644
--- a/meson.build
+++ b/meson.build
@@ -1,5 +1,5 @@
project('serd', ['c'],
- version: '0.30.11',
+ version: '1.0.1',
license: 'ISC',
meson_version: '>= 0.49.2',
default_options: [
diff --git a/src/node.c b/src/node.c
index 34de3bfb..c8fba903 100644
--- a/src/node.c
+++ b/src/node.c
@@ -204,28 +204,28 @@ serd_node_new_file_uri(const uint8_t* const path,
}
}
- SerdChunk chunk = {uri, uri_len};
+ SerdBuffer buffer = {uri, uri_len};
for (size_t i = 0; i < path_len; ++i) {
if (is_windows && path[i] == '\\') {
- serd_chunk_sink("/", 1, &chunk);
+ serd_buffer_sink("/", 1, &buffer);
} else if (path[i] == '%') {
- serd_chunk_sink("%%", 2, &chunk);
+ serd_buffer_sink("%%", 2, &buffer);
} else if (is_uri_path_char(path[i])) {
- serd_chunk_sink(path + i, 1, &chunk);
+ serd_buffer_sink(path + i, 1, &buffer);
} else {
char escape_str[4] = {'%', 0, 0, 0};
snprintf(escape_str + 1, sizeof(escape_str) - 1, "%X", (unsigned)path[i]);
- serd_chunk_sink(escape_str, 3, &chunk);
+ serd_buffer_sink(escape_str, 3, &buffer);
}
}
-
- serd_chunk_sink_finish(&chunk);
+ serd_buffer_sink_finish(&buffer);
if (out) {
- serd_uri_parse(chunk.buf, out);
+ serd_uri_parse((const uint8_t*)buffer.buf, out);
}
- return serd_node_from_substring(SERD_URI, chunk.buf, chunk.len);
+ return serd_node_from_substring(
+ SERD_URI, (const uint8_t*)buffer.buf, buffer.len);
}
SerdNode
diff --git a/src/serd_config.h b/src/serd_config.h
index 15508c81..7f58696e 100644
--- a/src/serd_config.h
+++ b/src/serd_config.h
@@ -29,7 +29,7 @@
#define SERD_CONFIG_H
// Define version unconditionally so a warning will catch a mismatch
-#define SERD_VERSION "0.30.11"
+#define SERD_VERSION "1.0.1"
#if !defined(SERD_NO_DEFAULT_CONFIG)
diff --git a/src/uri.c b/src/uri.c
index e0bfb4e5..41e406d9 100644
--- a/src/uri.c
+++ b/src/uri.c
@@ -41,7 +41,6 @@ serd_file_uri_parse(const uint8_t* const uri, uint8_t** const hostname)
if (!(path = (const uint8_t*)strchr((const char*)auth, '/'))) {
return NULL;
}
-
if (hostname) {
*hostname = (uint8_t*)calloc((size_t)(path - auth + 1), 1);
memcpy(*hostname, auth, (size_t)(path - auth));
@@ -53,26 +52,25 @@ serd_file_uri_parse(const uint8_t* const uri, uint8_t** const hostname)
++path;
}
- SerdChunk chunk = {NULL, 0};
+ SerdBuffer buffer = {NULL, 0};
for (const uint8_t* s = path; *s; ++s) {
if (*s == '%') {
if (*(s + 1) == '%') {
- serd_chunk_sink("%", 1, &chunk);
+ serd_buffer_sink("%", 1, &buffer);
++s;
} else if (is_hexdig(*(s + 1)) && is_hexdig(*(s + 2))) {
const uint8_t code[3] = {*(s + 1), *(s + 2), 0};
const uint8_t c = (uint8_t)strtoul((const char*)code, NULL, 16);
- serd_chunk_sink(&c, 1, &chunk);
+ serd_buffer_sink(&c, 1, &buffer);
s += 2;
} else {
s += 2; // Junk escape, ignore
}
} else {
- serd_chunk_sink(s, 1, &chunk);
+ serd_buffer_sink(s, 1, &buffer);
}
}
-
- return serd_chunk_sink_finish(&chunk);
+ return serd_buffer_sink_finish(&buffer);
}
bool
diff --git a/src/writer.c b/src/writer.c
index d208a1cf..4b4d480b 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -1085,18 +1085,19 @@ serd_file_sink(const void* buf, size_t len, void* stream)
}
size_t
-serd_chunk_sink(const void* buf, size_t len, void* stream)
+serd_buffer_sink(const void* const buf, const size_t len, void* const stream)
{
- SerdChunk* chunk = (SerdChunk*)stream;
- chunk->buf = (uint8_t*)realloc((uint8_t*)chunk->buf, chunk->len + len);
- memcpy((uint8_t*)chunk->buf + chunk->len, buf, len);
- chunk->len += len;
+ SerdBuffer* buffer = (SerdBuffer*)stream;
+
+ buffer->buf = (char*)realloc(buffer->buf, buffer->len + len);
+ memcpy((uint8_t*)buffer->buf + buffer->len, buf, len);
+ buffer->len += len;
return len;
}
uint8_t*
-serd_chunk_sink_finish(SerdChunk* stream)
+serd_buffer_sink_finish(SerdBuffer* const stream)
{
- serd_chunk_sink("", 1, stream);
+ serd_buffer_sink("", 1, stream);
return (uint8_t*)stream->buf;
}
diff --git a/test/test_reader_writer.c b/test/test_reader_writer.c
index 8bd09fe2..2d45a5be 100644
--- a/test/test_reader_writer.c
+++ b/test/test_reader_writer.c
@@ -261,16 +261,16 @@ test_writer(const char* const path)
serd_writer_free(writer);
- // Test chunk sink
- SerdChunk chunk = {NULL, 0};
- writer = serd_writer_new(
- SERD_TURTLE, (SerdStyle)0, env, NULL, serd_chunk_sink, &chunk);
+ // Test buffer sink
+ SerdBuffer buffer = {NULL, 0};
+ writer = serd_writer_new(
+ SERD_TURTLE, (SerdStyle)0, env, NULL, serd_buffer_sink, &buffer);
o = serd_node_from_string(SERD_URI, USTR("http://example.org/base"));
assert(!serd_writer_set_base_uri(writer, &o));
serd_writer_free(writer);
- uint8_t* out = serd_chunk_sink_finish(&chunk);
+ uint8_t* out = serd_buffer_sink_finish(&buffer);
assert(!strcmp((const char*)out, "@base <http://example.org/base> .\n"));
serd_free(out);
diff --git a/test/test_writer.c b/test/test_writer.c
index 35d0bcf3..472d7345 100644
--- a/test/test_writer.c
+++ b/test/test_writer.c
@@ -28,9 +28,9 @@ static void
test_write_long_literal(void)
{
SerdEnv* env = serd_env_new(NULL);
- SerdChunk chunk = {NULL, 0};
+ SerdBuffer buffer = {NULL, 0};
SerdWriter* writer = serd_writer_new(
- SERD_TURTLE, (SerdStyle)0, env, NULL, serd_chunk_sink, &chunk);
+ SERD_TURTLE, (SerdStyle)0, env, NULL, serd_buffer_sink, &buffer);
assert(writer);
@@ -44,7 +44,7 @@ test_write_long_literal(void)
serd_writer_free(writer);
serd_env_free(env);
- uint8_t* out = serd_chunk_sink_finish(&chunk);
+ uint8_t* out = serd_buffer_sink_finish(&buffer);
static const char* const expected =
"<http://example.org/s>\n"