| #include <cassert> |
| |
| #include "cn-cbor/cn-cbor.h" |
| #include <cose/cose.h> |
| #include <stdlib.h> |
| |
| #ifdef __MBED__ |
| #include <string.h> |
| #else |
| #include <memory.h> |
| #endif |
| |
| #define INIT_CB(v) \ |
| if (errp) { \ |
| errp->err = CN_CBOR_NO_ERROR; \ |
| } \ |
| (v) = static_cast<cn_cbor *>(CN_CALLOC_CONTEXT()); \ |
| if (!(v)) { \ |
| if (errp) { \ |
| errp->err = CN_CBOR_ERR_OUT_OF_MEMORY; \ |
| } \ |
| return false; \ |
| } |
| |
| #ifdef USE_CBOR_CONTEXT |
| #define CBOR_CONTEXT_PARAM , context |
| #define CBOR_CONTEXT_PARAM_COMMA context, |
| |
| #if 1 |
| #define CN_CALLOC(ctx) \ |
| ((ctx) && (ctx)->calloc_func) \ |
| ? (ctx)->calloc_func(1, sizeof(cn_cbor), (ctx)->context) \ |
| : calloc(1, sizeof(cn_cbor)) |
| #endif |
| |
| #define CN_CALLOC_CONTEXT() CN_CALLOC(context) |
| #define CN_CBOR_CALLOC(c, i, ctx) \ |
| ((ctx) && (ctx)->calloc_func) ? (ctx)->calloc_func(c, i, (ctx)->context) \ |
| : calloc(c, i) |
| #define COSE_FREE(ptr, ctx) \ |
| ((((ctx) && (ctx)->free_func)) ? ((ctx)->free_func((ptr), (ctx)->context)) \ |
| : free((ptr))) |
| |
| #else |
| #define CBOR_CONTEXT_PARAM |
| #define CBOR_CONTEXT_PARAM_COMMA |
| #define CN_CALLOC(ctx) calloc(1, sizeof(cn_cbor)) |
| #define CN_CALLOC_CONTEXT() CN_CALLOC(context) |
| #define CN_CBOR_CALLOC(c, i, ctx) calloc(c, i) |
| #define COSE_FREE(ptr, ctx) free(ptr) |
| #endif |
| |
| /*** |
| * Replace the i-th element in the array. |
| * Extend the array if necessary so it has enough elements. |
| * |
| * @param[in] cb_array Array to use |
| * @param[in] cb_value New item to be placed in the array |
| * @param[in] index Zero based index to be used |
| * @param[in] CBOR_CONTEXT Context based allocation structure |
| * @param[in,out] errp CBOR error return on failure |
| * returns Did we succeed? |
| */ |
| |
| bool cn_cbor_array_replace(cn_cbor *cb_array, |
| cn_cbor *cb_value, |
| int index, |
| CBOR_CONTEXT_COMMA cn_cbor_errback *errp) |
| { |
| int i; |
| cn_cbor *cb_temp; |
| cn_cbor *cb_temp2; |
| |
| if (!cb_array || !cb_value || cb_array->type != CN_CBOR_ARRAY) { |
| if (errp != nullptr) { |
| errp->err = CN_CBOR_ERR_INVALID_PARAMETER; |
| } |
| return false; |
| } |
| |
| if (index == 0) { |
| if (cb_array->length > 0) { |
| cb_temp = cb_array->first_child; |
| |
| cb_value->parent = cb_array; |
| cb_value->next = cb_temp->next; |
| if (cb_array->last_child == cb_temp) { |
| cb_array->last_child = cb_value; |
| } |
| cb_array->first_child = cb_value; |
| cb_temp->parent = nullptr; |
| cb_temp->next = nullptr; |
| cn_cbor_free(cb_temp CBOR_CONTEXT_PARAM); |
| return true; |
| } |
| return cn_cbor_array_append(cb_array, cb_value, errp); |
| } |
| |
| if (cb_array->first_child == nullptr) { |
| INIT_CB(cb_temp2); |
| cb_array->first_child = cb_array->last_child = cb_temp2; |
| cb_temp2->parent = cb_array; |
| cb_array->length = 1; |
| cb_temp2->type = CN_CBOR_INVALID; |
| } |
| |
| cb_temp = cb_array->first_child; |
| for (i = 1; i < index; i++) { |
| if (cb_temp->next == nullptr) { |
| INIT_CB(cb_temp2); |
| cb_temp2->type = CN_CBOR_INVALID; |
| cb_temp->next = cb_temp2; |
| cb_temp2->parent = cb_array; |
| cb_array->last_child = cb_temp2; |
| cb_array->length += 1; |
| } |
| |
| cb_temp = cb_temp->next; |
| } |
| |
| if (cb_temp->next == nullptr) { |
| cb_temp->next = cb_value; |
| cb_value->parent = cb_array; |
| cb_array->last_child = cb_value; |
| cb_array->length += 1; |
| return true; |
| } |
| |
| cb_temp2 = cb_temp->next; |
| cb_value->next = cb_temp2->next; |
| cb_temp->next = cb_value; |
| cb_value->parent = cb_array; |
| if (cb_array->last_child == cb_temp2) { |
| cb_array->last_child = cb_value; |
| } |
| |
| cb_temp2->next = nullptr; |
| cb_temp2->parent = nullptr; |
| cn_cbor_free(cb_temp2 CBOR_CONTEXT_PARAM); |
| |
| return true; |
| } |
| |
| cn_cbor *cn_cbor_clone(const cn_cbor *pIn, |
| CBOR_CONTEXT_COMMA cn_cbor_errback *pcn_cbor_error) |
| { |
| cn_cbor * pOut = nullptr; |
| char *sz; |
| unsigned char *pb; |
| cn_cbor *pTemp; |
| cn_cbor *pLast; |
| int count; |
| |
| switch (pIn->type) { |
| case CN_CBOR_TEXT: |
| sz = (char*)( CN_CBOR_CALLOC(pIn->length + 1, 1, context)); |
| if (sz == nullptr) { |
| return nullptr; |
| } |
| memcpy(sz, pIn->v.str, pIn->length); |
| sz[pIn->length] = 0; |
| pOut = cn_cbor_string_create2( |
| sz, 0 CBOR_CONTEXT_PARAM, pcn_cbor_error); |
| if (pOut == nullptr) { |
| COSE_FREE(sz, context); |
| } |
| break; |
| |
| case CN_CBOR_UINT: |
| pOut = cn_cbor_int_create( |
| pIn->v.sint CBOR_CONTEXT_PARAM, pcn_cbor_error); |
| break; |
| |
| case CN_CBOR_INT: |
| pOut = cn_cbor_int_create( |
| pIn->v.uint CBOR_CONTEXT_PARAM, pcn_cbor_error); |
| break; |
| |
| case CN_CBOR_TRUE: |
| pOut = cn_cbor_bool_create(true CBOR_CONTEXT_PARAM, pcn_cbor_error); |
| break; |
| |
| case CN_CBOR_FALSE: |
| pOut = |
| cn_cbor_bool_create(false CBOR_CONTEXT_PARAM, pcn_cbor_error); |
| break; |
| |
| case CN_CBOR_BYTES: |
| pb = static_cast<unsigned char *>( |
| CN_CBOR_CALLOC((int)pIn->length, 1, context)); |
| if (pb == nullptr) { |
| return nullptr; |
| } |
| memcpy(pb, pIn->v.bytes, pIn->length); |
| pOut = cn_cbor_data_create2( |
| pb, (int)pIn->length, 0 CBOR_CONTEXT_PARAM, pcn_cbor_error); |
| if (pOut == nullptr) { |
| COSE_FREE((cn_cbor *)pb, context); |
| } |
| break; |
| |
| case CN_CBOR_MAP: |
| pOut = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA pcn_cbor_error); |
| if (pOut == nullptr) { |
| return nullptr; |
| } |
| pTemp = pIn->first_child; |
| pLast = nullptr; |
| count = 0; |
| while (pTemp != nullptr) { |
| cn_cbor *p = cn_cbor_clone( |
| pTemp, CBOR_CONTEXT_PARAM_COMMA pcn_cbor_error); |
| if (p == nullptr) { |
| cn_cbor_free(pOut CBOR_CONTEXT_PARAM); |
| return nullptr; |
| } |
| if (pLast == nullptr) { |
| pOut->first_child = p; |
| pLast = p; |
| } |
| else { |
| pLast->next = p; |
| pLast = p; |
| } |
| p->parent = pOut; |
| count += 1; |
| pTemp = pTemp->next; |
| } |
| pOut->last_child = pLast; |
| pOut->length = count; |
| break; |
| |
| default: |
| assert(false); |
| break; |
| } |
| |
| return pOut; |
| } |
| |
| #ifndef CN_CBOR_VERSION |
| cn_cbor *cn_cbor_tag_create(int tag, |
| cn_cbor *child, |
| CBOR_CONTEXT_COMMA cn_cbor_errback *perr) |
| { |
| cn_cbor *pcnTag = CN_CALLOC(context); |
| if (pcnTag == nullptr) { |
| if (perr != nullptr) { |
| perr->err = CN_CBOR_ERR_OUT_OF_MEMORY; |
| } |
| return nullptr; |
| } |
| |
| pcnTag->type = CN_CBOR_TAG; |
| pcnTag->v.sint = tag; |
| pcnTag->first_child = child; |
| child->parent = pcnTag; |
| |
| return pcnTag; |
| } |
| |
| cn_cbor *cn_cbor_bool_create(int boolValue, |
| CBOR_CONTEXT_COMMA cn_cbor_errback *errp) |
| { |
| cn_cbor *pcn = CN_CALLOC(context); |
| if (pcn == nullptr) { |
| if (errp != nullptr) { |
| errp->err = CN_CBOR_ERR_OUT_OF_MEMORY; |
| } |
| return nullptr; |
| } |
| |
| pcn->type = CN_CBOR_FALSE + (boolValue != 0); |
| return pcn; |
| } |
| |
| cn_cbor *cn_cbor_null_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp) |
| { |
| cn_cbor *pcn = CN_CALLOC(context); |
| if (pcn == nullptr) { |
| if (errp != nullptr) { |
| errp->err = CN_CBOR_ERR_OUT_OF_MEMORY; |
| } |
| return nullptr; |
| } |
| pcn->type = CN_CBOR_NULL; |
| return pcn; |
| } |
| #endif |
| |
| size_t cn_cbor_encode_size(cn_cbor *object) |
| { |
| ssize_t size = cn_cbor_encoder_write(nullptr, 0, 0, object); |
| return size >= 0 ? size : 0; |
| } |