Browse Source

cbor: add zero copy string deserialization

pr/spi.typo
Lucio Torre 7 years ago committed by Oleg Hahm
parent
commit
d783d784c9
  1. 52
      sys/cbor/cbor.c
  2. 26
      sys/include/cbor.h
  3. 68
      tests/unittests/tests-cbor/tests-cbor.c

52
sys/cbor/cbor.c

@ -403,6 +403,31 @@ static size_t decode_bytes(const cbor_stream_t *s, size_t offset, char *out, siz
return (bytes_start + bytes_length);
}
/* A zero copy version of decode_bytes.
Will not null termiante input, but tell you the size of what you read.
Great for reading byte strings which could contain nulls inside
*/
static size_t decode_bytes_no_copy(const cbor_stream_t *s, size_t offset, unsigned char **out, size_t *length)
{
CBOR_ENSURE_SIZE_READ(s, offset + 1);
if ((CBOR_TYPE(s, offset) != CBOR_BYTES && CBOR_TYPE(s, offset) != CBOR_TEXT) || !out) {
return 0;
}
uint64_t bytes_length;
size_t bytes_start = decode_int(s, offset, &bytes_length);
if (!bytes_start) {
return 0;
}
CBOR_ENSURE_SIZE_READ(s, offset + bytes_start + bytes_length);
*out = &(s->data[offset + bytes_start]);
*length = bytes_length;
return (bytes_start + bytes_length);
}
size_t cbor_deserialize_int(const cbor_stream_t *stream, size_t offset, int *val)
{
CBOR_ENSURE_SIZE_READ(stream, offset + 1);
@ -594,14 +619,21 @@ size_t cbor_deserialize_byte_string(const cbor_stream_t *stream, size_t offset,
return decode_bytes(stream, offset, val, length);
}
size_t cbor_serialize_byte_string(cbor_stream_t *stream, const char *val)
size_t cbor_deserialize_byte_string_no_copy(const cbor_stream_t *stream, size_t offset, unsigned char **val,
size_t *length)
{
return encode_bytes(CBOR_BYTES, stream, val, strlen(val));
CBOR_ENSURE_SIZE_READ(stream, offset + 1);
if (CBOR_TYPE(stream, offset) != CBOR_BYTES) {
return 0;
}
return decode_bytes_no_copy(stream, offset, val, length);
}
size_t cbor_serialize_byte_stringl(cbor_stream_t *stream, const char *val, size_t length)
size_t cbor_serialize_byte_string(cbor_stream_t *stream, const char *val)
{
return encode_bytes(CBOR_BYTES, stream, val, length);
return encode_bytes(CBOR_BYTES, stream, val, strlen(val));
}
size_t cbor_deserialize_unicode_string(const cbor_stream_t *stream, size_t offset, char *val,
@ -616,6 +648,18 @@ size_t cbor_deserialize_unicode_string(const cbor_stream_t *stream, size_t offse
return decode_bytes(stream, offset, val, length);
}
size_t cbor_deserialize_unicode_string_no_copy(const cbor_stream_t *stream, size_t offset, unsigned char **val,
size_t *length)
{
CBOR_ENSURE_SIZE_READ(stream, offset + 1);
if (CBOR_TYPE(stream, offset) != CBOR_TEXT) {
return 0;
}
return decode_bytes_no_copy(stream, offset, val, length);
}
size_t cbor_serialize_unicode_string(cbor_stream_t *stream, const char *val)
{
return encode_bytes(CBOR_TEXT, stream, val, strlen(val));

26
sys/include/cbor.h

@ -365,16 +365,6 @@ size_t cbor_deserialize_double(const cbor_stream_t *stream, size_t offset,
*/
size_t cbor_serialize_byte_string(cbor_stream_t *stream, const char *val);
/**
* @brief Serializes an arbitrary byte string
*
* @param[out] stream The destination stream for serializing the byte stream
* @param[in] val The arbitrary byte string which may include null bytes
* @param[in] length The size of the byte string in bytes
*
* @return Number of bytes written to stream @p stream
*/
size_t cbor_serialize_byte_stringl(cbor_stream_t *stream, const char *val, size_t length);
/**
* @brief Deserialize bytes from @p stream to @p val
@ -391,6 +381,22 @@ size_t cbor_deserialize_byte_string(const cbor_stream_t *stream, size_t offset,
size_t cbor_serialize_unicode_string(cbor_stream_t *stream, const char *val);
/**
* @brief Deserialize bytes/unicode from @p stream to @p val (without copy)
*
* @param[in] stream The stream to deserialize
* @param[in] offset The offset within the stream where to start deserializing
* @param[out] val Pointer to a char *
* @param[out] length Pointer tp a size_t to store the size of the string
*
* @return Number of bytes written into @p val
*/
size_t cbor_deserialize_byte_string_no_copy(const cbor_stream_t *stream, size_t offset,
unsigned char **val, size_t *length);
size_t cbor_deserialize_unicode_string_no_copy(const cbor_stream_t *stream, size_t offset,
unsigned char **val, size_t *length);
/**
* @brief Deserialize unicode string from @p stream to @p val
*

68
tests/unittests/tests-cbor/tests-cbor.c

@ -279,6 +279,39 @@ static void test_byte_string(void)
}
}
static void test_byte_string_no_copy(void)
{
char buffer[128];
{
const char *input = "";
unsigned char data[] = {0x40};
unsigned char *out;
size_t size;
TEST_ASSERT(cbor_serialize_byte_string(&stream, input));
CBOR_CHECK_SERIALIZED(stream, data, sizeof(data));
TEST_ASSERT(cbor_deserialize_byte_string_no_copy(&stream, 0, &out, &size));
memcpy(buffer, out, size);
buffer[size] = '\0';
CBOR_CHECK_DESERIALIZED(input, buffer, EQUAL_STRING);
}
cbor_clear(&stream);
{
const char *input = "a";
unsigned char data[] = {0x41, 0x61};
unsigned char *out;
size_t size;
TEST_ASSERT(cbor_serialize_byte_string(&stream, input));
CBOR_CHECK_SERIALIZED(stream, data, sizeof(data));
TEST_ASSERT(cbor_deserialize_byte_string_no_copy(&stream, 0, &out, &size));
memcpy(buffer, out, size);
buffer[size] = '\0';
CBOR_CHECK_DESERIALIZED(input, buffer, EQUAL_STRING);
}
}
static void test_byte_string_invalid(void)
{
{
@ -318,6 +351,39 @@ static void test_unicode_string(void)
}
}
static void test_unicode_string_no_copy(void)
{
char buffer[128];
{
const char *input = "";
unsigned char data[] = {0x60};
unsigned char *out;
size_t size;
TEST_ASSERT(cbor_serialize_unicode_string(&stream, input));
CBOR_CHECK_SERIALIZED(stream, data, sizeof(data));
TEST_ASSERT(cbor_deserialize_unicode_string_no_copy(&stream, 0, &out, &size));
memcpy(buffer, out, size);
buffer[size] = '\0';
CBOR_CHECK_DESERIALIZED(input, buffer, EQUAL_STRING);
}
cbor_clear(&stream);
{
const char *input = "a";
unsigned char data[] = {0x61, 0x61};
unsigned char *out;
size_t size;
TEST_ASSERT(cbor_serialize_unicode_string(&stream, input));
CBOR_CHECK_SERIALIZED(stream, data, sizeof(data));
TEST_ASSERT(cbor_deserialize_unicode_string_no_copy(&stream, 0, &out, &size));
memcpy(buffer, out, size);
buffer[size] = '\0';
CBOR_CHECK_DESERIALIZED(input, buffer, EQUAL_STRING);
}
}
static void test_unicode_string_invalid(void)
{
{
@ -761,8 +827,10 @@ TestRef tests_cbor_all(void)
new_TestFixture(test_int64_t),
new_TestFixture(test_int64_t_invalid),
new_TestFixture(test_byte_string),
new_TestFixture(test_byte_string_no_copy),
new_TestFixture(test_byte_string_invalid),
new_TestFixture(test_unicode_string),
new_TestFixture(test_unicode_string_no_copy),
new_TestFixture(test_unicode_string_invalid),
new_TestFixture(test_array),
new_TestFixture(test_array_indefinite),

Loading…
Cancel
Save