1
0
mirror of https://github.com/openbsd/src.git synced 2025-01-03 06:45:37 -08:00

Add libcbor; an implementation of the Concise Binary Object

Representation (CBOR) encoding format defined in RFC7049.

This is a dependency of libfido2, that we'll use for U2F/FIDO
support in OpenSSH.

feedback and "Looks good enough to me" deraadt@
This commit is contained in:
djm 2019-11-14 21:11:34 +00:00
parent cdebaeb725
commit da0d961c2c
47 changed files with 5933 additions and 0 deletions

21
lib/libcbor/LICENSE.md Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2014-2017 Pavel Kalvoda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

45
lib/libcbor/Makefile Normal file
View File

@ -0,0 +1,45 @@
# $OpenBSD: Makefile,v 1.1 2019/11/14 21:11:34 djm Exp $
.PATH: ${.CURDIR}/src ${.CURDIR}/src/cbor ${.CURDIR}/src/cbor/internal
CFLAGS+= -I${.CURDIR}/src -DHAVE_ENDIAN_H
LIB= cbor
SRCS= cbor.c
#SRCS+= allocators.c
WARNINGS=yes
CDIAGFLAGS+= -Wall -Wextra -Wno-unused-parameter
#CDIAGFLAGS+= -Werror
# cbor/
SRCS+= arrays.c bytestrings.c callbacks.c common.c encoding.c floats_ctrls.c
SRCS+= ints.c maps.c serialization.c streaming.c tags.c strings.c
# cbor/internal
SRCS+= builder_callbacks.c encoders.c loaders.c memory_utils.c
SRCS+= stack.c unicode.c
HDRS= cbor.h
HDRS+= cbor/arrays.h cbor/bytestrings.h cbor/callbacks.h cbor/common.h
HDRS+= cbor/configuration.h cbor/data.h cbor/encoding.h cbor/floats_ctrls.h
HDRS+= cbor/ints.h cbor/maps.h cbor/serialization.h cbor/streaming.h
HDRS+= cbor/strings.h cbor/tags.h
NOMAN=
includes:
@for i in $(HDRS); do \
j="test -d ${DESTDIR}/usr/include/`dirname $$i` || \
${INSTALL} -d -o ${BINOWN} -g ${BINGRP} -m 755 \
${DESTDIR}/usr/include/`dirname $$i`"; \
echo $$j; \
eval "$$j"; \
j="cmp -s src/$$i ${DESTDIR}/usr/include/$$i || \
${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} \
-m 444 ${.CURDIR}/src/$$i ${DESTDIR}/usr/include/$$i"; \
echo $$j; \
eval "$$j"; \
done
.include <bsd.lib.mk>

50
lib/libcbor/README.md Normal file
View File

@ -0,0 +1,50 @@
# [libcbor](https://github.com/PJK/libcbor)
[![Build Status](https://travis-ci.org/PJK/libcbor.svg?branch=master)](https://travis-ci.org/PJK/libcbor)
[![Build status](https://ci.appveyor.com/api/projects/status/8kkmvmefelsxp5u2?svg=true)](https://ci.appveyor.com/project/PJK/libcbor)
[![Documentation Status](https://readthedocs.org/projects/libcbor/badge/?version=latest)](https://readthedocs.org/projects/libcbor/?badge=latest)
**libcbor** is a C library for parsing and generating [CBOR](http://tools.ietf.org/html/rfc7049), the general-purpose schema-less binary data format.
## Main features
- Complete RFC conformance
- Robust C99 implementation
- Layered architecture offers both control and convenience
- Flexible memory management
- No shared global state - threading friendly
- Proper handling of UTF-8
- Full support for streams & incremental processing
- Extensive documentation and test suite
- No runtime dependencies, small footprint
## Documentation
Get the latest documentation at [libcbor.readthedocs.org](http://libcbor.readthedocs.org/)
## Contributions
All bug reports and contributions are welcome. Please see https://github.com/PJK/libcbor for more info.
Kudos to all the [contributors](https://github.com/PJK/libcbor/graphs/contributors)!
## License
The MIT License (MIT)
Copyright (c) Pavel Kalvoda, 20142017
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,4 @@
This is an import of https://github.com/pjk/libcbor v0.5.0
Apart from README.md and LICENSE.md, only the src/ directory has been
imported.

View File

@ -0,0 +1,3 @@
major=0
minor=5

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "cbor/common.h"
_cbor_malloc_t _cbor_malloc = malloc;
_cbor_realloc_t _cbor_realloc = realloc;
_cbor_free_t _cbor_free = free;
void cbor_set_allocs(_cbor_malloc_t custom_malloc, _cbor_realloc_t custom_realloc, _cbor_free_t custom_free)
{
_cbor_malloc = custom_malloc;
_cbor_realloc = custom_realloc;
_cbor_free = custom_free;
}

391
lib/libcbor/src/cbor.c Normal file
View File

@ -0,0 +1,391 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "cbor.h"
#include "cbor/internal/builder_callbacks.h"
#include "cbor/internal/loaders.h"
cbor_item_t * cbor_load(cbor_data source,
size_t source_size,
struct cbor_load_result *result)
{
/* Context stack */
static struct cbor_callbacks callbacks = {
.uint8 = &cbor_builder_uint8_callback,
.uint16 = &cbor_builder_uint16_callback,
.uint32 = &cbor_builder_uint32_callback,
.uint64 = &cbor_builder_uint64_callback,
.negint8 = &cbor_builder_negint8_callback,
.negint16 = &cbor_builder_negint16_callback,
.negint32 = &cbor_builder_negint32_callback,
.negint64 = &cbor_builder_negint64_callback,
.byte_string = &cbor_builder_byte_string_callback,
.byte_string_start = &cbor_builder_byte_string_start_callback,
.string = &cbor_builder_string_callback,
.string_start = &cbor_builder_string_start_callback,
.array_start = &cbor_builder_array_start_callback,
.indef_array_start = &cbor_builder_indef_array_start_callback,
.map_start = &cbor_builder_map_start_callback,
.indef_map_start = &cbor_builder_indef_map_start_callback,
.tag = &cbor_builder_tag_callback,
.null = &cbor_builder_null_callback,
.undefined = &cbor_builder_undefined_callback,
.boolean = &cbor_builder_boolean_callback,
.float2 = &cbor_builder_float2_callback,
.float4 = &cbor_builder_float4_callback,
.float8 = &cbor_builder_float8_callback,
.indef_break = &cbor_builder_indef_break_callback
};
if (source_size == 0) {
result->error.code = CBOR_ERR_NODATA;
return NULL;
}
struct _cbor_stack stack = _cbor_stack_init();
/* Target for callbacks */
struct _cbor_decoder_context context = (struct _cbor_decoder_context) {
.stack = &stack,
.creation_failed = false,
.syntax_error = false
};
struct cbor_decoder_result decode_result;
*result = (struct cbor_load_result) {.read = 0, .error = {.code = CBOR_ERR_NONE}};
do {
if (source_size > result->read) { /* Check for overflows */
decode_result = cbor_stream_decode(
source + result->read,
source_size - result->read,
&callbacks,
&context);
} else {
result->error = (struct cbor_error) {
.code = CBOR_ERR_NOTENOUGHDATA,
.position = result->read
};
goto error;
}
switch (decode_result.status) {
case CBOR_DECODER_FINISHED:
/* Everything OK */
{
result->read += decode_result.read;
break;
}
case CBOR_DECODER_NEDATA:
/* Data length doesn't match MTB expectation */
{
result->error.code = CBOR_ERR_NOTENOUGHDATA;
goto error;
}
case CBOR_DECODER_EBUFFER:
/* Fallthrough */
case CBOR_DECODER_ERROR:
/* Reserved/malformated item */
{
result->error.code = CBOR_ERR_MALFORMATED;
goto error;
}
}
if (context.creation_failed) {
/* Most likely unsuccessful allocation - our callback has failed */
result->error.code = CBOR_ERR_MEMERROR;
goto error;
} else if (context.syntax_error) {
result->error.code = CBOR_ERR_SYNTAXERROR;
goto error;
}
} while (stack.size > 0);
/* Move the result before free */
cbor_item_t *result_item = context.root;
return result_item;
error:
result->error.position = result->read;
//debug_print("Failed with decoder error %d at %d\n", result->error.code, result->error.position);
//cbor_describe(stack.top->item, stdout);
/* Free the stack */
while (stack.size > 0) {
cbor_decref(&stack.top->item);
_cbor_stack_pop(&stack);
}
return NULL;
}
static cbor_item_t * _cbor_copy_int(cbor_item_t * item, bool negative)
{
cbor_item_t * res;
switch (cbor_int_get_width(item)) {
case CBOR_INT_8: res = cbor_build_uint8(cbor_get_uint8(item)); break;
case CBOR_INT_16: res = cbor_build_uint16(cbor_get_uint16(item)); break;
case CBOR_INT_32: res = cbor_build_uint32(cbor_get_uint32(item)); break;
case CBOR_INT_64: res = cbor_build_uint64(cbor_get_uint64(item)); break;
default: return NULL;
}
if (negative)
cbor_mark_negint(res);
return res;
}
static cbor_item_t * _cbor_copy_float_ctrl(cbor_item_t * item)
{
switch (cbor_float_get_width(item)) {
case CBOR_FLOAT_0:
return cbor_build_ctrl(cbor_ctrl_value(item));
case CBOR_FLOAT_16:
return cbor_build_float2(cbor_float_get_float2(item));
case CBOR_FLOAT_32:
return cbor_build_float4(cbor_float_get_float4(item));
case CBOR_FLOAT_64:
return cbor_build_float8(cbor_float_get_float8(item));
}
return NULL;
}
cbor_item_t * cbor_copy(cbor_item_t * item)
{
switch (cbor_typeof(item)) {
case CBOR_TYPE_UINT:
return _cbor_copy_int(item, false);
case CBOR_TYPE_NEGINT:
return _cbor_copy_int(item, true);
case CBOR_TYPE_BYTESTRING:
if (cbor_bytestring_is_definite(item)) {
return cbor_build_bytestring(cbor_bytestring_handle(item), cbor_bytestring_length(item));
} else {
cbor_item_t * res = cbor_new_indefinite_bytestring();
for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++)
cbor_bytestring_add_chunk(
res,
cbor_move(
cbor_copy(cbor_bytestring_chunks_handle(item)[i])
)
);
return res;
}
case CBOR_TYPE_STRING:
if (cbor_string_is_definite(item)) {
return cbor_build_stringn((const char *) cbor_string_handle(item), cbor_string_length(item));
} else {
cbor_item_t * res = cbor_new_indefinite_string();
for (size_t i = 0; i < cbor_string_chunk_count(item); i++)
cbor_string_add_chunk(
res,
cbor_move(
cbor_copy(cbor_string_chunks_handle(item)[i])
)
);
return res;
}
case CBOR_TYPE_ARRAY: {
cbor_item_t * res;
if (cbor_array_is_definite(item))
res = cbor_new_definite_array(cbor_array_size(item));
else
res = cbor_new_indefinite_array();
for (size_t i = 0; i < cbor_array_size(item); i++)
cbor_array_push(
res,
cbor_move(cbor_copy(cbor_move(cbor_array_get(item, i))))
);
return res;
}
case CBOR_TYPE_MAP: {
cbor_item_t * res;
if (cbor_map_is_definite(item))
res = cbor_new_definite_map(cbor_map_size(item));
else
res = cbor_new_indefinite_map();
struct cbor_pair * it = cbor_map_handle(item);
for (size_t i = 0; i < cbor_map_size(item); i++)
cbor_map_add(res, (struct cbor_pair) {
.key = cbor_move(cbor_copy(it[i].key)),
.value = cbor_move(cbor_copy(it[i].value))
});
return res;
}
case CBOR_TYPE_TAG:
return cbor_build_tag(
cbor_tag_value(item),
cbor_move(cbor_copy(cbor_tag_item(item)))
);
case CBOR_TYPE_FLOAT_CTRL:
return _cbor_copy_float_ctrl(item);
}
return NULL;
}
#if CBOR_PRETTY_PRINTER
#include <inttypes.h>
#include <wchar.h>
#include <locale.h>
#include <stdlib.h>
#define __STDC_FORMAT_MACROS
static int _pow(int b, int ex)
{
if (ex == 0) return 1;
int res = b;
while (--ex > 0) res *= b;
return res;
}
static void _cbor_nested_describe(cbor_item_t *item, FILE *out, int indent)
{
setlocale(LC_ALL, "");
switch (cbor_typeof(item)) {
case CBOR_TYPE_UINT: {
fprintf(out, "%*s[CBOR_TYPE_UINT] ", indent, " ");
fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item)));
fprintf(out, "Value: %"PRIu64"\n", cbor_get_int(item));
break;
};
case CBOR_TYPE_NEGINT: {
fprintf(out, "%*s[CBOR_TYPE_NEGINT] ", indent, " ");
fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item)));
fprintf(out, "Value: -%"PRIu64" -1\n", cbor_get_int(item));
break;
};
case CBOR_TYPE_BYTESTRING: {
fprintf(out, "%*s[CBOR_TYPE_BYTESTRING] ", indent, " ");
if (cbor_bytestring_is_indefinite(item)) {
fprintf(out,
"Indefinite, with %zu chunks:\n",
cbor_bytestring_chunk_count(item));
for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++)
_cbor_nested_describe(
cbor_bytestring_chunks_handle(item)[i],
out,
indent + 4);
} else {
fprintf(out,
"Definite, length %zuB\n",
cbor_bytestring_length(item));
}
break;
};
case CBOR_TYPE_STRING: {
fprintf(out, "%*s[CBOR_TYPE_STRING] ", indent, " ");
if (cbor_string_is_indefinite(item)) {
fprintf(out,
"Indefinite, with %zu chunks:\n",
cbor_string_chunk_count(item));
for (size_t i = 0; i < cbor_string_chunk_count(item); i++)
_cbor_nested_describe(
cbor_string_chunks_handle(item)[i],
out,
indent + 4);
} else {
fprintf(out,
"Definite, length %zuB, %zu codepoints\n",
cbor_string_length(item),
cbor_string_codepoint_count(item));
/* Careful - this doesn't support multibyte characters! */
/* Printing those is out of the scope of this demo :) */
/* libICU is your friend */
fprintf(out, "%*s", indent + 4, " ");
/* XXX: no null at the end -> confused vprintf */
fwrite(cbor_string_handle(item), (int) cbor_string_length(item), 1, out);
fprintf(out, "\n");
}
break;
};
case CBOR_TYPE_ARRAY: {
fprintf(out, "%*s[CBOR_TYPE_ARRAY] ", indent, " ");
if (cbor_array_is_definite(item)) {
fprintf(out,
"Definite, size: %zu\n",
cbor_array_size(item));
} else {
fprintf(out,
"Indefinite, size: %zu\n",
cbor_array_size(item));
}
for (size_t i = 0; i < cbor_array_size(item); i++)
_cbor_nested_describe(
cbor_array_handle(item)[i],
out,
indent + 4);
break;
};
case CBOR_TYPE_MAP: {
fprintf(out, "%*s[CBOR_TYPE_MAP] ", indent, " ");
if (cbor_map_is_definite(item)) {
fprintf(out,
"Definite, size: %zu\n",
cbor_map_size(item));
} else {
fprintf(out,
"Indefinite, size: %zu\n",
cbor_map_size(item));
}
for (size_t i = 0; i < cbor_map_size(item); i++) {
_cbor_nested_describe(
cbor_map_handle(item)[i].key,
out,
indent + 4);
_cbor_nested_describe(
cbor_map_handle(item)[i].value,
out,
indent + 4);
}
break;
};
case CBOR_TYPE_TAG: {
fprintf(out, "%*s[CBOR_TYPE_TAG] ", indent, " ");
fprintf(out, "Value: %"PRIu64"\n", cbor_tag_value(item));
_cbor_nested_describe(cbor_tag_item(item), out, indent + 4);
break;
};
case CBOR_TYPE_FLOAT_CTRL: {
fprintf(out, "%*s[CBOR_TYPE_FLOAT_CTRL] ", indent, " ");
if (cbor_float_ctrl_is_ctrl(item)) {
if (cbor_is_bool(item))
fprintf(out, "Bool: %s\n", cbor_ctrl_is_bool(item) ? "true" : "false");
else if (cbor_is_undef(item))
fprintf(out, "Undefined\n");
else if (cbor_is_null(item))
fprintf(out, "Null\n");
else
fprintf(out, "Simple value %d\n", cbor_ctrl_value(item));
} else {
fprintf(out, "Width: %dB, ", _pow(2, cbor_float_get_width(item)));
fprintf(out, "value: %lf\n", cbor_float_get_float(item));
}
break;
};
}
}
void cbor_describe(cbor_item_t *item, FILE *out)
{
_cbor_nested_describe(item, out, 0);
}
#endif

68
lib/libcbor/src/cbor.h Normal file
View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_H_
#define LIBCBOR_H_
#include "cbor/data.h"
#include "cbor/common.h"
#include "cbor/arrays.h"
#include "cbor/bytestrings.h"
#include "cbor/floats_ctrls.h"
#include "cbor/ints.h"
#include "cbor/maps.h"
#include "cbor/strings.h"
#include "cbor/tags.h"
#include "cbor/encoding.h"
#include "cbor/serialization.h"
#include "cbor/callbacks.h"
#include "cbor/streaming.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* ============================================================================
* High level decoding
* ============================================================================
*/
/** Loads data item from a buffer
*
* @param source The buffer
* @param source_size
* @param result[out] Result indicator. #CBOR_ERR_NONE on success
* @return **new** CBOR item or `NULL` on failure. In that case, \p result contains location and description of the error.
*/
cbor_item_t * cbor_load(cbor_data source,
size_t source_size,
struct cbor_load_result * result);
/** Deep copy of an item
*
* All the reference counts in the new structure are set to one.
*
* @param item[borrow] item to copy
* @return **new** CBOR deep copy
*/
cbor_item_t * cbor_copy(cbor_item_t * item);
#if CBOR_PRETTY_PRINTER
#include <stdio.h>
void cbor_describe(cbor_item_t * item, FILE * out);
#endif
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_H_

View File

@ -0,0 +1,157 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <string.h>
#include "arrays.h"
#include "internal/memory_utils.h"
size_t cbor_array_size(const cbor_item_t *item)
{
assert(cbor_isa_array(item));
return item->metadata.array_metadata.end_ptr;
}
size_t cbor_array_allocated(const cbor_item_t * item)
{
assert(cbor_isa_array(item));
return item->metadata.array_metadata.allocated;
}
cbor_item_t * cbor_array_get(const cbor_item_t * item, size_t index)
{
return cbor_incref(((cbor_item_t **) item->data)[index]);
}
bool cbor_array_set(cbor_item_t * item, size_t index, cbor_item_t * value)
{
if (index == item->metadata.array_metadata.end_ptr) {
return cbor_array_push(item, value);
} else if (index < item->metadata.array_metadata.end_ptr) {
return cbor_array_replace(item, index, value);
} else {
return false;
}
return true;
}
bool cbor_array_replace(cbor_item_t * item, size_t index, cbor_item_t * value)
{
if (index >= item->metadata.array_metadata.end_ptr)
return false;
/* We cannot use cbor_array_get as that would increase the refcount */
cbor_intermediate_decref(((cbor_item_t **) item->data)[index]);
((cbor_item_t **) item->data)[index] = cbor_incref(value);
return true;
}
bool cbor_array_push(cbor_item_t *array, cbor_item_t *pushee)
{
assert(cbor_isa_array(array));
struct _cbor_array_metadata *metadata = (struct _cbor_array_metadata *) &array->metadata;
cbor_item_t **data = (cbor_item_t **) array->data;
if (cbor_array_is_definite(array)) {
/* Do not reallocate definite arrays */
if (metadata->end_ptr >= metadata->allocated) {
return false;
}
data[metadata->end_ptr++] = pushee;
} else {
/* Exponential realloc */
if (metadata->end_ptr >= metadata->allocated) {
// Check for overflows first
if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) {
return false;
}
size_t new_allocation = metadata->allocated == 0 ? 1 : CBOR_BUFFER_GROWTH * metadata->allocated;
unsigned char * new_data = _cbor_realloc_multiple(array->data, sizeof(cbor_item_t *), new_allocation);
if (new_data == NULL) {
return false;
}
array->data = new_data;
metadata->allocated = new_allocation;
}
((cbor_item_t **)array->data)[metadata->end_ptr++] = pushee;
}
cbor_incref(pushee);
return true;
}
bool cbor_array_is_definite(const cbor_item_t *item)
{
assert(cbor_isa_array(item));
return item->metadata.array_metadata.type == _CBOR_METADATA_DEFINITE;
}
bool cbor_array_is_indefinite(const cbor_item_t *item)
{
assert(cbor_isa_array(item));
return item->metadata.array_metadata.type == _CBOR_METADATA_INDEFINITE;
}
cbor_item_t **cbor_array_handle(const cbor_item_t *item)
{
assert(cbor_isa_array(item));
return (cbor_item_t **) item->data;
}
cbor_item_t *cbor_new_definite_array(size_t size)
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
if (item == NULL) {
return NULL;
}
cbor_item_t ** data = _cbor_alloc_multiple(sizeof(cbor_item_t *), size);
if (data == NULL) {
_CBOR_FREE(item);
return NULL;
}
for (size_t i = 0; i < size; i++)
data[i] = NULL;
*item = (cbor_item_t) {
.refcount = 1,
.type = CBOR_TYPE_ARRAY,
.metadata = {
.array_metadata = {
.type = _CBOR_METADATA_DEFINITE,
.allocated = size,
.end_ptr = 0
}
},
.data = (unsigned char *)data
};
return item;
}
cbor_item_t *cbor_new_indefinite_array()
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
if (item == NULL)
return NULL;
*item = (cbor_item_t) {
.refcount = 1,
.type = CBOR_TYPE_ARRAY,
.metadata = {
.array_metadata = {
.type = _CBOR_METADATA_INDEFINITE,
.allocated = 0,
.end_ptr = 0
}
},
.data = NULL /* Can be safely realloc-ed */
};
return item;
}

