aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2021-01-13 14:31:00 +0100
committerDavid Robillard <d@drobilla.net>2021-03-07 15:32:23 -0500
commita7be33a7640ee51066c41eded5812d9cee5ad27e (patch)
tree8c2cbe96a6973c73320ff793d452e36fe511b745
parent96bcba9cd94879794de477ae7c5c04971fbd6f32 (diff)
downloadserd-a7be33a7640ee51066c41eded5812d9cee5ad27e.tar.gz
serd-a7be33a7640ee51066c41eded5812d9cee5ad27e.tar.bz2
serd-a7be33a7640ee51066c41eded5812d9cee5ad27e.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
8 files changed, 44 insertions, 38 deletions
diff --git a/NEWS b/NEWS
index 1de04d37..3d950775 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()
-- David Robillard <d@drobilla.net> Wed, 13 Jan 2021 13:29:44 +0000
diff --git a/include/serd/serd.h b/include/serd/serd.h
index cdcadcdb..c60bf465 100644
--- a/include/serd/serd.h
+++ b/include/serd/serd.h
@@ -198,6 +198,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;
+
/// An error description
typedef struct {
SerdStatus status; ///< Error code
@@ -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 d4266b1a..fadc0aa6 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 02aedbf2..415b4031 100644
--- a/src/node.c
+++ b/src/node.c
@@ -208,28 +208,28 @@ serd_node_new_file_uri(const uint8_t* 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 (!escape || 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 ed927695..baeb0fb2 100644
--- a/src/uri.c
+++ b/src/uri.c
@@ -41,7 +41,6 @@ serd_file_uri_parse(const uint8_t* uri, uint8_t** 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* uri, uint8_t** 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 af2980c5..ee9ae352 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -1105,18 +1105,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* buf, size_t len, void* 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* 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 573b13de..d25eb46a 100644
--- a/test/test_reader_writer.c
+++ b/test/test_reader_writer.c
@@ -244,16 +244,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);