blob: 2142a3f2cd0ef24f97d00a7c260c192521ee7689 [file] [log] [blame]
#ifndef CN_CREATE_C
#define CN_CREATE_C
#ifdef __cplusplus
extern "C" {
#endif
#include <string.h>
#include <stdlib.h>
#include "dll-export.h"
#include "cn-cbor/cn-cbor.h"
#include "cbor.h"
#define INIT_CB(v) \
if (errp) { \
errp->err = CN_CBOR_NO_ERROR; \
} \
(v) = CN_CALLOC_CONTEXT(); \
if (!(v)) { \
if (errp) { \
errp->err = CN_CBOR_ERR_OUT_OF_MEMORY; \
} \
return NULL; \
}
CN_CBOR_EXPORT
cn_cbor* cn_cbor_simple_create(int simpleValue, CBOR_CONTEXT_COMMA cn_cbor_errback* errp)
{
if (24 <= simpleValue && simpleValue <= 31) {
if (errp != NULL) {
errp->err = CN_CBOR_ERR_INVALID_PARAMETER;
}
return NULL;
}
cn_cbor* ret;
INIT_CB(ret);
switch (simpleValue) {
case 20:
ret->type = CN_CBOR_FALSE;
break;
case 21:
ret->type = CN_CBOR_TRUE;
break;
case 22:
ret->type = CN_CBOR_NULL;
break;
default:
ret->type = CN_CBOR_SIMPLE;
ret->v.uint = simpleValue;
break;
}
return ret;
}
CN_CBOR_EXPORT
cn_cbor* cn_cbor_tag_create(int tag, cn_cbor* child, CBOR_CONTEXT_COMMA cn_cbor_errback* errp)
{
cn_cbor* ret;
INIT_CB(ret);
ret->type = CN_CBOR_TAG;
ret->v.sint = tag;
ret->first_child = child;
child->parent = ret;
return ret;
}
CN_CBOR_EXPORT
cn_cbor* cn_cbor_map_create(CBOR_CONTEXT_COMMA cn_cbor_errback* errp)
{
cn_cbor* ret;
INIT_CB(ret);
ret->type = CN_CBOR_MAP;
ret->flags |= CN_CBOR_FL_COUNT;
return ret;
}
CN_CBOR_EXPORT
cn_cbor* cn_cbor_data_create(const uint8_t* data, int len, CBOR_CONTEXT_COMMA cn_cbor_errback* errp)
{
return cn_cbor_data_create2(data, len, CN_CBOR_FL_EXT_DATA CBOR_CONTEXT_PARAM, errp);
}
CN_CBOR_EXPORT
cn_cbor* cn_cbor_data_create2(const uint8_t* data, int len, int flags CBOR_CONTEXT, cn_cbor_errback* errp)
{
cn_cbor* ret = NULL;
INIT_CB(ret);
ret->type = CN_CBOR_BYTES;
ret->length = len;
ret->v.str = (const char*)data; // TODO: add v.ustr to the union?
ret->flags |= flags;
return ret;
}
CN_CBOR_EXPORT
cn_cbor* cn_cbor_string_create(const char* data, CBOR_CONTEXT_COMMA cn_cbor_errback* errp)
{
return cn_cbor_string_create2(data, CN_CBOR_FL_EXT_DATA CBOR_CONTEXT_PARAM, errp);
}
CN_CBOR_EXPORT
cn_cbor* cn_cbor_string_create2(const char* data, int flags CBOR_CONTEXT, cn_cbor_errback* errp)
{
cn_cbor* ret = NULL;
INIT_CB(ret);
ret->type = CN_CBOR_TEXT;
ret->length = strlen(data);
ret->v.str = data;
ret->flags |= flags;
return ret;
}
CN_CBOR_EXPORT
cn_cbor* cn_cbor_int_create(int64_t value CBOR_CONTEXT, cn_cbor_errback* errp)
{
cn_cbor* ret;
INIT_CB(ret);
if (value < 0) {
ret->type = CN_CBOR_INT;
ret->v.sint = value;
}
else {
ret->type = CN_CBOR_UINT;
ret->v.uint = value;
}
return ret;
}
#ifndef CBOR_NO_FLOAT
cn_cbor* cn_cbor_float_create(float value CBOR_CONTEXT, cn_cbor_errback* errp)
{
cn_cbor* ret;
INIT_CB(ret);
ret->type = CN_CBOR_FLOAT;
ret->v.f = value;
return ret;
}
cn_cbor* cn_cbor_double_create(double value CBOR_CONTEXT, cn_cbor_errback* errp)
{
cn_cbor* ret;
INIT_CB(ret);
ret->type = CN_CBOR_DOUBLE;
ret->v.dbl = value;
return ret;
}
#endif /* CBOR_NO_FLOAT */
static bool _append_kv(cn_cbor* cb_map, cn_cbor* key, cn_cbor* val)
{
// Connect key and value and insert them into the map.
key->parent = cb_map;
key->next = val;
val->parent = cb_map;
val->next = NULL;
if (cb_map->last_child) {
cb_map->last_child->next = key;
}
else {
cb_map->first_child = key;
}
cb_map->last_child = val;
cb_map->length += 2;
return true;
}
CN_CBOR_EXPORT
bool cn_cbor_map_put(cn_cbor* cb_map, cn_cbor* cb_key, cn_cbor* cb_value, cn_cbor_errback* errp)
{
// Make sure input is a map. Otherwise
if (!cb_map || !cb_key || !cb_value || cb_map->type != CN_CBOR_MAP) {
if (errp) {
errp->err = CN_CBOR_ERR_INVALID_PARAMETER;
}
return false;
}
return _append_kv(cb_map, cb_key, cb_value);
}
CN_CBOR_EXPORT
bool cn_cbor_mapput_int(cn_cbor* cb_map, int64_t key, cn_cbor* cb_value CBOR_CONTEXT, cn_cbor_errback* errp)
{
cn_cbor* cb_key;
// Make sure input is a map. Otherwise
if (!cb_map || !cb_value || cb_map->type != CN_CBOR_MAP) {
if (errp) {
errp->err = CN_CBOR_ERR_INVALID_PARAMETER;
}
return false;
}
cb_key = cn_cbor_int_create(key CBOR_CONTEXT_PARAM, errp);
if (!cb_key) {
return false;
}
return _append_kv(cb_map, cb_key, cb_value);
}
CN_CBOR_EXPORT
bool cn_cbor_mapput_string(cn_cbor* cb_map, const char* key, cn_cbor* cb_value CBOR_CONTEXT, cn_cbor_errback* errp)
{
return cn_cbor_mapput_string2(cb_map, key, cb_value, CN_CBOR_FL_EXT_DATA CBOR_CONTEXT_PARAM, errp);
}
CN_CBOR_EXPORT
bool cn_cbor_mapput_string2(cn_cbor* cb_map,
const char* key,
cn_cbor* cb_value,
int flags CBOR_CONTEXT,
cn_cbor_errback* errp)
{
// Make sure input is a map. Otherwise
if (!cb_map || !cb_value || cb_map->type != CN_CBOR_MAP) {
if (errp) {
errp->err = CN_CBOR_ERR_INVALID_PARAMETER;
}
return false;
}
cn_cbor* cb_key = cn_cbor_string_create2(key, flags CBOR_CONTEXT_PARAM, errp);
if (!cb_key) {
return false;
}
return _append_kv(cb_map, cb_key, cb_value);
}
CN_CBOR_EXPORT
cn_cbor* cn_cbor_array_create(CBOR_CONTEXT_COMMA cn_cbor_errback* errp)
{
cn_cbor* ret;
INIT_CB(ret);
ret->type = CN_CBOR_ARRAY;
ret->flags |= CN_CBOR_FL_COUNT;
return ret;
}
CN_CBOR_EXPORT
bool cn_cbor_array_append(cn_cbor* cb_array, cn_cbor* cb_value, cn_cbor_errback* errp)
{
// Make sure input is an array.
if (!cb_array || !cb_value || cb_array->type != CN_CBOR_ARRAY) {
if (errp) {
errp->err = CN_CBOR_ERR_INVALID_PARAMETER;
}
return false;
}
cb_value->parent = cb_array;
cb_value->next = NULL;
if (cb_array->last_child) {
cb_array->last_child->next = cb_value;
}
else {
cb_array->first_child = cb_value;
}
cb_array->last_child = cb_value;
cb_array->length++;
return true;
}
CN_CBOR_EXPORT
cn_cbor* cn_cbor_chunked_create(int type, CBOR_CONTEXT_COMMA cn_cbor_errback* errp)
{
cn_cbor* ret;
INIT_CB(ret);
switch (type) {
case CN_CBOR_BYTES:
ret->type = CN_CBOR_BYTES_CHUNKED;
break;
case CN_CBOR_TEXT:
ret->type = CN_CBOR_TEXT_CHUNKED;
break;
default:
return NULL;
}
ret->flags |= CN_CBOR_FL_INDEF;
return ret;
}
CN_CBOR_EXPORT
bool cn_cbor_chunked_append(cn_cbor* cb_array, cn_cbor* cb_value, cn_cbor_errback* errp)
{
// Make sure input is an array.
if (!cb_array || !cb_value || (cb_array->type != CN_CBOR_BYTES_CHUNKED && cb_array->type != CN_CBOR_TEXT_CHUNKED)) {
if (errp) {
errp->err = CN_CBOR_ERR_INVALID_PARAMETER;
}
return false;
}
if (cb_array->type == CN_CBOR_BYTES_CHUNKED && cb_value->type != CN_CBOR_BYTES) {
if (errp) {
errp->err = CN_CBOR_ERR_INVALID_PARAMETER;
}
return false;
}
if (cb_array->type == CN_CBOR_TEXT_CHUNKED && cb_value->type != CN_CBOR_TEXT) {
if (errp) {
errp->err = CN_CBOR_ERR_INVALID_PARAMETER;
}
return false;
}
cb_value->parent = cb_array;
cb_value->next = NULL;
if (cb_array->last_child) {
cb_array->last_child->next = cb_value;
}
else {
cb_array->first_child = cb_value;
}
cb_array->last_child = cb_value;
cb_array->length++;
return true;
}
#ifdef __cplusplus
}
#endif
#endif /* CN_CBOR_C */