View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_ARRAYS_H
#define LIBCBOR_ARRAYS_H
#include "cbor/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Get the number of members
*
* @param item[borrow] An array
* @return The number of members
*/
size_t cbor_array_size(const cbor_item_t * item);
/** Get the size of the allocated storage
*
* @param item[borrow] An array
* @return The size of the allocated storage (number of items)
*/
size_t cbor_array_allocated(const cbor_item_t * item);
/** Get item by index
*
* @param item[borrow] An array
* @param index The index
* @return **incref** The item, or `NULL` in case of boundary violation
*/
cbor_item_t * cbor_array_get(const cbor_item_t * item, size_t index);
/** Set item by index
*
* Creating arrays with holes is not possible
*
* @param item[borrow] An array
* @param value[incref] The item to assign
* @param index The index, first item is 0.
* @return true on success, false on allocation failure.
*/
bool cbor_array_set(cbor_item_t * item, size_t index, cbor_item_t * value);
/** Replace item at an index
*
* The item being replace will be #cbor_decref 'ed.
*
* @param item[borrow] An array
* @param value[incref] The item to assign
* @param index The index, first item is 0.
* @return true on success, false on allocation failure.
*/
bool cbor_array_replace(cbor_item_t * item, size_t index, cbor_item_t * value);
/** Is the array definite?
*
* @param item[borrow] An array
* @return Is the array definite?
*/
bool cbor_array_is_definite(const cbor_item_t * item);
/** Is the array indefinite?
*
* @param item[borrow] An array
* @return Is the array indefinite?
*/
bool cbor_array_is_indefinite(const cbor_item_t * item);
/** Get the array contents
*
* The items may be reordered and modified as long as references remain consistent.
*
* @param item[borrow] An array
* @return #cbor_array_size items
*/
cbor_item_t ** cbor_array_handle(const cbor_item_t * item);
/** Create new definite array
*
* @param size Number of slots to preallocate
* @return **new** array or `NULL` upon malloc failure
*/
cbor_item_t * cbor_new_definite_array(size_t size);
/** Create new indefinite array
*
* @return **new** array or `NULL` upon malloc failure
*/
cbor_item_t * cbor_new_indefinite_array();
/** Append to the end
*
* For indefinite items, storage may be realloacted. For definite items, only the
* preallocated capacity is available.
*
* @param array[borrow] An array
* @param pushee[incref] The item to push
* @return true on success, false on failure
*/
bool cbor_array_push(cbor_item_t * array, cbor_item_t * pushee);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_ARRAYS_H

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <string.h>
#include "bytestrings.h"
#include "internal/memory_utils.h"
size_t cbor_bytestring_length(const cbor_item_t *item)
{
assert(cbor_isa_bytestring(item));
return item->metadata.bytestring_metadata.length;
}
unsigned char *cbor_bytestring_handle(const cbor_item_t *item)
{
assert(cbor_isa_bytestring(item));
return item->data;
}
bool cbor_bytestring_is_definite(const cbor_item_t *item)
{
assert(cbor_isa_bytestring(item));
return item->metadata.bytestring_metadata.type == _CBOR_METADATA_DEFINITE;
}
bool cbor_bytestring_is_indefinite(const cbor_item_t *item)
{
return !cbor_bytestring_is_definite(item);
}
cbor_item_t *cbor_new_definite_bytestring()
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
*item = (cbor_item_t) {
.refcount = 1,
.type = CBOR_TYPE_BYTESTRING,
.metadata = {.bytestring_metadata = {_CBOR_METADATA_DEFINITE, 0}}
};
return item;
}
cbor_item_t *cbor_new_indefinite_bytestring()
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
*item = (cbor_item_t) {
.refcount = 1,
.type = CBOR_TYPE_BYTESTRING,
.metadata = {.bytestring_metadata = {.type = _CBOR_METADATA_INDEFINITE, .length = 0}},
.data = _CBOR_MALLOC(sizeof(struct cbor_indefinite_string_data))
};
*((struct cbor_indefinite_string_data *) item->data) = (struct cbor_indefinite_string_data) {
.chunk_count = 0,
.chunk_capacity = 0,
.chunks = NULL,
};
return item;
}
cbor_item_t *cbor_build_bytestring(cbor_data handle, size_t length)
{
cbor_item_t *res = cbor_new_definite_bytestring();
void * content = _CBOR_MALLOC(length);
memcpy(content, handle, length);
cbor_bytestring_set_handle(res, content, length);
return res;
}
void cbor_bytestring_set_handle(cbor_item_t *item, cbor_mutable_data CBOR_RESTRICT_POINTER data, size_t length)
{
assert(cbor_isa_bytestring(item));
assert(cbor_bytestring_is_definite(item));
item->data = data;
item->metadata.bytestring_metadata.length = length;
}
cbor_item_t **cbor_bytestring_chunks_handle(const cbor_item_t *item)
{
assert(cbor_isa_bytestring(item));
assert(cbor_bytestring_is_indefinite(item));
return ((struct cbor_indefinite_string_data *) item->data)->chunks;
}
size_t cbor_bytestring_chunk_count(const cbor_item_t *item)
{
assert(cbor_isa_bytestring(item));
assert(cbor_bytestring_is_indefinite(item));
return ((struct cbor_indefinite_string_data *) item->data)->chunk_count;
}
bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk)
{
assert(cbor_isa_bytestring(item));
assert(cbor_bytestring_is_indefinite(item));
struct cbor_indefinite_string_data *data = (struct cbor_indefinite_string_data *) item->data;
if (data->chunk_count == data->chunk_capacity) {
/* We need more space */
if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) {
return false;
}
data->chunk_capacity = data->chunk_capacity == 0 ? 1 : CBOR_BUFFER_GROWTH * (data->chunk_capacity);
cbor_item_t **new_chunks_data = _cbor_realloc_multiple(data->chunks, sizeof(cbor_item_t *), data->chunk_capacity);
if (new_chunks_data == NULL) {
return false;
}
data->chunks = new_chunks_data;
}
data->chunks[data->chunk_count++] = cbor_incref(chunk);
return true;
}

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_BYTESTRINGS_H
#define LIBCBOR_BYTESTRINGS_H
#include "cbor/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* ============================================================================
* Byte string manipulation
* ============================================================================
*/
/** Returns the length of the binary data
*
* For definite byte strings only
*
* @param item[borrow] a definite bytestring
* @return length of the binary data. Zero if no chunk has been attached yet
*/
size_t cbor_bytestring_length(const cbor_item_t *item);
/** Is the byte string definite?
*
* @param item[borrow] a byte string
* @return Is the byte string definite?
*/
bool cbor_bytestring_is_definite(const cbor_item_t *item);
/** Is the byte string indefinite?
*
* @param item[borrow] a byte string
* @return Is the byte string indefinite?
*/
bool cbor_bytestring_is_indefinite(const cbor_item_t *item);
/** Get the handle to the binary data
*
* Definite items only. Modifying the data is allowed. In that case, the caller takes
* responsibility for the effect on items this item might be a part of
*
* @param item[borrow] A definite byte string
* @return The address of the binary data. `NULL` if no data have been assigned yet.
*/
cbor_mutable_data cbor_bytestring_handle(const cbor_item_t *item);
/** Set the handle to the binary data
*
* @param item[borrow] A definite byte string
* @param data The memory block. The caller gives up the ownership of the block. libcbor will deallocate it when appropriate using its free function
* @param length Length of the data block
*/
void cbor_bytestring_set_handle(cbor_item_t *item, cbor_mutable_data CBOR_RESTRICT_POINTER data, size_t length);
/** Get the handle to the array of chunks
*
* Manipulations with the memory block (e.g. sorting it) are allowed, but the validity and the number of chunks must be retained.
*
* @param item[borrow] A indefinite byte string
* @return array of #cbor_bytestring_chunk_count definite bytestrings
*/
cbor_item_t **cbor_bytestring_chunks_handle(const cbor_item_t *item);
/** Get the number of chunks this string consist of
*
* @param item[borrow] A indefinite bytestring
* @return The chunk count. 0 for freshly created items.
*/
size_t cbor_bytestring_chunk_count(const cbor_item_t *item);
/** Appends a chunk to the bytestring
*
* Indefinite byte strings only.
*
* May realloc the chunk storage.
*
* @param item[borrow] An indefinite byte string
* @param item[incref] A definite byte string
* @return true on success, false on realloc failure. In that case, the refcount of `chunk` is not increased and the `item` is left intact.
*/
bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk);
/** Creates a new definite byte string
*
* The handle is initialized to `NULL` and length to 0
*
* @return **new** definite bytestring. `NULL` on malloc failure.
*/
cbor_item_t *cbor_new_definite_bytestring();
/** Creates a new indefinite byte string
*
* The chunks array is initialized to `NULL` and chunkcount to 0
*
* @return **new** indefinite bytestring. `NULL` on malloc failure.
*/
cbor_item_t *cbor_new_indefinite_bytestring();
/** Creates a new byte string and initializes it
*
* The `handle` will be copied to a newly allocated block
*
* @param handle Block of binary data
* @param length Length of `data`
* @return A **new** byte string with content `handle`. `NULL` on malloc failure.
*/
cbor_item_t *cbor_build_bytestring(cbor_data handle, size_t length);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_BYTESTRINGS_H

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "callbacks.h"
#define CBOR_DUMMY_CALLBACK { }
void cbor_null_uint8_callback(void *_ctx, uint8_t _val) CBOR_DUMMY_CALLBACK
void cbor_null_uint16_callback(void *_ctx, uint16_t _val) CBOR_DUMMY_CALLBACK
void cbor_null_uint32_callback(void *_ctx, uint32_t _val) CBOR_DUMMY_CALLBACK
void cbor_null_uint64_callback(void *_ctx, uint64_t _val) CBOR_DUMMY_CALLBACK
void cbor_null_negint8_callback(void *_ctx, uint8_t _val) CBOR_DUMMY_CALLBACK
void cbor_null_negint16_callback(void *_ctx, uint16_t _val) CBOR_DUMMY_CALLBACK
void cbor_null_negint32_callback(void *_ctx, uint32_t _val) CBOR_DUMMY_CALLBACK
void cbor_null_negint64_callback(void *_ctx, uint64_t _val) CBOR_DUMMY_CALLBACK
void cbor_null_string_callback(void *_ctx, cbor_data _val, size_t _val2) CBOR_DUMMY_CALLBACK
void cbor_null_string_start_callback(void *_ctx) CBOR_DUMMY_CALLBACK
void cbor_null_byte_string_callback(void *_ctx, cbor_data _val, size_t _val2) CBOR_DUMMY_CALLBACK
void cbor_null_byte_string_start_callback(void *_ctx) CBOR_DUMMY_CALLBACK
void cbor_null_array_start_callback(void *_ctx, size_t _val) CBOR_DUMMY_CALLBACK
void cbor_null_indef_array_start_callback(void *_ctx) CBOR_DUMMY_CALLBACK
void cbor_null_map_start_callback(void *_ctx, size_t _val) CBOR_DUMMY_CALLBACK
void cbor_null_indef_map_start_callback(void *_ctx) CBOR_DUMMY_CALLBACK
void cbor_null_tag_callback(void *_ctx, uint64_t _val) CBOR_DUMMY_CALLBACK
void cbor_null_float2_callback(void *_ctx, float _val) CBOR_DUMMY_CALLBACK
void cbor_null_float4_callback(void *_ctx, float _val) CBOR_DUMMY_CALLBACK
void cbor_null_float8_callback(void *_ctx, double _val) CBOR_DUMMY_CALLBACK
void cbor_null_null_callback(void *_ctx) CBOR_DUMMY_CALLBACK
void cbor_null_undefined_callback(void *_ctx) CBOR_DUMMY_CALLBACK
void cbor_null_boolean_callback(void *_ctx, bool _val) CBOR_DUMMY_CALLBACK
void cbor_null_indef_break_callback(void *_ctx) CBOR_DUMMY_CALLBACK
const struct cbor_callbacks cbor_empty_callbacks = {
/* Type 0 - Unsigned integers */
.uint8 = cbor_null_uint8_callback,
.uint16 = cbor_null_uint16_callback,
.uint32 = cbor_null_uint32_callback,
.uint64 = cbor_null_uint64_callback,
/* Type 1 - Negative integers */
.negint8 = cbor_null_negint8_callback,
.negint16 = cbor_null_negint16_callback,
.negint32 = cbor_null_negint32_callback,
.negint64 = cbor_null_negint64_callback,
/* Type 2 - Byte strings */
.byte_string_start = cbor_null_byte_string_start_callback,
.byte_string = cbor_null_byte_string_callback,
/* Type 3 - Strings */
.string_start = cbor_null_string_start_callback,
.string = cbor_null_string_callback,
/* Type 4 - Arrays */
.indef_array_start = cbor_null_indef_array_start_callback,
.array_start = cbor_null_array_start_callback,
/* Type 5 - Maps */
.indef_map_start = cbor_null_indef_map_start_callback,
.map_start = cbor_null_map_start_callback,
/* Type 6 - Tags */
.tag = cbor_null_tag_callback,
/* Type 7 - Floats & misc */
/* Type names cannot be member names */
.float2 = cbor_null_float2_callback,
/* 2B float is not supported in standard C */
.float4 = cbor_null_float4_callback,
.float8 = cbor_null_float8_callback,
.undefined = cbor_null_undefined_callback,
.null = cbor_null_null_callback,
.boolean = cbor_null_boolean_callback,
/* Shared indefinites */
.indef_break = cbor_null_indef_break_callback,
};

View File

@ -0,0 +1,187 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_CALLBACKS_H
#define LIBCBOR_CALLBACKS_H
#include "cbor/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Callback prototype */
typedef void(*cbor_int8_callback)(void *, uint8_t);
/** Callback prototype */
typedef void(*cbor_int16_callback)(void *, uint16_t);
/** Callback prototype */
typedef void(*cbor_int32_callback)(void *, uint32_t);
/** Callback prototype */
typedef void(*cbor_int64_callback)(void *, uint64_t);
/** Callback prototype */
typedef void(*cbor_simple_callback)(void *);
/** Callback prototype */
typedef void(*cbor_string_callback)(void *, cbor_data, size_t);
/** Callback prototype */
typedef void(*cbor_collection_callback)(void *, size_t);
/** Callback prototype */
typedef void(*cbor_float_callback)(void *, float);
/** Callback prototype */
typedef void(*cbor_double_callback)(void *, double);
/** Callback prototype */
typedef void(*cbor_bool_callback)(void *, bool);
/** Callback bundle -- passed to the decoder */
struct cbor_callbacks {
/** Unsigned int */
cbor_int8_callback uint8;
/** Unsigned int */
cbor_int16_callback uint16;
/** Unsigned int */
cbor_int32_callback uint32;
/** Unsigned int */
cbor_int64_callback uint64;
/** Negative int */
cbor_int64_callback negint64;
/** Negative int */
cbor_int32_callback negint32;
/** Negative int */
cbor_int16_callback negint16;
/** Negative int */
cbor_int8_callback negint8;
/** Definite byte string */
cbor_simple_callback byte_string_start;
/** Indefinite byte string start */
cbor_string_callback byte_string;
/** Definite string */
cbor_string_callback string;
/** Indefinite string start */
cbor_simple_callback string_start;
/** Definite array */
cbor_simple_callback indef_array_start;
/** Indefinite array */
cbor_collection_callback array_start;
/** Definite map */
cbor_simple_callback indef_map_start;
/** Indefinite map */
cbor_collection_callback map_start;
/** Tags */
cbor_int64_callback tag;
/** Half float */
cbor_float_callback float2;
/** Single float */
cbor_float_callback float4;
/** Double float */
cbor_double_callback float8;
/** Undef */
cbor_simple_callback undefined;
/** Null */
cbor_simple_callback null;
/** Bool */
cbor_bool_callback boolean;
/** Indefinite item break */
cbor_simple_callback indef_break;
};
/** Dummy callback implementation - does nothing */
void cbor_null_uint8_callback(void *, uint8_t);
/** Dummy callback implementation - does nothing */
void cbor_null_uint16_callback(void *, uint16_t);
/** Dummy callback implementation - does nothing */
void cbor_null_uint32_callback(void *, uint32_t);
/** Dummy callback implementation - does nothing */
void cbor_null_uint64_callback(void *, uint64_t);
/** Dummy callback implementation - does nothing */
void cbor_null_negint8_callback(void *, uint8_t);
/** Dummy callback implementation - does nothing */
void cbor_null_negint16_callback(void *, uint16_t);
/** Dummy callback implementation - does nothing */
void cbor_null_negint32_callback(void *, uint32_t);
/** Dummy callback implementation - does nothing */
void cbor_null_negint64_callback(void *, uint64_t);
/** Dummy callback implementation - does nothing */
void cbor_null_string_callback(void *, cbor_data, size_t);
/** Dummy callback implementation - does nothing */
void cbor_null_string_start_callback(void *);
/** Dummy callback implementation - does nothing */
void cbor_null_byte_string_callback(void *, cbor_data, size_t);
/** Dummy callback implementation - does nothing */
void cbor_null_byte_string_start_callback(void *);
/** Dummy callback implementation - does nothing */
void cbor_null_array_start_callback(void *, size_t);
/** Dummy callback implementation - does nothing */
void cbor_null_indef_array_start_callback(void *);
/** Dummy callback implementation - does nothing */
void cbor_null_map_start_callback(void *, size_t);
/** Dummy callback implementation - does nothing */
void cbor_null_indef_map_start_callback(void *);
/** Dummy callback implementation - does nothing */
void cbor_null_tag_callback(void *, uint64_t);
/** Dummy callback implementation - does nothing */
void cbor_null_float2_callback(void *, float);
/** Dummy callback implementation - does nothing */
void cbor_null_float4_callback(void *, float);
/** Dummy callback implementation - does nothing */
void cbor_null_float8_callback(void *, double);
/** Dummy callback implementation - does nothing */
void cbor_null_null_callback(void *);
/** Dummy callback implementation - does nothing */
void cbor_null_undefined_callback(void *);
/** Dummy callback implementation - does nothing */
void cbor_null_boolean_callback(void *, bool);
/** Dummy callback implementation - does nothing */
void cbor_null_indef_break_callback(void *);
/** Dummy callback bundle - does nothing */
extern const struct cbor_callbacks cbor_empty_callbacks;
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_CALLBACKS_H

