1*10ff414cSEd Maste /* 2*10ff414cSEd Maste * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com> 3*10ff414cSEd Maste * 4*10ff414cSEd Maste * libcbor is free software; you can redistribute it and/or modify 5*10ff414cSEd Maste * it under the terms of the MIT license. See LICENSE for details. 6*10ff414cSEd Maste */ 7*10ff414cSEd Maste 8*10ff414cSEd Maste #include "serialization.h" 9*10ff414cSEd Maste #include <string.h> 10*10ff414cSEd Maste #include "cbor/arrays.h" 11*10ff414cSEd Maste #include "cbor/bytestrings.h" 12*10ff414cSEd Maste #include "cbor/floats_ctrls.h" 13*10ff414cSEd Maste #include "cbor/ints.h" 14*10ff414cSEd Maste #include "cbor/maps.h" 15*10ff414cSEd Maste #include "cbor/strings.h" 16*10ff414cSEd Maste #include "cbor/tags.h" 17*10ff414cSEd Maste #include "encoding.h" 18*10ff414cSEd Maste #include "internal/memory_utils.h" 19*10ff414cSEd Maste 20*10ff414cSEd Maste size_t cbor_serialize(const cbor_item_t *item, unsigned char *buffer, 21*10ff414cSEd Maste size_t buffer_size) { 22*10ff414cSEd Maste switch (cbor_typeof(item)) { 23*10ff414cSEd Maste case CBOR_TYPE_UINT: 24*10ff414cSEd Maste return cbor_serialize_uint(item, buffer, buffer_size); 25*10ff414cSEd Maste case CBOR_TYPE_NEGINT: 26*10ff414cSEd Maste return cbor_serialize_negint(item, buffer, buffer_size); 27*10ff414cSEd Maste case CBOR_TYPE_BYTESTRING: 28*10ff414cSEd Maste return cbor_serialize_bytestring(item, buffer, buffer_size); 29*10ff414cSEd Maste case CBOR_TYPE_STRING: 30*10ff414cSEd Maste return cbor_serialize_string(item, buffer, buffer_size); 31*10ff414cSEd Maste case CBOR_TYPE_ARRAY: 32*10ff414cSEd Maste return cbor_serialize_array(item, buffer, buffer_size); 33*10ff414cSEd Maste case CBOR_TYPE_MAP: 34*10ff414cSEd Maste return cbor_serialize_map(item, buffer, buffer_size); 35*10ff414cSEd Maste case CBOR_TYPE_TAG: 36*10ff414cSEd Maste return cbor_serialize_tag(item, buffer, buffer_size); 37*10ff414cSEd Maste case CBOR_TYPE_FLOAT_CTRL: 38*10ff414cSEd Maste return cbor_serialize_float_ctrl(item, buffer, buffer_size); 39*10ff414cSEd Maste default: 40*10ff414cSEd Maste return 0; 41*10ff414cSEd Maste } 42*10ff414cSEd Maste } 43*10ff414cSEd Maste 44*10ff414cSEd Maste size_t cbor_serialize_alloc(const cbor_item_t *item, unsigned char **buffer, 45*10ff414cSEd Maste size_t *buffer_size) { 46*10ff414cSEd Maste size_t bfr_size = 32; 47*10ff414cSEd Maste unsigned char *bfr = _CBOR_MALLOC(bfr_size), *tmp_bfr; 48*10ff414cSEd Maste if (bfr == NULL) { 49*10ff414cSEd Maste return 0; 50*10ff414cSEd Maste } 51*10ff414cSEd Maste 52*10ff414cSEd Maste size_t written; 53*10ff414cSEd Maste 54*10ff414cSEd Maste /* This is waaay too optimistic - figure out something smarter (eventually) */ 55*10ff414cSEd Maste while ((written = cbor_serialize(item, bfr, bfr_size)) == 0) { 56*10ff414cSEd Maste if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, bfr_size)) { 57*10ff414cSEd Maste _CBOR_FREE(bfr); 58*10ff414cSEd Maste return 0; 59*10ff414cSEd Maste } 60*10ff414cSEd Maste 61*10ff414cSEd Maste tmp_bfr = _CBOR_REALLOC(bfr, bfr_size *= 2); 62*10ff414cSEd Maste 63*10ff414cSEd Maste if (tmp_bfr == NULL) { 64*10ff414cSEd Maste _CBOR_FREE(bfr); 65*10ff414cSEd Maste return 0; 66*10ff414cSEd Maste } 67*10ff414cSEd Maste bfr = tmp_bfr; 68*10ff414cSEd Maste } 69*10ff414cSEd Maste *buffer = bfr; 70*10ff414cSEd Maste *buffer_size = bfr_size; 71*10ff414cSEd Maste return written; 72*10ff414cSEd Maste } 73*10ff414cSEd Maste 74*10ff414cSEd Maste size_t cbor_serialize_uint(const cbor_item_t *item, unsigned char *buffer, 75*10ff414cSEd Maste size_t buffer_size) { 76*10ff414cSEd Maste assert(cbor_isa_uint(item)); 77*10ff414cSEd Maste switch (cbor_int_get_width(item)) { 78*10ff414cSEd Maste case CBOR_INT_8: 79*10ff414cSEd Maste return cbor_encode_uint8(cbor_get_uint8(item), buffer, buffer_size); 80*10ff414cSEd Maste case CBOR_INT_16: 81*10ff414cSEd Maste return cbor_encode_uint16(cbor_get_uint16(item), buffer, buffer_size); 82*10ff414cSEd Maste case CBOR_INT_32: 83*10ff414cSEd Maste return cbor_encode_uint32(cbor_get_uint32(item), buffer, buffer_size); 84*10ff414cSEd Maste case CBOR_INT_64: 85*10ff414cSEd Maste return cbor_encode_uint64(cbor_get_uint64(item), buffer, buffer_size); 86*10ff414cSEd Maste default: 87*10ff414cSEd Maste return 0; 88*10ff414cSEd Maste } 89*10ff414cSEd Maste } 90*10ff414cSEd Maste 91*10ff414cSEd Maste size_t cbor_serialize_negint(const cbor_item_t *item, unsigned char *buffer, 92*10ff414cSEd Maste size_t buffer_size) { 93*10ff414cSEd Maste assert(cbor_isa_negint(item)); 94*10ff414cSEd Maste switch (cbor_int_get_width(item)) { 95*10ff414cSEd Maste case CBOR_INT_8: 96*10ff414cSEd Maste return cbor_encode_negint8(cbor_get_uint8(item), buffer, buffer_size); 97*10ff414cSEd Maste case CBOR_INT_16: 98*10ff414cSEd Maste return cbor_encode_negint16(cbor_get_uint16(item), buffer, buffer_size); 99*10ff414cSEd Maste case CBOR_INT_32: 100*10ff414cSEd Maste return cbor_encode_negint32(cbor_get_uint32(item), buffer, buffer_size); 101*10ff414cSEd Maste case CBOR_INT_64: 102*10ff414cSEd Maste return cbor_encode_negint64(cbor_get_uint64(item), buffer, buffer_size); 103*10ff414cSEd Maste default: 104*10ff414cSEd Maste return 0; 105*10ff414cSEd Maste } 106*10ff414cSEd Maste } 107*10ff414cSEd Maste 108*10ff414cSEd Maste size_t cbor_serialize_bytestring(const cbor_item_t *item, unsigned char *buffer, 109*10ff414cSEd Maste size_t buffer_size) { 110*10ff414cSEd Maste assert(cbor_isa_bytestring(item)); 111*10ff414cSEd Maste if (cbor_bytestring_is_definite(item)) { 112*10ff414cSEd Maste size_t length = cbor_bytestring_length(item); 113*10ff414cSEd Maste size_t written = cbor_encode_bytestring_start(length, buffer, buffer_size); 114*10ff414cSEd Maste if (written && (buffer_size - written >= length)) { 115*10ff414cSEd Maste memcpy(buffer + written, cbor_bytestring_handle(item), length); 116*10ff414cSEd Maste return written + length; 117*10ff414cSEd Maste } else 118*10ff414cSEd Maste return 0; 119*10ff414cSEd Maste } else { 120*10ff414cSEd Maste assert(cbor_bytestring_is_indefinite(item)); 121*10ff414cSEd Maste size_t chunk_count = cbor_bytestring_chunk_count(item); 122*10ff414cSEd Maste size_t written = cbor_encode_indef_bytestring_start(buffer, buffer_size); 123*10ff414cSEd Maste 124*10ff414cSEd Maste if (written == 0) return 0; 125*10ff414cSEd Maste 126*10ff414cSEd Maste cbor_item_t **chunks = cbor_bytestring_chunks_handle(item); 127*10ff414cSEd Maste for (size_t i = 0; i < chunk_count; i++) { 128*10ff414cSEd Maste size_t chunk_written = cbor_serialize_bytestring( 129*10ff414cSEd Maste chunks[i], buffer + written, buffer_size - written); 130*10ff414cSEd Maste if (chunk_written == 0) 131*10ff414cSEd Maste return 0; 132*10ff414cSEd Maste else 133*10ff414cSEd Maste written += chunk_written; 134*10ff414cSEd Maste } 135*10ff414cSEd Maste if (cbor_encode_break(buffer + written, buffer_size - written) > 0) 136*10ff414cSEd Maste return written + 1; 137*10ff414cSEd Maste else 138*10ff414cSEd Maste return 0; 139*10ff414cSEd Maste } 140*10ff414cSEd Maste } 141*10ff414cSEd Maste 142*10ff414cSEd Maste size_t cbor_serialize_string(const cbor_item_t *item, unsigned char *buffer, 143*10ff414cSEd Maste size_t buffer_size) { 144*10ff414cSEd Maste assert(cbor_isa_string(item)); 145*10ff414cSEd Maste if (cbor_string_is_definite(item)) { 146*10ff414cSEd Maste size_t length = cbor_string_length(item); 147*10ff414cSEd Maste size_t written = cbor_encode_string_start(length, buffer, buffer_size); 148*10ff414cSEd Maste if (written && (buffer_size - written >= length)) { 149*10ff414cSEd Maste memcpy(buffer + written, cbor_string_handle(item), length); 150*10ff414cSEd Maste return written + length; 151*10ff414cSEd Maste } else 152*10ff414cSEd Maste return 0; 153*10ff414cSEd Maste } else { 154*10ff414cSEd Maste assert(cbor_string_is_indefinite(item)); 155*10ff414cSEd Maste size_t chunk_count = cbor_string_chunk_count(item); 156*10ff414cSEd Maste size_t written = cbor_encode_indef_string_start(buffer, buffer_size); 157*10ff414cSEd Maste 158*10ff414cSEd Maste if (written == 0) return 0; 159*10ff414cSEd Maste 160*10ff414cSEd Maste cbor_item_t **chunks = cbor_string_chunks_handle(item); 161*10ff414cSEd Maste for (size_t i = 0; i < chunk_count; i++) { 162*10ff414cSEd Maste size_t chunk_written = cbor_serialize_string(chunks[i], buffer + written, 163*10ff414cSEd Maste buffer_size - written); 164*10ff414cSEd Maste if (chunk_written == 0) 165*10ff414cSEd Maste return 0; 166*10ff414cSEd Maste else 167*10ff414cSEd Maste written += chunk_written; 168*10ff414cSEd Maste } 169*10ff414cSEd Maste if (cbor_encode_break(buffer + written, buffer_size - written) > 0) 170*10ff414cSEd Maste return written + 1; 171*10ff414cSEd Maste else 172*10ff414cSEd Maste return 0; 173*10ff414cSEd Maste } 174*10ff414cSEd Maste } 175*10ff414cSEd Maste 176*10ff414cSEd Maste size_t cbor_serialize_array(const cbor_item_t *item, unsigned char *buffer, 177*10ff414cSEd Maste size_t buffer_size) { 178*10ff414cSEd Maste assert(cbor_isa_array(item)); 179*10ff414cSEd Maste size_t size = cbor_array_size(item), written = 0; 180*10ff414cSEd Maste cbor_item_t **handle = cbor_array_handle(item); 181*10ff414cSEd Maste if (cbor_array_is_definite(item)) { 182*10ff414cSEd Maste written = cbor_encode_array_start(size, buffer, buffer_size); 183*10ff414cSEd Maste } else { 184*10ff414cSEd Maste assert(cbor_array_is_indefinite(item)); 185*10ff414cSEd Maste written = cbor_encode_indef_array_start(buffer, buffer_size); 186*10ff414cSEd Maste } 187*10ff414cSEd Maste if (written == 0) return 0; 188*10ff414cSEd Maste 189*10ff414cSEd Maste size_t item_written; 190*10ff414cSEd Maste for (size_t i = 0; i < size; i++) { 191*10ff414cSEd Maste item_written = 192*10ff414cSEd Maste cbor_serialize(*(handle++), buffer + written, buffer_size - written); 193*10ff414cSEd Maste if (item_written == 0) 194*10ff414cSEd Maste return 0; 195*10ff414cSEd Maste else 196*10ff414cSEd Maste written += item_written; 197*10ff414cSEd Maste } 198*10ff414cSEd Maste 199*10ff414cSEd Maste if (cbor_array_is_definite(item)) { 200*10ff414cSEd Maste return written; 201*10ff414cSEd Maste } else { 202*10ff414cSEd Maste assert(cbor_array_is_indefinite(item)); 203*10ff414cSEd Maste item_written = cbor_encode_break(buffer + written, buffer_size - written); 204*10ff414cSEd Maste if (item_written == 0) 205*10ff414cSEd Maste return 0; 206*10ff414cSEd Maste else 207*10ff414cSEd Maste return written + 1; 208*10ff414cSEd Maste } 209*10ff414cSEd Maste } 210*10ff414cSEd Maste 211*10ff414cSEd Maste size_t cbor_serialize_map(const cbor_item_t *item, unsigned char *buffer, 212*10ff414cSEd Maste size_t buffer_size) { 213*10ff414cSEd Maste assert(cbor_isa_map(item)); 214*10ff414cSEd Maste size_t size = cbor_map_size(item), written = 0; 215*10ff414cSEd Maste struct cbor_pair *handle = cbor_map_handle(item); 216*10ff414cSEd Maste 217*10ff414cSEd Maste if (cbor_map_is_definite(item)) { 218*10ff414cSEd Maste written = cbor_encode_map_start(size, buffer, buffer_size); 219*10ff414cSEd Maste } else { 220*10ff414cSEd Maste assert(cbor_map_is_indefinite(item)); 221*10ff414cSEd Maste written = cbor_encode_indef_map_start(buffer, buffer_size); 222*10ff414cSEd Maste } 223*10ff414cSEd Maste if (written == 0) return 0; 224*10ff414cSEd Maste 225*10ff414cSEd Maste size_t item_written; 226*10ff414cSEd Maste for (size_t i = 0; i < size; i++) { 227*10ff414cSEd Maste item_written = 228*10ff414cSEd Maste cbor_serialize(handle->key, buffer + written, buffer_size - written); 229*10ff414cSEd Maste if (item_written == 0) 230*10ff414cSEd Maste return 0; 231*10ff414cSEd Maste else 232*10ff414cSEd Maste written += item_written; 233*10ff414cSEd Maste item_written = cbor_serialize((handle++)->value, buffer + written, 234*10ff414cSEd Maste buffer_size - written); 235*10ff414cSEd Maste if (item_written == 0) 236*10ff414cSEd Maste return 0; 237*10ff414cSEd Maste else 238*10ff414cSEd Maste written += item_written; 239*10ff414cSEd Maste } 240*10ff414cSEd Maste 241*10ff414cSEd Maste if (cbor_map_is_definite(item)) { 242*10ff414cSEd Maste return written; 243*10ff414cSEd Maste } else { 244*10ff414cSEd Maste assert(cbor_map_is_indefinite(item)); 245*10ff414cSEd Maste item_written = cbor_encode_break(buffer + written, buffer_size - written); 246*10ff414cSEd Maste if (item_written == 0) 247*10ff414cSEd Maste return 0; 248*10ff414cSEd Maste else 249*10ff414cSEd Maste return written + 1; 250*10ff414cSEd Maste } 251*10ff414cSEd Maste } 252*10ff414cSEd Maste 253*10ff414cSEd Maste size_t cbor_serialize_tag(const cbor_item_t *item, unsigned char *buffer, 254*10ff414cSEd Maste size_t buffer_size) { 255*10ff414cSEd Maste assert(cbor_isa_tag(item)); 256*10ff414cSEd Maste size_t written = cbor_encode_tag(cbor_tag_value(item), buffer, buffer_size); 257*10ff414cSEd Maste if (written == 0) return 0; 258*10ff414cSEd Maste 259*10ff414cSEd Maste size_t item_written = cbor_serialize(cbor_move(cbor_tag_item(item)), 260*10ff414cSEd Maste buffer + written, buffer_size - written); 261*10ff414cSEd Maste if (item_written == 0) 262*10ff414cSEd Maste return 0; 263*10ff414cSEd Maste else 264*10ff414cSEd Maste return written + item_written; 265*10ff414cSEd Maste } 266*10ff414cSEd Maste 267*10ff414cSEd Maste size_t cbor_serialize_float_ctrl(const cbor_item_t *item, unsigned char *buffer, 268*10ff414cSEd Maste size_t buffer_size) { 269*10ff414cSEd Maste assert(cbor_isa_float_ctrl(item)); 270*10ff414cSEd Maste switch (cbor_float_get_width(item)) { 271*10ff414cSEd Maste case CBOR_FLOAT_0: 272*10ff414cSEd Maste /* CTRL - special treatment */ 273*10ff414cSEd Maste return cbor_encode_ctrl(cbor_ctrl_value(item), buffer, buffer_size); 274*10ff414cSEd Maste case CBOR_FLOAT_16: 275*10ff414cSEd Maste return cbor_encode_half(cbor_float_get_float2(item), buffer, buffer_size); 276*10ff414cSEd Maste case CBOR_FLOAT_32: 277*10ff414cSEd Maste return cbor_encode_single(cbor_float_get_float4(item), buffer, 278*10ff414cSEd Maste buffer_size); 279*10ff414cSEd Maste case CBOR_FLOAT_64: 280*10ff414cSEd Maste return cbor_encode_double(cbor_float_get_float8(item), buffer, 281*10ff414cSEd Maste buffer_size); 282*10ff414cSEd Maste } 283*10ff414cSEd Maste 284*10ff414cSEd Maste /* Should never happen - make the compiler happy */ 285*10ff414cSEd Maste return 0; 286*10ff414cSEd Maste } 287