View File

@ -0,0 +1,188 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "cbor/common.h"
#include "arrays.h"
#include "bytestrings.h"
#include "data.h"
#include "floats_ctrls.h"
#include "ints.h"
#include "maps.h"
#include "strings.h"
#include "tags.h"
bool cbor_isa_uint(const cbor_item_t *item)
{
return item->type == CBOR_TYPE_UINT;
}
bool cbor_isa_negint(const cbor_item_t *item)
{
return item->type == CBOR_TYPE_NEGINT;
}
bool cbor_isa_bytestring(const cbor_item_t *item)
{
return item->type == CBOR_TYPE_BYTESTRING;
}
bool cbor_isa_string(const cbor_item_t *item)
{
return item->type == CBOR_TYPE_STRING;
}
bool cbor_isa_array(const cbor_item_t *item)
{
return item->type == CBOR_TYPE_ARRAY;
}
bool cbor_isa_map(const cbor_item_t *item)
{
return item->type == CBOR_TYPE_MAP;
}
bool cbor_isa_tag(const cbor_item_t *item)
{
return item->type == CBOR_TYPE_TAG;
}
bool cbor_isa_float_ctrl(const cbor_item_t *item)
{
return item->type == CBOR_TYPE_FLOAT_CTRL;
}
cbor_type cbor_typeof(const cbor_item_t *item)
{
return item->type;
}
bool cbor_is_int(const cbor_item_t *item)
{
return cbor_isa_uint(item) || cbor_isa_negint(item);
}
bool cbor_is_bool(const cbor_item_t *item)
{
return cbor_isa_float_ctrl(item) &&
(cbor_ctrl_value(item) == CBOR_CTRL_FALSE || cbor_ctrl_value(item) == CBOR_CTRL_TRUE);
}
bool cbor_is_null(const cbor_item_t *item)
{
return cbor_isa_float_ctrl(item) && cbor_ctrl_value(item) == CBOR_CTRL_NULL;
}
bool cbor_is_undef(const cbor_item_t *item)
{
return cbor_isa_float_ctrl(item) && cbor_ctrl_value(item) == CBOR_CTRL_UNDEF;
}
bool cbor_is_float(const cbor_item_t *item)
{
return cbor_isa_float_ctrl(item) && !cbor_float_ctrl_is_ctrl(item);
}
cbor_item_t * cbor_incref(cbor_item_t *item)
{
item->refcount++;
return item;
}
void cbor_decref(cbor_item_t **item_ref)
{
cbor_item_t * item = *item_ref;
if (--item->refcount == 0) {
switch (item->type) {
case CBOR_TYPE_UINT:
/* Fallthrough */
case CBOR_TYPE_NEGINT:
/* Combined allocation, freeing the item suffices */
{
break;
}
case CBOR_TYPE_BYTESTRING: {
if (cbor_bytestring_is_definite(item)) {
_CBOR_FREE(item->data);
} else {
/* We need to decref all chunks */
cbor_item_t **handle = cbor_bytestring_chunks_handle(item);
for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++)
cbor_decref(&handle[i]);
_CBOR_FREE(((struct cbor_indefinite_string_data *) item->data)->chunks);
_CBOR_FREE(item->data);
}
break;
}
case CBOR_TYPE_STRING: {
if (cbor_string_is_definite(item)) {
_CBOR_FREE(item->data);
} else {
/* We need to decref all chunks */
cbor_item_t **handle = cbor_string_chunks_handle(item);
for (size_t i = 0; i < cbor_string_chunk_count(item); i++)
cbor_decref(&handle[i]);
_CBOR_FREE(((struct cbor_indefinite_string_data *) item->data)->chunks);
_CBOR_FREE(item->data);
}
break;
}
case CBOR_TYPE_ARRAY: {
/* Get all items and decref them */
cbor_item_t **handle = cbor_array_handle(item);
size_t size = cbor_array_size(item);
for (size_t i = 0; i < size; i++)
if (handle[i] != NULL)
cbor_decref(&handle[i]);
_CBOR_FREE(item->data);
break;
}
case CBOR_TYPE_MAP: {
struct cbor_pair *handle = cbor_map_handle(item);
for (size_t i = 0; i < item->metadata.map_metadata.end_ptr; i++, handle++) {
cbor_decref(&handle->key);
if (handle->value != NULL)
cbor_decref(&handle->value);
}
_CBOR_FREE(item->data);
break;
};
case CBOR_TYPE_TAG: {
if (item->metadata.tag_metadata.tagged_item != NULL)
cbor_decref(&item->metadata.tag_metadata.tagged_item);
_CBOR_FREE(item->data);
break;
}
case CBOR_TYPE_FLOAT_CTRL: {
/* Floats have combined allocation */
break;
}
}
_CBOR_FREE(item);
//TODO
*item_ref = NULL;
}
}
void cbor_intermediate_decref(cbor_item_t * item)
{
cbor_decref(&item);
}
size_t cbor_refcount(const cbor_item_t * item)
{
return item->refcount;
}
cbor_item_t * cbor_move(cbor_item_t * item)
{
item->refcount--;
return item;
}

View File

@ -0,0 +1,261 @@
/*
* Copyright (c) 2014-2015 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_COMMON_H
#define LIBCBOR_COMMON_H
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include "data.h"
#include "cbor/configuration.h"
#ifdef __cplusplus
extern "C" {
/** C++ is not a subset of C99 -- 'restrict' qualifier is not a part of the language.
* This is a workaround to keep it in C headers -- compilers allow linking non-restrict
* signatures with restrict implementations.
*
* If you know a nicer way, please do let me know.
*/
#define CBOR_RESTRICT_POINTER
#else
// MSVC + C++ workaround
#define CBOR_RESTRICT_POINTER CBOR_RESTRICT_SPECIFIER
#endif
static const uint8_t cbor_major_version = CBOR_MAJOR_VERSION;
static const uint8_t cbor_minor_version = CBOR_MINOR_VERSION;
static const uint8_t cbor_patch_version = CBOR_PATCH_VERSION;
#define CBOR_VERSION TO_STR(CBOR_MAJOR_VERSION) "." TO_STR(CBOR_MINOR_VERSION) "." TO_STR(CBOR_PATCH_VERSION)
#define CBOR_HEX_VERSION ((CBOR_MAJOR_VERSION << 16) | (CBOR_MINOR_VERSION << 8) | CBOR_PATCH_VERSION)
/* http://stackoverflow.com/questions/1644868/c-define-macro-for-debug-printing */
#ifdef DEBUG
#include <stdio.h>
#define debug_print(fmt, ...) do { \
if (DEBUG) \
fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, __VA_ARGS__); \
} while (0)
#else
#define debug_print(fmt, ...) do {} while (0)
#endif
#define TO_STR_(x) #x
#define TO_STR(x) TO_STR_(x) /* enables proper double expansion */
#if CBOR_CUSTOM_ALLOC
typedef void * (* _cbor_malloc_t)(size_t);
typedef void * (* _cbor_realloc_t)(void *, size_t);
typedef void (* _cbor_free_t)(void *);
extern _cbor_malloc_t _cbor_malloc;
extern _cbor_realloc_t _cbor_realloc;
extern _cbor_free_t _cbor_free;
/** Sets the memory management routines to use.
*
* Only available when CBOR_CUSTOM_ALLOC is truthy
*
* \rst
* .. warning:: This function modifies the global state and should therefore be used accordingly. Changing the memory handlers while allocated items exist will result in a ``free``/``malloc`` mismatch. This function is not thread safe with respect to both itself and all the other *libcbor* functions that work with the heap.
* .. note:: `realloc` implementation must correctly support `NULL` reallocation
* \endrst
*
* @param custom_malloc malloc implementation
* @param custom_realloc realloc implementation
* @param custom_free free implementation
*/
void cbor_set_allocs(_cbor_malloc_t custom_malloc, _cbor_realloc_t custom_realloc, _cbor_free_t custom_free);
#define _CBOR_MALLOC _cbor_malloc
#define _CBOR_REALLOC _cbor_realloc
#define _CBOR_FREE _cbor_free
#else
#define _CBOR_MALLOC malloc
#define _CBOR_REALLOC realloc
#define _CBOR_FREE free
#endif
/*
* ============================================================================
* Type manipulation
* ============================================================================
*/
/** Get the type of the item
*
* @param item[borrow]
* @return The type
*/
cbor_type cbor_typeof(const cbor_item_t * item); /* Will be inlined iff link-time opt is enabled */
/* Standard item types as described by the RFC */
/** Does the item have the appropriate major type?
* @param item[borrow] the item
* @return Is the item an #CBOR_TYPE_UINT?
*/
bool cbor_isa_uint(const cbor_item_t * item);
/** Does the item have the appropriate major type?
* @param item[borrow] the item
* @return Is the item a #CBOR_TYPE_NEGINT?
*/
bool cbor_isa_negint(const cbor_item_t * item);
/** Does the item have the appropriate major type?
* @param item[borrow] the item
* @return Is the item a #CBOR_TYPE_BYTESTRING?
*/
bool cbor_isa_bytestring(const cbor_item_t * item);
/** Does the item have the appropriate major type?
* @param item[borrow] the item
* @return Is the item a #CBOR_TYPE_STRING?
*/
bool cbor_isa_string(const cbor_item_t * item);
/** Does the item have the appropriate major type?
* @param item[borrow] the item
* @return Is the item an #CBOR_TYPE_ARRAY?
*/
bool cbor_isa_array(const cbor_item_t * item);
/** Does the item have the appropriate major type?
* @param item[borrow] the item
* @return Is the item a #CBOR_TYPE_MAP?
*/
bool cbor_isa_map(const cbor_item_t * item);
/** Does the item have the appropriate major type?
* @param item[borrow] the item
* @return Is the item a #CBOR_TYPE_TAG?
*/
bool cbor_isa_tag(const cbor_item_t * item);
/** Does the item have the appropriate major type?
* @param item[borrow] the item
* @return Is the item a #CBOR_TYPE_FLOAT_CTRL?
*/
bool cbor_isa_float_ctrl(const cbor_item_t * item);
/* Practical types with respect to their semantics (but not tag values) */
/** Is the item an integer, either positive or negative?
* @param item[borrow] the item
* @return Is the item an integer, either positive or negative?
*/
bool cbor_is_int(const cbor_item_t * item);
/** Is the item an a floating point number?
* @param item[borrow] the item
* @return Is the item a floating point number?
*/
bool cbor_is_float(const cbor_item_t * item);
/** Is the item an a boolean?
* @param item[borrow] the item
* @return Is the item a boolean?
*/
bool cbor_is_bool(const cbor_item_t * item);
/** Does this item represent `null`
* \rst
* .. warning:: This is in no way related to the value of the pointer. Passing a null pointer will most likely result in a crash.
* \endrst
* @param item[borrow] the item
* @return Is the item (CBOR logical) null?
*/
bool cbor_is_null(const cbor_item_t * item);
/** Does this item represent `undefined`
* \rst
* .. warning:: Care must be taken to distinguish nulls and undefined values in C.
* \endrst
* @param item[borrow] the item
* @return Is the item (CBOR logical) undefined?
*/
bool cbor_is_undef(const cbor_item_t * item);
/*
* ============================================================================
* Memory management
* ============================================================================
*/
/** Increases the reference count by one
*
* No dependent items are affected.
*
* @param item[incref] item the item
* @return the input reference
*/
cbor_item_t * cbor_incref(cbor_item_t * item);
/** Decreases the reference count by one, deallocating the item if needed
*
* In case the item is deallocated, the reference count of any dependent items
* is adjusted accordingly in a recursive manner.
*
* @param item[take] the item. Set to `NULL` if deallocated
*/
void cbor_decref(cbor_item_t ** item);
/** Decreases the reference count by one, deallocating the item if needed
*
* Convenience wrapper for #cbor_decref when its set-to-null behavior is not needed
*
* @param item[take] the item
*/
void cbor_intermediate_decref(cbor_item_t * item);
/** Get the reference count
*
* \rst
* .. warning:: This does *not* account for transitive references.
* \endrst
*
* @param item[borrow] the item
* @return the reference count
*/
size_t cbor_refcount(const cbor_item_t * item);
/** Provides CPP-like move construct
*
* Decreases the reference count by one, but does not deallocate the item even if its refcount
* reaches zero. This is useful for passing intermediate values to functions that increase
* reference count. Should only be used with functions that `incref` their arguments.
*
* \rst
* .. warning:: If the item is moved without correctly increasing the reference count afterwards, the memory will be leaked.
* \endrst
*
* @param item[take] the item
* @return the item with reference count decreased by one
*/
cbor_item_t * cbor_move(cbor_item_t * item);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_COMMON_H

View File

@ -0,0 +1,15 @@
#ifndef LIBCBOR_CONFIGURATION_H
#define LIBCBOR_CONFIGURATION_H
#define CBOR_MAJOR_VERSION 0
#define CBOR_MINOR_VERSION 5
#define CBOR_PATCH_VERSION 0
#define CBOR_CUSTOM_ALLOC 0
#define CBOR_BUFFER_GROWTH 2
#define CBOR_PRETTY_PRINTER 1
#define CBOR_RESTRICT_SPECIFIER restrict
#define CBOR_INLINE_SPECIFIER
#endif //LIBCBOR_CONFIGURATION_H

View File

@ -0,0 +1,15 @@
#ifndef LIBCBOR_CONFIGURATION_H
#define LIBCBOR_CONFIGURATION_H
#define CBOR_MAJOR_VERSION ${CBOR_VERSION_MAJOR}
#define CBOR_MINOR_VERSION ${CBOR_VERSION_MINOR}
#define CBOR_PATCH_VERSION ${CBOR_VERSION_PATCH}
#cmakedefine01 CBOR_CUSTOM_ALLOC
#define CBOR_BUFFER_GROWTH ${CBOR_BUFFER_GROWTH}
#cmakedefine01 CBOR_PRETTY_PRINTER
#define CBOR_RESTRICT_SPECIFIER ${CBOR_RESTRICT_SPECIFIER}
#define CBOR_INLINE_SPECIFIER ${CBOR_INLINE_SPECIFIER}
#endif //LIBCBOR_CONFIGURATION_H

212
lib/libcbor/src/cbor/data.h Normal file
View File

@ -0,0 +1,212 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_DATA_H
#define LIBCBOR_DATA_H
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef const unsigned char * cbor_data;
typedef unsigned char * cbor_mutable_data;
/** Specifies the Major type of ::cbor_item_t */
typedef enum cbor_type {
CBOR_TYPE_UINT /** 0 - positive integers */
,CBOR_TYPE_NEGINT /** 1 - negative integers*/
,CBOR_TYPE_BYTESTRING /** 2 - byte strings */
,CBOR_TYPE_STRING /** 3 - strings */
,CBOR_TYPE_ARRAY /** 4 - arrays */
,CBOR_TYPE_MAP /** 5 - maps */
,CBOR_TYPE_TAG /** 6 - tags */
,CBOR_TYPE_FLOAT_CTRL /** 7 - decimals and special values (true, false, nil, ...) */
} cbor_type;
/** Possible decoding errors */
typedef enum {
CBOR_ERR_NONE
,CBOR_ERR_NOTENOUGHDATA
,CBOR_ERR_NODATA
,CBOR_ERR_MALFORMATED
,CBOR_ERR_MEMERROR /** Memory error - item allocation failed. Is it too big for your allocator? */
,CBOR_ERR_SYNTAXERROR /** Stack parsing algorithm failed */
} cbor_error_code;
/** Possible widths of #CBOR_TYPE_UINT items */
typedef enum {
CBOR_INT_8
,CBOR_INT_16
,CBOR_INT_32
,CBOR_INT_64
} cbor_int_width;
/** Possible widths of #CBOR_TYPE_FLOAT_CTRL items */
typedef enum {
CBOR_FLOAT_0 /** Internal use - ctrl and special values */
,CBOR_FLOAT_16 /** Half float */
,CBOR_FLOAT_32 /** Single float */
,CBOR_FLOAT_64 /** Double */
} cbor_float_width;
/** Metadata for dynamically sized types */
typedef enum {
_CBOR_METADATA_DEFINITE
,_CBOR_METADATA_INDEFINITE
} _cbor_dst_metadata;
/** Semantic mapping for CTRL simple values */
typedef enum {
CBOR_CTRL_NONE = 0,
CBOR_CTRL_FALSE = 20,
CBOR_CTRL_TRUE = 21,
CBOR_CTRL_NULL = 22,
CBOR_CTRL_UNDEF = 23
} _cbor_ctrl;
/** Integers specific metadata */
struct _cbor_int_metadata {
cbor_int_width width;
};
/** Bytestrings specific metadata */
struct _cbor_bytestring_metadata {
size_t length;
_cbor_dst_metadata type;
};
/** Strings specific metadata */
struct _cbor_string_metadata {
size_t length;
size_t codepoint_count; /* Sum of chunks' codepoint_counts for indefinite strings */
_cbor_dst_metadata type;
};
/** Arrays specific metadata */
struct _cbor_array_metadata {
size_t allocated;
size_t end_ptr;
_cbor_dst_metadata type;
};
/** Maps specific metadata */
struct _cbor_map_metadata {
size_t allocated;
size_t end_ptr;
_cbor_dst_metadata type;
};
/** Arrays specific metadata
*
* The pointer is included - cbor_item_metadata is
* 2 * sizeof(size_t) + sizeof(_cbor_string_type_metadata),
* lets use the space
*/
struct _cbor_tag_metadata {
struct cbor_item_t * tagged_item;
uint64_t value;
};
/** Floats specific metadata - includes CTRL values */
struct _cbor_float_ctrl_metadata {
cbor_float_width width;
uint8_t ctrl;
};
/** Raw memory casts helper */
union _cbor_float_helper {
float as_float;
uint32_t as_uint;
};
/** Raw memory casts helper */
union _cbor_double_helper {
double as_double;
uint64_t as_uint;
};
/** Union of metadata across all possible types - discriminated in #cbor_item_t */
union cbor_item_metadata {
struct _cbor_int_metadata int_metadata;
struct _cbor_bytestring_metadata bytestring_metadata;
struct _cbor_string_metadata string_metadata;
struct _cbor_array_metadata array_metadata;
struct _cbor_map_metadata map_metadata;
struct _cbor_tag_metadata tag_metadata;
struct _cbor_float_ctrl_metadata float_ctrl_metadata;
};
/** The item handle */
typedef struct cbor_item_t {
/** Discriminated by type */
union cbor_item_metadata metadata;
/** Reference count - initialize to 0 */
size_t refcount;
/** Major type discriminator */
cbor_type type;
/** Raw data block - interpretation depends on metadata */
unsigned char * data;
} cbor_item_t;
/** Defines cbor_item_t#data structure for indefinite strings and bytestrings
*
* Used to cast the raw representation for a sane manipulation
*/
struct cbor_indefinite_string_data {
size_t chunk_count;
size_t chunk_capacity;
cbor_item_t * * chunks;
};
/** High-level decoding error */
struct cbor_error {
/** Aproximate position */
size_t position;
/** Description */
cbor_error_code code;
};
/** Simple pair of items for use in maps */
struct cbor_pair {
cbor_item_t * key, * value;
};
/** High-level decoding result */
struct cbor_load_result {
/** Error indicator */
struct cbor_error error;
/** Number of bytes read*/
size_t read;
};
/** Streaming decoder result - status */
enum cbor_decoder_status {
CBOR_DECODER_FINISHED /** OK, finished */
,CBOR_DECODER_NEDATA /** Not enough data - mismatch with MTB */
,CBOR_DECODER_EBUFFER /** Buffer manipulation problem */
,CBOR_DECODER_ERROR /** Malformed or reserved MTB/value */
};
/** Streaming decoder result */
struct cbor_decoder_result {
/** Bytes read */
size_t read;
/** The result */
enum cbor_decoder_status status;
};
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_DATA_H

View File

@ -0,0 +1,186 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "encoding.h"
#include "internal/encoders.h"
size_t cbor_encode_uint8(uint8_t value, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint8(value, buffer, buffer_size, 0x00);
}
size_t cbor_encode_uint16(uint16_t value, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint16(value, buffer, buffer_size, 0x00);
}
size_t cbor_encode_uint32(uint32_t value, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint32(value, buffer, buffer_size, 0x00);
}
size_t cbor_encode_uint64(uint64_t value, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint64(value, buffer, buffer_size, 0x00);
}
size_t cbor_encode_uint(uint64_t value, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint(value, buffer, buffer_size, 0x00);
}
size_t cbor_encode_negint8(uint8_t value, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint8(value, buffer, buffer_size, 0x20);
}
size_t cbor_encode_negint16(uint16_t value, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint16(value, buffer, buffer_size, 0x20);
}
size_t cbor_encode_negint32(uint32_t value, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint32(value, buffer, buffer_size, 0x20);
}
size_t cbor_encode_negint64(uint64_t value, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint64(value, buffer, buffer_size, 0x20);
}
size_t cbor_encode_negint(uint64_t value, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint(value, buffer, buffer_size, 0x20);
}
size_t cbor_encode_bytestring_start(size_t length, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint((size_t) length, buffer, buffer_size, 0x40);
}
size_t _cbor_encode_byte(uint8_t value, unsigned char *buffer, size_t buffer_size)
{
if (buffer_size >= 1) {
buffer[0] = value;
return 1;
} else
return 0;
}
size_t cbor_encode_indef_bytestring_start(unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_byte(0x5F, buffer, buffer_size);
}
size_t cbor_encode_string_start(size_t length, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint((size_t) length, buffer, buffer_size, 0x60);
}
size_t cbor_encode_indef_string_start(unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_byte(0x7F, buffer, buffer_size);
}
size_t cbor_encode_array_start(size_t length, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint((size_t) length, buffer, buffer_size, 0x80);
}
size_t cbor_encode_indef_array_start(unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_byte(0x9F, buffer, buffer_size);
}
size_t cbor_encode_map_start(size_t length, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint((size_t) length, buffer, buffer_size, 0xA0);
}
size_t cbor_encode_indef_map_start(unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_byte(0xBF, buffer, buffer_size);
}
size_t cbor_encode_tag(uint64_t value, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint(value, buffer, buffer_size, 0xC0);
}
size_t cbor_encode_bool(bool value, unsigned char *buffer, size_t buffer_size)
{
return value ? _cbor_encode_byte(0xF5, buffer, buffer_size) : _cbor_encode_byte(0xF4, buffer, buffer_size);
}
size_t cbor_encode_null(unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_byte(0xF6, buffer, buffer_size);
}
size_t cbor_encode_undef(unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_byte(0xF7, buffer, buffer_size);
}
size_t cbor_encode_half(float value, unsigned char *buffer, size_t buffer_size)
{
/* Assuming value is normalized */
uint32_t val = ((union _cbor_float_helper) {.as_float = value}).as_uint;
uint16_t res;
uint8_t exp = (uint8_t) ((val & 0x7F800000) >> 23); /* 0b0111_1111_1000_0000_0000_0000_0000_0000 */
uint32_t mant = val & 0x7FFFFF; /* 0b0000_0000_0111_1111_1111_1111_1111_1111 */
if (exp == 0xFF) { /* Infinity or NaNs */
if (value != value) {
res = (uint16_t) 0x00e700; /* Not IEEE semantics - required by CBOR [s. 3.9] */
} else {
res = (uint16_t) ((val & 0x80000000) >> 16 | 0x7C00 | (mant ? 1 : 0) << 15);
}
} else if (exp == 0x00) { /* Zeroes or subnorms */
res = (uint16_t) ((val & 0x80000000) >> 16 | mant >> 13);
} else { /* Normal numbers */
int8_t logical_exp = (int8_t) (exp - 127);
assert(logical_exp == exp - 127);
// Now we know that 2^exp <= 0 logically
if (logical_exp < -24) {
/* No unambiguous representation exists, this float is not a half float and is too small to
be represented using a half, round off to zero. Consistent with the reference implementation. */
res = 0;
} else if (logical_exp < -14) {
/* Offset the remaining decimal places by shifting the significand, the value is lost.
This is an implementation decision that works around the absence of standard half-float
in the language. */
res = (uint16_t) (val & 0x80000000) >> 16 | (uint16_t) (1 << (24 + logical_exp));
} else {
res = (uint16_t) ((val & 0x80000000) >> 16 | ((((uint8_t) logical_exp) + 15) << 10) | (uint16_t) (mant >> 13));
}
}
return _cbor_encode_uint16(res, buffer, buffer_size, 0xE0);
}
size_t cbor_encode_single(float value, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint32(((union _cbor_float_helper) {.as_float = value}).as_uint, buffer, buffer_size, 0xE0);
}
size_t cbor_encode_double(double value, unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_uint64(((union _cbor_double_helper) {.as_double = value}).as_uint, buffer, buffer_size, 0xE0);
}
size_t cbor_encode_break(unsigned char *buffer, size_t buffer_size)
{
return _cbor_encode_byte(0xFF, buffer, buffer_size);
}
size_t cbor_encode_ctrl(uint8_t value, unsigned char * buffer, size_t buffer_size)
{
return _cbor_encode_uint8(value, buffer, buffer_size, 0xE0);
}

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_ENCODING_H
#define LIBCBOR_ENCODING_H
#include "cbor/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* ============================================================================
* Primitives encoding
* ============================================================================
*/
size_t cbor_encode_uint8(uint8_t, unsigned char *, size_t);
size_t cbor_encode_uint16(uint16_t, unsigned char *, size_t);
size_t cbor_encode_uint32(uint32_t, unsigned char *, size_t);
size_t cbor_encode_uint64(uint64_t, unsigned char *, size_t);
size_t cbor_encode_uint(uint64_t, unsigned char *, size_t);
size_t cbor_encode_negint8(uint8_t, unsigned char *, size_t);
size_t cbor_encode_negint16(uint16_t, unsigned char *, size_t);
size_t cbor_encode_negint32(uint32_t, unsigned char *, size_t);
size_t cbor_encode_negint64(uint64_t, unsigned char *, size_t);
size_t cbor_encode_negint(uint64_t, unsigned char *, size_t);
size_t cbor_encode_bytestring_start(size_t, unsigned char *, size_t);
size_t cbor_encode_indef_bytestring_start(unsigned char *, size_t);
size_t cbor_encode_string_start(size_t, unsigned char *, size_t);
size_t cbor_encode_indef_string_start(unsigned char *, size_t);
size_t cbor_encode_array_start(size_t, unsigned char *, size_t);
size_t cbor_encode_indef_array_start(unsigned char *, size_t);
size_t cbor_encode_map_start(size_t, unsigned char *, size_t);
size_t cbor_encode_indef_map_start(unsigned char *, size_t);
size_t cbor_encode_tag(uint64_t, unsigned char *, size_t);
size_t cbor_encode_bool(bool, unsigned char *, size_t);
size_t cbor_encode_null(unsigned char *, size_t);
size_t cbor_encode_undef(unsigned char *, size_t);
/** Encodes a half-precision float
*
* Since there is no native representation or semantics for half floats
* in the language, we use single-precision floats, as every value that
* can be expressed as a half-float can also be expressed as a float.
*
* This however means that not all floats passed to this function can be
* unambiguously encoded. The behavior is as follows:
* - Infinity, NaN are preserved
* - Zero is preserved
* - Denormalized numbers keep their sign bit and 10 most significant bit of the significand
* - All other numbers
* - If the logical value of the exponent is < -24, the output is zero
* - If the logical value of the exponent is between -23 and -14, the output
* is cut off to represent the 'magnitude' of the input, by which we
* mean (-1)^{signbit} x 1.0e{exponent}. The value in the significand is lost.
* - In all other cases, the sign bit, the exponent, and 10 most significant bits
* of the significand are kept
*
* @param value
* @param buffer Target buffer
* @param buffer_size Available space in the buffer
* @return number of bytes written
*/
size_t cbor_encode_half(float, unsigned char *, size_t);
size_t cbor_encode_single(float, unsigned char *, size_t);
size_t cbor_encode_double(double, unsigned char *, size_t);
size_t cbor_encode_break(unsigned char *, size_t);
size_t cbor_encode_ctrl(uint8_t, unsigned char *, size_t);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_ENCODING_H

View File

@ -0,0 +1,191 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "floats_ctrls.h"
#include "assert.h"
#include <math.h>
cbor_float_width cbor_float_get_width(const cbor_item_t *item)
{
assert(cbor_isa_float_ctrl(item));
return item->metadata.float_ctrl_metadata.width;
}
uint8_t cbor_ctrl_value(const cbor_item_t *item)
{
assert(cbor_isa_float_ctrl(item));
assert(cbor_float_get_width(item) == CBOR_FLOAT_0);
return item->metadata.float_ctrl_metadata.ctrl;
}
bool cbor_float_ctrl_is_ctrl(const cbor_item_t *item)
{
assert(cbor_isa_float_ctrl(item));
return cbor_float_get_width(item) == CBOR_FLOAT_0;
}
float cbor_float_get_float2(const cbor_item_t *item)
{
assert(cbor_is_float(item));
assert(cbor_float_get_width(item) == CBOR_FLOAT_16);
return *(float *) item->data;
}
float cbor_float_get_float4(const cbor_item_t *item)
{
assert(cbor_is_float(item));
assert(cbor_float_get_width(item) == CBOR_FLOAT_32);
return *(float *) item->data;
}
double cbor_float_get_float8(const cbor_item_t *item)
{
assert(cbor_is_float(item));
assert(cbor_float_get_width(item) == CBOR_FLOAT_64);
return *(double *) item->data;
}
double cbor_float_get_float(const cbor_item_t * item)
{
assert(cbor_is_float(item));
switch(cbor_float_get_width(item)) {
case CBOR_FLOAT_0: return NAN;
case CBOR_FLOAT_16: return cbor_float_get_float2(item);
case CBOR_FLOAT_32: return cbor_float_get_float4(item);
case CBOR_FLOAT_64: return cbor_float_get_float8(item);
}
return NAN; /* Compiler complaints */
}
void cbor_set_float2(cbor_item_t *item, float value)
{
assert(cbor_is_float(item));
assert(cbor_float_get_width(item) == CBOR_FLOAT_16);
*((float *) item->data) = value;
}
void cbor_set_float4(cbor_item_t *item, float value)
{
assert(cbor_is_float(item));
assert(cbor_float_get_width(item) == CBOR_FLOAT_32);
*((float *) item->data) = value;
}
void cbor_set_float8(cbor_item_t *item, double value)
{
assert(cbor_is_float(item));
assert(cbor_float_get_width(item) == CBOR_FLOAT_64);
*((double *) item->data) = value;
}
void cbor_set_ctrl(cbor_item_t *item, uint8_t value)
{
assert(cbor_isa_float_ctrl(item));
assert(cbor_float_get_width(item) == CBOR_FLOAT_0);
item->metadata.float_ctrl_metadata.ctrl = value;
}
bool cbor_ctrl_is_bool(const cbor_item_t *item)
{
assert(cbor_is_bool(item));
return item->metadata.float_ctrl_metadata.ctrl == CBOR_CTRL_TRUE;
}
cbor_item_t *cbor_new_ctrl()
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
*item = (cbor_item_t) {
.type = CBOR_TYPE_FLOAT_CTRL,
.data = NULL,
.refcount = 1,
.metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_0, .ctrl = CBOR_CTRL_NONE}}
};
return item;
}
cbor_item_t *cbor_new_float2()
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 4);
*item = (cbor_item_t) {
.type = CBOR_TYPE_FLOAT_CTRL,
.data = (unsigned char *) item + sizeof(cbor_item_t),
.refcount = 1,
.metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_16}}
};
return item;
}
cbor_item_t *cbor_new_float4()
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 4);
*item = (cbor_item_t) {
.type = CBOR_TYPE_FLOAT_CTRL,
.data = (unsigned char *) item + sizeof(cbor_item_t),
.refcount = 1,
.metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_32}}
};
return item;
}
cbor_item_t *cbor_new_float8()
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 8);
*item = (cbor_item_t) {
.type = CBOR_TYPE_FLOAT_CTRL,
.data = (unsigned char *) item + sizeof(cbor_item_t),
.refcount = 1,
.metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_64}}
};
return item;
}
cbor_item_t *cbor_new_null()
{
cbor_item_t *item = cbor_new_ctrl();
cbor_set_ctrl(item, CBOR_CTRL_NULL);
return item;
}
cbor_item_t *cbor_new_undef()
{
cbor_item_t *item = cbor_new_ctrl();
cbor_set_ctrl(item, CBOR_CTRL_UNDEF);
return item;
}
cbor_item_t *cbor_build_bool(bool value)
{
return cbor_build_ctrl(value ? CBOR_CTRL_TRUE : CBOR_CTRL_FALSE);
}
cbor_item_t *cbor_build_float2(float value)
{
cbor_item_t *item = cbor_new_float2();
cbor_set_float2(item, value);
return item;
}
cbor_item_t *cbor_build_float4(float value)
{
cbor_item_t *item = cbor_new_float4();
cbor_set_float4(item, value);
return item;
}
cbor_item_t *cbor_build_float8(double value)
{
cbor_item_t *item = cbor_new_float8();
cbor_set_float8(item, value);
return item;
}
cbor_item_t *cbor_build_ctrl(uint8_t value)
{
cbor_item_t *item = cbor_new_ctrl();
cbor_set_ctrl(item, value);
return item;
}

View File

@ -0,0 +1,203 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_FLOATS_CTRLS_H
#define LIBCBOR_FLOATS_CTRLS_H
#include "cbor/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* ============================================================================
* Float manipulation
* ============================================================================
*/
/** Is this a ctrl value?
*
* @param item[borrow] A float or ctrl item
* @return Is this a ctrl value?
*/
bool cbor_float_ctrl_is_ctrl(const cbor_item_t * item);
/** Get the float width
*
* @param item[borrow] A float or ctrl item
* @return The width.
*/
cbor_float_width cbor_float_get_width(const cbor_item_t * item);
/** Get a half precision float
*
* The item must have the corresponding width
*
* @param[borrow] A half precision float
* @return half precision value
*/
float cbor_float_get_float2(const cbor_item_t * item);
/** Get a single precision float
*
* The item must have the corresponding width
*
* @param[borrow] A signle precision float
* @return single precision value
*/
float cbor_float_get_float4(const cbor_item_t * item);
/** Get a double precision float
*
* The item must have the corresponding width
*
* @param[borrow] A double precision float
* @return double precision value
*/
double cbor_float_get_float8(const cbor_item_t * item);
/** Get the float value represented as double
*
* Can be used regardless of the width.
*
* @param[borrow] Any float
* @return double precision value
*/
double cbor_float_get_float(const cbor_item_t * item);
/** Constructs a new ctrl item
*
* The width cannot be changed once the item is created
*
* @return **new** 1B ctrl
*/
cbor_item_t * cbor_new_ctrl();
/** Constructs a new float item
*
* The width cannot be changed once the item is created
*
* @return **new** 2B float
*/
cbor_item_t * cbor_new_float2();
/** Constructs a new float item
*
* The width cannot be changed once the item is created
*
* @return **new** 4B float
*/
cbor_item_t * cbor_new_float4();
/** Constructs a new float item
*
* The width cannot be changed once the item is created
*
* @return **new** 8B float
*/
cbor_item_t * cbor_new_float8();
/** Constructs new null ctrl item
*
* @return **new** null ctrl item
*/
cbor_item_t * cbor_new_null();
/** Constructs new under ctrl item
*
* @return **new** under ctrl item
*/
cbor_item_t * cbor_new_undef();
/** Constructs new boolean ctrl item
*
* @param value The value to use
* @return **new** boolen ctrl item
*/
cbor_item_t * cbor_build_bool(bool value);
/** Assign a control value
*
* \rst
* .. warning:: It is possible to produce an invalid CBOR value by assigning a invalid value using this mechanism. Please consult the standard before use.
* \endrst
*
* @param item[borrow] A ctrl item
* @param value The simple value to assign. Please consult the standard for allowed values
*/
void cbor_set_ctrl(cbor_item_t * item, uint8_t value);
/** Assigns a float value
*
* @param item[borrow] A half precision float
* @param value The value to assign
*/
void cbor_set_float2(cbor_item_t * item, float value);
/** Assigns a float value
*
* @param item[borrow] A single precision float
* @param value The value to assign
*/
void cbor_set_float4(cbor_item_t * item, float value);
/** Assigns a float value
*
* @param item[borrow] A double precision float
* @param value The value to assign
*/
void cbor_set_float8(cbor_item_t * item, double value);
/** Reads the control value
*
* @param item[borrow] A ctrl item
* @return the simple value
*/
uint8_t cbor_ctrl_value(const cbor_item_t * item);
/** Is this ctrl item a boolean?
*
* @param item[borrow] A ctrl item
* @return Is this ctrl item a boolean?
*/
bool cbor_ctrl_is_bool(const cbor_item_t * item);
/** Constructs a new float
*
* @param value the value to use
* @return **new** float
*/
cbor_item_t *cbor_build_float2(float value);
/** Constructs a new float
*
* @param value the value to use
* @return **new** float
*/
cbor_item_t *cbor_build_float4(float value);
/** Constructs a new float
*
* @param value the value to use
* @return **new** float
*/
cbor_item_t *cbor_build_float8(double value);
/** Constructs a ctrl item
*
* @param value the value to use
* @return **new** ctrl item
*/
cbor_item_t *cbor_build_ctrl(uint8_t value);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_FLOATS_CTRLS_H

View File

@ -0,0 +1,359 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "builder_callbacks.h"
#include "unicode.h"
#include <string.h>
#include "../arrays.h"
#include "../bytestrings.h"
#include "../floats_ctrls.h"
#include "../ints.h"
#include "../maps.h"
#include "../strings.h"
#include "../tags.h"
void _cbor_builder_append(cbor_item_t *item, struct _cbor_decoder_context *ctx)
{
if (ctx->stack->size == 0) {
/* Top level item */
ctx->root = item;
} else {
/* Part of a bigger structure */
switch (ctx->stack->top->item->type) {
case CBOR_TYPE_ARRAY: {
if (cbor_array_is_definite(ctx->stack->top->item)) {
assert(ctx->stack->top->subitems > 0);
cbor_array_push(ctx->stack->top->item, item);
ctx->stack->top->subitems--;
if (ctx->stack->top->subitems == 0) {
cbor_item_t *item = ctx->stack->top->item;
_cbor_stack_pop(ctx->stack);
_cbor_builder_append(item, ctx);
}
cbor_decref(&item);
} else {
/* Indefinite array, don't bother with subitems */
cbor_array_push(ctx->stack->top->item, item);
cbor_decref(&item);
}
break;
}
case CBOR_TYPE_MAP: {
/* We use 0 and 1 subitems to distinguish between keys and values in indefinite items */
if (ctx->stack->top->subitems % 2) {
/* Odd record, this is a value */
_cbor_map_add_value(ctx->stack->top->item, cbor_move(item));
} else {
/* Even record, this is a key */
_cbor_map_add_key(ctx->stack->top->item, cbor_move(item));
}
if (cbor_map_is_definite(ctx->stack->top->item)) {
ctx->stack->top->subitems--;
if (ctx->stack->top->subitems == 0) {
cbor_item_t *item = ctx->stack->top->item;
_cbor_stack_pop(ctx->stack);
_cbor_builder_append(item, ctx);
}
} else {
ctx->stack->top->subitems ^= 1; /* Flip the indicator for indefinite items */
}
break;
}
case CBOR_TYPE_TAG: {
assert(ctx->stack->top->subitems == 1);
cbor_tag_set_item(ctx->stack->top->item, item);
cbor_decref(&item); /* Give up on our reference */
cbor_item_t *item = ctx->stack->top->item;
_cbor_stack_pop(ctx->stack);
_cbor_builder_append(item, ctx);
break;
}
default: {
cbor_decref(&item);
ctx->syntax_error = true;
}
}
}
}
#define CHECK_RES do { if (res == NULL) { ctx->creation_failed = true; return; } } while (0)
void cbor_builder_uint8_callback(void *context, uint8_t value)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_int8();
CHECK_RES;
cbor_mark_uint(res);
cbor_set_uint8(res, value);
_cbor_builder_append(res, ctx);
}
void cbor_builder_uint16_callback(void *context, uint16_t value)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_int16();
CHECK_RES;
cbor_mark_uint(res);
cbor_set_uint16(res, value);
_cbor_builder_append(res, ctx);
}
void cbor_builder_uint32_callback(void *context, uint32_t value)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_int32();
CHECK_RES;
cbor_mark_uint(res);
cbor_set_uint32(res, value);
_cbor_builder_append(res, ctx);
}
void cbor_builder_uint64_callback(void *context, uint64_t value)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_int64();
CHECK_RES;
cbor_mark_uint(res);
cbor_set_uint64(res, value);
_cbor_builder_append(res, ctx);
}
void cbor_builder_negint8_callback(void *context, uint8_t value)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_int8();
CHECK_RES;
cbor_mark_negint(res);
cbor_set_uint8(res, value);
_cbor_builder_append(res, ctx);
}
void cbor_builder_negint16_callback(void *context, uint16_t value)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_int16();
cbor_mark_negint(res);
cbor_set_uint16(res, value);
_cbor_builder_append(res, ctx);
}
void cbor_builder_negint32_callback(void *context, uint32_t value)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_int32();
CHECK_RES;
cbor_mark_negint(res);
cbor_set_uint32(res, value);
_cbor_builder_append(res, ctx);
}
void cbor_builder_negint64_callback(void *context, uint64_t value)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_int64();
CHECK_RES;
cbor_mark_negint(res);
cbor_set_uint64(res, value);
_cbor_builder_append(res, ctx);
}
void cbor_builder_byte_string_callback(void *context, cbor_data data, size_t length)
{
struct _cbor_decoder_context *ctx = context;
unsigned char *new_handle = _CBOR_MALLOC(length);
if (new_handle == NULL) {
ctx->creation_failed = true;
return;
}
memcpy(new_handle, data, length);
cbor_item_t *res = cbor_new_definite_bytestring();
if (res == NULL) {
_CBOR_FREE(new_handle);
ctx->creation_failed = true;
return;
}
cbor_bytestring_set_handle(res, new_handle, length);
if (ctx->stack->size > 0 && cbor_isa_bytestring(ctx->stack->top->item)) {
if (cbor_bytestring_is_indefinite(ctx->stack->top->item)) {
cbor_bytestring_add_chunk(ctx->stack->top->item, cbor_move(res));
} else {
cbor_decref(&res);
ctx->syntax_error = true;
}
} else {
_cbor_builder_append(res, ctx);
}
}
void cbor_builder_byte_string_start_callback(void *context)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_indefinite_bytestring();
CHECK_RES;
_cbor_stack_push(ctx->stack, res, 0);
}
void cbor_builder_string_callback(void *context, cbor_data data, size_t length)
{
struct _cbor_decoder_context *ctx = context;
struct _cbor_unicode_status unicode_status;
size_t codepoint_count = _cbor_unicode_codepoint_count(data, length, &unicode_status);
if (unicode_status.status == _CBOR_UNICODE_BADCP) {
ctx->syntax_error = true;
return;
}
unsigned char *new_handle = _CBOR_MALLOC(length);
if (new_handle == NULL) {
ctx->creation_failed = true;
return;
}
memcpy(new_handle, data, length);
cbor_item_t *res = cbor_new_definite_string();
cbor_string_set_handle(res, new_handle, length);
res->metadata.string_metadata.codepoint_count = codepoint_count;
/* Careful here: order matters */
if (ctx->stack->size > 0 && cbor_isa_string(ctx->stack->top->item)) {
if (cbor_string_is_indefinite(ctx->stack->top->item)) {
cbor_string_add_chunk(ctx->stack->top->item, cbor_move(res));
} else {
cbor_decref(&res);
ctx->syntax_error = true;
}
} else {
_cbor_builder_append(res, ctx);
}
}
void cbor_builder_string_start_callback(void *context)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_indefinite_string();
CHECK_RES;
_cbor_stack_push(ctx->stack, res, 0);
}
void cbor_builder_array_start_callback(void *context, size_t size)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_definite_array(size);
CHECK_RES;
if (size > 0) {
_cbor_stack_push(ctx->stack, res, size);
} else {
_cbor_builder_append(res, ctx);
}
}
void cbor_builder_indef_array_start_callback(void *context)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_indefinite_array();
CHECK_RES;
_cbor_stack_push(ctx->stack, res, 0);
}
void cbor_builder_indef_map_start_callback(void *context)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_indefinite_map();
CHECK_RES;
_cbor_stack_push(ctx->stack, res, 0);
}
void cbor_builder_map_start_callback(void *context, size_t size)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_definite_map(size);
CHECK_RES;
if (size > 0) {
_cbor_stack_push(ctx->stack, res, size * 2);
} else {
_cbor_builder_append(res, ctx);
}
}
void cbor_builder_indef_break_callback(void *context)
{
struct _cbor_decoder_context *ctx = context;
if (ctx->stack->size == 0) {
// TODO complain
} else {
cbor_item_t *item = ctx->stack->top->item;
_cbor_stack_pop(ctx->stack);
_cbor_builder_append(item, ctx);
}
}
void cbor_builder_float2_callback(void *context, float value)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_float2();
cbor_set_float2(res, value);
_cbor_builder_append(res, ctx);
}
void cbor_builder_float4_callback(void *context, float value)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_float4();
CHECK_RES;
cbor_set_float4(res, value);
_cbor_builder_append(res, ctx);
}
void cbor_builder_float8_callback(void *context, double value)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_float8();
CHECK_RES;
cbor_set_float8(res, value);
_cbor_builder_append(res, ctx);
}
void cbor_builder_null_callback(void *context)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_null();
CHECK_RES;
_cbor_builder_append(res, ctx);
}
void cbor_builder_undefined_callback(void *context)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_undef();
CHECK_RES;
_cbor_builder_append(res, ctx);
}
void cbor_builder_boolean_callback(void *context, bool value)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_build_bool(value);
CHECK_RES;
_cbor_builder_append(res, ctx);
}
void cbor_builder_tag_callback(void *context, uint64_t value)
{
struct _cbor_decoder_context *ctx = context;
cbor_item_t *res = cbor_new_tag(value);
CHECK_RES;
_cbor_stack_push(ctx->stack, res, 1);
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_BUILDER_CALLBACKS_H
#define LIBCBOR_BUILDER_CALLBACKS_H
#include "cbor/common.h"
#include "../callbacks.h"
#include "stack.h"
#ifdef __cplusplus
extern "C" {
#endif
/** High-level decoding context */
struct _cbor_decoder_context {
/** Callback creating the last item has failed */
bool creation_failed;
/** Stack expectation mismatch */
bool syntax_error;
cbor_item_t *root;
struct _cbor_stack *stack;
};
void cbor_builder_uint8_callback(void *, uint8_t);
void cbor_builder_uint16_callback(void *, uint16_t);
void cbor_builder_uint32_callback(void *, uint32_t);
void cbor_builder_uint64_callback(void *, uint64_t);
void cbor_builder_negint8_callback(void *, uint8_t);
void cbor_builder_negint16_callback(void *, uint16_t);
void cbor_builder_negint32_callback(void *, uint32_t);
void cbor_builder_negint64_callback(void *, uint64_t);
void cbor_builder_string_callback(void *, cbor_data, size_t);
void cbor_builder_string_start_callback(void *);
void cbor_builder_byte_string_callback(void *, cbor_data, size_t);
void cbor_builder_byte_string_start_callback(void *);
void cbor_builder_array_start_callback(void *, size_t);
void cbor_builder_indef_array_start_callback(void *);
void cbor_builder_map_start_callback(void *, size_t);
void cbor_builder_indef_map_start_callback(void *);
void cbor_builder_tag_callback(void *, uint64_t);
void cbor_builder_float2_callback(void *, float);
void cbor_builder_float4_callback(void *, float);
void cbor_builder_float8_callback(void *, double);
void cbor_builder_null_callback(void *);
void cbor_builder_undefined_callback(void *);
void cbor_builder_boolean_callback(void *, bool);
void cbor_builder_indef_break_callback(void *);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_BUILDER_CALLBACKS_H

View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "encoders.h"
#if HAVE_ENDIAN_H
#include <endian.h>
#endif
size_t _cbor_encode_uint8(uint8_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
{
if (value <= 23) {
if (buffer_size >= 1) {
buffer[0] = value + offset;
return 1;
}
} else {
if (buffer_size >= 2) {
buffer[0] = 0x18 + offset;
buffer[1] = value;
return 2;
}
}
return 0;
}
size_t _cbor_encode_uint16(uint16_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
{
if (buffer_size >= 3) {
buffer[0] = 0x19 + offset;
#ifdef HAVE_ENDIAN_H
*(uint16_t *) &buffer[1] = htobe16(value);
#else
#ifdef IS_BIG_ENDIAN
*(uint16_t *) &buffer[1] = value;
#else
buffer[1] = value >> 8;
buffer[2] = value;
#endif
#endif
return 3;
} else
return 0;
}
size_t _cbor_encode_uint32(uint32_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
{
if (buffer_size >= 5) {
buffer[0] = 0x1A + offset;
#ifdef HAVE_ENDIAN_H
*(uint32_t *) &buffer[1] = htobe32(value);
#else
#ifdef IS_BIG_ENDIAN
*(uint32_t *) &buffer[1] = value;
#else
buffer[1] = value >> 24;
buffer[2] = value >> 16;
buffer[3] = value >> 8;
buffer[4] = value;
#endif
#endif
return 5;
} else
return 0;
}
size_t _cbor_encode_uint64(uint64_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
{
if (buffer_size >= 9) {
buffer[0] = 0x1B + offset;
#ifdef HAVE_ENDIAN_H
*(uint64_t *) &buffer[1] = htobe64(value);
#else
#ifdef IS_BIG_ENDIAN
*(uint64_t *) &buffer[1] = value;
#else
buffer[1] = value >> 56;
buffer[2] = value >> 48;
buffer[3] = value >> 40;
buffer[4] = value >> 32;
buffer[5] = value >> 24;
buffer[6] = value >> 16;
buffer[7] = value >> 8;
buffer[8] = value;
#endif
#endif
return 9;
} else
return 0;
}
size_t _cbor_encode_uint(uint64_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset)
{
if (value <= UINT16_MAX) if (value <= UINT8_MAX)
return _cbor_encode_uint8((uint8_t) value, buffer, buffer_size, offset);
else
return _cbor_encode_uint16((uint16_t) value, buffer, buffer_size, offset);
else if (value <= UINT32_MAX)
return _cbor_encode_uint32((uint32_t) value, buffer, buffer_size, offset);
else
return _cbor_encode_uint64((uint64_t) value, buffer, buffer_size, offset);
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_ENCODERS_H
#define LIBCBOR_ENCODERS_H
#include "cbor/common.h"
#ifdef __cplusplus
extern "C" {
#endif
size_t _cbor_encode_uint8(uint8_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset);
size_t _cbor_encode_uint16(uint16_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset);
size_t _cbor_encode_uint32(uint32_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset);
size_t _cbor_encode_uint64(uint64_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset);
size_t _cbor_encode_uint(uint64_t value, unsigned char *buffer, size_t buffer_size, uint8_t offset);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_ENCODERS_H

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "loaders.h"
#include <math.h>
#ifdef HAVE_ENDIAN_H
#include <endian.h>
#endif
uint8_t _cbor_load_uint8(cbor_data source)
{
return (uint8_t) *source;
}
uint16_t _cbor_load_uint16(const unsigned char *source)
{
#ifdef HAVE_ENDIAN_H
return be16toh(*(uint16_t *) source);
#else
#ifdef IS_BIG_ENDIAN
return *(uint16_t *) source;
#else
return ((uint16_t) *(source + 0) << 8) +
(uint8_t) *(source + 1);
#endif
#endif
}
uint32_t _cbor_load_uint32(const unsigned char *source)
{
#ifdef HAVE_ENDIAN_H
return be32toh(*(uint32_t *) source);
#else
#ifdef IS_BIG_ENDIAN
return *(uint32_t *) source;
#else
return ((uint32_t) *(source + 0) << 0x18) +
((uint32_t) *(source + 1) << 0x10) +
((uint16_t) *(source + 2) << 0x08) +
(uint8_t) *(source + 3);
#endif
#endif
}
uint64_t _cbor_load_uint64(const unsigned char *source)
{
#ifdef HAVE_ENDIAN_H
return be64toh(*(uint64_t *) source);
#else
#ifdef IS_BIG_ENDIAN
return *(uint64_t *) source;
#else
return ((uint64_t) *(source + 0) << 0x38) +
((uint64_t) *(source + 1) << 0x30) +
((uint64_t) *(source + 2) << 0x28) +
((uint64_t) *(source + 3) << 0x20) +
((uint32_t) *(source + 4) << 0x18) +
((uint32_t) *(source + 5) << 0x10) +
((uint16_t) *(source + 6) << 0x08) +
(uint8_t) *(source + 7);
#endif
#endif
}
/* As per http://tools.ietf.org/html/rfc7049#appendix-D */
float _cbor_decode_half(unsigned char *halfp)
{
int half = (halfp[0] << 8) + halfp[1];
int exp = (half >> 10) & 0x1f;
int mant = half & 0x3ff;
double val;
if (exp == 0) val = ldexp(mant, -24);
else if (exp != 31) val = ldexp(mant + 1024, exp - 25);
else val = mant == 0 ? INFINITY : NAN;
return (float) (half & 0x8000 ? -val : val);
}
double _cbor_load_half(cbor_data source)
{
/* Discard const */
return _cbor_decode_half((unsigned char *) source);
}
float _cbor_load_float(cbor_data source)
{
union _cbor_float_helper helper = {.as_uint = _cbor_load_uint32(source)};
return helper.as_float;
}
double _cbor_load_double(cbor_data source)
{
union _cbor_double_helper helper = {.as_uint = _cbor_load_uint64(source)};
return helper.as_double;
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_LOADERS_H
#define LIBCBOR_LOADERS_H
#include "cbor/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Read the given uint from the given location, no questions asked */
uint8_t _cbor_load_uint8(const unsigned char *source);
uint16_t _cbor_load_uint16(const unsigned char *source);
uint32_t _cbor_load_uint32(const unsigned char *source);
uint64_t _cbor_load_uint64(const unsigned char *source);
double _cbor_load_half(cbor_data source);
float _cbor_load_float(cbor_data source);
double _cbor_load_double(cbor_data source);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_LOADERS_H

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "memory_utils.h"
#include "cbor/common.h"
// TODO: Consider builtins (https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html)
/** Highest on bit position */
size_t _cbor_highest_bit(size_t number)
{
size_t bit = 0;
while (number != 0) {
bit++;
number >>= 1;
}
return bit;
}
bool _cbor_safe_to_multiply(size_t a, size_t b)
{
return _cbor_highest_bit(a) + _cbor_highest_bit(b) <= sizeof(size_t) * 8;
}
void * _cbor_alloc_multiple(size_t item_size, size_t item_count)
{
if (_cbor_safe_to_multiply(item_size, item_count)) {
return _CBOR_MALLOC(item_size * item_count);
} else {
return NULL;
}
}
void * _cbor_realloc_multiple(void * pointer, size_t item_size, size_t item_count)
{
if (_cbor_safe_to_multiply(item_size, item_count)) {
return _CBOR_REALLOC(pointer, item_size * item_count);
} else {
return NULL;
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_MEMORY_UTILS_H
#define LIBCBOR_MEMORY_UTILS_H
#include <string.h>
#include <stdbool.h>
/** Can a and b be multiplied without overflowing size_t? */
bool _cbor_safe_to_multiply(size_t a, size_t b);
/** Overflow-proof contiguous array allocation
*
* @param item_size
* @param item_count
* @return Region of item_size * item_count bytes, or NULL if the total size overflows size_t or the underlying allocator failed
*/
void * _cbor_alloc_multiple(size_t item_size, size_t item_count);
/** Overflow-proof contiguous array reallocation
*
* This implements the OpenBSD `reallocarray` functionality.
*
* @param pointer
* @param item_size
* @param item_count
* @return Realloc'd of item_size * item_count bytes, or NULL if the total size overflows size_t or the underlying allocator failed
*/
void * _cbor_realloc_multiple(void * pointer, size_t item_size, size_t item_count);
#endif //LIBCBOR_MEMORY_UTILS_H

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "stack.h"
struct _cbor_stack _cbor_stack_init()
{
return (struct _cbor_stack) {.top = NULL, .size = 0};
}
void _cbor_stack_pop(struct _cbor_stack *stack)
{
struct _cbor_stack_record *top = stack->top;
stack->top = stack->top->lower;
_CBOR_FREE(top);
stack->size--;
}
struct _cbor_stack_record *_cbor_stack_push(struct _cbor_stack *stack, cbor_item_t *item, size_t subitems)
{
struct _cbor_stack_record *new_top = _CBOR_MALLOC(sizeof(struct _cbor_stack_record));
if (new_top == NULL)
return NULL;
*new_top = (struct _cbor_stack_record) {stack->top, item, subitems};
stack->top = new_top;
stack->size++;
return new_top;
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_STACK_H
#define LIBCBOR_STACK_H
#include "cbor/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Simple stack record for the parser */
struct _cbor_stack_record {
struct _cbor_stack_record *lower;
cbor_item_t *item;
size_t subitems;
};
/** Stack handle - contents and size */
struct _cbor_stack {
struct _cbor_stack_record *top;
size_t size;
};
struct _cbor_stack _cbor_stack_init();
void _cbor_stack_pop(struct _cbor_stack *);
struct _cbor_stack_record *_cbor_stack_push(struct _cbor_stack *, cbor_item_t *, size_t);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_STACK_H

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "unicode.h"
#define UTF8_ACCEPT 0
#define UTF8_REJECT 1
static const uint8_t utf8d[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 00..1f */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 20..3f */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40..5f */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 60..7f */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, /* 80..9f */
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* a0..bf */
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* c0..df */
0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, /* e0..ef */
0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, /* f0..ff */
0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, /* s0..s0 */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, /* s1..s2 */
1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, /* s3..s4 */
1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, /* s5..s6 */
1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* s7..s8 */
};
/* Copyright of this function: (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> */
/* See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. */
uint32_t _cbor_unicode_decode(uint32_t* state, uint32_t* codep, uint32_t byte) {
uint32_t type = utf8d[byte];
*codep = (*state != UTF8_ACCEPT) ?
(byte & 0x3fu) | (*codep << 6) :
(0xff >> type) & (byte);
*state = utf8d[256 + *state * 16 + type];
return *state;
}
size_t _cbor_unicode_codepoint_count(cbor_data source, size_t source_length, struct _cbor_unicode_status * status)
{
*status = (struct _cbor_unicode_status) { .location = 0, .status = _CBOR_UNICODE_OK };
uint32_t codepoint, state = UTF8_ACCEPT, res;
size_t pos = 0, count = 0;
for (; pos < source_length; pos++)
{
res = _cbor_unicode_decode(&state, &codepoint, source[pos]);
if (res == UTF8_ACCEPT) {
count++;
} else if (res == UTF8_REJECT) {
goto error;
}
}
/* Unfinished multibyte codepoint */
if (state != UTF8_ACCEPT)
goto error;
return count;
error:
*status = (struct _cbor_unicode_status) { .location = pos, .status = _CBOR_UNICODE_BADCP };
return -1;
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_UNICODE_H
#define LIBCBOR_UNICODE_H
#include "cbor/common.h"
#ifdef __cplusplus
extern "C" {
#endif
enum _cbor_unicode_status_error {
_CBOR_UNICODE_OK,
_CBOR_UNICODE_BADCP
};
/** Signals unicode validation error and possibly its location */
struct _cbor_unicode_status {
enum _cbor_unicode_status_error status;
size_t location;
};
size_t _cbor_unicode_codepoint_count(cbor_data source, size_t source_length, struct _cbor_unicode_status * status);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_UNICODE_H

207
lib/libcbor/src/cbor/ints.c Normal file
View File

@ -0,0 +1,207 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "ints.h"
cbor_int_width cbor_int_get_width(const cbor_item_t *item)
{
assert(cbor_is_int(item));
return item->metadata.int_metadata.width;
}
uint8_t cbor_get_uint8(const cbor_item_t *item)
{
assert(cbor_is_int(item));
assert(cbor_int_get_width(item) == CBOR_INT_8);
return *item->data;
}
uint16_t cbor_get_uint16(const cbor_item_t *item)
{
assert(cbor_is_int(item));
assert(cbor_int_get_width(item) == CBOR_INT_16);
return *(uint16_t *) item->data;
}
uint32_t cbor_get_uint32(const cbor_item_t *item)
{
assert(cbor_is_int(item));
assert(cbor_int_get_width(item) == CBOR_INT_32);
return *(uint32_t *) item->data;
}
uint64_t cbor_get_uint64(const cbor_item_t *item)
{
assert(cbor_is_int(item));
assert(cbor_int_get_width(item) == CBOR_INT_64);
return *(uint64_t *) item->data;
}
uint64_t cbor_get_int(const cbor_item_t * item)
{
assert(cbor_is_int(item));
switch(cbor_int_get_width(item)) {
case CBOR_INT_8: return cbor_get_uint8(item);
case CBOR_INT_16: return cbor_get_uint16(item);
case CBOR_INT_32: return cbor_get_uint32(item);
case CBOR_INT_64: return cbor_get_uint64(item);
}
return 0xDEADBEEF; /* Compiler complaints */
}
void cbor_set_uint8(cbor_item_t *item, uint8_t value)
{
assert(cbor_is_int(item));
assert(cbor_int_get_width(item) == CBOR_INT_8);
*item->data = value;
}
void cbor_set_uint16(cbor_item_t *item, uint16_t value)
{
assert(cbor_is_int(item));
assert(cbor_int_get_width(item) == CBOR_INT_16);
*(uint16_t *) item->data = value;
}
void cbor_set_uint32(cbor_item_t *item, uint32_t value)
{
assert(cbor_is_int(item));
assert(cbor_int_get_width(item) == CBOR_INT_32);
*(uint32_t *) item->data = value;
}
void cbor_set_uint64(cbor_item_t *item, uint64_t value)
{
assert(cbor_is_int(item));
assert(cbor_int_get_width(item) == CBOR_INT_64);
*(uint64_t *) item->data = value;
}
void cbor_mark_uint(cbor_item_t *item)
{
assert(cbor_is_int(item));
item->type = CBOR_TYPE_UINT;
}
void cbor_mark_negint(cbor_item_t *item)
{
assert(cbor_is_int(item));
item->type = CBOR_TYPE_NEGINT;
}
cbor_item_t *cbor_new_int8()
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 1);
*item = (cbor_item_t) {
.data = (unsigned char *) item + sizeof(cbor_item_t),
.refcount = 1,
.metadata = {.int_metadata = {.width = CBOR_INT_8}},
.type = CBOR_TYPE_UINT
};
return item;
}
cbor_item_t *cbor_new_int16()
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 2);
*item = (cbor_item_t) {
.data = (unsigned char *) item + sizeof(cbor_item_t),
.refcount = 1,
.metadata = {.int_metadata = {.width = CBOR_INT_16}},
.type = CBOR_TYPE_UINT
};
return item;
}
cbor_item_t *cbor_new_int32()
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 4);
*item = (cbor_item_t) {
.data = (unsigned char *) item + sizeof(cbor_item_t),
.refcount = 1,
.metadata = {.int_metadata = {.width = CBOR_INT_32}},
.type = CBOR_TYPE_UINT
};
return item;
}
cbor_item_t *cbor_new_int64()
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 8);
*item = (cbor_item_t) {
.data = (unsigned char *) item + sizeof(cbor_item_t),
.refcount = 1,
.metadata = {.int_metadata = {.width = CBOR_INT_64}},
.type = CBOR_TYPE_UINT
};
return item;
}
cbor_item_t *cbor_build_uint8(uint8_t value)
{
cbor_item_t *item = cbor_new_int8();
cbor_set_uint8(item, value);
cbor_mark_uint(item);
return item;
}
cbor_item_t *cbor_build_uint16(uint16_t value)
{
cbor_item_t *item = cbor_new_int16();
cbor_set_uint16(item, value);
cbor_mark_uint(item);
return item;
}
cbor_item_t *cbor_build_uint32(uint32_t value)
{
cbor_item_t *item = cbor_new_int32();
cbor_set_uint32(item, value);
cbor_mark_uint(item);
return item;
}
cbor_item_t *cbor_build_uint64(uint64_t value)
{
cbor_item_t *item = cbor_new_int64();
cbor_set_uint64(item, value);
cbor_mark_uint(item);
return item;
}
cbor_item_t *cbor_build_negint8(uint8_t value)
{
cbor_item_t *item = cbor_new_int8();
cbor_set_uint8(item, value);
cbor_mark_negint(item);
return item;
}
cbor_item_t *cbor_build_negint16(uint16_t value)
{
cbor_item_t *item = cbor_new_int16();
cbor_set_uint16(item, value);
cbor_mark_negint(item);
return item;
}
cbor_item_t *cbor_build_negint32(uint32_t value)
{
cbor_item_t *item = cbor_new_int32();
cbor_set_uint32(item, value);
cbor_mark_negint(item);
return item;
}
cbor_item_t *cbor_build_negint64(uint64_t value)
{
cbor_item_t *item = cbor_new_int64();
cbor_set_uint64(item, value);
cbor_mark_negint(item);
return item;
}

203
lib/libcbor/src/cbor/ints.h Normal file
View File

@ -0,0 +1,203 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_INTS_H
#define LIBCBOR_INTS_H
#include "cbor/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* ============================================================================
* Integer (uints and negints) manipulation
* ============================================================================
*/
/** Extracts the integer value
*
* @param item[borrow] positive or negative integer
* @return the value
*/
uint8_t cbor_get_uint8(const cbor_item_t *item);
/** Extracts the integer value
*
* @param item[borrow] positive or negative integer
* @return the value
*/
uint16_t cbor_get_uint16(const cbor_item_t *item);
/** Extracts the integer value
*
* @param item[borrow] positive or negative integer
* @return the value
*/
uint32_t cbor_get_uint32(const cbor_item_t *item);
/** Extracts the integer value
*
* @param item[borrow] positive or negative integer
* @return the value
*/
uint64_t cbor_get_uint64(const cbor_item_t *item);
/** Extracts the integer value
*
* @param item[borrow] positive or negative integer
* @return the value, extended to `uint64_t`
*/
uint64_t cbor_get_int(const cbor_item_t *item);
/** Assigns the integer value
*
* @param item[borrow] positive or negative integer item
* @param value the value to assign. For negative integer, the logical value is `-value - 1`
*/
void cbor_set_uint8(cbor_item_t *item, uint8_t value);
/** Assigns the integer value
*
* @param item[borrow] positive or negative integer item
* @param value the value to assign. For negative integer, the logical value is `-value - 1`
*/
void cbor_set_uint16(cbor_item_t *item, uint16_t value);
/** Assigns the integer value
*
* @param item[borrow] positive or negative integer item
* @param value the value to assign. For negative integer, the logical value is `-value - 1`
*/
void cbor_set_uint32(cbor_item_t *item, uint32_t value);
/** Assigns the integer value
*
* @param item[borrow] positive or negative integer item
* @param value the value to assign. For negative integer, the logical value is `-value - 1`
*/
void cbor_set_uint64(cbor_item_t *item, uint64_t value);
/** Queries the integer width
*
* @param item[borrow] positive or negative integer item
* @return the width
*/
cbor_int_width cbor_int_get_width(const cbor_item_t *item);
/** Marks the integer item as a positive integer
*
* The data value is not changed
*
* @param item[borrow] positive or negative integer item
*/
void cbor_mark_uint(cbor_item_t *item);
/** Marks the integer item as a negative integer
*
* The data value is not changed
*
* @param item[borrow] positive or negative integer item
*/
void cbor_mark_negint(cbor_item_t *item);
/** Allocates new integer with 1B width
*
* The width cannot be changed once allocated
*
* @return **new** positive integer. The value is not initialized.
*/
cbor_item_t *cbor_new_int8();
/** Allocates new integer with 2B width
*
* The width cannot be changed once allocated
*
* @return **new** positive integer. The value is not initialized.
*/
cbor_item_t *cbor_new_int16();
/** Allocates new integer with 4B width
*
* The width cannot be changed once allocated
*
* @return **new** positive integer. The value is not initialized.
*/
cbor_item_t *cbor_new_int32();
/** Allocates new integer with 8B width
*
* The width cannot be changed once allocated
*
* @return **new** positive integer. The value is not initialized.
*/
cbor_item_t *cbor_new_int64();
/** Constructs a new positive integer
*
* @param value the value to use
* @return **new** positive integer
*/
cbor_item_t *cbor_build_uint8(uint8_t value);
/** Constructs a new positive integer
*
* @param value the value to use
* @return **new** positive integer
*/
cbor_item_t *cbor_build_uint16(uint16_t value);
/** Constructs a new positive integer
*
* @param value the value to use
* @return **new** positive integer
*/
cbor_item_t *cbor_build_uint32(uint32_t value);
/** Constructs a new positive integer
*
* @param value the value to use
* @return **new** positive integer
*/
cbor_item_t *cbor_build_uint64(uint64_t value);
/** Constructs a new negative integer
*
* @param value the value to use
* @return **new** negative integer
*/
cbor_item_t *cbor_build_negint8(uint8_t value);
/** Constructs a new negative integer
*
* @param value the value to use
* @return **new** negative integer
*/
cbor_item_t *cbor_build_negint16(uint16_t value);
/** Constructs a new negative integer
*
* @param value the value to use
* @return **new** negative integer
*/
cbor_item_t *cbor_build_negint32(uint32_t value);
/** Constructs a new negative integer
*
* @param value the value to use
* @return **new** negative integer
*/
cbor_item_t *cbor_build_negint64(uint64_t value);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_INTS_H

141
lib/libcbor/src/cbor/maps.c Normal file
View File

@ -0,0 +1,141 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "maps.h"
#include "internal/memory_utils.h"
size_t cbor_map_size(const cbor_item_t *item)
{
assert(cbor_isa_map(item));
return item->metadata.map_metadata.end_ptr;
}
size_t cbor_map_allocated(const cbor_item_t *item)
{
assert(cbor_isa_map(item));
return item->metadata.map_metadata.allocated;
}
cbor_item_t *cbor_new_definite_map(size_t size)
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
if (item == NULL) {
return NULL;
}
*item = (cbor_item_t) {
.refcount = 1,
.type = CBOR_TYPE_MAP,
.metadata = {.map_metadata = {
.allocated = size,
.type = _CBOR_METADATA_DEFINITE,
.end_ptr = 0
}},
.data = _cbor_alloc_multiple(sizeof(struct cbor_pair), size)
};
if (item->data == NULL) {
_CBOR_FREE(item);
return NULL;
}
return item;
}
cbor_item_t *cbor_new_indefinite_map()
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
if (item == NULL)
return NULL;
*item = (cbor_item_t) {
.refcount = 1,
.type = CBOR_TYPE_MAP,
.metadata = {.map_metadata = {
.allocated = 0,
.type = _CBOR_METADATA_INDEFINITE,
.end_ptr = 0
}},
.data = NULL
};
return item;
}
bool _cbor_map_add_key(cbor_item_t *item, cbor_item_t *key)
{
assert(cbor_isa_map(item));
struct _cbor_map_metadata *metadata = (struct _cbor_map_metadata *) &item->metadata;
if (cbor_map_is_definite(item)) {
struct cbor_pair *data = cbor_map_handle(item);
if (metadata->end_ptr >= metadata->allocated) {
/* Don't realloc definite preallocated map */
return false;
}
data[metadata->end_ptr].key = key;
data[metadata->end_ptr++].value = NULL;
} else {
if (metadata->end_ptr >= metadata->allocated) {
/* Exponential realloc */
// Check for overflows first
if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) {
return false;
}
size_t new_allocation = metadata->allocated == 0 ? 1 : CBOR_BUFFER_GROWTH * metadata->allocated;
unsigned char * new_data = _cbor_realloc_multiple(item->data, sizeof(struct cbor_pair), new_allocation);
if (new_data == NULL) {
return false;
}
item->data = new_data;
metadata->allocated = new_allocation;
}
struct cbor_pair *data = cbor_map_handle(item);
data[metadata->end_ptr].key = key;
data[metadata->end_ptr++].value = NULL;
}
cbor_incref(key);
return true;
}
bool _cbor_map_add_value(cbor_item_t *item, cbor_item_t *value)
{
assert(cbor_isa_map(item));
cbor_incref(value);
cbor_map_handle(item)[
/* Move one back since we are assuming _add_key (which increased the ptr)
* was the previous operation on this object */
item->metadata.map_metadata.end_ptr - 1
].value = value;
return true;
}
bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair)
{
assert(cbor_isa_map(item));
if (!_cbor_map_add_key(item, pair.key))
return false;
return _cbor_map_add_value(item, pair.value);
}
bool cbor_map_is_definite(const cbor_item_t *item)
{
assert(cbor_isa_map(item));
return item->metadata.map_metadata.type == _CBOR_METADATA_DEFINITE;
}
bool cbor_map_is_indefinite(const cbor_item_t *item)
{
return !cbor_map_is_definite(item);
}
struct cbor_pair *cbor_map_handle(const cbor_item_t *item)
{
assert(cbor_isa_map(item));
return (struct cbor_pair *) item->data;
}

107
lib/libcbor/src/cbor/maps.h Normal file
View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_MAPS_H
#define LIBCBOR_MAPS_H
#include "cbor/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* ============================================================================
* Map manipulation
* ============================================================================
*/
/** Get the number of pairs
*
* @param item[borrow] A map
* @return The number of pairs
*/
size_t cbor_map_size(const cbor_item_t *item);
/** Get the size of the allocated storage
*
* @param item[borrow] A map
* @return Allocated storage size (as the number of #cbor_pair items)
*/
size_t cbor_map_allocated(const cbor_item_t *item);
/** Create a new definite map
*
* @param size The number of slots to preallocate
* @return **new** definite map. `NULL` on malloc failure.
*/
cbor_item_t *cbor_new_definite_map(size_t size);
/** Create a new indefinite map
*
* @param size The number of slots to preallocate
* @return **new** definite map. `NULL` on malloc failure.
*/
cbor_item_t *cbor_new_indefinite_map();
/** Add a pair to the map
*
* For definite maps, items can only be added to the preallocated space. For indefinite
* maps, the storage will be expanded as needed
*
* @param item[borrow] A map
* @param pair[incref] The key-value pair to add (incref is member-wise)
* @return `true` on success, `false` if either reallocation failed or the preallcoated storage is full
*/
bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair);
/** Add a key to the map
*
* Sets the value to `NULL`. Internal API.
*
* @param item[borrow] A map
* @param key[incref] The key
* @return `true` on success, `false` if either reallocation failed or the preallcoated storage is full
*/
bool _cbor_map_add_key(cbor_item_t *item, cbor_item_t *key);
/** Add a value to the map
*
* Assumes that #_cbor_map_add_key has been called. Internal API.
*
* @param item[borrow] A map
* @param key[incref] The value
* @return `true` on success, `false` if either reallocation failed or the preallcoated storage is full
*/
bool _cbor_map_add_value(cbor_item_t *item, cbor_item_t *value);
/** Is this map definite?
*
* @param item[borrow] A map
* @return Is this map definite?
*/
bool cbor_map_is_definite(const cbor_item_t *item);
/** Is this map indefinite?
*
* @param item[borrow] A map
* @return Is this map indefinite?
*/
bool cbor_map_is_indefinite(const cbor_item_t *item);
/** Get the pairs storage
*
* @param item[borrow] A map
* @return Array of #cbor_map_size pairs. Manipulation is possible as long as references remain valid.
*/
struct cbor_pair *cbor_map_handle(const cbor_item_t *item);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_MAPS_H

View File

@ -0,0 +1,287 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "serialization.h"
#include "encoding.h"
#include "cbor/arrays.h"
#include "cbor/bytestrings.h"
#include "cbor/floats_ctrls.h"
#include "cbor/ints.h"
#include "cbor/maps.h"
#include "cbor/strings.h"
#include "cbor/tags.h"
#include "internal/memory_utils.h"
#include <string.h>
size_t cbor_serialize(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
{
switch (cbor_typeof(item)) {
case CBOR_TYPE_UINT:
return cbor_serialize_uint(item, buffer, buffer_size);
case CBOR_TYPE_NEGINT:
return cbor_serialize_negint(item, buffer, buffer_size);
case CBOR_TYPE_BYTESTRING:
return cbor_serialize_bytestring(item, buffer, buffer_size);
case CBOR_TYPE_STRING:
return cbor_serialize_string(item, buffer, buffer_size);
case CBOR_TYPE_ARRAY:
return cbor_serialize_array(item, buffer, buffer_size);
case CBOR_TYPE_MAP:
return cbor_serialize_map(item, buffer, buffer_size);
case CBOR_TYPE_TAG:
return cbor_serialize_tag(item, buffer, buffer_size);
case CBOR_TYPE_FLOAT_CTRL:
return cbor_serialize_float_ctrl(item, buffer, buffer_size);
default:
return 0;
}
}
size_t cbor_serialize_alloc(const cbor_item_t * item,
unsigned char ** buffer,
size_t * buffer_size)
{
size_t bfr_size = 32;
unsigned char * bfr = _CBOR_MALLOC(bfr_size), * tmp_bfr;
if (bfr == NULL) {
return 0;
}
size_t written;
/* This is waaay too optimistic - figure out something smarter (eventually) */
while ((written = cbor_serialize(item, bfr, bfr_size)) == 0) {
if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, bfr_size)) {
_CBOR_FREE(bfr);
return 0;
}
tmp_bfr = _CBOR_REALLOC(bfr, bfr_size *= 2);
if (tmp_bfr == NULL) {
_CBOR_FREE(bfr);
return 0;
}
bfr = tmp_bfr;
}
*buffer = bfr;
*buffer_size = bfr_size;
return written;
}
size_t cbor_serialize_uint(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
{
assert(cbor_isa_uint(item));
switch (cbor_int_get_width(item)) {
case CBOR_INT_8:
return cbor_encode_uint8(cbor_get_uint8(item), buffer, buffer_size);
case CBOR_INT_16:
return cbor_encode_uint16(cbor_get_uint16(item), buffer, buffer_size);
case CBOR_INT_32:
return cbor_encode_uint32(cbor_get_uint32(item), buffer, buffer_size);
case CBOR_INT_64:
return cbor_encode_uint64(cbor_get_uint64(item), buffer, buffer_size);
default:
return 0;
}
}
size_t cbor_serialize_negint(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
{
assert(cbor_isa_negint(item));
switch (cbor_int_get_width(item)) {
case CBOR_INT_8:
return cbor_encode_negint8(cbor_get_uint8(item), buffer, buffer_size);
case CBOR_INT_16:
return cbor_encode_negint16(cbor_get_uint16(item), buffer, buffer_size);
case CBOR_INT_32:
return cbor_encode_negint32(cbor_get_uint32(item), buffer, buffer_size);
case CBOR_INT_64:
return cbor_encode_negint64(cbor_get_uint64(item), buffer, buffer_size);
default:
return 0;
}
}
size_t cbor_serialize_bytestring(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
{
assert(cbor_isa_bytestring(item));
if (cbor_bytestring_is_definite(item)) {
size_t length = cbor_bytestring_length(item);
size_t written = cbor_encode_bytestring_start(length, buffer, buffer_size);
if (written && (buffer_size - written >= length)) {
memcpy(buffer + written, cbor_bytestring_handle(item), length);
return written + length;
} else
return 0;
} else {
assert(cbor_bytestring_is_indefinite(item));
size_t chunk_count = cbor_bytestring_chunk_count(item);
size_t written = cbor_encode_indef_bytestring_start(buffer, buffer_size);
if (written == 0)
return 0;
cbor_item_t **chunks = cbor_bytestring_chunks_handle(item);
for (size_t i = 0; i < chunk_count; i++) {
size_t chunk_written = cbor_serialize_bytestring(chunks[i], buffer + written, buffer_size - written);
if (chunk_written == 0)
return 0;
else
written += chunk_written;
}
if (cbor_encode_break(buffer + written, buffer_size - written) > 0)
return written + 1;
else
return 0;
}
}
size_t cbor_serialize_string(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
{
assert(cbor_isa_string(item));
if (cbor_string_is_definite(item)) {
size_t length = cbor_string_length(item);
size_t written = cbor_encode_string_start(length, buffer, buffer_size);
if (written && (buffer_size - written >= length)) {
memcpy(buffer + written, cbor_string_handle(item), length);
return written + length;
} else
return 0;
} else {
assert(cbor_string_is_indefinite(item));
size_t chunk_count = cbor_string_chunk_count(item);
size_t written = cbor_encode_indef_string_start(buffer, buffer_size);
if (written == 0)
return 0;
cbor_item_t **chunks = cbor_string_chunks_handle(item);
for (size_t i = 0; i < chunk_count; i++) {
size_t chunk_written = cbor_serialize_string(chunks[i], buffer + written, buffer_size - written);
if (chunk_written == 0)
return 0;
else
written += chunk_written;
}
if (cbor_encode_break(buffer + written, buffer_size - written) > 0)
return written + 1;
else
return 0;
}
}
size_t cbor_serialize_array(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
{
assert(cbor_isa_array(item));
size_t size = cbor_array_size(item),
written = 0;
cbor_item_t **handle = cbor_array_handle(item);
if (cbor_array_is_definite(item)) {
written = cbor_encode_array_start(size, buffer, buffer_size);
} else {
assert(cbor_array_is_indefinite(item));
written = cbor_encode_indef_array_start(buffer, buffer_size);
}
if (written == 0)
return 0;
size_t item_written;
for (size_t i = 0; i < size; i++) {
item_written = cbor_serialize(*(handle++), buffer + written, buffer_size - written);
if (item_written == 0)
return 0;
else
written += item_written;
}
if (cbor_array_is_definite(item)) {
return written;
} else {
assert(cbor_array_is_indefinite(item));
item_written = cbor_encode_break(buffer + written, buffer_size - written);
if (item_written == 0)
return 0;
else
return written + 1;
}
}
size_t cbor_serialize_map(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
{
assert(cbor_isa_map(item));
size_t size = cbor_map_size(item),
written = 0;
struct cbor_pair * handle = cbor_map_handle(item);
if (cbor_map_is_definite(item)) {
written = cbor_encode_map_start(size, buffer, buffer_size);
} else {
assert(cbor_map_is_indefinite(item));
written = cbor_encode_indef_map_start(buffer, buffer_size);
}
if (written == 0)
return 0;
size_t item_written;
for (size_t i = 0; i < size; i++) {
item_written = cbor_serialize(handle->key, buffer + written, buffer_size - written);
if (item_written == 0)
return 0;
else
written += item_written;
item_written = cbor_serialize((handle++)->value, buffer + written, buffer_size - written);
if (item_written == 0)
return 0;
else
written += item_written;
}
if (cbor_map_is_definite(item)) {
return written;
} else {
assert(cbor_map_is_indefinite(item));
item_written = cbor_encode_break(buffer + written, buffer_size - written);
if (item_written == 0)
return 0;
else
return written + 1;
}
}
size_t cbor_serialize_tag(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
{
assert(cbor_isa_tag(item));
size_t written = cbor_encode_tag(cbor_tag_value(item), buffer, buffer_size);
if (written == 0)
return 0;
size_t item_written = cbor_serialize(cbor_tag_item(item), buffer + written, buffer_size - written);
if (item_written == 0)
return 0;
else
return written + item_written;
}
size_t cbor_serialize_float_ctrl(const cbor_item_t *item, unsigned char *buffer, size_t buffer_size)
{
assert(cbor_isa_float_ctrl(item));
switch (cbor_float_get_width(item)) {
case CBOR_FLOAT_0:
/* CTRL - special treatment */
return cbor_encode_ctrl(cbor_ctrl_value(item), buffer, buffer_size);
case CBOR_FLOAT_16:
return cbor_encode_half(cbor_float_get_float2(item), buffer, buffer_size);
case CBOR_FLOAT_32:
return cbor_encode_single(cbor_float_get_float4(item), buffer, buffer_size);
case CBOR_FLOAT_64:
return cbor_encode_double(cbor_float_get_float8(item), buffer, buffer_size);
}
/* Should never happen - make the compiler happy */
return 0;
}

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_SERIALIZATION_H
#define LIBCBOR_SERIALIZATION_H
#include "cbor/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* ============================================================================
* High level encoding
* ============================================================================
*/
/** Serialize the given item
*
* @param item[borrow] A data item
* @param buffer Buffer to serialize to
* @param buffer_size Size of the \p buffer
* @return Length of the result. 0 on failure.
*/
size_t cbor_serialize(const cbor_item_t * item, cbor_mutable_data buffer, size_t buffer_size);
/** Serialize the given item, allocating buffers as needed
*
* \rst
* .. warning:: It is your responsibility to free the buffer using an appropriate ``free`` implementation.
* \endrst
*
* @param item[borrow] A data item
* @param buffer[out] Buffer containing the result
* @param buffer_size[out] Size of the \p buffer
* @return Length of the result. 0 on failure, in which case \p buffer is ``NULL``.
*/
size_t cbor_serialize_alloc(const cbor_item_t * item, cbor_mutable_data * buffer, size_t * buffer_size);
/** Serialize an uint
*
* @param item[borrow] A uint
* @param buffer Buffer to serialize to
* @param buffer_size Size of the \p buffer
* @return Length of the result. 0 on failure.
*/
size_t cbor_serialize_uint(const cbor_item_t *, cbor_mutable_data, size_t);
/** Serialize a negint
*
* @param item[borrow] A neging
* @param buffer Buffer to serialize to
* @param buffer_size Size of the \p buffer
* @return Length of the result. 0 on failure.
*/
size_t cbor_serialize_negint(const cbor_item_t *, cbor_mutable_data, size_t);
/** Serialize a bytestring
*
* @param item[borrow] A bytestring
* @param buffer Buffer to serialize to
* @param buffer_size Size of the \p buffer
* @return Length of the result. 0 on failure.
*/
size_t cbor_serialize_bytestring(const cbor_item_t *, cbor_mutable_data, size_t);
/** Serialize a string
*
* @param item[borrow] A string
* @param buffer Buffer to serialize to
* @param buffer_size Size of the \p buffer
* @return Length of the result. 0 on failure.
*/
size_t cbor_serialize_string(const cbor_item_t *, cbor_mutable_data, size_t);
/** Serialize an array
*
* @param item[borrow] An array
* @param buffer Buffer to serialize to
* @param buffer_size Size of the \p buffer
* @return Length of the result. 0 on failure.
*/
size_t cbor_serialize_array(const cbor_item_t *, cbor_mutable_data, size_t);
/** Serialize a map
*
* @param item[borrow] A map
* @param buffer Buffer to serialize to
* @param buffer_size Size of the \p buffer
* @return Length of the result. 0 on failure.
*/
size_t cbor_serialize_map(const cbor_item_t *, cbor_mutable_data, size_t);
/** Serialize a tag
*
* @param item[borrow] A tag
* @param buffer Buffer to serialize to
* @param buffer_size Size of the \p buffer
* @return Length of the result. 0 on failure.
*/
size_t cbor_serialize_tag(const cbor_item_t *, cbor_mutable_data, size_t);
/** Serialize a
*
* @param item[borrow] A float or ctrl
* @param buffer Buffer to serialize to
* @param buffer_size Size of the \p buffer
* @return Length of the result. 0 on failure.
*/
size_t cbor_serialize_float_ctrl(const cbor_item_t *, cbor_mutable_data, size_t);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_SERIALIZATION_H

View File

@ -0,0 +1,684 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "streaming.h"
#include "internal/loaders.h"
bool static _cbor_claim_bytes(size_t required,
size_t provided, struct cbor_decoder_result *result)
{
if (required > (provided - result->read)) {
/* We need to keep all the metadata if parsing is to be resumed */
result->read = 0;
result->status = CBOR_DECODER_NEDATA;
return false;
} else {
result->read += required;
return true;
}
}
struct cbor_decoder_result cbor_stream_decode(cbor_data source, size_t source_size,
const struct cbor_callbacks *callbacks,
void *context)
{
/* If we have no data, we cannot read even the MTB */
if (source_size < 1) {
return (struct cbor_decoder_result) {0, CBOR_DECODER_EBUFFER};
}
/* If we have a byte, assume it's the MTB */
struct cbor_decoder_result result = {1, CBOR_DECODER_FINISHED};
switch (*source) {
case 0x00: /* Fallthrough */
case 0x01: /* Fallthrough */
case 0x02: /* Fallthrough */
case 0x03: /* Fallthrough */
case 0x04: /* Fallthrough */
case 0x05: /* Fallthrough */
case 0x06: /* Fallthrough */
case 0x07: /* Fallthrough */
case 0x08: /* Fallthrough */
case 0x09: /* Fallthrough */
case 0x0A: /* Fallthrough */
case 0x0B: /* Fallthrough */
case 0x0C: /* Fallthrough */
case 0x0D: /* Fallthrough */
case 0x0E: /* Fallthrough */
case 0x0F: /* Fallthrough */
case 0x10: /* Fallthrough */
case 0x11: /* Fallthrough */
case 0x12: /* Fallthrough */
case 0x13: /* Fallthrough */
case 0x14: /* Fallthrough */
case 0x15: /* Fallthrough */
case 0x16: /* Fallthrough */
case 0x17:
/* Embedded one byte unsigned integer */
{
callbacks->uint8(context, _cbor_load_uint8(source));
return result;
}
case 0x18:
/* One byte unsigned integer */
{
if (_cbor_claim_bytes(1, source_size, &result)) {
callbacks->uint8(context, _cbor_load_uint8(source + 1));
}
return result;
}
case 0x19:
/* Two bytes unsigned integer */
{
if (_cbor_claim_bytes(2, source_size, &result)) {
callbacks->uint16(context, _cbor_load_uint16(source + 1));
}
return result;
}
case 0x1A:
/* Four bytes unsigned integer */
{
if (_cbor_claim_bytes(4, source_size, &result)) {
callbacks->uint32(context, _cbor_load_uint32(source + 1));
}
return result;
}
case 0x1B:
/* Eight bytes unsigned integer */
{
if (_cbor_claim_bytes(8, source_size, &result)) {
callbacks->uint64(context, _cbor_load_uint64(source + 1));
}
return result;
}
case 0x1C: /* Fallthrough */
case 0x1D: /* Fallthrough */
case 0x1E: /* Fallthrough */
case 0x1F:
/* Reserved */
{
return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
}
case 0x20: /* Fallthrough */
case 0x21: /* Fallthrough */
case 0x22: /* Fallthrough */
case 0x23: /* Fallthrough */
case 0x24: /* Fallthrough */
case 0x25: /* Fallthrough */
case 0x26: /* Fallthrough */
case 0x27: /* Fallthrough */
case 0x28: /* Fallthrough */
case 0x29: /* Fallthrough */
case 0x2A: /* Fallthrough */
case 0x2B: /* Fallthrough */
case 0x2C: /* Fallthrough */
case 0x2D: /* Fallthrough */
case 0x2E: /* Fallthrough */
case 0x2F: /* Fallthrough */
case 0x30: /* Fallthrough */
case 0x31: /* Fallthrough */
case 0x32: /* Fallthrough */
case 0x33: /* Fallthrough */
case 0x34: /* Fallthrough */
case 0x35: /* Fallthrough */
case 0x36: /* Fallthrough */
case 0x37:
/* Embedded one byte negative integer */
{
callbacks->negint8(context, _cbor_load_uint8(source) - 0x20); /* 0x20 offset */
return result;
}
case 0x38:
/* One byte negative integer */
{
if (_cbor_claim_bytes(1, source_size, &result)) {
callbacks->negint8(context, _cbor_load_uint8(source + 1));
}
return result;
}
case 0x39:
/* Two bytes negative integer */
{
if (_cbor_claim_bytes(2, source_size, &result)) {
callbacks->negint16(context, _cbor_load_uint16(source + 1));
}
return result;
}
case 0x3A:
/* Four bytes negative integer */
{
if (_cbor_claim_bytes(4, source_size, &result)) {
callbacks->negint32(context, _cbor_load_uint32(source + 1));
}
return result;
}
case 0x3B:
/* Eight bytes negative integer */
{
if (_cbor_claim_bytes(8, source_size, &result)) {
callbacks->negint64(context, _cbor_load_uint64(source + 1));
}
return result;
}
case 0x3C: /* Fallthrough */
case 0x3D: /* Fallthrough */
case 0x3E: /* Fallthrough */
case 0x3F:
/* Reserved */
{
return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
}
case 0x40: /* Fallthrough */
case 0x41: /* Fallthrough */
case 0x42: /* Fallthrough */
case 0x43: /* Fallthrough */
case 0x44: /* Fallthrough */
case 0x45: /* Fallthrough */
case 0x46: /* Fallthrough */
case 0x47: /* Fallthrough */
case 0x48: /* Fallthrough */
case 0x49: /* Fallthrough */
case 0x4A: /* Fallthrough */
case 0x4B: /* Fallthrough */
case 0x4C: /* Fallthrough */
case 0x4D: /* Fallthrough */
case 0x4E: /* Fallthrough */
case 0x4F: /* Fallthrough */
case 0x50: /* Fallthrough */
case 0x51: /* Fallthrough */
case 0x52: /* Fallthrough */
case 0x53: /* Fallthrough */
case 0x54: /* Fallthrough */
case 0x55: /* Fallthrough */
case 0x56: /* Fallthrough */
case 0x57:
/* Embedded length byte string */
{
size_t length = (size_t) _cbor_load_uint8(source) - 0x40; /* 0x40 offset */
if (_cbor_claim_bytes(length, source_size, &result)) {
callbacks->byte_string(context, source + 1, length);
}
return result;
}
case 0x58:
/* One byte length byte string */
// TODO template this?
{
if (_cbor_claim_bytes(1, source_size, &result)) {
size_t length = (size_t) _cbor_load_uint8(source + 1);
if (_cbor_claim_bytes(length, source_size, &result)) {
callbacks->byte_string(context, source + 1 + 1, length);
}
}
return result;
}
case 0x59:
/* Two bytes length byte string */
{
if (_cbor_claim_bytes(2, source_size, &result)) {
size_t length = (size_t) _cbor_load_uint16(source + 1);
if (_cbor_claim_bytes(length, source_size, &result)) {
callbacks->byte_string(context, source + 1 + 2, length);
}
}
return result;
}
case 0x5A:
/* Four bytes length byte string */
{
if (_cbor_claim_bytes(4, source_size, &result)) {
size_t length = (size_t) _cbor_load_uint32(source + 1);
if (_cbor_claim_bytes(length, source_size, &result)) {
callbacks->byte_string(context, source + 1 + 4, length);
}
}
return result;
}
case 0x5B:
/* Eight bytes length byte string */
{
if (_cbor_claim_bytes(8, source_size, &result)) {
size_t length = (size_t) _cbor_load_uint64(source + 1);
if (_cbor_claim_bytes(length, source_size, &result)) {
callbacks->byte_string(context, source + 1 + 8, length);
}
}
return result;
}
case 0x5C: /* Fallthrough */
case 0x5D: /* Fallthrough */
case 0x5E:
/* Reserved */
{
return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
}
case 0x5F:
/* Indefinite byte string */
{
callbacks->byte_string_start(context);
return result;
}
case 0x60: /* Fallthrough */
case 0x61: /* Fallthrough */
case 0x62: /* Fallthrough */
case 0x63: /* Fallthrough */
case 0x64: /* Fallthrough */
case 0x65: /* Fallthrough */
case 0x66: /* Fallthrough */
case 0x67: /* Fallthrough */
case 0x68: /* Fallthrough */
case 0x69: /* Fallthrough */
case 0x6A: /* Fallthrough */
case 0x6B: /* Fallthrough */
case 0x6C: /* Fallthrough */
case 0x6D: /* Fallthrough */
case 0x6E: /* Fallthrough */
case 0x6F: /* Fallthrough */
case 0x70: /* Fallthrough */
case 0x71: /* Fallthrough */
case 0x72: /* Fallthrough */
case 0x73: /* Fallthrough */
case 0x74: /* Fallthrough */
case 0x75: /* Fallthrough */
case 0x76: /* Fallthrough */
case 0x77:
/* Embedded one byte length string */
{
size_t length = (size_t) _cbor_load_uint8(source) - 0x60; /* 0x60 offset */
if (_cbor_claim_bytes(length, source_size, &result)) {
callbacks->string(context, source + 1, length);
}
return result;
}
case 0x78:
/* One byte length string */
{
if (_cbor_claim_bytes(1, source_size, &result)) {
size_t length = (size_t) _cbor_load_uint8(source + 1);
if (_cbor_claim_bytes(length, source_size, &result)) {
callbacks->string(context, source + 1 + 1, length);
}
}
return result;
}
case 0x79:
/* Two bytes length string */
{
if (_cbor_claim_bytes(2, source_size, &result)) {
size_t length = (size_t) _cbor_load_uint16(source + 1);
if (_cbor_claim_bytes(length, source_size, &result)) {
callbacks->string(context, source + 1 + 2, length);
}
}
return result;
}
case 0x7A:
/* Four bytes length string */
{
if (_cbor_claim_bytes(4, source_size, &result)) {
size_t length = (size_t) _cbor_load_uint32(source + 1);
if (_cbor_claim_bytes(length, source_size, &result)) {
callbacks->string(context, source + 1 + 4, length);
}
}
return result;
}
case 0x7B:
/* Eight bytes length string */
{
if (_cbor_claim_bytes(8, source_size, &result)) {
size_t length = (size_t) _cbor_load_uint64(source + 1);
if (_cbor_claim_bytes(length, source_size, &result)) {
callbacks->string(context, source + 1 + 8, length);
}
}
return result;
}
case 0x7C: /* Fallthrough */
case 0x7D: /* Fallthrough */
case 0x7E:
/* Reserved */
{
return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
}
case 0x7F:
/* Indefinite length string */
{
callbacks->string_start(context);
return result;
}
case 0x80: /* Fallthrough */
case 0x81: /* Fallthrough */
case 0x82: /* Fallthrough */
case 0x83: /* Fallthrough */
case 0x84: /* Fallthrough */
case 0x85: /* Fallthrough */
case 0x86: /* Fallthrough */
case 0x87: /* Fallthrough */
case 0x88: /* Fallthrough */
case 0x89: /* Fallthrough */
case 0x8A: /* Fallthrough */
case 0x8B: /* Fallthrough */
case 0x8C: /* Fallthrough */
case 0x8D: /* Fallthrough */
case 0x8E: /* Fallthrough */
case 0x8F: /* Fallthrough */
case 0x90: /* Fallthrough */
case 0x91: /* Fallthrough */
case 0x92: /* Fallthrough */
case 0x93: /* Fallthrough */
case 0x94: /* Fallthrough */
case 0x95: /* Fallthrough */
case 0x96: /* Fallthrough */
case 0x97:
/* Embedded one byte length array */
{
callbacks->array_start(context, (size_t) _cbor_load_uint8(source) - 0x80); /* 0x40 offset */
return result;
}
case 0x98:
/* One byte length array */
{
if (_cbor_claim_bytes(1, source_size, &result)) {
callbacks->array_start(context, (size_t) _cbor_load_uint8(source + 1));
}
return result;
}
case 0x99:
/* Two bytes length string */
{
if (_cbor_claim_bytes(2, source_size, &result)) {
callbacks->array_start(context, (size_t) _cbor_load_uint16(source + 1));
}
return result;
}
case 0x9A:
/* Four bytes length string */
{
if (_cbor_claim_bytes(4, source_size, &result)) {
callbacks->array_start(context, (size_t) _cbor_load_uint32(source + 1));
}
return result;
}
case 0x9B:
/* Eight bytes length string */
{
if (_cbor_claim_bytes(8, source_size, &result)) {
callbacks->array_start(context, (size_t) _cbor_load_uint64(source + 1));
}
return result;
}
case 0x9C: /* Fallthrough */
case 0x9D: /* Fallthrough */
case 0x9E:
/* Reserved */
{
return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
}
case 0x9F:
/* Indefinite length array */
{
callbacks->indef_array_start(context);
return result;
}
case 0xA0: /* Fallthrough */
case 0xA1: /* Fallthrough */
case 0xA2: /* Fallthrough */
case 0xA3: /* Fallthrough */
case 0xA4: /* Fallthrough */
case 0xA5: /* Fallthrough */
case 0xA6: /* Fallthrough */
case 0xA7: /* Fallthrough */
case 0xA8: /* Fallthrough */
case 0xA9: /* Fallthrough */
case 0xAA: /* Fallthrough */
case 0xAB: /* Fallthrough */
case 0xAC: /* Fallthrough */
case 0xAD: /* Fallthrough */
case 0xAE: /* Fallthrough */
case 0xAF: /* Fallthrough */
case 0xB0: /* Fallthrough */
case 0xB1: /* Fallthrough */
case 0xB2: /* Fallthrough */
case 0xB3: /* Fallthrough */
case 0xB4: /* Fallthrough */
case 0xB5: /* Fallthrough */
case 0xB6: /* Fallthrough */
case 0xB7:
/* Embedded one byte length map */
{
callbacks->map_start(context, (size_t) _cbor_load_uint8(source) - 0xA0); /* 0xA0 offset */
return result;
}
case 0xB8:
/* One byte length map */
{
if (_cbor_claim_bytes(1, source_size, &result)) {
callbacks->map_start(context, (size_t) _cbor_load_uint8(source + 1));
}
return result;
}
case 0xB9:
/* Two bytes length map */
{
if (_cbor_claim_bytes(2, source_size, &result)) {
callbacks->map_start(context, (size_t) _cbor_load_uint16(source + 1));
}
return result;
}
case 0xBA:
/* Four bytes length map */
{
if (_cbor_claim_bytes(4, source_size, &result)) {
callbacks->map_start(context, (size_t) _cbor_load_uint32(source + 1));
}
return result;
}
case 0xBB:
/* Eight bytes length map */
{
if (_cbor_claim_bytes(8, source_size, &result)) {
callbacks->map_start(context, (size_t) _cbor_load_uint64(source + 1));
}
return result;
}
case 0xBC: /* Fallthrough */
case 0xBD: /* Fallthrough */
case 0xBE:
/* Reserved */
{
return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
}
case 0xBF:
/* Indefinite length map */
{
callbacks->indef_map_start(context);
return result;
}
case 0xC0:
/* Text date/time - RFC 3339 tag, fallthrough */
case 0xC1:
/* Epoch date tag, fallthrough */
case 0xC2:
/* Positive bignum tag, fallthrough */
case 0xC3:
/* Negative bignum tag, fallthrough */
case 0xC4:
/* Fraction, fallthrough */
case 0xC5:
/* Big float */
{
callbacks->tag(context, _cbor_load_uint8(source) - 0xC0); /* 0xC0 offset */
return result;
}
case 0xC6: /* Fallthrough */
case 0xC7: /* Fallthrough */
case 0xC8: /* Fallthrough */
case 0xC9: /* Fallthrough */
case 0xCA: /* Fallthrough */
case 0xCB: /* Fallthrough */
case 0xCC: /* Fallthrough */
case 0xCD: /* Fallthrough */
case 0xCE: /* Fallthrough */
case 0xCF: /* Fallthrough */
case 0xD0: /* Fallthrough */
case 0xD1: /* Fallthrough */
case 0xD2: /* Fallthrough */
case 0xD3: /* Fallthrough */
case 0xD4: /* Unassigned tag value */
{
return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
}
case 0xD5: /* Expected b64url conversion tag - fallthrough */
case 0xD6: /* Expected b64 conversion tag - fallthrough */
case 0xD7: /* Expected b16 conversion tag */
{
callbacks->tag(context, _cbor_load_uint8(source) - 0xC0); /* 0xC0 offset */
return result;
}
case 0xD8: /* 1B tag */
{
if (_cbor_claim_bytes(1, source_size, &result)) {
callbacks->tag(context, _cbor_load_uint8(source + 1));
}
return result;
}
case 0xD9: /* 2B tag */
{
if (_cbor_claim_bytes(2, source_size, &result)) {
callbacks->tag(context, _cbor_load_uint16(source + 1));
}
return result;
}
case 0xDA: /* 4B tag */
{
if (_cbor_claim_bytes(4, source_size, &result)) {
callbacks->tag(context, _cbor_load_uint32(source + 1));
}
return result;
}
case 0xDB: /* 8B tag */
{
if (_cbor_claim_bytes(8, source_size, &result)) {
callbacks->tag(context, _cbor_load_uint64(source + 1));
}
return result;
}
case 0xDC: /* Fallthrough */
case 0xDD: /* Fallthrough */
case 0xDE: /* Fallthrough */
case 0xDF: /* Reserved */
{
return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
}
case 0xE0: /* Fallthrough */
case 0xE1: /* Fallthrough */
case 0xE2: /* Fallthrough */
case 0xE3: /* Fallthrough */
case 0xE4: /* Fallthrough */
case 0xE5: /* Fallthrough */
case 0xE6: /* Fallthrough */
case 0xE7: /* Fallthrough */
case 0xE8: /* Fallthrough */
case 0xE9: /* Fallthrough */
case 0xEA: /* Fallthrough */
case 0xEB: /* Fallthrough */
case 0xEC: /* Fallthrough */
case 0xED: /* Fallthrough */
case 0xEE: /* Fallthrough */
case 0xEF: /* Fallthrough */
case 0xF0: /* Fallthrough */
case 0xF1: /* Fallthrough */
case 0xF2: /* Fallthrough */
case 0xF3: /* Simple value - unassigned */
{
return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
}
case 0xF4:
/* False */
{
callbacks->boolean(context, false);
return result;
}
case 0xF5:
/* True */
{
callbacks->boolean(context, true);
return result;
}
case 0xF6:
/* Null */
{
callbacks->null(context);
return result;
}
case 0xF7:
/* Undefined */
{
callbacks->undefined(context);
return result;
}
case 0xF8:
/* 1B simple value, unassigned */
{
return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
}
case 0xF9:
/* 2B float */
{
if (_cbor_claim_bytes(2, source_size, &result)) {
callbacks->float2(context, _cbor_load_half(source + 1));
}
return result;
}
case 0xFA:
/* 4B float */
{
if (_cbor_claim_bytes(4, source_size, &result)) {
callbacks->float4(context, _cbor_load_float(source + 1));
}
return result;
}
case 0xFB:
/* 8B float */
{
if (_cbor_claim_bytes(8, source_size, &result)) {
callbacks->float8(context, _cbor_load_double(source + 1));
}
return result;
}
case 0xFC: /* Fallthrough */
case 0xFD: /* Fallthrough */
case 0xFE:
/* Reserved */
{
return (struct cbor_decoder_result) {0, CBOR_DECODER_ERROR};
}
case 0xFF:
/* Break */
{
callbacks->indef_break(context);
return result;
}
default: /* Never happens - this shuts up the compiler */
{
return result;
}
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_STREAMING_H
#define LIBCBOR_STREAMING_H
#include "cbor/common.h"
#include "callbacks.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Stateless decoder
*
* Will try parsing the \p buffer and will invoke the appropriate callback on success.
* Decodes one item at a time. No memory allocations occur.
*
* @param buffer Input buffer
* @param buffer_size Length of the buffer
* @param callbacks The callback bundle
* @param context An arbitrary pointer to allow for maintaining context.
*/
struct cbor_decoder_result cbor_stream_decode(cbor_data buffer,
size_t buffer_size,
const struct cbor_callbacks * callbacks,
void * context);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_STREAMING_H

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <string.h>
#include "strings.h"
#include "internal/memory_utils.h"
cbor_item_t *cbor_new_definite_string()
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
*item = (cbor_item_t) {
.refcount = 1,
.type = CBOR_TYPE_STRING,
.metadata = {.string_metadata = {_CBOR_METADATA_DEFINITE, 0}}
};
return item;
}
cbor_item_t *cbor_new_indefinite_string()
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
*item = (cbor_item_t) {
.refcount = 1,
.type = CBOR_TYPE_STRING,
.metadata = {.string_metadata = {.type = _CBOR_METADATA_INDEFINITE, .length = 0}},
.data = _CBOR_MALLOC(sizeof(struct cbor_indefinite_string_data))
};
*((struct cbor_indefinite_string_data *) item->data) = (struct cbor_indefinite_string_data) {
.chunk_count = 0,
.chunk_capacity = 0,
.chunks = NULL,
};
return item;
}
cbor_item_t *cbor_build_string(const char *val)
{
cbor_item_t *item = cbor_new_definite_string();
size_t len = strlen(val);
unsigned char * handle = _CBOR_MALLOC(len);
memcpy(handle, val, len);
cbor_string_set_handle(item, handle, len);
return item;
}
cbor_item_t *cbor_build_stringn(const char *val, size_t length)
{
cbor_item_t *item = cbor_new_definite_string();
unsigned char * handle = _CBOR_MALLOC(length);
memcpy(handle, val, length);
cbor_string_set_handle(item, handle, length);
return item;
}
void cbor_string_set_handle(cbor_item_t *item, cbor_mutable_data CBOR_RESTRICT_POINTER data, size_t length)
{
assert(cbor_isa_string(item));
assert(cbor_string_is_definite(item));
item->data = data;
item->metadata.string_metadata.length = length;
}
cbor_item_t **cbor_string_chunks_handle(const cbor_item_t *item)
{
assert(cbor_isa_string(item));
assert(cbor_string_is_indefinite(item));
return ((struct cbor_indefinite_string_data *) item->data)->chunks;
}
size_t cbor_string_chunk_count(const cbor_item_t *item)
{
assert(cbor_isa_string(item));
assert(cbor_string_is_indefinite(item));
return ((struct cbor_indefinite_string_data *) item->data)->chunk_count;
}
bool cbor_string_add_chunk(cbor_item_t *item, cbor_item_t *chunk)
{
assert(cbor_isa_string(item));
assert(cbor_string_is_indefinite(item));
struct cbor_indefinite_string_data *data = (struct cbor_indefinite_string_data *) item->data;
if (data->chunk_count == data->chunk_capacity) {
/* We need more space */
if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) {
return false;
}
data->chunk_capacity = data->chunk_capacity == 0 ? 1 : CBOR_BUFFER_GROWTH * (data->chunk_capacity);
cbor_item_t **new_chunks_data = _cbor_realloc_multiple(data->chunks, sizeof(cbor_item_t *), data->chunk_capacity);
if (new_chunks_data == NULL) {
return false;
}
data->chunks = new_chunks_data;
}
data->chunks[data->chunk_count++] = cbor_incref(chunk);
return true;
}
size_t cbor_string_length(const cbor_item_t *item)
{
assert(cbor_isa_string(item));
return item->metadata.string_metadata.length;
}
unsigned char *cbor_string_handle(const cbor_item_t *item)
{
assert(cbor_isa_string(item));
return item->data;
}
size_t cbor_string_codepoint_count(const cbor_item_t *item)
{
assert(cbor_isa_string(item));
return item->metadata.string_metadata.codepoint_count;
}
bool cbor_string_is_definite(const cbor_item_t *item)
{
assert(cbor_isa_string(item));
return item->metadata.string_metadata.type == _CBOR_METADATA_DEFINITE;
}
bool cbor_string_is_indefinite(const cbor_item_t *item)
{
return !cbor_string_is_definite(item);
}

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_STRINGS_H
#define LIBCBOR_STRINGS_H
#include "cbor/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* ============================================================================
* String manipulation
* ============================================================================
*/
/** Returns the length of the underlying string
*
* For definite strings only
*
* @param item[borrow] a definite string
* @return length of the string. Zero if no chunk has been attached yet
*/
size_t cbor_string_length(const cbor_item_t *item);
/** The number of codepoints in this string
*
* Might differ from length if there are multibyte ones
*
* @param item[borrow] A string
* @return The number of codepoints in this string
*/
size_t cbor_string_codepoint_count(const cbor_item_t *item);
/** Is the string definite?
*
* @param item[borrow] a string
* @return Is the string definite?
*/
bool cbor_string_is_definite(const cbor_item_t *item);
/** Is the string indefinite?
*
* @param item[borrow] a string
* @return Is the string indefinite?
*/
bool cbor_string_is_indefinite(const cbor_item_t *item);
/** Get the handle to the underlying string
*
* Definite items only. Modifying the data is allowed. In that case, the caller takes
* responsibility for the effect on items this item might be a part of
*
* @param item[borrow] A definite string
* @return The address of the underlying string. `NULL` if no data have been assigned yet.
*/
cbor_mutable_data cbor_string_handle(const cbor_item_t *item);
/** Set the handle to the underlying string
*
*
* \rst
* .. warning:: Using a pointer to a stack allocated constant is a common mistake. Lifetime of the string will expire when it goes out of scope and the CBOR item will be left inconsistent.
* \endrst
*
* @param item[borrow] A definite string
* @param data The memory block. The caller gives up the ownership of the block. libcbor will deallocate it when appropriate using its free function
* @param length Length of the data block
*/
void cbor_string_set_handle(cbor_item_t *item, cbor_mutable_data CBOR_RESTRICT_POINTER data, size_t length);
/** Get the handle to the array of chunks
*
* Manipulations with the memory block (e.g. sorting it) are allowed, but the validity and the number of chunks must be retained.
*
* @param item[borrow] A indefinite string
* @return array of #cbor_string_chunk_count definite strings
*/
cbor_item_t **cbor_string_chunks_handle(const cbor_item_t *item);
/** Get the number of chunks this string consist of
*
* @param item[borrow] A indefinite string
* @return The chunk count. 0 for freshly created items.
*/
size_t cbor_string_chunk_count(const cbor_item_t *item);
/** Appends a chunk to the string
*
* Indefinite strings only.
*
* May realloc the chunk storage.
*
* @param item[borrow] An indefinite string
* @param item[incref] A definite string
* @return true on success. false on realloc failure. In that case, the refcount of `chunk` is not increased and the `item` is left intact.
*/
bool cbor_string_add_chunk(cbor_item_t *item, cbor_item_t *chunk);
/** Creates a new definite string
*
* The handle is initialized to `NULL` and length to 0
*
* @return **new** definite string. `NULL` on malloc failure.
*/
cbor_item_t *cbor_new_definite_string();
/** Creates a new indefinite string
*
* The chunks array is initialized to `NULL` and chunkcount to 0
*
* @return **new** indefinite string. `NULL` on malloc failure.
*/
cbor_item_t *cbor_new_indefinite_string();
/** Creates a new string and initializes it
*
* The `val` will be copied to a newly allocated block
*
* @param val A null-terminated UTF-8 string
* @return A **new** string with content `handle`. `NULL` on malloc failure.
*/
cbor_item_t *cbor_build_string(const char *val);
/** Creates a new string and initializes it
*
* The `handle` will be copied to a newly allocated block
*
* @param val A UTF-8 string, at least \p length long (excluding the null byte)
* @return A **new** string with content `handle`. `NULL` on malloc failure.
*/
cbor_item_t *cbor_build_stringn(const char *val, size_t length);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_STRINGS_H

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "tags.h"
cbor_item_t *cbor_new_tag(uint64_t value)
{
cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
*item = (cbor_item_t) {
.refcount = 1,
.type = CBOR_TYPE_TAG,
.metadata = {.tag_metadata = {.value = value, .tagged_item = NULL}},
.data = NULL /* Never used */
};
return item;
}
cbor_item_t *cbor_tag_item(const cbor_item_t *item)
{
assert(cbor_isa_tag(item));
return item->metadata.tag_metadata.tagged_item;
}
uint64_t cbor_tag_value(const cbor_item_t *item)
{
assert(cbor_isa_tag(item));
return item->metadata.tag_metadata.value;
}
void cbor_tag_set_item(cbor_item_t *item, cbor_item_t *tagged_item)
{
assert(cbor_isa_tag(item));
cbor_incref(tagged_item);
item->metadata.tag_metadata.tagged_item = tagged_item;
}
cbor_item_t * cbor_build_tag(uint64_t value, cbor_item_t * item) {
cbor_item_t *res = cbor_new_tag(value);
cbor_tag_set_item(res, item);
return res;
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2014-2017 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIBCBOR_TAGS_H
#define LIBCBOR_TAGS_H
#include "cbor/common.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* ============================================================================
* Tag manipulation
* ============================================================================
*/
/** Create a new tag
*
* @param value The tag value. Please consult the tag repository
* @return **new** tag. Item reference is `NULL`.
*/
cbor_item_t *cbor_new_tag(uint64_t value);
/** Get the tagged item
*
* @param item[borrow] A tag
* @return **incref** the tagged item
*/
cbor_item_t *cbor_tag_item(const cbor_item_t *item);
/** Get tag value
*
* @param item[borrow] A tag
* @return The tag value. Please consult the tag repository
*/
uint64_t cbor_tag_value(const cbor_item_t *item);
/** Set the tagged item
*
* @param item[borrow] A tag
* @param tagged_item[incref] The item to tag
*/
void cbor_tag_set_item(cbor_item_t *item, cbor_item_t *tagged_item);
/** Build a new tag
*
* @param item[incref] The tagee
* @param value Tag value
* @return **new** tag item
*/
cbor_item_t * cbor_build_tag(uint64_t value, cbor_item_t * item);
#ifdef __cplusplus
}
#endif
#endif //LIBCBOR_TAGS_H