From e31fb1c6296ec281460c16902d0dd2309711903d Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 20 Nov 2024 12:14:14 +0100 Subject: [PATCH 1/2] Use Arduino_CloudUtils --- src/ota/implementation/OTAUnoR4.cpp | 1 - src/ota/interface/OTAInterface.h | 2 +- src/ota/interface/OTAInterfaceDefault.cpp | 56 +------- src/ota/interface/OTAInterfaceDefault.h | 4 +- src/tls/utility/SHA256.cpp | 47 ------- src/tls/utility/SHA256.h | 48 ------- src/utility/lzss/lzss.cpp | 163 ---------------------- src/utility/lzss/lzss.h | 108 -------------- 8 files changed, 8 insertions(+), 421 deletions(-) delete mode 100644 src/tls/utility/SHA256.cpp delete mode 100644 src/tls/utility/SHA256.h delete mode 100644 src/utility/lzss/lzss.cpp delete mode 100644 src/utility/lzss/lzss.h diff --git a/src/ota/implementation/OTAUnoR4.cpp b/src/ota/implementation/OTAUnoR4.cpp index 8119c243..f2883b30 100644 --- a/src/ota/implementation/OTAUnoR4.cpp +++ b/src/ota/implementation/OTAUnoR4.cpp @@ -14,7 +14,6 @@ #include "OTAUnoR4.h" #include -#include "tls/utility/SHA256.h" #include "fsp_common_api.h" #include "r_flash_lp.h" #include "WiFi.h" diff --git a/src/ota/interface/OTAInterface.h b/src/ota/interface/OTAInterface.h index a62b7cb2..d2d54f38 100644 --- a/src/ota/interface/OTAInterface.h +++ b/src/ota/interface/OTAInterface.h @@ -18,7 +18,7 @@ #if OTA_ENABLED #include "../OTATypes.h" -#include "tls/utility/SHA256.h" +#include #include #include diff --git a/src/ota/interface/OTAInterfaceDefault.cpp b/src/ota/interface/OTAInterfaceDefault.cpp index 82bfd9e8..0fe8e2eb 100644 --- a/src/ota/interface/OTAInterfaceDefault.cpp +++ b/src/ota/interface/OTAInterfaceDefault.cpp @@ -10,6 +10,7 @@ #include #if OTA_ENABLED && ! defined(OFFLOADED_DOWNLOAD) +#include #include "OTAInterfaceDefault.h" #include "../OTA.h" @@ -128,7 +129,7 @@ OTACloudProcessInterface::State OTADefaultCloudProcessInterface::fetch() { // this could distinguish between consistency of the downloaded bytes and filesize // validate CRC - context->calculatedCrc32 ^= 0xFFFFFFFF; // finalize CRC + arduino::crc32::finalize(context->calculatedCrc32); if(context->header.header.crc32 == context->calculatedCrc32) { DEBUG_VERBOSE("Ota download completed successfully"); res = FlashOTA; @@ -168,7 +169,7 @@ void OTADefaultCloudProcessInterface::parseOta(uint8_t* buffer, size_t buf_len) if(sizeof(context->header.buf) == context->headerCopiedBytes) { context->downloadState = OtaDownloadFile; - context->calculatedCrc32 = crc_update( + context->calculatedCrc32 = arduino::crc32::update( context->calculatedCrc32, &(context->header.header.magic_number), sizeof(context->header) - offsetof(ota::OTAHeader, header.magic_number) @@ -188,7 +189,7 @@ void OTADefaultCloudProcessInterface::parseOta(uint8_t* buffer, size_t buf_len) const uint32_t dataLeft = buf_len - (cursor-buffer); context->decoder.decompress(cursor, dataLeft); // TODO verify return value - context->calculatedCrc32 = crc_update( + context->calculatedCrc32 = arduino::crc32::update( context->calculatedCrc32, cursor, dataLeft @@ -246,58 +247,11 @@ OTADefaultCloudProcessInterface::Context::Context( const char* url, std::function putc) : parsed_url(url) , downloadState(OtaDownloadHeader) - , calculatedCrc32(0xFFFFFFFF) + , calculatedCrc32(arduino::crc32::begin()) , headerCopiedBytes(0) , downloadedSize(0) , lastReportTime(0) , writeError(false) , decoder(putc) { } -static const uint32_t crc_table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, - 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, - 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, - 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, - 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, - 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, - 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, - 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, - 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - -uint32_t crc_update(uint32_t crc, const void * data, size_t data_len) { - const unsigned char *d = (const unsigned char *)data; - unsigned int tbl_idx; - - while (data_len--) { - tbl_idx = (crc ^ *d) & 0xff; - crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff; - d++; - } - - return crc & 0xffffffff; -} #endif /* OTA_ENABLED && ! defined(OFFLOADED_DOWNLOAD) */ diff --git a/src/ota/interface/OTAInterfaceDefault.h b/src/ota/interface/OTAInterfaceDefault.h index 95384817..b3c86988 100644 --- a/src/ota/interface/OTAInterfaceDefault.h +++ b/src/ota/interface/OTAInterfaceDefault.h @@ -16,7 +16,7 @@ #include #include -#include "utility/lzss/lzss.h" +#include #include "OTAInterface.h" /** @@ -77,7 +77,7 @@ class OTADefaultCloudProcessInterface: public OTACloudProcessInterface { bool writeError; // LZSS decoder - LZSSDecoder decoder; + arduino::lzss::Decoder decoder; const size_t buf_len = 64; uint8_t buffer[64]; diff --git a/src/tls/utility/SHA256.cpp b/src/tls/utility/SHA256.cpp deleted file mode 100644 index ffed6e58..00000000 --- a/src/tls/utility/SHA256.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2020 ARDUINO SA (http://www.arduino.cc/) - - This software is released under the GNU General Public License version 3, - which covers the main part of arduino-cli. - The terms of this license can be found at: - https://www.gnu.org/licenses/gpl-3.0.en.html - - You can be released from the requirements of the above licenses by purchasing - a commercial license. Buying such a license is mandatory if you want to modify or - otherwise use the software for commercial activities involving the Arduino - software without disclosing the source code of your own applications. To purchase - a commercial license, send an email to license@arduino.cc. -*/ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include "SHA256.h" - -/****************************************************************************** - * STATIC MEMBER DECLARATION - ******************************************************************************/ - -constexpr size_t SHA256::HASH_SIZE; - -/****************************************************************************** - * PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -void SHA256::begin() -{ - br_sha256_init(&_ctx); -} - -void SHA256::update(uint8_t const * data, size_t const len) -{ - br_sha256_update(&_ctx, data, len); -} - -void SHA256::finalize(uint8_t * hash) -{ - br_sha256_out(&_ctx, hash); -} diff --git a/src/tls/utility/SHA256.h b/src/tls/utility/SHA256.h deleted file mode 100644 index ed0ce1d5..00000000 --- a/src/tls/utility/SHA256.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2020 ARDUINO SA (http://www.arduino.cc/) - - This software is released under the GNU General Public License version 3, - which covers the main part of arduino-cli. - The terms of this license can be found at: - https://www.gnu.org/licenses/gpl-3.0.en.html - - You can be released from the requirements of the above licenses by purchasing - a commercial license. Buying such a license is mandatory if you want to modify or - otherwise use the software for commercial activities involving the Arduino - software without disclosing the source code of your own applications. To purchase - a commercial license, send an email to license@arduino.cc. -*/ - -#ifndef ARDUINO_TLS_UTILITY_SHA256_H_ -#define ARDUINO_TLS_UTILITY_SHA256_H_ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include "../bearssl/bearssl_hash.h" - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class SHA256 -{ - -public: - - static constexpr size_t HASH_SIZE = 32; - - void begin (); - void update (uint8_t const * data, size_t const len); - void finalize(uint8_t * hash); - -private: - - br_sha256_context _ctx; - -}; - -#endif /* ARDUINO_TLS_UTILITY_SHA256_H_ */ diff --git a/src/utility/lzss/lzss.cpp b/src/utility/lzss/lzss.cpp deleted file mode 100644 index 1a11399f..00000000 --- a/src/utility/lzss/lzss.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - This file is part of the ArduinoIoTCloud library. - - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - - This implementation took inspiration from https://okumuralab.org/~okumura/compression/lzss.c source code -*/ - -/************************************************************************************** - INCLUDE - **************************************************************************************/ -#include "lzss.h" - -#include - -/************************************************************************************** - LZSS DECODER CLASS IMPLEMENTATION - **************************************************************************************/ - -// get the number of bits the algorithm will try to get given the state -uint8_t LZSSDecoder::bits_required(LZSSDecoder::FSM_STATES s) { - switch(s) { - case FSM_0: - return 1; - case FSM_1: - return 8; - case FSM_2: - return EI; - case FSM_3: - return EJ; - default: - return 0; - } -} - -LZSSDecoder::LZSSDecoder(std::function getc_cbk, std::function putc_cbk) -: available(0), state(FSM_0), put_char_cbk(putc_cbk), get_char_cbk(getc_cbk) { - for (int i = 0; i < N - F; i++) buffer[i] = ' '; - r = N - F; -} - - -LZSSDecoder::LZSSDecoder(std::function putc_cbk) -: available(0), state(FSM_0), put_char_cbk(putc_cbk), get_char_cbk(nullptr) { - for (int i = 0; i < N - F; i++) buffer[i] = ' '; - r = N - F; -} - -LZSSDecoder::status LZSSDecoder::handle_state() { - LZSSDecoder::status res = IN_PROGRESS; - - int c = getbit(bits_required(this->state)); - - if(c == LZSS_BUFFER_EMPTY) { - res = NOT_COMPLETED; - } else if (c == LZSS_EOF) { - res = DONE; - this->state = FSM_EOF; - } else { - switch(this->state) { - case FSM_0: - if(c) { - this->state = FSM_1; - } else { - this->state = FSM_2; - } - break; - case FSM_1: - putc(c); - buffer[r++] = c; - r &= (N - 1); // equivalent to r = r % N when N is a power of 2 - - this->state = FSM_0; - break; - case FSM_2: - this->i = c; - this->state = FSM_3; - break; - case FSM_3: { - int j = c; - - // This is where the actual decompression takes place: we look into the local buffer for reuse - // of byte chunks. This can be improved by means of memcpy and by changing the putc function - // into a put_buf function in order to avoid buffering on the other end. - // TODO improve this section of code - for (int k = 0; k <= j + 1; k++) { - c = buffer[(this->i + k) & (N - 1)]; // equivalent to buffer[(i+k) % N] when N is a power of 2 - putc(c); - buffer[r++] = c; - r &= (N - 1); // equivalent to r = r % N - } - this->state = FSM_0; - - break; - } - case FSM_EOF: - break; - } - } - - return res; -} - -LZSSDecoder::status LZSSDecoder::decompress(uint8_t* const buffer, uint32_t size) { - if(!get_char_cbk) { - this->in_buffer = buffer; - this->available += size; - } - - status res = IN_PROGRESS; - - while((res = handle_state()) == IN_PROGRESS); - - this->in_buffer = nullptr; - - return res; -} - -int LZSSDecoder::getbit(uint8_t n) { // get n bits from buffer - int x=0, c; - - // if the local bit buffer doesn't have enough bit get them - while(buf_size < n) { - switch(c=getc()) { - case LZSS_EOF: - case LZSS_BUFFER_EMPTY: - return c; - } - buf <<= 8; - - buf |= (uint8_t)c; - buf_size += sizeof(uint8_t)*8; - } - - // the result is the content of the buffer starting from msb to n successive bits - x = buf >> (buf_size-n); - - // remove from the buffer the read bits with a mask - buf &= (1<<(buf_size-n))-1; - - buf_size-=n; - - return x; -} - -int LZSSDecoder::getc() { - int c; - - if(get_char_cbk) { - c = get_char_cbk(); - } else if(in_buffer == nullptr || available == 0) { - c = LZSS_BUFFER_EMPTY; - } else { - c = *in_buffer; - in_buffer++; - available--; - } - return c; -} \ No newline at end of file diff --git a/src/utility/lzss/lzss.h b/src/utility/lzss/lzss.h deleted file mode 100644 index bf652026..00000000 --- a/src/utility/lzss/lzss.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - This file is part of the ArduinoIoTCloud library. - - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ - -#pragma once - -/************************************************************************************** - INCLUDE - **************************************************************************************/ -#include -#include -#include - -/************************************************************************************** - FUNCTION DEFINITION - **************************************************************************************/ - -/************************************************************************************** - LZSS DECODER CLASS - **************************************************************************************/ - - -class LZSSDecoder { -public: - - /** - * Build an LZSS decoder by providing a callback for storing the decoded bytes - * @param putc_cbk: a callback that takes a char and stores it e.g. a callback to fwrite - */ - LZSSDecoder(std::function putc_cbk); - - /** - * Build an LZSS decoder providing a callback for getting a char and putting a char - * in this way you need to call decompress with no parameters - * @param putc_cbk: a callback that takes a char and stores it e.g. a callback to fwrite - * @param getc_cbk: a callback that returns the next char to consume - * -1 means EOF, -2 means buffer is temporairly finished - */ - LZSSDecoder(std::function getc_cbk, std::function putc_cbk); - - /** - * this enum describes the result of the computation of a single FSM computation - * DONE: the decompression is completed - * IN_PROGRESS: the decompression cycle completed successfully, ready to compute next - * NOT_COMPLETED: the current cycle didn't complete because the available data is not enough - */ - enum status: uint8_t { - DONE, - IN_PROGRESS, - NOT_COMPLETED - }; - - /** - * decode the provided buffer until buffer ends, then pause the process - * @return DONE if the decompression is completed, NOT_COMPLETED if not - */ - status decompress(uint8_t* const buffer=nullptr, uint32_t size=0); - - static const int LZSS_EOF = -1; - static const int LZSS_BUFFER_EMPTY = -2; -private: - // TODO provide a way for the user to set these parameters - static const int EI = 11; /* typically 10..13 */ - static const int EJ = 4; /* typically 4..5 */ - static const int N = (1 << EI); /* buffer size */ - static const int F = ((1 << EJ) + 1); /* lookahead buffer size */ - - // algorithm specific buffer used to store text that could be later referenced and copied - uint8_t buffer[N * 2]; - - // this function gets 1 single char from the input buffer - int getc(); - uint8_t* in_buffer = nullptr; - uint32_t available = 0; - - status handle_state(); - - // get 1 bit from the available input buffer - int getbit(uint8_t n); - // the following 2 are variables used by getbits - uint32_t buf, buf_size=0; - - enum FSM_STATES: uint8_t { - FSM_0 = 0, - FSM_1 = 1, - FSM_2 = 2, - FSM_3 = 3, - FSM_EOF - } state; - - // these variable are used in a decode session and specific to the old C implementation - // there is no documentation about their meaning - int i, r; - - std::function put_char_cbk; - std::function get_char_cbk; - - inline void putc(const uint8_t c) { if(put_char_cbk) { put_char_cbk(c); } } - - // get the number of bits the FSM will require given its state - uint8_t bits_required(FSM_STATES s); -}; \ No newline at end of file From 7fc1fa3223422b909d20c9cddaecfc70392bf16d Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 20 Nov 2024 12:58:18 +0100 Subject: [PATCH 2/2] offload tinycbor to CloudUtils --- src/cbor/CBOREncoder.cpp | 2 +- src/cbor/MessageDecoder.h | 2 +- src/cbor/MessageEncoder.cpp | 1 - src/cbor/MessageEncoder.h | 2 +- src/cbor/lib/tinycbor/cbor-lib.h | 36 - src/cbor/lib/tinycbor/src/cbor.dox | 123 -- src/cbor/lib/tinycbor/src/cbor.h | 639 -------- src/cbor/lib/tinycbor/src/cborencoder.c | 650 -------- .../src/cborencoder_close_container_checked.c | 62 - src/cbor/lib/tinycbor/src/cborerrorstrings.c | 190 --- src/cbor/lib/tinycbor/src/cborinternal_p.h | 161 -- src/cbor/lib/tinycbor/src/cborjson.h | 62 - src/cbor/lib/tinycbor/src/cborparser.c | 1435 ----------------- .../lib/tinycbor/src/cborparser_dup_string.c | 124 -- src/cbor/lib/tinycbor/src/cborpretty.c | 583 ------- src/cbor/lib/tinycbor/src/cborpretty_stdio.c | 91 -- src/cbor/lib/tinycbor/src/cbortojson.c | 704 -------- src/cbor/lib/tinycbor/src/cborvalidation.c | 671 -------- src/cbor/lib/tinycbor/src/compilersupport_p.h | 205 --- src/cbor/lib/tinycbor/src/open_memstream.c | 112 -- src/cbor/lib/tinycbor/src/tags.txt | 23 - src/cbor/lib/tinycbor/src/tinycbor-version.h | 3 - src/cbor/lib/tinycbor/src/utf8_p.h | 104 -- src/property/Property.h | 2 +- 24 files changed, 4 insertions(+), 5983 deletions(-) delete mode 100644 src/cbor/lib/tinycbor/cbor-lib.h delete mode 100644 src/cbor/lib/tinycbor/src/cbor.dox delete mode 100644 src/cbor/lib/tinycbor/src/cbor.h delete mode 100644 src/cbor/lib/tinycbor/src/cborencoder.c delete mode 100644 src/cbor/lib/tinycbor/src/cborencoder_close_container_checked.c delete mode 100644 src/cbor/lib/tinycbor/src/cborerrorstrings.c delete mode 100644 src/cbor/lib/tinycbor/src/cborinternal_p.h delete mode 100644 src/cbor/lib/tinycbor/src/cborjson.h delete mode 100644 src/cbor/lib/tinycbor/src/cborparser.c delete mode 100644 src/cbor/lib/tinycbor/src/cborparser_dup_string.c delete mode 100644 src/cbor/lib/tinycbor/src/cborpretty.c delete mode 100644 src/cbor/lib/tinycbor/src/cborpretty_stdio.c delete mode 100644 src/cbor/lib/tinycbor/src/cbortojson.c delete mode 100644 src/cbor/lib/tinycbor/src/cborvalidation.c delete mode 100644 src/cbor/lib/tinycbor/src/compilersupport_p.h delete mode 100644 src/cbor/lib/tinycbor/src/open_memstream.c delete mode 100644 src/cbor/lib/tinycbor/src/tags.txt delete mode 100644 src/cbor/lib/tinycbor/src/tinycbor-version.h delete mode 100644 src/cbor/lib/tinycbor/src/utf8_p.h diff --git a/src/cbor/CBOREncoder.cpp b/src/cbor/CBOREncoder.cpp index d166756d..74106cde 100644 --- a/src/cbor/CBOREncoder.cpp +++ b/src/cbor/CBOREncoder.cpp @@ -26,7 +26,7 @@ #include #include -#include "lib/tinycbor/cbor-lib.h" +#include /****************************************************************************** * PUBLIC MEMBER FUNCTIONS diff --git a/src/cbor/MessageDecoder.h b/src/cbor/MessageDecoder.h index 1223e947..2ade0eaf 100644 --- a/src/cbor/MessageDecoder.h +++ b/src/cbor/MessageDecoder.h @@ -23,7 +23,7 @@ #include "CBOR.h" #include "../interfaces/Decoder.h" -#include "lib/tinycbor/cbor-lib.h" +#include /****************************************************************************** CLASS DECLARATION diff --git a/src/cbor/MessageEncoder.cpp b/src/cbor/MessageEncoder.cpp index cdeb0f8e..56bae9ef 100644 --- a/src/cbor/MessageEncoder.cpp +++ b/src/cbor/MessageEncoder.cpp @@ -19,7 +19,6 @@ #include #include -#include "lib/tinycbor/cbor-lib.h" #include "MessageEncoder.h" /****************************************************************************** diff --git a/src/cbor/MessageEncoder.h b/src/cbor/MessageEncoder.h index 86792eb1..81ae94ce 100644 --- a/src/cbor/MessageEncoder.h +++ b/src/cbor/MessageEncoder.h @@ -23,7 +23,7 @@ #include "CBOR.h" #include "../interfaces/Encoder.h" -#include "lib/tinycbor/cbor-lib.h" +#include /****************************************************************************** * CLASS DECLARATION diff --git a/src/cbor/lib/tinycbor/cbor-lib.h b/src/cbor/lib/tinycbor/cbor-lib.h deleted file mode 100644 index e8d8004e..00000000 --- a/src/cbor/lib/tinycbor/cbor-lib.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef CBOR_LIB_H -#define CBOR_LIB_H - -/****************************************************************************** - INCLUDE - ******************************************************************************/ - -#include "src/cbor.h" - -/****************************************************************************** - * DEFINE - ******************************************************************************/ - -#ifndef CHECK_CBOR - #define CHECK_CBOR(expr) \ - do { \ - CborError error = CborNoError; \ - error = (expr); \ - if (CborNoError != error) \ - return error; \ - } while(0); -#endif /* CHECK_CBOR */ - -#ifndef CHECK_CBOR_MULTI - #define CHECK_CBOR_MULTI(expr) \ - do { \ - CborError error = CborNoError; \ - error = (expr); \ - if (CborErrorOutOfMemory == error) \ - return CborErrorSplitItems; \ - if (CborNoError != error) \ - return error; \ - } while(0); -#endif /* CHECK_CBOR_MULTI */ - -#endif \ No newline at end of file diff --git a/src/cbor/lib/tinycbor/src/cbor.dox b/src/cbor/lib/tinycbor/src/cbor.dox deleted file mode 100644 index 0bf5c54c..00000000 --- a/src/cbor/lib/tinycbor/src/cbor.dox +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation -** -** 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. -** -****************************************************************************/ - -/** - * \mainpage - * The TinyCBOR $(VERSION) library is a small CBOR encoder and decoder library, - * optimized for very fast operation with very small footprint. The main encoder - * and decoder functions do not allocate memory. - * - * TinyCBOR is divided into the following groups of functions and structures: - * - \ref CborGlobals - * - \ref CborEncoding - * - \ref CborParsing - * - \ref CborPretty - * - \ref CborToJson - */ - -/** - * \file - * The is the main header in TinyCBOR and defines the constants used by most functions - * as well as the structures for encoding (CborEncoder) and decoding (CborValue). - * - * \sa - */ - -/** - * \file - * The file contains the routines that are used to convert a CBOR - * data stream into JSON. - * - * \sa - */ - -/** - * \defgroup CborGlobals Global constants - * \brief Constants used by all TinyCBOR function groups. - */ - -/** - * \addtogroup CborGlobals - * @{ - */ - -/** - * \var size_t CborIndefiniteLength - * - * This variable is a constant used to indicate that the length of the map or - * array is not yet determined. It is used in functions - * cbor_encoder_create_map() and cbor_encoder_create_array() - */ - -/** - * \enum CborType - * The CborType enum contains the types known to TinyCBOR. - * - * \value CborIntegerType Type is an integer value, positive, negative or zero - * \value CborByteStringType Type is a string of arbitrary raw bytes - * \value CborTextStringType Type is a text string encoded in UTF-8 - * \value CborArrayType Type is a CBOR array - * \value CborMapType Type is a CBOR map (an associative container with key and value pairs) - * \value CborTagType Type is a CBOR tag (a 64-bit integer describing the item that follows, see CborKnownTags) - * \value CborSimpleType Type is one of the CBOR Simple Types - * \value CborBooleanType Type is a boolean (true or false) - * \value CborNullType Type encodes a null - * \value CborUndefinedType Type encodes an undefined value - * \value CborHalfFloatType Type is an IEEE 754 half precision (16-bit) floating point type - * \value CborFloatType Type is an IEEE 754 single precision (32-bit) floating point type - * \value CborDoubleType Type is an IEEE 754 double precision (64-bit) floating point type - * \value CborInvalidType Type is not valid (this value is used to indicate error conditions) - */ - -/** - * \enum CborKnownTags - * The CborKnownTags enum contains known tags specified in RFC 7049, for use by the application. - * TinyCBOR does not usually interpret the meaning of these tags and does not add them to the - * output stream, unless specifically instructed to do so in functions for that effect. - * - * \value CborDateTimeStringTag Text string contains a date-time encoded in RFC 3339 format, "YYYY-MM-DD hh:mm:ss+zzzz" - * \value CborUnixTime_tTag Number is a Unix time_t quantity, the number of seconds since 1970-01-01 midnight UTC - * \value CborPositiveBignumTag Item is a CBOR byte string encoding a positive integer of arbitrary precision - * \value CborNegativeBignumTag Item is a CBOR byte string encoding a negative integer of arbitrary precision - * \value CborDecimalTag Item is a CBOR array of two integers encoding a fixed-point decimal - * \value CborBigfloatTag Item is a bigfloat - * \value CborExpectedBase64urlTag Item is a CBOR byte string that is expected to be encoded as Base64Url - * \value CborExpectedBase64Tag Item is a CBOR byte string that is expected to be encoded as Base64 - * \value CborExpectedBase16Tag Item is a CBOR byte string that is expected to be encoded as Base16 (also known as "hexdump") - * \value CborUriTag Item is a CBOR text string containing a URI (RFC 3986) or IRI (RFC 3987) - * \value CborBase64urlTag Item is a CBOR text string that was encoded as Base64Url - * \value CborBase64Tag Item is a CBOR text string that was encoded as Base64 - * \value CborRegularExpressionTag Item is a CBOR text string containing a regular expression - * \value CborMimeMessageTag Item is a CBOR text string containing a MIME message (RFC 2045, 2046, 2047, 2822) - * \value CborSignatureTag Item contains CBOR-encoded data. - * This tag is also used as "file magic," marking a file as containing CBOR - */ - -/** - * \typedef CborTag - * This typedef is an unsigned 64-bit integer. Known CBOR tags can be used from the CborKnownTags enum - * but the user application may use other tag values than the ones specified in RFC 7049. - */ - -/** @} */ diff --git a/src/cbor/lib/tinycbor/src/cbor.h b/src/cbor/lib/tinycbor/src/cbor.h deleted file mode 100644 index 27a4fe4a..00000000 --- a/src/cbor/lib/tinycbor/src/cbor.h +++ /dev/null @@ -1,639 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#ifndef CBOR_H -#define CBOR_H - -#ifndef assert -#include -#endif -#include -#include -#include -#include -#include - -#include "tinycbor-version.h" - -#define TINYCBOR_VERSION ((TINYCBOR_VERSION_MAJOR << 16) | (TINYCBOR_VERSION_MINOR << 8) | TINYCBOR_VERSION_PATCH) - -#ifdef __cplusplus -extern "C" { -#else -#include -#endif - -#ifndef SIZE_MAX -/* Some systems fail to define SIZE_MAX in , even though C99 requires it... - * Conversion from signed to unsigned is defined in 6.3.1.3 (Signed and unsigned integers) p2, - * which says: "the value is converted by repeatedly adding or subtracting one more than the - * maximum value that can be represented in the new type until the value is in the range of the - * new type." - * So -1 gets converted to size_t by adding SIZE_MAX + 1, which results in SIZE_MAX. - */ -# define SIZE_MAX ((size_t)-1) -#endif - -#ifndef CBOR_API -# define CBOR_API -#endif -#ifndef CBOR_PRIVATE_API -# define CBOR_PRIVATE_API -#endif -#ifndef CBOR_INLINE_API -# if defined(__cplusplus) -# define CBOR_INLINE inline -# define CBOR_INLINE_API inline -# else -# define CBOR_INLINE_API static CBOR_INLINE -# if defined(_MSC_VER) -# define CBOR_INLINE __inline -# elif defined(__GNUC__) -# define CBOR_INLINE __inline__ -# elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -# define CBOR_INLINE inline -# else -# define CBOR_INLINE -# endif -# endif -#endif - -typedef enum CborType { - CborIntegerType = 0x00, - CborByteStringType = 0x40, - CborTextStringType = 0x60, - CborArrayType = 0x80, - CborMapType = 0xa0, - CborTagType = 0xc0, - CborSimpleType = 0xe0, - CborBooleanType = 0xf5, - CborNullType = 0xf6, - CborUndefinedType = 0xf7, - CborHalfFloatType = 0xf9, - CborFloatType = 0xfa, - CborDoubleType = 0xfb, - - CborInvalidType = 0xff /* equivalent to the break byte, so it will never be used */ -} CborType; - -typedef uint64_t CborTag; -typedef enum CborKnownTags { - CborDateTimeStringTag = 0, - CborUnixTime_tTag = 1, - CborPositiveBignumTag = 2, - CborNegativeBignumTag = 3, - CborDecimalTag = 4, - CborBigfloatTag = 5, - CborCOSE_Encrypt0Tag = 16, - CborCOSE_Mac0Tag = 17, - CborCOSE_Sign1Tag = 18, - CborExpectedBase64urlTag = 21, - CborExpectedBase64Tag = 22, - CborExpectedBase16Tag = 23, - CborEncodedCborTag = 24, - CborUrlTag = 32, - CborBase64urlTag = 33, - CborBase64Tag = 34, - CborRegularExpressionTag = 35, - CborMimeMessageTag = 36, - CborCOSE_EncryptTag = 96, - CborCOSE_MacTag = 97, - CborCOSE_SignTag = 98, - CborSignatureTag = 55799 -} CborKnownTags; - -/* #define the constants so we can check with #ifdef */ -#define CborDateTimeStringTag CborDateTimeStringTag -#define CborUnixTime_tTag CborUnixTime_tTag -#define CborPositiveBignumTag CborPositiveBignumTag -#define CborNegativeBignumTag CborNegativeBignumTag -#define CborDecimalTag CborDecimalTag -#define CborBigfloatTag CborBigfloatTag -#define CborCOSE_Encrypt0Tag CborCOSE_Encrypt0Tag -#define CborCOSE_Mac0Tag CborCOSE_Mac0Tag -#define CborCOSE_Sign1Tag CborCOSE_Sign1Tag -#define CborExpectedBase64urlTag CborExpectedBase64urlTag -#define CborExpectedBase64Tag CborExpectedBase64Tag -#define CborExpectedBase16Tag CborExpectedBase16Tag -#define CborEncodedCborTag CborEncodedCborTag -#define CborUrlTag CborUrlTag -#define CborBase64urlTag CborBase64urlTag -#define CborBase64Tag CborBase64Tag -#define CborRegularExpressionTag CborRegularExpressionTag -#define CborMimeMessageTag CborMimeMessageTag -#define CborCOSE_EncryptTag CborCOSE_EncryptTag -#define CborCOSE_MacTag CborCOSE_MacTag -#define CborCOSE_SignTag CborCOSE_SignTag -#define CborSignatureTag CborSignatureTag - -/* Error API */ - -typedef enum CborError { - CborNoError = 0, - - /* errors in all modes */ - CborUnknownError, - CborErrorUnknownLength, /* request for length in array, map, or string with indeterminate length */ - CborErrorAdvancePastEOF, - CborErrorIO, - - /* parser errors streaming errors */ - CborErrorGarbageAtEnd = 256, - CborErrorUnexpectedEOF, - CborErrorUnexpectedBreak, - CborErrorUnknownType, /* can only happen in major type 7 */ - CborErrorIllegalType, /* type not allowed here */ - CborErrorIllegalNumber, - CborErrorIllegalSimpleType, /* types of value less than 32 encoded in two bytes */ - - /* parser errors in strict mode parsing only */ - CborErrorUnknownSimpleType = 512, - CborErrorUnknownTag, - CborErrorInappropriateTagForType, - CborErrorDuplicateObjectKeys, - CborErrorInvalidUtf8TextString, - CborErrorExcludedType, - CborErrorExcludedValue, - CborErrorImproperValue, - CborErrorOverlongEncoding, - CborErrorMapKeyNotString, - CborErrorMapNotSorted, - CborErrorMapKeysNotUnique, - - /* encoder errors */ - CborErrorTooManyItems = 768, - CborErrorTooFewItems, - CborErrorSplitItems, - - /* internal implementation errors */ - CborErrorDataTooLarge = 1024, - CborErrorNestingTooDeep, - CborErrorUnsupportedType, - - /* errors in converting to JSON */ - CborErrorJsonObjectKeyIsAggregate = 1280, - CborErrorJsonObjectKeyNotString, - CborErrorJsonNotImplemented, - - CborErrorOutOfMemory = (int) (~0U / 2 + 1), - CborErrorInternalError = (int) (~0U / 2) /* INT_MAX on two's complement machines */ -} CborError; - -CBOR_API const char *cbor_error_string(CborError error); - -/* Encoder API */ -struct CborEncoder -{ - union { - uint8_t *ptr; - ptrdiff_t bytes_needed; - } data; - const uint8_t *end; - size_t remaining; - int flags; -}; -typedef struct CborEncoder CborEncoder; - -static const size_t CborIndefiniteLength = SIZE_MAX; - -CBOR_API void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags); -CBOR_API CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value); -CBOR_API CborError cbor_encode_int(CborEncoder *encoder, int64_t value); -CBOR_API CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value); -CBOR_API CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value); -CBOR_API CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag); -CBOR_API CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length); -CBOR_INLINE_API CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string) -{ return cbor_encode_text_string(encoder, string, strlen(string)); } -CBOR_API CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length); -CBOR_API CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value); - -CBOR_INLINE_API CborError cbor_encode_boolean(CborEncoder *encoder, bool value) -{ return cbor_encode_simple_value(encoder, (int)value - 1 + (CborBooleanType & 0x1f)); } -CBOR_INLINE_API CborError cbor_encode_null(CborEncoder *encoder) -{ return cbor_encode_simple_value(encoder, CborNullType & 0x1f); } -CBOR_INLINE_API CborError cbor_encode_undefined(CborEncoder *encoder) -{ return cbor_encode_simple_value(encoder, CborUndefinedType & 0x1f); } - -CBOR_INLINE_API CborError cbor_encode_half_float(CborEncoder *encoder, const void *value) -{ return cbor_encode_floating_point(encoder, CborHalfFloatType, value); } -CBOR_INLINE_API CborError cbor_encode_float(CborEncoder *encoder, float value) -{ return cbor_encode_floating_point(encoder, CborFloatType, &value); } -CBOR_INLINE_API CborError cbor_encode_double(CborEncoder *encoder, double value) -{ return cbor_encode_floating_point(encoder, CborDoubleType, &value); } - -CBOR_API CborError cbor_encoder_create_array(CborEncoder *encoder, CborEncoder *arrayEncoder, size_t length); -CBOR_API CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length); -CBOR_API CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder); -CBOR_API CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder); - -CBOR_INLINE_API uint8_t *_cbor_encoder_get_buffer_pointer(const CborEncoder *encoder) -{ - return encoder->data.ptr; -} - -CBOR_INLINE_API size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer) -{ - return (size_t)(encoder->data.ptr - buffer); -} - -CBOR_INLINE_API size_t cbor_encoder_get_extra_bytes_needed(const CborEncoder *encoder) -{ - return encoder->end ? 0 : (size_t)encoder->data.bytes_needed; -} - -/* Parser API */ - -enum CborParserIteratorFlags -{ - CborIteratorFlag_IntegerValueTooLarge = 0x01, - CborIteratorFlag_NegativeInteger = 0x02, - CborIteratorFlag_IteratingStringChunks = 0x02, - CborIteratorFlag_UnknownLength = 0x04, - CborIteratorFlag_ContainerIsMap = 0x20 -}; - -struct CborParser -{ - const uint8_t *end; - uint32_t flags; -}; -typedef struct CborParser CborParser; - -struct CborValue -{ - const CborParser *parser; - const uint8_t *ptr; - uint32_t remaining; - uint16_t extra; - uint8_t type; - uint8_t flags; -}; -typedef struct CborValue CborValue; - -CBOR_API CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it); - -CBOR_API CborError cbor_value_validate_basic(const CborValue *it); - -CBOR_INLINE_API bool cbor_value_at_end(const CborValue *it) -{ return it->remaining == 0; } -CBOR_INLINE_API const uint8_t *cbor_value_get_next_byte(const CborValue *it) -{ return it->ptr; } -CBOR_API CborError cbor_value_advance_fixed(CborValue *it); -CBOR_API CborError cbor_value_advance(CborValue *it); -CBOR_INLINE_API bool cbor_value_is_container(const CborValue *it) -{ return it->type == CborArrayType || it->type == CborMapType; } -CBOR_API CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed); -CBOR_API CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed); - -CBOR_PRIVATE_API uint64_t _cbor_value_decode_int64_internal(const CborValue *value); -CBOR_INLINE_API uint64_t _cbor_value_extract_int64_helper(const CborValue *value) -{ - return value->flags & CborIteratorFlag_IntegerValueTooLarge ? - _cbor_value_decode_int64_internal(value) : value->extra; -} - -CBOR_INLINE_API bool cbor_value_is_valid(const CborValue *value) -{ return value && value->type != CborInvalidType; } -CBOR_INLINE_API CborType cbor_value_get_type(const CborValue *value) -{ return (CborType)value->type; } - -/* Null & undefined type */ -CBOR_INLINE_API bool cbor_value_is_null(const CborValue *value) -{ return value->type == CborNullType; } -CBOR_INLINE_API bool cbor_value_is_undefined(const CborValue *value) -{ return value->type == CborUndefinedType; } - -/* Booleans */ -CBOR_INLINE_API bool cbor_value_is_boolean(const CborValue *value) -{ return value->type == CborBooleanType; } -CBOR_INLINE_API CborError cbor_value_get_boolean(const CborValue *value, bool *result) -{ -#ifdef HOST - assert(cbor_value_is_boolean(value)); -#endif - *result = !!value->extra; - return CborNoError; -} - -/* Simple types */ -CBOR_INLINE_API bool cbor_value_is_simple_type(const CborValue *value) -{ return value->type == CborSimpleType; } -CBOR_INLINE_API CborError cbor_value_get_simple_type(const CborValue *value, uint8_t *result) -{ -#ifdef HOST - assert(cbor_value_is_simple_type(value)); -#endif - *result = (uint8_t)value->extra; - return CborNoError; -} - -/* Integers */ -CBOR_INLINE_API bool cbor_value_is_integer(const CborValue *value) -{ return value->type == CborIntegerType; } -CBOR_INLINE_API bool cbor_value_is_unsigned_integer(const CborValue *value) -{ return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger) == 0; } -CBOR_INLINE_API bool cbor_value_is_negative_integer(const CborValue *value) -{ return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger); } - -CBOR_INLINE_API CborError cbor_value_get_raw_integer(const CborValue *value, uint64_t *result) -{ -#ifdef HOST - assert(cbor_value_is_integer(value)); -#endif - *result = _cbor_value_extract_int64_helper(value); - return CborNoError; -} - -CBOR_INLINE_API CborError cbor_value_get_uint64(const CborValue *value, uint64_t *result) -{ -#ifdef HOST - assert(cbor_value_is_unsigned_integer(value)); -#endif - *result = _cbor_value_extract_int64_helper(value); - return CborNoError; -} - -CBOR_INLINE_API CborError cbor_value_get_int64(const CborValue *value, int64_t *result) -{ -#ifdef HOST - assert(cbor_value_is_integer(value)); -#endif - *result = (int64_t) _cbor_value_extract_int64_helper(value); - if (value->flags & CborIteratorFlag_NegativeInteger) - *result = -*result - 1; - return CborNoError; -} - -CBOR_INLINE_API CborError cbor_value_get_int(const CborValue *value, int *result) -{ -#ifdef HOST - assert(cbor_value_is_integer(value)); -#endif - *result = (int) _cbor_value_extract_int64_helper(value); - if (value->flags & CborIteratorFlag_NegativeInteger) - *result = -*result - 1; - return CborNoError; -} - -CBOR_API CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result); -CBOR_API CborError cbor_value_get_int_checked(const CborValue *value, int *result); - -CBOR_INLINE_API bool cbor_value_is_length_known(const CborValue *value) -{ return (value->flags & CborIteratorFlag_UnknownLength) == 0; } - -/* Tags */ -CBOR_INLINE_API bool cbor_value_is_tag(const CborValue *value) -{ return value->type == CborTagType; } -CBOR_INLINE_API CborError cbor_value_get_tag(const CborValue *value, CborTag *result) -{ -#ifdef HOST - assert(cbor_value_is_tag(value)); -#endif - *result = _cbor_value_extract_int64_helper(value); - return CborNoError; -} -CBOR_API CborError cbor_value_skip_tag(CborValue *it); - -/* Strings */ -CBOR_INLINE_API bool cbor_value_is_byte_string(const CborValue *value) -{ return value->type == CborByteStringType; } -CBOR_INLINE_API bool cbor_value_is_text_string(const CborValue *value) -{ return value->type == CborTextStringType; } - -CBOR_INLINE_API CborError cbor_value_get_string_length(const CborValue *value, size_t *length) -{ - uint64_t v; -#ifdef HOST - assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value)); -#endif - if (!cbor_value_is_length_known(value)) - return CborErrorUnknownLength; - v = _cbor_value_extract_int64_helper(value); - *length = (size_t)v; - if (*length != v) - return CborErrorDataTooLarge; - return CborNoError; -} - -CBOR_PRIVATE_API CborError _cbor_value_copy_string(const CborValue *value, void *buffer, - size_t *buflen, CborValue *next); -CBOR_PRIVATE_API CborError _cbor_value_dup_string(const CborValue *value, void **buffer, - size_t *buflen, CborValue *next); - -CBOR_API CborError cbor_value_calculate_string_length(const CborValue *value, size_t *length); - -CBOR_INLINE_API CborError cbor_value_copy_text_string(const CborValue *value, char *buffer, - size_t *buflen, CborValue *next) -{ -#ifdef HOST - assert(cbor_value_is_text_string(value)); -#endif - return _cbor_value_copy_string(value, buffer, buflen, next); -} -CBOR_INLINE_API CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer, - size_t *buflen, CborValue *next) -{ -#ifdef HOST - assert(cbor_value_is_byte_string(value)); -#endif - return _cbor_value_copy_string(value, buffer, buflen, next); -} - -CBOR_INLINE_API CborError cbor_value_dup_text_string(const CborValue *value, char **buffer, - size_t *buflen, CborValue *next) -{ -#ifdef HOST - assert(cbor_value_is_text_string(value)); -#endif - return _cbor_value_dup_string(value, (void **)buffer, buflen, next); -} -CBOR_INLINE_API CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer, - size_t *buflen, CborValue *next) -{ -#ifdef HOST - assert(cbor_value_is_byte_string(value)); -#endif - return _cbor_value_dup_string(value, (void **)buffer, buflen, next); -} - -CBOR_API CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result); - -/* Maps and arrays */ -CBOR_INLINE_API bool cbor_value_is_array(const CborValue *value) -{ return value->type == CborArrayType; } -CBOR_INLINE_API bool cbor_value_is_map(const CborValue *value) -{ return value->type == CborMapType; } - -CBOR_INLINE_API CborError cbor_value_get_array_length(const CborValue *value, size_t *length) -{ - uint64_t v; -#ifdef HOST - assert(cbor_value_is_array(value)); -#endif - if (!cbor_value_is_length_known(value)) - return CborErrorUnknownLength; - v = _cbor_value_extract_int64_helper(value); - *length = (size_t)v; - if (*length != v) - return CborErrorDataTooLarge; - return CborNoError; -} - -CBOR_INLINE_API CborError cbor_value_get_map_length(const CborValue *value, size_t *length) -{ - uint64_t v; -#ifdef HOST - assert(cbor_value_is_map(value)); -#endif - if (!cbor_value_is_length_known(value)) - return CborErrorUnknownLength; - v = _cbor_value_extract_int64_helper(value); - *length = (size_t)v; - if (*length != v) - return CborErrorDataTooLarge; - return CborNoError; -} - -CBOR_API CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element); - -/* Floating point */ -CBOR_INLINE_API bool cbor_value_is_half_float(const CborValue *value) -{ return value->type == CborHalfFloatType; } -CBOR_API CborError cbor_value_get_half_float(const CborValue *value, void *result); - -CBOR_INLINE_API bool cbor_value_is_float(const CborValue *value) -{ return value->type == CborFloatType; } -CBOR_INLINE_API CborError cbor_value_get_float(const CborValue *value, float *result) -{ - uint32_t data; -#ifdef HOST - assert(cbor_value_is_float(value)); - assert(value->flags & CborIteratorFlag_IntegerValueTooLarge); -#endif - data = (uint32_t)_cbor_value_decode_int64_internal(value); - memcpy(result, &data, sizeof(*result)); - return CborNoError; -} - -CBOR_INLINE_API bool cbor_value_is_double(const CborValue *value) -{ return value->type == CborDoubleType; } -CBOR_INLINE_API CborError cbor_value_get_double(const CborValue *value, double *result) -{ - uint64_t data; -#ifdef HOST - assert(cbor_value_is_double(value)); - assert(value->flags & CborIteratorFlag_IntegerValueTooLarge); -#endif - data = _cbor_value_decode_int64_internal(value); - memcpy(result, &data, sizeof(*result)); - return CborNoError; -} - -/* Validation API */ - -enum CborValidationFlags { - /* Bit mapping: - * bits 0-7 (8 bits): canonical format - * bits 8-11 (4 bits): canonical format & strict mode - * bits 12-20 (8 bits): strict mode - * bits 21-31 (10 bits): other - */ - - CborValidateShortestIntegrals = 0x0001, - CborValidateShortestFloatingPoint = 0x0002, - CborValidateShortestNumbers = CborValidateShortestIntegrals | CborValidateShortestFloatingPoint, - CborValidateNoIndeterminateLength = 0x0100, - CborValidateMapIsSorted = 0x0200 | CborValidateNoIndeterminateLength, - - CborValidateCanonicalFormat = 0x0fff, - - CborValidateMapKeysAreUnique = 0x1000 | CborValidateMapIsSorted, - CborValidateTagUse = 0x2000, - CborValidateUtf8 = 0x4000, - - CborValidateStrictMode = 0xfff00, - - CborValidateMapKeysAreString = 0x100000, - CborValidateNoUndefined = 0x200000, - CborValidateNoTags = 0x400000, - CborValidateFiniteFloatingPoint = 0x800000, - /* unused = 0x1000000, */ - /* unused = 0x2000000, */ - - CborValidateNoUnknownSimpleTypesSA = 0x4000000, - CborValidateNoUnknownSimpleTypes = 0x8000000 | CborValidateNoUnknownSimpleTypesSA, - CborValidateNoUnknownTagsSA = 0x10000000, - CborValidateNoUnknownTagsSR = 0x20000000 | CborValidateNoUnknownTagsSA, - CborValidateNoUnknownTags = 0x40000000 | CborValidateNoUnknownTagsSR, - - CborValidateCompleteData = (int)0x80000000, - - CborValidateStrictest = (int)~0U, - CborValidateBasic = 0 -}; - -CBOR_API CborError cbor_value_validate(const CborValue *it, uint32_t flags); - -/* Human-readable (dump) API */ - -enum CborPrettyFlags { - CborPrettyNumericEncodingIndicators = 0x01, - CborPrettyTextualEncodingIndicators = 0, - - CborPrettyIndicateIndeterminateLength = 0x02, - CborPrettyIndicateIndetermineLength = CborPrettyIndicateIndeterminateLength, /* deprecated */ - CborPrettyIndicateOverlongNumbers = 0x04, - - CborPrettyShowStringFragments = 0x100, - CborPrettyMergeStringFragments = 0, - - CborPrettyDefaultFlags = CborPrettyIndicateIndeterminateLength -}; - -typedef CborError (*CborStreamFunction)(void *token, const char *fmt, ...) -#ifdef __GNUC__ - __attribute__((__format__(printf, 2, 3))) -#endif -; - -CBOR_API CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *token, CborValue *value, int flags); - -/* The following API requires a hosted C implementation (uses FILE*) */ -#if !defined(__STDC_HOSTED__) || __STDC_HOSTED__-0 == 1 -CBOR_API CborError cbor_value_to_pretty_advance_flags(FILE *out, CborValue *value, int flags); -CBOR_API CborError cbor_value_to_pretty_advance(FILE *out, CborValue *value); -CBOR_INLINE_API CborError cbor_value_to_pretty(FILE *out, const CborValue *value) -{ - CborValue copy = *value; - return cbor_value_to_pretty_advance_flags(out, ©, CborPrettyDefaultFlags); -} -#endif /* __STDC_HOSTED__ check */ - -#ifdef __cplusplus -} -#endif - -#endif /* CBOR_H */ - diff --git a/src/cbor/lib/tinycbor/src/cborencoder.c b/src/cbor/lib/tinycbor/src/cborencoder.c deleted file mode 100644 index 23a9721a..00000000 --- a/src/cbor/lib/tinycbor/src/cborencoder.c +++ /dev/null @@ -1,650 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#ifndef _BSD_SOURCE -#define _BSD_SOURCE 1 -#endif -#ifndef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE 1 -#endif -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" - -#include -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \defgroup CborEncoding Encoding to CBOR - * \brief Group of functions used to encode data to CBOR. - * - * CborEncoder is used to encode data into a CBOR stream. The outermost - * CborEncoder is initialized by calling cbor_encoder_init(), with the buffer - * where the CBOR stream will be stored. The outermost CborEncoder is usually - * used to encode exactly one item, most often an array or map. It is possible - * to encode more than one item, but care must then be taken on the decoder - * side to ensure the state is reset after each item was decoded. - * - * Nested CborEncoder objects are created using cbor_encoder_create_array() and - * cbor_encoder_create_map(), later closed with cbor_encoder_close_container() - * or cbor_encoder_close_container_checked(). The pairs of creation and closing - * must be exactly matched and their parameters are always the same. - * - * CborEncoder writes directly to the user-supplied buffer, without extra - * buffering. CborEncoder does not allocate memory and CborEncoder objects are - * usually created on the stack of the encoding functions. - * - * The example below initializes a CborEncoder object with a buffer and encodes - * a single integer. - * - * \code - * uint8_t buf[16]; - * CborEncoder encoder; - * cbor_encoder_init(&encoder, &buf, sizeof(buf), 0); - * cbor_encode_int(&encoder, some_value); - * \endcode - * - * As explained before, usually the outermost CborEncoder object is used to add - * one array or map, which in turn contains multiple elements. The example - * below creates a CBOR map with one element: a key "foo" and a boolean value. - * - * \code - * uint8_t buf[16]; - * CborEncoder encoder, mapEncoder; - * cbor_encoder_init(&encoder, &buf, sizeof(buf), 0); - * cbor_encoder_create_map(&encoder, &mapEncoder, 1); - * cbor_encode_text_stringz(&mapEncoder, "foo"); - * cbor_encode_boolean(&mapEncoder, some_value); - * cbor_encoder_close_container(&encoder, &mapEncoder); - * \endcode - * - *

Error checking and buffer size

- * - * All functions operating on CborEncoder return a condition of type CborError. - * If the encoding was successful, they return CborNoError. Some functions do - * extra checking on the input provided and may return some other error - * conditions (for example, cbor_encode_simple_value() checks that the type is - * of the correct type). - * - * In addition, all functions check whether the buffer has enough bytes to - * encode the item being appended. If that is not possible, they return - * CborErrorOutOfMemory. - * - * It is possible to continue with the encoding of data past the first function - * that returns CborErrorOutOfMemory. CborEncoder functions will not overrun - * the buffer, but will instead count how many more bytes are needed to - * complete the encoding. At the end, you can obtain that count by calling - * cbor_encoder_get_extra_bytes_needed(). - * - * \section1 Finalizing the encoding - * - * Once all items have been appended and the containers have all been properly - * closed, the user-supplied buffer will contain the CBOR stream and may be - * immediately used. To obtain the size of the buffer, call - * cbor_encoder_get_buffer_size() with the original buffer pointer. - * - * The example below illustrates how one can encode an item with error checking - * and then pass on the buffer for network sending. - * - * \code - * uint8_t buf[16]; - * CborError err; - * CborEncoder encoder, mapEncoder; - * cbor_encoder_init(&encoder, &buf, sizeof(buf), 0); - * err = cbor_encoder_create_map(&encoder, &mapEncoder, 1); - * if (!err) - * return err; - * err = cbor_encode_text_stringz(&mapEncoder, "foo"); - * if (!err) - * return err; - * err = cbor_encode_boolean(&mapEncoder, some_value); - * if (!err) - * return err; - * err = cbor_encoder_close_container_checked(&encoder, &mapEncoder); - * if (!err) - * return err; - * - * size_t len = cbor_encoder_get_buffer_size(&encoder, buf); - * send_payload(buf, len); - * return CborNoError; - * \endcode - * - * Finally, the example below expands on the one above and also - * deals with dynamically growing the buffer if the initial allocation wasn't - * big enough. Note the two places where the error checking was replaced with - * an cbor_assertion, showing where the author assumes no error can occur. - * - * \code - * uint8_t *encode_string_array(const char **strings, int n, size_t *bufsize) - * { - * CborError err; - * CborEncoder encoder, arrayEncoder; - * size_t size = 256; - * uint8_t *buf = NULL; - * - * while (1) { - * int i; - * size_t more_bytes; - * uint8_t *nbuf = realloc(buf, size); - * if (nbuf == NULL) - * goto error; - * buf = nbuf; - * - * cbor_encoder_init(&encoder, &buf, size, 0); - * err = cbor_encoder_create_array(&encoder, &arrayEncoder, n); - * cbor_assert(err); // can't fail, the buffer is always big enough - * - * for (i = 0; i < n; ++i) { - * err = cbor_encode_text_stringz(&arrayEncoder, strings[i]); - * if (err && err != CborErrorOutOfMemory) - * goto error; - * } - * - * err = cbor_encoder_close_container_checked(&encoder, &arrayEncoder); - * cbor_assert(err); // shouldn't fail! - * - * more_bytes = cbor_encoder_get_extra_bytes_needed(encoder); - * if (more_size) { - * // buffer wasn't big enough, try again - * size += more_bytes; - * continue; - * } - * - * *bufsize = cbor_encoder_get_buffer_size(encoder, buf); - * return buf; - * } - * error: - * free(buf); - * return NULL; - * } - * \endcode - */ - -/** - * \addtogroup CborEncoding - * @{ - */ - -/** - * \struct CborEncoder - * Structure used to encode to CBOR. - */ - -/** - * Initializes a CborEncoder structure \a encoder by pointing it to buffer \a - * buffer of size \a size. The \a flags field is currently unused and must be - * zero. - */ -void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags) -{ - encoder->data.ptr = buffer; - encoder->end = buffer + size; - encoder->remaining = 2; - encoder->flags = flags; -} - -static inline void put16(void *where, uint16_t v) -{ - v = cbor_htons(v); - memcpy(where, &v, sizeof(v)); -} - -/* Note: Since this is currently only used in situations where OOM is the only - * valid error, we KNOW this to be true. Thus, this function now returns just 'true', - * but if in the future, any function starts returning a non-OOM error, this will need - * to be changed to the test. At the moment, this is done to prevent more branches - * being created in the tinycbor output */ -static inline bool isOomError(CborError err) -{ - (void) err; - return true; -} - -static inline void put32(void *where, uint32_t v) -{ - v = cbor_htonl(v); - memcpy(where, &v, sizeof(v)); -} - -static inline void put64(void *where, uint64_t v) -{ - v = cbor_htonll(v); - memcpy(where, &v, sizeof(v)); -} - -static inline bool would_overflow(CborEncoder *encoder, size_t len) -{ - ptrdiff_t remaining = (ptrdiff_t)encoder->end; - remaining -= remaining ? (ptrdiff_t)encoder->data.ptr : encoder->data.bytes_needed; - remaining -= (ptrdiff_t)len; - return unlikely(remaining < 0); -} - -static inline void advance_ptr(CborEncoder *encoder, size_t n) -{ - if (encoder->end) - encoder->data.ptr += n; - else - encoder->data.bytes_needed += n; -} - -static inline CborError append_to_buffer(CborEncoder *encoder, const void *data, size_t len) -{ - if (would_overflow(encoder, len)) { - if (encoder->end != NULL) { - len -= encoder->end - encoder->data.ptr; - encoder->end = NULL; - encoder->data.bytes_needed = 0; - } - - advance_ptr(encoder, len); - return CborErrorOutOfMemory; - } - - memcpy(encoder->data.ptr, data, len); - encoder->data.ptr += len; - return CborNoError; -} - -static inline CborError append_byte_to_buffer(CborEncoder *encoder, uint8_t byte) -{ - return append_to_buffer(encoder, &byte, 1); -} - -static inline CborError encode_number_no_update(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType) -{ - /* Little-endian would have been so much more convenient here: - * We could just write at the beginning of buf but append_to_buffer - * only the necessary bytes. - * Since it has to be big endian, do it the other way around: - * write from the end. */ - uint64_t buf[2]; - uint8_t *const bufend = (uint8_t *)buf + sizeof(buf); - uint8_t *bufstart = bufend - 1; - put64(buf + 1, ui); /* we probably have a bunch of zeros in the beginning */ - - if (ui < Value8Bit) { - *bufstart += shiftedMajorType; - } else { - uint8_t more = 0; - if (ui > 0xffU) - ++more; - if (ui > 0xffffU) - ++more; - if (ui > 0xffffffffU) - ++more; - bufstart -= (size_t)1 << more; - *bufstart = shiftedMajorType + Value8Bit + more; - } - - return append_to_buffer(encoder, bufstart, bufend - bufstart); -} - -static inline void saturated_decrement(CborEncoder *encoder) -{ - if (encoder->remaining) - --encoder->remaining; -} - -static inline CborError encode_number(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType) -{ - saturated_decrement(encoder); - return encode_number_no_update(encoder, ui, shiftedMajorType); -} - -/** - * Appends the unsigned 64-bit integer \a value to the CBOR stream provided by - * \a encoder. - * - * \sa cbor_encode_negative_int, cbor_encode_int - */ -CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value) -{ - return encode_number(encoder, value, UnsignedIntegerType << MajorTypeShift); -} - -/** - * Appends the negative 64-bit integer whose absolute value is \a - * absolute_value to the CBOR stream provided by \a encoder. - * - * If the value \a absolute_value is zero, this function encodes -2^64. - * - * \sa cbor_encode_uint, cbor_encode_int - */ -CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value) -{ - return encode_number(encoder, absolute_value - 1, NegativeIntegerType << MajorTypeShift); -} - -/** - * Appends the signed 64-bit integer \a value to the CBOR stream provided by - * \a encoder. - * - * \sa cbor_encode_negative_int, cbor_encode_uint - */ -CborError cbor_encode_int(CborEncoder *encoder, int64_t value) -{ - /* adapted from code in RFC 7049 appendix C (pseudocode) */ - uint64_t ui = value >> 63; /* extend sign to whole length */ - uint8_t majorType = ui & 0x20; /* extract major type */ - ui ^= value; /* complement negatives */ - return encode_number(encoder, ui, majorType); -} - -/** - * Appends the CBOR Simple Type of value \a value to the CBOR stream provided by - * \a encoder. - * - * This function may return error CborErrorIllegalSimpleType if the \a value - * variable contains a number that is not a valid simple type. - */ -CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value) -{ -#ifndef CBOR_ENCODER_NO_CHECK_USER - /* check if this is a valid simple type */ - if (value >= HalfPrecisionFloat && value <= Break) - return CborErrorIllegalSimpleType; -#endif - return encode_number(encoder, value, SimpleTypesType << MajorTypeShift); -} - -/** - * Appends the floating-point value of type \a fpType and pointed to by \a - * value to the CBOR stream provided by \a encoder. The value of \a fpType must - * be one of CborHalfFloatType, CborFloatType or CborDoubleType, otherwise the - * behavior of this function is undefined. - * - * This function is useful for code that needs to pass through floating point - * values but does not wish to have the actual floating-point code. - * - * \sa cbor_encode_half_float, cbor_encode_float, cbor_encode_double - */ -CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value) -{ - unsigned size; - uint8_t buf[1 + sizeof(uint64_t)]; - cbor_assert(fpType == CborHalfFloatType || fpType == CborFloatType || fpType == CborDoubleType); - buf[0] = fpType; - - size = 2U << (fpType - CborHalfFloatType); - if (size == 8) - put64(buf + 1, *(const uint64_t*)value); - else if (size == 4) - put32(buf + 1, *(const uint32_t*)value); - else - put16(buf + 1, *(const uint16_t*)value); - saturated_decrement(encoder); - return append_to_buffer(encoder, buf, size + 1); -} - -/** - * Appends the CBOR tag \a tag to the CBOR stream provided by \a encoder. - * - * \sa CborTag - */ -CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag) -{ - /* tags don't count towards the number of elements in an array or map */ - return encode_number_no_update(encoder, tag, TagType << MajorTypeShift); -} - -static CborError encode_string(CborEncoder *encoder, size_t length, uint8_t shiftedMajorType, const void *string) -{ - CborError err = encode_number(encoder, length, shiftedMajorType); - if (err && !isOomError(err)) - return err; - return append_to_buffer(encoder, string, length); -} - -/** - * \fn CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string) - * - * Appends the null-terminated text string \a string to the CBOR stream - * provided by \a encoder. CBOR requires that \a string be valid UTF-8, but - * TinyCBOR makes no verification of correctness. The terminating null is not - * included in the stream. - * - * \sa cbor_encode_text_string, cbor_encode_byte_string - */ - -/** - * Appends the text string \a string of length \a length to the CBOR stream - * provided by \a encoder. CBOR requires that \a string be valid UTF-8, but - * TinyCBOR makes no verification of correctness. - * - * \sa CborError cbor_encode_text_stringz, cbor_encode_byte_string - */ -CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length) -{ - return encode_string(encoder, length, ByteStringType << MajorTypeShift, string); -} - -/** - * Appends the byte string \a string of length \a length to the CBOR stream - * provided by \a encoder. CBOR byte strings are arbitrary raw data. - * - * \sa cbor_encode_text_stringz, cbor_encode_text_string - */ -CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length) -{ - return encode_string(encoder, length, TextStringType << MajorTypeShift, string); -} - -#ifdef __GNUC__ -__attribute__((noinline)) -#endif -static CborError create_container(CborEncoder *encoder, CborEncoder *container, size_t length, uint8_t shiftedMajorType) -{ - CborError err; - container->data.ptr = encoder->data.ptr; - container->end = encoder->end; - saturated_decrement(encoder); - container->remaining = length + 1; /* overflow ok on CborIndefiniteLength */ - - cbor_static_assert(((MapType << MajorTypeShift) & CborIteratorFlag_ContainerIsMap) == CborIteratorFlag_ContainerIsMap); - cbor_static_assert(((ArrayType << MajorTypeShift) & CborIteratorFlag_ContainerIsMap) == 0); - container->flags = shiftedMajorType & CborIteratorFlag_ContainerIsMap; - - if (length == CborIndefiniteLength) { - container->flags |= CborIteratorFlag_UnknownLength; - err = append_byte_to_buffer(container, shiftedMajorType + IndefiniteLength); - } else { - if (shiftedMajorType & CborIteratorFlag_ContainerIsMap) - container->remaining += length; - err = encode_number_no_update(container, length, shiftedMajorType); - } - return err; -} - -/** - * Creates a CBOR array in the CBOR stream provided by \a encoder and - * initializes \a arrayEncoder so that items can be added to the array using - * the CborEncoder functions. The array must be terminated by calling either - * cbor_encoder_close_container() or cbor_encoder_close_container_checked() - * with the same \a encoder and \a arrayEncoder parameters. - * - * The number of items inserted into the array must be exactly \a length items, - * otherwise the stream is invalid. If the number of items is not known when - * creating the array, the constant \ref CborIndefiniteLength may be passed as - * length instead. - * - * \sa cbor_encoder_create_map - */ -CborError cbor_encoder_create_array(CborEncoder *encoder, CborEncoder *arrayEncoder, size_t length) -{ - return create_container(encoder, arrayEncoder, length, ArrayType << MajorTypeShift); -} - -/** - * Creates a CBOR map in the CBOR stream provided by \a encoder and - * initializes \a mapEncoder so that items can be added to the map using - * the CborEncoder functions. The map must be terminated by calling either - * cbor_encoder_close_container() or cbor_encoder_close_container_checked() - * with the same \a encoder and \a mapEncoder parameters. - * - * The number of pair of items inserted into the map must be exactly \a length - * items, otherwise the stream is invalid. If the number is not known - * when creating the map, the constant \ref CborIndefiniteLength may be passed as - * length instead. - * - * \b{Implementation limitation:} TinyCBOR cannot encode more than SIZE_MAX/2 - * key-value pairs in the stream. If the length \a length is larger than this - * value (and is not \ref CborIndefiniteLength), this function returns error - * CborErrorDataTooLarge. - * - * \sa cbor_encoder_create_array - */ -CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length) -{ - if (length != CborIndefiniteLength && length > SIZE_MAX / 2) - return CborErrorDataTooLarge; - return create_container(encoder, mapEncoder, length, MapType << MajorTypeShift); -} - -/** - * Closes the CBOR container (array or map) provided by \a containerEncoder and - * updates the CBOR stream provided by \a encoder. Both parameters must be the - * same as were passed to cbor_encoder_create_array() or - * cbor_encoder_create_map(). - * - * Since version 0.5, this function verifies that the number of items (or pairs - * of items, in the case of a map) was correct. It is no longer necessary to call - * cbor_encoder_close_container_checked() instead. - * - * \sa cbor_encoder_create_array(), cbor_encoder_create_map() - */ -CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder) -{ - if (encoder->end) - encoder->data.ptr = containerEncoder->data.ptr; - else - encoder->data.bytes_needed = containerEncoder->data.bytes_needed; - encoder->end = containerEncoder->end; - if (containerEncoder->flags & CborIteratorFlag_UnknownLength) - return append_byte_to_buffer(encoder, BreakByte); - - if (containerEncoder->remaining != 1) - return containerEncoder->remaining == 0 ? CborErrorTooManyItems : CborErrorTooFewItems; - - if (!encoder->end) - return CborErrorOutOfMemory; /* keep the state */ - return CborNoError; -} - -/** - * \fn CborError cbor_encode_boolean(CborEncoder *encoder, bool value) - * - * Appends the boolean value \a value to the CBOR stream provided by \a encoder. - */ - -/** - * \fn CborError cbor_encode_null(CborEncoder *encoder) - * - * Appends the CBOR type representing a null value to the CBOR stream provided - * by \a encoder. - * - * \sa cbor_encode_undefined() - */ - -/** - * \fn CborError cbor_encode_undefined(CborEncoder *encoder) - * - * Appends the CBOR type representing an undefined value to the CBOR stream - * provided by \a encoder. - * - * \sa cbor_encode_null() - */ - -/** - * \fn CborError cbor_encode_half_float(CborEncoder *encoder, const void *value) - * - * Appends the IEEE 754 half-precision (16-bit) floating point value pointed to - * by \a value to the CBOR stream provided by \a encoder. - * - * \sa cbor_encode_floating_point(), cbor_encode_float(), cbor_encode_double() - */ - -/** - * \fn CborError cbor_encode_float(CborEncoder *encoder, float value) - * - * Appends the IEEE 754 single-precision (32-bit) floating point value \a value - * to the CBOR stream provided by \a encoder. - * - * \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_double() - */ - -/** - * \fn CborError cbor_encode_double(CborEncoder *encoder, double value) - * - * Appends the IEEE 754 double-precision (64-bit) floating point value \a value - * to the CBOR stream provided by \a encoder. - * - * \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_float() - */ - -/** - * \fn size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer) - * - * Returns the total size of the buffer starting at \a buffer after the - * encoding finished without errors. The \a encoder and \a buffer arguments - * must be the same as supplied to cbor_encoder_init(). - * - * If the encoding process had errors, the return value of this function is - * meaningless. If the only errors were CborErrorOutOfMemory, instead use - * cbor_encoder_get_extra_bytes_needed() to find out by how much to grow the - * buffer before encoding again. - * - * See \ref CborEncoding for an example of using this function. - * - * \sa cbor_encoder_init(), cbor_encoder_get_extra_bytes_needed(), CborEncoding - */ - -/** - * \fn size_t cbor_encoder_get_extra_bytes_needed(const CborEncoder *encoder) - * - * Returns how many more bytes the original buffer supplied to - * cbor_encoder_init() needs to be extended by so that no CborErrorOutOfMemory - * condition will happen for the encoding. If the buffer was big enough, this - * function returns 0. The \a encoder must be the original argument as passed - * to cbor_encoder_init(). - * - * This function is usually called after an encoding sequence ended with one or - * more CborErrorOutOfMemory errors, but no other error. If any other error - * happened, the return value of this function is meaningless. - * - * See \ref CborEncoding for an example of using this function. - * - * \sa cbor_encoder_init(), cbor_encoder_get_buffer_size(), CborEncoding - */ - -#pragma GCC diagnostic pop - -/** @} */ diff --git a/src/cbor/lib/tinycbor/src/cborencoder_close_container_checked.c b/src/cbor/lib/tinycbor/src/cborencoder_close_container_checked.c deleted file mode 100644 index 1165d370..00000000 --- a/src/cbor/lib/tinycbor/src/cborencoder_close_container_checked.c +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \addtogroup CborEncoding - * @{ - */ - -/** - * @deprecated - * - * Closes the CBOR container (array or map) provided by \a containerEncoder and - * updates the CBOR stream provided by \a encoder. Both parameters must be the - * same as were passed to cbor_encoder_create_array() or - * cbor_encoder_create_map(). - * - * Prior to version 0.5, cbor_encoder_close_container() did not check the - * number of items added. Since that version, it does and now - * cbor_encoder_close_container_checked() is no longer needed. - * - * \sa cbor_encoder_create_array(), cbor_encoder_create_map() - */ -CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder) -{ - return cbor_encoder_close_container(encoder, containerEncoder); -} - -#pragma GCC diagnostic pop - -/** @} */ diff --git a/src/cbor/lib/tinycbor/src/cborerrorstrings.c b/src/cbor/lib/tinycbor/src/cborerrorstrings.c deleted file mode 100644 index d0ba66c3..00000000 --- a/src/cbor/lib/tinycbor/src/cborerrorstrings.c +++ /dev/null @@ -1,190 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#include "cbor.h" - -#ifndef _ -# define _(msg) msg -#endif - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \enum CborError - * \ingroup CborGlobals - * The CborError enum contains the possible error values used by the CBOR encoder and decoder. - * - * TinyCBOR functions report success by returning CborNoError, or one error - * condition by returning one of the values below. One exception is the - * out-of-memory condition (CborErrorOutOfMemory), which the functions for \ref - * CborEncoding may report in bit-wise OR with other conditions. - * - * This technique allows code to determine whether the only error condition was - * a lack of buffer space, which may not be a fatal condition if the buffer can - * be resized. Additionally, the functions for \ref CborEncoding may continue - * to be used even after CborErrorOutOfMemory is returned, and instead they - * will simply calculate the extra space needed. - * - * \value CborNoError No error occurred - * \omitvalue CborUnknownError - * \value CborErrorUnknownLength Request for the length of an array, map or string whose length is not provided in the CBOR stream - * \value CborErrorAdvancePastEOF Not enough data in the stream to decode item (decoding would advance past end of stream) - * \value CborErrorIO An I/O error occurred, probably due to an out-of-memory situation - * \value CborErrorGarbageAtEnd Bytes exist past the end of the CBOR stream - * \value CborErrorUnexpectedEOF End of stream reached unexpectedly - * \value CborErrorUnexpectedBreak A CBOR break byte was found where not expected - * \value CborErrorUnknownType An unknown type (future extension to CBOR) was found in the stream - * \value CborErrorIllegalType An invalid type was found while parsing a chunked CBOR string - * \value CborErrorIllegalNumber An illegal initial byte (encoding unspecified additional information) was found - * \value CborErrorIllegalSimpleType An illegal encoding of a CBOR Simple Type of value less than 32 was found - * \omitvalue CborErrorUnknownSimpleType - * \omitvalue CborErrorUnknownTag - * \omitvalue CborErrorInappropriateTagForType - * \omitvalue CborErrorDuplicateObjectKeys - * \value CborErrorInvalidUtf8TextString Illegal UTF-8 encoding found while parsing CBOR Text String - * \value CborErrorTooManyItems Too many items were added to CBOR map or array of pre-determined length - * \value CborErrorTooFewItems Too few items were added to CBOR map or array of pre-determined length - * \value CborErrorDataTooLarge Data item size exceeds TinyCBOR's implementation limits - * \value CborErrorNestingTooDeep Data item nesting exceeds TinyCBOR's implementation limits - * \omitvalue CborErrorUnsupportedType - * \value CborErrorJsonObjectKeyIsAggregate Conversion to JSON failed because the key in a map is a CBOR map or array - * \value CborErrorJsonObjectKeyNotString Conversion to JSON failed because the key in a map is not a text string - * \value CborErrorOutOfMemory During CBOR encoding, the buffer provided is insufficient for encoding the data item; - * in other situations, TinyCBOR failed to allocate memory - * \value CborErrorInternalError An internal error occurred in TinyCBOR - */ - -/** - * \ingroup CborGlobals - * Returns the error string corresponding to the CBOR error condition \a error. - */ -const char *cbor_error_string(CborError error) -{ - switch (error) { - case CborNoError: - return ""; - - case CborUnknownError: - return _("unknown error"); - - case CborErrorOutOfMemory: - return _("out of memory/need more memory"); - - case CborErrorUnknownLength: - return _("unknown length (attempted to get the length of a map/array/string of indeterminate length"); - - case CborErrorAdvancePastEOF: - return _("attempted to advance past EOF"); - - case CborErrorIO: - return _("I/O error"); - - case CborErrorGarbageAtEnd: - return _("garbage after the end of the content"); - - case CborErrorUnexpectedEOF: - return _("unexpected end of data"); - - case CborErrorUnexpectedBreak: - return _("unexpected 'break' byte"); - - case CborErrorUnknownType: - return _("illegal byte (encodes future extension type)"); - - case CborErrorIllegalType: - return _("mismatched string type in chunked string"); - - case CborErrorIllegalNumber: - return _("illegal initial byte (encodes unspecified additional information)"); - - case CborErrorIllegalSimpleType: - return _("illegal encoding of simple type smaller than 32"); - - case CborErrorUnknownSimpleType: - return _("unknown simple type"); - - case CborErrorUnknownTag: - return _("unknown tag"); - - case CborErrorInappropriateTagForType: - return _("inappropriate tag for type"); - - case CborErrorDuplicateObjectKeys: - return _("duplicate keys in object"); - - case CborErrorInvalidUtf8TextString: - return _("invalid UTF-8 content in string"); - - case CborErrorExcludedType: - return _("excluded type found"); - - case CborErrorExcludedValue: - return _("excluded value found"); - - case CborErrorImproperValue: - case CborErrorOverlongEncoding: - return _("value encoded in non-canonical form"); - - case CborErrorMapKeyNotString: - case CborErrorJsonObjectKeyNotString: - return _("key in map is not a string"); - - case CborErrorMapNotSorted: - return _("map is not sorted"); - - case CborErrorMapKeysNotUnique: - return _("map keys are not unique"); - - case CborErrorTooManyItems: - return _("too many items added to encoder"); - - case CborErrorTooFewItems: - return _("too few items added to encoder"); - - case CborErrorSplitItems: - return _("splitted item added to encoder"); - - case CborErrorDataTooLarge: - return _("internal error: data too large"); - - case CborErrorNestingTooDeep: - return _("internal error: too many nested containers found in recursive function"); - - case CborErrorUnsupportedType: - return _("unsupported type"); - - case CborErrorJsonObjectKeyIsAggregate: - return _("conversion to JSON failed: key in object is an array or map"); - - case CborErrorJsonNotImplemented: - return _("conversion to JSON failed: open_memstream unavailable"); - - case CborErrorInternalError: - return _("internal error"); - } - return cbor_error_string(CborUnknownError); -} - -#pragma GCC diagnostic pop diff --git a/src/cbor/lib/tinycbor/src/cborinternal_p.h b/src/cbor/lib/tinycbor/src/cborinternal_p.h deleted file mode 100644 index a85a9297..00000000 --- a/src/cbor/lib/tinycbor/src/cborinternal_p.h +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#ifndef CBORINTERNAL_P_H -#define CBORINTERNAL_P_H - -#include "compilersupport_p.h" - -#ifndef CBOR_NO_FLOATING_POINT -# include -# include -#else -# ifndef CBOR_NO_HALF_FLOAT_TYPE -# define CBOR_NO_HALF_FLOAT_TYPE 1 -# endif -#endif - -#ifndef CBOR_NO_HALF_FLOAT_TYPE -# ifdef __F16C__ -# include -static inline unsigned short encode_half(double val) -{ - return _cvtss_sh((float)val, 3); -} -static inline double decode_half(unsigned short half) -{ - return _cvtsh_ss(half); -} -# else -/* software implementation of float-to-fp16 conversions */ -static inline unsigned short encode_half(double val) -{ - uint64_t v; - int sign, exp, mant; - memcpy(&v, &val, sizeof(v)); - sign = v >> 63 << 15; - exp = (v >> 52) & 0x7ff; - mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */ - exp -= 1023; - if (exp == 1024) { - /* infinity or NaN */ - exp = 16; - mant >>= 1; - } else if (exp >= 16) { - /* overflow, as largest number */ - exp = 15; - mant = 1023; - } else if (exp >= -14) { - /* regular normal */ - } else if (exp >= -24) { - /* subnormal */ - mant |= 1024; - mant >>= -(exp + 14); - exp = -15; - } else { - /* underflow, make zero */ - return 0; - } - - /* safe cast here as bit operations above guarantee not to overflow */ - return (unsigned short)(sign | ((exp + 15) << 10) | mant); -} - -/* this function was copied & adapted from RFC 7049 Appendix D */ -static inline double decode_half(unsigned short half) -{ - 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 half & 0x8000 ? -val : val; -} -# endif -#endif /* CBOR_NO_HALF_FLOAT_TYPE */ - -#ifndef CBOR_INTERNAL_API -# define CBOR_INTERNAL_API -#endif - -#ifndef CBOR_PARSER_MAX_RECURSIONS -# define CBOR_PARSER_MAX_RECURSIONS 1024 -#endif - -/* - * CBOR Major types - * Encoded in the high 3 bits of the descriptor byte - * See http://tools.ietf.org/html/rfc7049#section-2.1 - */ -typedef enum CborMajorTypes { - UnsignedIntegerType = 0U, - NegativeIntegerType = 1U, - ByteStringType = 2U, - TextStringType = 3U, - ArrayType = 4U, - MapType = 5U, /* a.k.a. object */ - TagType = 6U, - SimpleTypesType = 7U -} CborMajorTypes; - -/* - * CBOR simple and floating point types - * Encoded in the low 8 bits of the descriptor byte when the - * Major Type is 7. - */ -typedef enum CborSimpleTypes { - FalseValue = 20, - TrueValue = 21, - NullValue = 22, - UndefinedValue = 23, - SimpleTypeInNextByte = 24, /* not really a simple type */ - HalfPrecisionFloat = 25, /* ditto */ - SinglePrecisionFloat = 26, /* ditto */ - DoublePrecisionFloat = 27, /* ditto */ - Break = 31 -} CborSimpleTypes; - -enum { - SmallValueBitLength = 5U, - SmallValueMask = (1U << SmallValueBitLength) - 1, /* 31 */ - Value8Bit = 24U, - Value16Bit = 25U, - Value32Bit = 26U, - Value64Bit = 27U, - IndefiniteLength = 31U, - - MajorTypeShift = SmallValueBitLength, - MajorTypeMask = (int) (~0U << MajorTypeShift), - - BreakByte = (unsigned)Break | (SimpleTypesType << MajorTypeShift) -}; - -CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_extract_number(const uint8_t **ptr, const uint8_t *end, uint64_t *len); -CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_prepare_string_iteration(CborValue *it); -CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_get_string_chunk(const CborValue *value, const void **bufferptr, - size_t *len, CborValue *next); - - -#endif /* CBORINTERNAL_P_H */ diff --git a/src/cbor/lib/tinycbor/src/cborjson.h b/src/cbor/lib/tinycbor/src/cborjson.h deleted file mode 100644 index 8ff27b92..00000000 --- a/src/cbor/lib/tinycbor/src/cborjson.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#ifndef CBORJSON_H -#define CBORJSON_H - -#include "cbor.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Conversion to JSON */ -enum CborToJsonFlags -{ - CborConvertAddMetadata = 1, - CborConvertTagsToObjects = 2, - CborConvertIgnoreTags = 0, - - CborConvertObeyByteStringTags = 0, - CborConvertByteStringsToBase64Url = 4, - - CborConvertRequireMapStringKeys = 0, - CborConvertStringifyMapKeys = 8, - - CborConvertDefaultFlags = 0 -}; - -CBOR_API CborError cbor_value_to_json_advance(FILE *out, CborValue *value, int flags); -CBOR_INLINE_API CborError cbor_value_to_json(FILE *out, const CborValue *value, int flags) -{ - CborValue copy = *value; - return cbor_value_to_json_advance(out, ©, flags); -} - -#ifdef __cplusplus -} -#endif - -#endif /* CBORJSON_H */ - diff --git a/src/cbor/lib/tinycbor/src/cborparser.c b/src/cbor/lib/tinycbor/src/cborparser.c deleted file mode 100644 index 42815923..00000000 --- a/src/cbor/lib/tinycbor/src/cborparser.c +++ /dev/null @@ -1,1435 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#ifndef _BSD_SOURCE -#define _BSD_SOURCE 1 -#endif -#ifndef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE 1 -#endif -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" - -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \defgroup CborParsing Parsing CBOR streams - * \brief Group of functions used to parse CBOR streams. - * - * TinyCBOR provides functions for pull-based stream parsing of a CBOR-encoded - * payload. The main data type for the parsing is a CborValue, which behaves - * like an iterator and can be used to extract the encoded data. It is first - * initialized with a call to cbor_parser_init() and is usually used to extract - * exactly one item, most often an array or map. - * - * Nested CborValue objects can be parsed using cbor_value_enter_container(). - * Each call to cbor_value_enter_container() must be matched by a call to - * cbor_value_leave_container(), with the exact same parameters. - * - * The example below initializes a CborParser object, begins the parsing with a - * CborValue and decodes a single integer: - * - * \code - * int extract_int(const uint8_t *buffer, size_t len) - * { - * CborParser parser; - * CborValue value; - * int result; - * cbor_parser_init(buffer, len, 0, &parser, &value); - * cbor_value_get_int(&value, &result); - * return result; - * } - * \endcode - * - * The code above does no error checking, which means it assumes the data comes - * from a source trusted to send one properly-encoded integer. The following - * example does the exact same operation, but includes error checking and - * returns 0 on parsing failure: - * - * \code - * int extract_int(const uint8_t *buffer, size_t len) - * { - * CborParser parser; - * CborValue value; - * int result; - * if (cbor_parser_init(buffer, len, 0, &parser, &value) != CborNoError) - * return 0; - * if (!cbor_value_is_integer(&value) || - * cbor_value_get_int(&value, &result) != CborNoError) - * return 0; - * return result; - * } - * \endcode - * - * Note, in the example above, that one can't distinguish a parsing failure - * from an encoded value of zero. Reporting a parsing error is left as an - * exercise to the reader. - * - * The code above does not execute a range-check either: it is possible that - * the value decoded from the CBOR stream encodes a number larger than what can - * be represented in a variable of type \c{int}. If detecting that case is - * important, the code should call cbor_value_get_int_checked() instead. - * - *

Memory and parsing constraints

- * - * TinyCBOR is designed to run with little memory and with minimal overhead. - * Except where otherwise noted, the parser functions always run on constant - * time (O(1)), do not recurse and never allocate memory (thus, stack usage is - * bounded and is O(1)). - * - *

Error handling and preconditions

- * - * All functions operating on a CborValue return a CborError condition, with - * CborNoError standing for the normal situation in which no parsing error - * occurred. All functions may return parsing errors in case the stream cannot - * be decoded properly, be it due to corrupted data or due to reaching the end - * of the input buffer. - * - * Error conditions must not be ignored. All decoder functions have undefined - * behavior if called after an error has been reported, and may crash. - * - * Some functions are also documented to have preconditions, like - * cbor_value_get_int() requiring that the input be an integral value. - * Violation of preconditions also results in undefined behavior and the - * program may crash. - */ - -/** - * \addtogroup CborParsing - * @{ - */ - -/** - * \struct CborValue - * - * This type contains one value parsed from the CBOR stream. Each CborValue - * behaves as an iterator in a StAX-style parser. - * - * \if privatedocs - * Implementation details: the CborValue contains these fields: - * \list - * \li ptr: pointer to the actual data - * \li flags: flags from the decoder - * \li extra: partially decoded integer value (0, 1 or 2 bytes) - * \li remaining: remaining items in this collection after this item or UINT32_MAX if length is unknown - * \endlist - * \endif - */ - -static inline uint16_t get16(const uint8_t *ptr) -{ - uint16_t result; - memcpy(&result, ptr, sizeof(result)); - return cbor_ntohs(result); -} - -static inline uint32_t get32(const uint8_t *ptr) -{ - uint32_t result; - memcpy(&result, ptr, sizeof(result)); - return cbor_ntohl(result); -} - -static inline uint64_t get64(const uint8_t *ptr) -{ - uint64_t result; - memcpy(&result, ptr, sizeof(result)); - return cbor_ntohll(result); -} - -CborError CBOR_INTERNAL_API_CC _cbor_value_extract_number(const uint8_t **ptr, const uint8_t *end, uint64_t *len) -{ - size_t bytesNeeded; - uint8_t additional_information = **ptr & SmallValueMask; - ++*ptr; - if (additional_information < Value8Bit) { - *len = additional_information; - return CborNoError; - } - if (unlikely(additional_information > Value64Bit)) - return CborErrorIllegalNumber; - - bytesNeeded = (size_t)(1 << (additional_information - Value8Bit)); - if (unlikely(bytesNeeded > (size_t)(end - *ptr))) { - return CborErrorUnexpectedEOF; - } else if (bytesNeeded == 1) { - *len = (uint8_t)(*ptr)[0]; - } else if (bytesNeeded == 2) { - *len = get16(*ptr); - } else if (bytesNeeded == 4) { - *len = get32(*ptr); - } else { - *len = get64(*ptr); - } - *ptr += bytesNeeded; - return CborNoError; -} - -static CborError extract_length(const CborParser *parser, const uint8_t **ptr, size_t *len) -{ - uint64_t v; - CborError err = _cbor_value_extract_number(ptr, parser->end, &v); - if (err) { - *len = 0; - return err; - } - - *len = (size_t)v; - if (v != *len) - return CborErrorDataTooLarge; - return CborNoError; -} - -static bool is_fixed_type(uint8_t type) -{ - return type != CborTextStringType && type != CborByteStringType && type != CborArrayType && - type != CborMapType; -} - -static CborError preparse_value(CborValue *it) -{ - const CborParser *parser = it->parser; - it->type = CborInvalidType; - - /* are we at the end? */ - if (it->ptr == parser->end) - return CborErrorUnexpectedEOF; - - uint8_t descriptor = *it->ptr; - uint8_t type = descriptor & MajorTypeMask; - it->type = type; - it->flags = 0; - it->extra = (descriptor &= SmallValueMask); - - if (descriptor > Value64Bit) { - if (unlikely(descriptor != IndefiniteLength)) - return type == CborSimpleType ? CborErrorUnknownType : CborErrorIllegalNumber; - if (likely(!is_fixed_type(type))) { - /* special case */ - it->flags |= CborIteratorFlag_UnknownLength; - it->type = type; - return CborNoError; - } - return type == CborSimpleType ? CborErrorUnexpectedBreak : CborErrorIllegalNumber; - } - - size_t bytesNeeded = descriptor < Value8Bit ? 0 : (1 << (descriptor - Value8Bit)); - if (bytesNeeded + 1 > (size_t)(parser->end - it->ptr)) - return CborErrorUnexpectedEOF; - - uint8_t majortype = type >> MajorTypeShift; - if (majortype == NegativeIntegerType) { - it->flags |= CborIteratorFlag_NegativeInteger; - it->type = CborIntegerType; - } else if (majortype == SimpleTypesType) { - switch (descriptor) { - case FalseValue: - it->extra = false; - it->type = CborBooleanType; - break; - - case SinglePrecisionFloat: - case DoublePrecisionFloat: - it->flags |= CborIteratorFlag_IntegerValueTooLarge; - /* fall through */ - case TrueValue: - case NullValue: - case UndefinedValue: - case HalfPrecisionFloat: - it->type = *it->ptr; - break; - - case SimpleTypeInNextByte: - it->extra = (uint8_t)it->ptr[1]; -#ifndef CBOR_PARSER_NO_STRICT_CHECKS - if (unlikely(it->extra < 32)) { - it->type = CborInvalidType; - return CborErrorIllegalSimpleType; - } -#endif - break; - - case 28: - case 29: - case 30: - case Break: - cbor_assert(false); /* these conditions can't be reached */ - return CborErrorUnexpectedBreak; - } - return CborNoError; - } - - /* try to decode up to 16 bits */ - if (descriptor < Value8Bit) - return CborNoError; - - if (descriptor == Value8Bit) - it->extra = (uint8_t)it->ptr[1]; - else if (descriptor == Value16Bit) - it->extra = get16(it->ptr + 1); - else - it->flags |= CborIteratorFlag_IntegerValueTooLarge; /* Value32Bit or Value64Bit */ - return CborNoError; -} - -static CborError preparse_next_value_nodecrement(CborValue *it) -{ - if (it->remaining == UINT32_MAX && it->ptr != it->parser->end && *it->ptr == (uint8_t)BreakByte) { - /* end of map or array */ - ++it->ptr; - it->type = CborInvalidType; - it->remaining = 0; - return CborNoError; - } - - return preparse_value(it); -} - -static CborError preparse_next_value(CborValue *it) -{ - if (it->remaining != UINT32_MAX) { - /* don't decrement the item count if the current item is tag: they don't count */ - if (it->type != CborTagType && --it->remaining == 0) { - it->type = CborInvalidType; - return CborNoError; - } - } - return preparse_next_value_nodecrement(it); -} - -static CborError advance_internal(CborValue *it) -{ - uint64_t length; - CborError err = _cbor_value_extract_number(&it->ptr, it->parser->end, &length); - cbor_assert(err == CborNoError); - - if (it->type == CborByteStringType || it->type == CborTextStringType) { - cbor_assert(length == (size_t)length); - cbor_assert((it->flags & CborIteratorFlag_UnknownLength) == 0); - it->ptr += length; - } - - return preparse_next_value(it); -} - -/** \internal - * - * Decodes the CBOR integer value when it is larger than the 16 bits available - * in value->extra. This function requires that value->flags have the - * CborIteratorFlag_IntegerValueTooLarge flag set. - * - * This function is also used to extract single- and double-precision floating - * point values (SinglePrecisionFloat == Value32Bit and DoublePrecisionFloat == - * Value64Bit). - */ -uint64_t _cbor_value_decode_int64_internal(const CborValue *value) -{ - cbor_assert(value->flags & CborIteratorFlag_IntegerValueTooLarge || - value->type == CborFloatType || value->type == CborDoubleType); - - /* since the additional information can only be Value32Bit or Value64Bit, - * we just need to test for the one bit those two options differ */ - cbor_assert((*value->ptr & SmallValueMask) == Value32Bit || (*value->ptr & SmallValueMask) == Value64Bit); - if ((*value->ptr & 1) == (Value32Bit & 1)) - return get32(value->ptr + 1); - - cbor_assert((*value->ptr & SmallValueMask) == Value64Bit); - return get64(value->ptr + 1); -} - -/** - * Initializes the CBOR parser for parsing \a size bytes beginning at \a - * buffer. Parsing will use flags set in \a flags. The iterator to the first - * element is returned in \a it. - * - * The \a parser structure needs to remain valid throughout the decoding - * process. It is not thread-safe to share one CborParser among multiple - * threads iterating at the same time, but the object can be copied so multiple - * threads can iterate. - */ -CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it) -{ - memset(parser, 0, sizeof(*parser)); - parser->end = buffer + size; - parser->flags = flags; - it->parser = parser; - it->ptr = buffer; - it->remaining = 1; /* there's one type altogether, usually an array or map */ - return preparse_value(it); -} - -/** - * \fn bool cbor_value_at_end(const CborValue *it) - * - * Returns true if \a it has reached the end of the iteration, usually when - * advancing after the last item in an array or map. - * - * In the case of the outermost CborValue object, this function returns true - * after decoding a single element. A pointer to the first byte of the - * remaining data (if any) can be obtained with cbor_value_get_next_byte(). - * - * \sa cbor_value_advance(), cbor_value_is_valid(), cbor_value_get_next_byte() - */ - -/** - * \fn const uint8_t *cbor_value_get_next_byte(const CborValue *it) - * - * Returns a pointer to the next byte that would be decoded if this CborValue - * object were advanced. - * - * This function is useful if cbor_value_at_end() returns true for the - * outermost CborValue: the pointer returned is the first byte of the data - * remaining in the buffer, if any. Code can decide whether to begin decoding a - * new CBOR data stream from this point, or parse some other data appended to - * the same buffer. - * - * This function may be used even after a parsing error. If that occurred, - * then this function returns a pointer to where the parsing error occurred. - * Note that the error recovery is not precise and the pointer may not indicate - * the exact byte containing bad data. - * - * \sa cbor_value_at_end() - */ - -/** - * \fn bool cbor_value_is_valid(const CborValue *it) - * - * Returns true if the iterator \a it contains a valid value. Invalid iterators - * happen when iteration reaches the end of a container (see \ref - * cbor_value_at_end()) or when a search function resulted in no matches. - * - * \sa cbor_value_advance(), cbor_value_at_end(), cbor_value_get_type() - */ - -/** - * Performs a basic validation of the CBOR stream pointed by \a it and returns - * the error it found. If no error was found, it returns CborNoError and the - * application can iterate over the items with certainty that no other errors - * will appear during parsing. - * - * A basic validation checks for: - * \list - * \li absence of undefined additional information bytes; - * \li well-formedness of all numbers, lengths, and simple values; - * \li string contents match reported sizes; - * \li arrays and maps contain the number of elements they are reported to have; - * \endlist - * - * For further checks, see cbor_value_validate(). - * - * This function has the same timing and memory requirements as - * cbor_value_advance(). - * - * \sa cbor_value_validate(), cbor_value_advance() - */ -CborError cbor_value_validate_basic(const CborValue *it) -{ - CborValue value = *it; - return cbor_value_advance(&value); -} - -/** - * Advances the CBOR value \a it by one fixed-size position. Fixed-size types - * are: integers, tags, simple types (including boolean, null and undefined - * values) and floating point types. - * - * If the type is not of fixed size, this function has undefined behavior. Code - * must be sure that the current type is one of the fixed-size types before - * calling this function. This function is provided because it can guarantee - * that it runs in constant time (O(1)). - * - * If the caller is not able to determine whether the type is fixed or not, code - * can use the cbor_value_advance() function instead. - * - * \sa cbor_value_at_end(), cbor_value_advance(), cbor_value_enter_container(), cbor_value_leave_container() - */ -CborError cbor_value_advance_fixed(CborValue *it) -{ - cbor_assert(it->type != CborInvalidType); - cbor_assert(is_fixed_type(it->type)); - if (!it->remaining) - return CborErrorAdvancePastEOF; - return advance_internal(it); -} - -static CborError advance_recursive(CborValue *it, int nestingLevel) -{ - CborError err; - CborValue recursed; - - if (is_fixed_type(it->type)) - return advance_internal(it); - - if (!cbor_value_is_container(it)) { - size_t len = SIZE_MAX; - return _cbor_value_copy_string(it, NULL, &len, it); - } - - /* map or array */ - if (nestingLevel == 0) - return CborErrorNestingTooDeep; - - err = cbor_value_enter_container(it, &recursed); - if (err) - return err; - while (!cbor_value_at_end(&recursed)) { - err = advance_recursive(&recursed, nestingLevel - 1); - if (err) - return err; - } - return cbor_value_leave_container(it, &recursed); -} - - -/** - * Advances the CBOR value \a it by one element, skipping over containers. - * Unlike cbor_value_advance_fixed(), this function can be called on a CBOR - * value of any type. However, if the type is a container (map or array) or a - * string with a chunked payload, this function will not run in constant time - * and will recurse into itself (it will run on O(n) time for the number of - * elements or chunks and will use O(n) memory for the number of nested - * containers). - * - * The number of recursions can be limited at compile time to avoid stack - * exhaustion in constrained systems. - * - * \sa cbor_value_at_end(), cbor_value_advance_fixed(), cbor_value_enter_container(), cbor_value_leave_container() - */ -CborError cbor_value_advance(CborValue *it) -{ - cbor_assert(it->type != CborInvalidType); - if (!it->remaining) - return CborErrorAdvancePastEOF; - return advance_recursive(it, CBOR_PARSER_MAX_RECURSIONS); -} - -/** - * \fn bool cbor_value_is_tag(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR tag. - * - * \sa cbor_value_get_tag(), cbor_value_skip_tag() - */ - -/** - * \fn CborError cbor_value_get_tag(const CborValue *value, CborTag *result) - * - * Retrieves the CBOR tag value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to a CBOR tag value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_tag is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_tag() - */ - -/** - * Advances the CBOR value \a it until it no longer points to a tag. If \a it is - * already not pointing to a tag, then this function returns it unchanged. - * - * This function does not run in constant time: it will run on O(n) for n being - * the number of tags. It does use constant memory (O(1) memory requirements). - * - * \sa cbor_value_advance_fixed(), cbor_value_advance() - */ -CborError cbor_value_skip_tag(CborValue *it) -{ - while (cbor_value_is_tag(it)) { - CborError err = cbor_value_advance_fixed(it); - if (err) - return err; - } - return CborNoError; -} - -/** - * \fn bool cbor_value_is_container(const CborValue *it) - * - * Returns true if the \a it value is a container and requires recursion in - * order to decode (maps and arrays), false otherwise. - */ - -/** - * Creates a CborValue iterator pointing to the first element of the container - * represented by \a it and saves it in \a recursed. The \a it container object - * needs to be kept and passed again to cbor_value_leave_container() in order - * to continue iterating past this container. - * - * The \a it CborValue iterator must point to a container. - * - * \sa cbor_value_is_container(), cbor_value_leave_container(), cbor_value_advance() - */ -CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed) -{ - cbor_assert(cbor_value_is_container(it)); - *recursed = *it; - - if (it->flags & CborIteratorFlag_UnknownLength) { - recursed->remaining = UINT32_MAX; - ++recursed->ptr; - } else { - uint64_t len; - CborError err = _cbor_value_extract_number(&recursed->ptr, recursed->parser->end, &len); - cbor_assert(err == CborNoError); - - recursed->remaining = (uint32_t)len; - if (recursed->remaining != len || len == UINT32_MAX) { - /* back track the pointer to indicate where the error occurred */ - recursed->ptr = it->ptr; - return CborErrorDataTooLarge; - } - if (recursed->type == CborMapType) { - /* maps have keys and values, so we need to multiply by 2 */ - if (recursed->remaining > UINT32_MAX / 2) { - /* back track the pointer to indicate where the error occurred */ - recursed->ptr = it->ptr; - return CborErrorDataTooLarge; - } - recursed->remaining *= 2; - } - if (len == 0) { - /* the case of the empty container */ - recursed->type = CborInvalidType; - return CborNoError; - } - } - return preparse_next_value_nodecrement(recursed); -} - -/** - * Updates \a it to point to the next element after the container. The \a - * recursed object needs to point to the element obtained either by advancing - * the last element of the container (via cbor_value_advance(), - * cbor_value_advance_fixed(), a nested cbor_value_leave_container(), or the \c - * next pointer from cbor_value_copy_string() or cbor_value_dup_string()). - * - * The \a it and \a recursed parameters must be the exact same as passed to - * cbor_value_enter_container(). - * - * \sa cbor_value_enter_container(), cbor_value_at_end() - */ -CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed) -{ - cbor_assert(cbor_value_is_container(it)); - cbor_assert(recursed->type == CborInvalidType); - it->ptr = recursed->ptr; - return preparse_next_value(it); -} - - -/** - * \fn CborType cbor_value_get_type(const CborValue *value) - * - * Returns the type of the CBOR value that the iterator \a value points to. If - * \a value does not point to a valid value, this function returns \ref - * CborInvalidType. - * - * TinyCBOR also provides functions to test directly if a given CborValue object - * is of a given type, like cbor_value_is_text_string() and cbor_value_is_null(). - * - * \sa cbor_value_is_valid() - */ - -/** - * \fn bool cbor_value_is_null(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR null type. - * - * \sa cbor_value_is_valid(), cbor_value_is_undefined() - */ - -/** - * \fn bool cbor_value_is_undefined(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR undefined type. - * - * \sa cbor_value_is_valid(), cbor_value_is_null() - */ - -/** - * \fn bool cbor_value_is_boolean(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR boolean - * type (true or false). - * - * \sa cbor_value_is_valid(), cbor_value_get_boolean() - */ - -/** - * \fn CborError cbor_value_get_boolean(const CborValue *value, bool *result) - * - * Retrieves the boolean value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to a boolean value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_boolean is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_boolean() - */ - -/** - * \fn bool cbor_value_is_simple_type(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR Simple Type - * type (other than true, false, null and undefined). - * - * \sa cbor_value_is_valid(), cbor_value_get_simple_type() - */ - -/** - * \fn CborError cbor_value_get_simple_type(const CborValue *value, uint8_t *result) - * - * Retrieves the CBOR Simple Type value that \a value points to and stores it - * in \a result. If the iterator \a value does not point to a simple_type - * value, the behavior is undefined, so checking with \ref cbor_value_get_type - * or with \ref cbor_value_is_simple_type is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_simple_type() - */ - -/** - * \fn bool cbor_value_is_integer(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR integer - * type. - * - * \sa cbor_value_is_valid(), cbor_value_get_int, cbor_value_get_int64, cbor_value_get_uint64, cbor_value_get_raw_integer - */ - -/** - * \fn bool cbor_value_is_unsigned_integer(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR unsigned - * integer type (positive values or zero). - * - * \sa cbor_value_is_valid(), cbor_value_get_uint64() - */ - -/** - * \fn bool cbor_value_is_negative_integer(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR negative - * integer type. - * - * \sa cbor_value_is_valid(), cbor_value_get_int, cbor_value_get_int64, cbor_value_get_raw_integer - */ - -/** - * \fn CborError cbor_value_get_int(const CborValue *value, int *result) - * - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * Note that this function does not do range-checking: integral values that do - * not fit in a variable of type \c{int} are silently truncated to fit. Use - * cbor_value_get_int_checked() if that is not acceptable. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer() - */ - -/** - * \fn CborError cbor_value_get_int64(const CborValue *value, int64_t *result) - * - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * Note that this function does not do range-checking: integral values that do - * not fit in a variable of type \c{int64_t} are silently truncated to fit. Use - * cbor_value_get_int64_checked() that is not acceptable. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer() - */ - -/** - * \fn CborError cbor_value_get_uint64(const CborValue *value, uint64_t *result) - * - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an unsigned integer - * value, the behavior is undefined, so checking with \ref cbor_value_get_type - * or with \ref cbor_value_is_unsigned_integer is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_unsigned_integer() - */ - -/** - * \fn CborError cbor_value_get_raw_integer(const CborValue *value, uint64_t *result) - * - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * This function is provided because CBOR negative integers can assume values - * that cannot be represented with normal 64-bit integer variables. - * - * If the integer is unsigned (that is, if cbor_value_is_unsigned_integer() - * returns true), then \a result will contain the actual value. If the integer - * is negative, then \a result will contain the absolute value of that integer, - * minus one. That is, \c {actual = -result - 1}. On architectures using two's - * complement for representation of negative integers, it is equivalent to say - * that \a result will contain the bitwise negation of the actual value. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer() - */ - -/** - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * Unlike \ref cbor_value_get_int64(), this function performs a check to see if the - * stored integer fits in \a result without data loss. If the number is outside - * the valid range for the data type, this function returns the recoverable - * error CborErrorDataTooLarge. In that case, use either - * cbor_value_get_uint64() (if the number is positive) or - * cbor_value_get_raw_integer(). - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer(), cbor_value_get_int64() - */ -CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result) -{ - uint64_t v; - cbor_assert(cbor_value_is_integer(value)); - v = _cbor_value_extract_int64_helper(value); - - /* Check before converting, as the standard says (C11 6.3.1.3 paragraph 3): - * "[if] the new type is signed and the value cannot be represented in it; either the - * result is implementation-defined or an implementation-defined signal is raised." - * - * The range for int64_t is -2^63 to 2^63-1 (int64_t is required to be - * two's complement, C11 7.20.1.1 paragraph 3), which in CBOR is - * represented the same way, differing only on the "sign bit" (the major - * type). - */ - - if (unlikely(v > (uint64_t)INT64_MAX)) - return CborErrorDataTooLarge; - - *result = v; - if (value->flags & CborIteratorFlag_NegativeInteger) - *result = -*result - 1; - return CborNoError; -} - -/** - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * Unlike \ref cbor_value_get_int(), this function performs a check to see if the - * stored integer fits in \a result without data loss. If the number is outside - * the valid range for the data type, this function returns the recoverable - * error CborErrorDataTooLarge. In that case, use one of the other integer - * functions to obtain the value. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer(), cbor_value_get_int64(), - * cbor_value_get_uint64(), cbor_value_get_int64_checked(), cbor_value_get_raw_integer() - */ -CborError cbor_value_get_int_checked(const CborValue *value, int *result) -{ - uint64_t v; - cbor_assert(cbor_value_is_integer(value)); - v = _cbor_value_extract_int64_helper(value); - - /* Check before converting, as the standard says (C11 6.3.1.3 paragraph 3): - * "[if] the new type is signed and the value cannot be represented in it; either the - * result is implementation-defined or an implementation-defined signal is raised." - * - * But we can convert from signed to unsigned without fault (paragraph 2). - * - * The range for int is implementation-defined and int is not guaranteed to use - * two's complement representation (although int32_t is). - */ - - if (value->flags & CborIteratorFlag_NegativeInteger) { - if (unlikely(v > (unsigned) -(INT_MIN + 1))) - return CborErrorDataTooLarge; - - *result = (int)v; - *result = -*result - 1; - } else { - if (unlikely(v > (uint64_t)INT_MAX)) - return CborErrorDataTooLarge; - - *result = (int)v; - } - return CborNoError; - -} - -/** - * \fn bool cbor_value_is_length_known(const CborValue *value) - * - * Returns true if the length of this type is known without calculation. That - * is, if the length of this CBOR string, map or array is encoded in the data - * stream, this function returns true. If the length is not encoded, it returns - * false. - * - * If the length is known, code can call cbor_value_get_string_length(), - * cbor_value_get_array_length() or cbor_value_get_map_length() to obtain the - * length. If the length is not known but is necessary, code can use the - * cbor_value_calculate_string_length() function (no equivalent function is - * provided for maps and arrays). - */ - -/** - * \fn bool cbor_value_is_text_string(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR text - * string. CBOR text strings are UTF-8 encoded and usually contain - * human-readable text. - * - * \sa cbor_value_is_valid(), cbor_value_get_string_length(), cbor_value_calculate_string_length(), - * cbor_value_copy_text_string(), cbor_value_dup_text_string() - */ - -/** - * \fn bool cbor_value_is_byte_string(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR text - * string. CBOR byte strings are binary data with no specified encoding or - * format. - * - * \sa cbor_value_is_valid(), cbor_value_get_string_length(), cbor_value_calculate_string_length(), - * cbor_value_copy_byte_string(), cbor_value_dup_byte_string() - */ - -/** - * \fn CborError cbor_value_get_string_length(const CborValue *value, size_t *length) - * - * Extracts the length of the byte or text string that \a value points to and - * stores it in \a result. If the iterator \a value does not point to a text - * string or a byte string, the behaviour is undefined, so checking with \ref - * cbor_value_get_type, with \ref cbor_value_is_text_string or \ref - * cbor_value_is_byte_string is recommended. - * - * If the length of this string is not encoded in the CBOR data stream, this - * function will return the recoverable error CborErrorUnknownLength. You may - * also check whether that is the case by using cbor_value_is_length_known(). - * - * If the length of the string is required but the length was not encoded, use - * cbor_value_calculate_string_length(), but note that that function does not - * run in constant time. - * - * \note On 32-bit platforms, this function will return error condition of \ref - * CborErrorDataTooLarge if the stream indicates a length that is too big to - * fit in 32-bit. - * - * \sa cbor_value_is_valid(), cbor_value_is_length_known(), cbor_value_calculate_string_length() - */ - -/** - * Calculates the length of the byte or text string that \a value points to and - * stores it in \a len. If the iterator \a value does not point to a text - * string or a byte string, the behaviour is undefined, so checking with \ref - * cbor_value_get_type, with \ref cbor_value_is_text_string or \ref - * cbor_value_is_byte_string is recommended. - * - * This function is different from cbor_value_get_string_length() in that it - * calculates the length even for strings sent in chunks. For that reason, this - * function may not run in constant time (it will run in O(n) time on the - * number of chunks). It does use constant memory (O(1)). - * - * \note On 32-bit platforms, this function will return error condition of \ref - * CborErrorDataTooLarge if the stream indicates a length that is too big to - * fit in 32-bit. - * - * \sa cbor_value_get_string_length(), cbor_value_copy_text_string(), cbor_value_copy_byte_string(), cbor_value_is_length_known() - */ -CborError cbor_value_calculate_string_length(const CborValue *value, size_t *len) -{ - *len = SIZE_MAX; - return _cbor_value_copy_string(value, NULL, len, NULL); -} - -static inline void prepare_string_iteration(CborValue *it) -{ - if (!cbor_value_is_length_known(it)) { - /* chunked string: we're before the first chunk; - * advance to the first chunk */ - ++it->ptr; - it->flags |= CborIteratorFlag_IteratingStringChunks; - } -} - -CborError CBOR_INTERNAL_API_CC _cbor_value_prepare_string_iteration(CborValue *it) -{ - cbor_assert((it->flags & CborIteratorFlag_IteratingStringChunks) == 0); - prepare_string_iteration(it); - - /* are we at the end? */ - if (it->ptr == it->parser->end) - return CborErrorUnexpectedEOF; - return CborNoError; -} - -static CborError get_string_chunk(CborValue *it, const void **bufferptr, size_t *len) -{ - CborError err; - - /* Possible states: - * length known | iterating | meaning - * no | no | before the first chunk of a chunked string - * yes | no | at a non-chunked string - * no | yes | second or later chunk - * yes | yes | after a non-chunked string - */ - if (it->flags & CborIteratorFlag_IteratingStringChunks) { - /* already iterating */ - if (cbor_value_is_length_known(it)) { - /* if the length was known, it wasn't chunked, so finish iteration */ - goto last_chunk; - } - } else { - prepare_string_iteration(it); - } - - /* are we at the end? */ - if (it->ptr == it->parser->end) - return CborErrorUnexpectedEOF; - - if (*it->ptr == BreakByte) { - /* last chunk */ - ++it->ptr; -last_chunk: - *bufferptr = NULL; - *len = 0; - return preparse_next_value(it); - } else if ((uint8_t)(*it->ptr & MajorTypeMask) == it->type) { - err = extract_length(it->parser, &it->ptr, len); - if (err) - return err; - if (*len > (size_t)(it->parser->end - it->ptr)) - return CborErrorUnexpectedEOF; - - *bufferptr = it->ptr; - it->ptr += *len; - } else { - return CborErrorIllegalType; - } - - it->flags |= CborIteratorFlag_IteratingStringChunks; - return CborNoError; -} - -CborError CBOR_INTERNAL_API_CC -_cbor_value_get_string_chunk(const CborValue *value, const void **bufferptr, - size_t *len, CborValue *next) -{ - CborValue tmp; - if (!next) - next = &tmp; - *next = *value; - return get_string_chunk(next, bufferptr, len); -} - -/* We return uintptr_t so that we can pass memcpy directly as the iteration - * function. The choice is to optimize for memcpy, which is used in the base - * parser API (cbor_value_copy_string), while memcmp is used in convenience API - * only. */ -typedef uintptr_t (*IterateFunction)(char *, const uint8_t *, size_t); - -static uintptr_t iterate_noop(char *dest, const uint8_t *src, size_t len) -{ - (void)dest; - (void)src; - (void)len; - return true; -} - -static uintptr_t iterate_memcmp(char *s1, const uint8_t *s2, size_t len) -{ - return memcmp(s1, (const char *)s2, len) == 0; -} - -static uintptr_t iterate_memcpy(char *dest, const uint8_t *src, size_t len) -{ - return (uintptr_t)memcpy(dest, src, len); -} - -static CborError iterate_string_chunks(const CborValue *value, char *buffer, size_t *buflen, - bool *result, CborValue *next, IterateFunction func) -{ - CborError err; - CborValue tmp; - size_t total = 0; - const void *ptr; - - cbor_assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value)); - if (!next) - next = &tmp; - *next = *value; - *result = true; - - while (1) { - size_t newTotal; - size_t chunkLen; - err = get_string_chunk(next, &ptr, &chunkLen); - if (err) - return err; - if (!ptr) - break; - - if (unlikely(add_check_overflow(total, chunkLen, &newTotal))) - return CborErrorDataTooLarge; - - if (*result && *buflen >= newTotal) - *result = !!func(buffer + total, (const uint8_t *)ptr, chunkLen); - else - *result = false; - - total = newTotal; - } - - /* is there enough room for the ending NUL byte? */ - if (*result && *buflen > total) { - uint8_t nul[] = { 0 }; - *result = !!func(buffer + total, nul, 1); - } - *buflen = total; - return CborNoError; -} - -/** - * \fn CborError cbor_value_copy_text_string(const CborValue *value, char *buffer, size_t *buflen, CborValue *next) - * - * Copies the string pointed to by \a value into the buffer provided at \a buffer - * of \a buflen bytes. If \a buffer is a NULL pointer, this function will not - * copy anything and will only update the \a next value. - * - * If the iterator \a value does not point to a text string, the behaviour is - * undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_text_string is recommended. - * - * If the provided buffer length was too small, this function returns an error - * condition of \ref CborErrorOutOfMemory. If you need to calculate the length - * of the string in order to preallocate a buffer, use - * cbor_value_calculate_string_length(). - * - * On success, this function sets the number of bytes copied to \c{*buflen}. If - * the buffer is large enough, this function will insert a null byte after the - * last copied byte, to facilitate manipulation of text strings. That byte is - * not included in the returned value of \c{*buflen}. If there was no space for - * the terminating null, no error is returned, so callers must check the value - * of *buflen after the call, before relying on the '\0'; if it has not been - * changed by the call, there is no '\0'-termination on the buffer's contents. - * - * The \a next pointer, if not null, will be updated to point to the next item - * after this string. If \a value points to the last item, then \a next will be - * invalid. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)). - * - * \note This function does not perform UTF-8 validation on the incoming text - * string. - * - * \sa cbor_value_get_text_string_chunk() cbor_value_dup_text_string(), cbor_value_copy_byte_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length() - */ - -/** - * \fn CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer, size_t *buflen, CborValue *next) - * - * Copies the string pointed by \a value into the buffer provided at \a buffer - * of \a buflen bytes. If \a buffer is a NULL pointer, this function will not - * copy anything and will only update the \a next value. - * - * If the iterator \a value does not point to a byte string, the behaviour is - * undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_byte_string is recommended. - * - * If the provided buffer length was too small, this function returns an error - * condition of \ref CborErrorOutOfMemory. If you need to calculate the length - * of the string in order to preallocate a buffer, use - * cbor_value_calculate_string_length(). - * - * On success, this function sets the number of bytes copied to \c{*buflen}. If - * the buffer is large enough, this function will insert a null byte after the - * last copied byte, to facilitate manipulation of null-terminated strings. - * That byte is not included in the returned value of \c{*buflen}. - * - * The \a next pointer, if not null, will be updated to point to the next item - * after this string. If \a value points to the last item, then \a next will be - * invalid. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)). - * - * \sa cbor_value_get_byte_string_chunk(), cbor_value_dup_text_string(), cbor_value_copy_text_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length() - */ - -CborError _cbor_value_copy_string(const CborValue *value, void *buffer, - size_t *buflen, CborValue *next) -{ - bool copied_all; - CborError err = iterate_string_chunks(value, (char*)buffer, buflen, &copied_all, next, - buffer ? iterate_memcpy : iterate_noop); - return err ? err : - copied_all ? CborNoError : CborErrorOutOfMemory; -} - -/** - * Compares the entry \a value with the string \a string and stores the result - * in \a result. If the value is different from \a string \a result will - * contain \c false. - * - * The entry at \a value may be a tagged string. If \a value is not a string or - * a tagged string, the comparison result will be false. - * - * CBOR requires text strings to be encoded in UTF-8, but this function does - * not validate either the strings in the stream or the string \a string to be - * matched. Moreover, comparison is done on strict codepoint comparison, - * without any Unicode normalization. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)). - * - * \sa cbor_value_skip_tag(), cbor_value_copy_text_string() - */ -CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result) -{ - size_t len; - CborValue copy = *value; - CborError err = cbor_value_skip_tag(©); - if (err) - return err; - if (!cbor_value_is_text_string(©)) { - *result = false; - return CborNoError; - } - - len = strlen(string); - return iterate_string_chunks(©, CONST_CAST(char *, string), &len, result, NULL, iterate_memcmp); -} - -/** - * \fn bool cbor_value_is_array(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR array. - * - * \sa cbor_value_is_valid(), cbor_value_is_map() - */ - -/** - * \fn CborError cbor_value_get_array_length(const CborValue *value, size_t *length) - * - * Extracts the length of the CBOR array that \a value points to and stores it - * in \a result. If the iterator \a value does not point to a CBOR array, the - * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_array is recommended. - * - * If the length of this array is not encoded in the CBOR data stream, this - * function will return the recoverable error CborErrorUnknownLength. You may - * also check whether that is the case by using cbor_value_is_length_known(). - * - * \note On 32-bit platforms, this function will return error condition of \ref - * CborErrorDataTooLarge if the stream indicates a length that is too big to - * fit in 32-bit. - * - * \sa cbor_value_is_valid(), cbor_value_is_length_known() - */ - -/** - * \fn bool cbor_value_is_map(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR map. - * - * \sa cbor_value_is_valid(), cbor_value_is_array() - */ - -/** - * \fn CborError cbor_value_get_map_length(const CborValue *value, size_t *length) - * - * Extracts the length of the CBOR map that \a value points to and stores it in - * \a result. If the iterator \a value does not point to a CBOR map, the - * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_map is recommended. - * - * If the length of this map is not encoded in the CBOR data stream, this - * function will return the recoverable error CborErrorUnknownLength. You may - * also check whether that is the case by using cbor_value_is_length_known(). - * - * \note On 32-bit platforms, this function will return error condition of \ref - * CborErrorDataTooLarge if the stream indicates a length that is too big to - * fit in 32-bit. - * - * \sa cbor_value_is_valid(), cbor_value_is_length_known() - */ - -/** - * Attempts to find the value in map \a map that corresponds to the text string - * entry \a string. If the iterator \a value does not point to a CBOR map, the - * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_map is recommended. - * - * If the item is found, it is stored in \a result. If no item is found - * matching the key, then \a result will contain an element of type \ref - * CborInvalidType. Matching is performed using - * cbor_value_text_string_equals(), so tagged strings will also match. - * - * This function has a time complexity of O(n) where n is the number of - * elements in the map to be searched. In addition, this function is has O(n) - * memory requirement based on the number of nested containers (maps or arrays) - * found as elements of this map. - * - * \sa cbor_value_is_valid(), cbor_value_text_string_equals(), cbor_value_advance() - */ -CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element) -{ - CborError err; - size_t len = strlen(string); - cbor_assert(cbor_value_is_map(map)); - err = cbor_value_enter_container(map, element); - if (err) - goto error; - - while (!cbor_value_at_end(element)) { - /* find the non-tag so we can compare */ - err = cbor_value_skip_tag(element); - if (err) - goto error; - if (cbor_value_is_text_string(element)) { - bool equals; - size_t dummyLen = len; - err = iterate_string_chunks(element, CONST_CAST(char *, string), &dummyLen, - &equals, element, iterate_memcmp); - if (err) - goto error; - if (equals) - return preparse_value(element); - } else { - /* skip this key */ - err = cbor_value_advance(element); - if (err) - goto error; - } - - /* skip this value */ - err = cbor_value_skip_tag(element); - if (err) - goto error; - err = cbor_value_advance(element); - if (err) - goto error; - } - - /* not found */ - element->type = CborInvalidType; - return CborNoError; - -error: - element->type = CborInvalidType; - return err; -} - -/** - * \fn bool cbor_value_is_float(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR - * single-precision floating point (32-bit). - * - * \sa cbor_value_is_valid(), cbor_value_is_double(), cbor_value_is_half_float() - */ - -/** - * \fn CborError cbor_value_get_float(const CborValue *value, float *result) - * - * Retrieves the CBOR single-precision floating point (32-bit) value that \a - * value points to and stores it in \a result. If the iterator \a value does - * not point to a single-precision floating point value, the behavior is - * undefined, so checking with \ref cbor_value_get_type or with \ref - * cbor_value_is_float is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_float(), cbor_value_get_double() - */ - -/** - * \fn bool cbor_value_is_double(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR - * double-precision floating point (64-bit). - * - * \sa cbor_value_is_valid(), cbor_value_is_float(), cbor_value_is_half_float() - */ - -/** - * \fn CborError cbor_value_get_double(const CborValue *value, float *result) - * - * Retrieves the CBOR double-precision floating point (64-bit) value that \a - * value points to and stores it in \a result. If the iterator \a value does - * not point to a double-precision floating point value, the behavior is - * undefined, so checking with \ref cbor_value_get_type or with \ref - * cbor_value_is_double is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_double(), cbor_value_get_float() - */ - -/** - * \fn bool cbor_value_is_half_float(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR - * single-precision floating point (16-bit). - * - * \sa cbor_value_is_valid(), cbor_value_is_double(), cbor_value_is_float() - */ - -/** - * Retrieves the CBOR half-precision floating point (16-bit) value that \a - * value points to and stores it in \a result. If the iterator \a value does - * not point to a half-precision floating point value, the behavior is - * undefined, so checking with \ref cbor_value_get_type or with \ref - * cbor_value_is_half_float is recommended. - * - * Note: since the C language does not have a standard type for half-precision - * floating point, this function takes a \c{void *} as a parameter for the - * storage area, which must be at least 16 bits wide. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_half_float(), cbor_value_get_float() - */ -CborError cbor_value_get_half_float(const CborValue *value, void *result) -{ - uint16_t v; - cbor_assert(cbor_value_is_half_float(value)); - - /* size has been computed already */ - v = get16(value->ptr + 1); - memcpy(result, &v, sizeof(v)); - return CborNoError; -} - -#pragma GCC diagnostic pop - -/** @} */ diff --git a/src/cbor/lib/tinycbor/src/cborparser_dup_string.c b/src/cbor/lib/tinycbor/src/cborparser_dup_string.c deleted file mode 100644 index 1360d8b1..00000000 --- a/src/cbor/lib/tinycbor/src/cborparser_dup_string.c +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#ifndef _BSD_SOURCE -#define _BSD_SOURCE 1 -#endif -#ifndef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE 1 -#endif -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "compilersupport_p.h" -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \fn CborError cbor_value_dup_text_string(const CborValue *value, char **buffer, size_t *buflen, CborValue *next) - * - * Allocates memory for the string pointed by \a value and copies it into this - * buffer. The pointer to the buffer is stored in \a buffer and the number of - * bytes copied is stored in \a buflen (those variables must not be NULL). - * - * If the iterator \a value does not point to a text string, the behaviour is - * undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_text_string is recommended. - * - * If \c malloc returns a NULL pointer, this function will return error - * condition \ref CborErrorOutOfMemory. - * - * On success, \c{*buffer} will contain a valid pointer that must be freed by - * calling \c{free()}. This is the case even for zero-length strings. - * - * The \a next pointer, if not null, will be updated to point to the next item - * after this string. If \a value points to the last item, then \a next will be - * invalid. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)) in addition to the - * malloc'ed block. - * - * \note This function does not perform UTF-8 validation on the incoming text - * string. - * - * \sa cbor_value_get_text_string_chunk(), cbor_value_copy_text_string(), cbor_value_dup_byte_string() - */ - -/** - * \fn CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer, size_t *buflen, CborValue *next) - * - * Allocates memory for the string pointed by \a value and copies it into this - * buffer. The pointer to the buffer is stored in \a buffer and the number of - * bytes copied is stored in \a buflen (those variables must not be NULL). - * - * If the iterator \a value does not point to a byte string, the behaviour is - * undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_byte_string is recommended. - * - * If \c malloc returns a NULL pointer, this function will return error - * condition \ref CborErrorOutOfMemory. - * - * On success, \c{*buffer} will contain a valid pointer that must be freed by - * calling \c{free()}. This is the case even for zero-length strings. - * - * The \a next pointer, if not null, will be updated to point to the next item - * after this string. If \a value points to the last item, then \a next will be - * invalid. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)) in addition to the - * malloc'ed block. - * - * \sa cbor_value_get_text_string_chunk(), cbor_value_copy_byte_string(), cbor_value_dup_text_string() - */ -CborError _cbor_value_dup_string(const CborValue *value, void **buffer, size_t *buflen, CborValue *next) -{ - CborError err; - cbor_assert(buffer); - cbor_assert(buflen); - *buflen = SIZE_MAX; - err = _cbor_value_copy_string(value, NULL, buflen, NULL); - if (err) - return err; - - ++*buflen; - *buffer = malloc(*buflen); - if (!*buffer) { - /* out of memory */ - return CborErrorOutOfMemory; - } - err = _cbor_value_copy_string(value, *buffer, buflen, next); - if (err) { - free(*buffer); - return err; - } - return CborNoError; -} - -#pragma GCC diagnostic pop diff --git a/src/cbor/lib/tinycbor/src/cborpretty.c b/src/cbor/lib/tinycbor/src/cborpretty.c deleted file mode 100644 index 2db4b253..00000000 --- a/src/cbor/lib/tinycbor/src/cborpretty.c +++ /dev/null @@ -1,583 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" -#include "utf8_p.h" - -#include -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \defgroup CborPretty Converting CBOR to text - * \brief Group of functions used to convert CBOR to text form. - * - * This group contains two functions that can be used to convert a \ref - * CborValue object to a text representation. This module attempts to follow - * the recommendations from RFC 7049 section 6 "Diagnostic Notation", though it - * has a few differences. They are noted below. - * - * TinyCBOR does not provide a way to convert from the text representation back - * to encoded form. To produce a text form meant to be parsed, CborToJson is - * recommended instead. - * - * Either of the functions in this section will attempt to convert exactly one - * CborValue object to text. Those functions may return any error documented - * for the functions for CborParsing. In addition, if the C standard library - * stream functions return with error, the text conversion will return with - * error CborErrorIO. - * - * These functions also perform UTF-8 validation in CBOR text strings. If they - * encounter a sequence of bytes that is not permitted in UTF-8, they will return - * CborErrorInvalidUtf8TextString. That includes encoding of surrogate points - * in UTF-8. - * - * \warning The output type produced by these functions is not guaranteed to - * remain stable. A future update of TinyCBOR may produce different output for - * the same input and parsers may be unable to handle it. - * - * \sa CborParsing, CborToJson, cbor_parser_init() - */ - -/** - * \addtogroup CborPretty - * @{ - *

Text format

- * - * As described in RFC 7049 section 6 "Diagnostic Notation", the format is - * largely borrowed from JSON, but modified to suit CBOR's different data - * types. TinyCBOR makes further modifications to distinguish different, but - * similar values. - * - * CBOR values are currently encoded as follows: - * \par Integrals (unsigned and negative) - * Base-10 (decimal) text representation of the value - * \par Byte strings: - * "h'" followed by the Base16 (hex) representation of the binary data, followed by an ending quote (') - * \par Text strings: - * C-style escaped string in quotes, with C11/C++11 escaping of Unicode codepoints above U+007F. - * \par Tags: - * Tag value, with the tagged value in parentheses. No special encoding of the tagged value is performed. - * \par Simple types: - * "simple(nn)" where \c nn is the simple value - * \par Null: - * \c null - * \par Undefined: - * \c undefined - * \par Booleans: - * \c true or \c false - * \par Floating point: - * If NaN or infinite, the actual words \c NaN or \c infinite. - * Otherwise, the decimal representation with as many digits as necessary to ensure no loss of information. - * By default, float values are suffixed by "f" and half-float values suffixed by "f16" (doubles have no suffix). - * If the CborPrettyNumericEncodingIndicators flag is active, the values instead are encoded following the - * Section 6 recommended encoding indicators: float values are suffixed with "_2" and half-float with "_1". - * A decimal point is always present. - * \par Arrays: - * Comma-separated list of elements, enclosed in square brackets ("[" and "]"). - * \par Maps: - * Comma-separated list of key-value pairs, with the key and value separated - * by a colon (":"), enclosed in curly braces ("{" and "}"). - * - * The CborPrettyFlags enumerator contains flags to control some aspects of the - * encoding: - * \par String fragmentation - * When the CborPrettyShowStringFragments option is active, text and byte - * strings that are transmitted in fragments are shown instead inside - * parentheses ("(" and ")") with no preceding number and each fragment is - * displayed individually. If a tag precedes the string, then the output - * will contain a double set of parentheses. If the option is not active, - * the fragments are merged together and the display will not show any - * difference from a string transmitted with determinate length. - * \par Encoding indicators - * Numbers and lengths in CBOR can be encoded in multiple representations. - * If the CborPrettyIndicateOverlongNumbers option is active, numbers - * and lengths that are transmitted in a longer encoding than necessary - * will be indicated, by appending an underscore ("_") to either the - * number or the opening bracket or brace, followed by a number - * indicating the CBOR additional information: 0 for 1 byte, 1 for 2 - * bytes, 2 for 4 bytes and 3 for 8 bytes. - * If the CborPrettyIndicateIndeterminateLength option is active, maps, - * arrays and strings encoded with indeterminate length will be marked by - * an underscore after the opening bracket or brace or the string (if not - * showing fragments), without a number after it. - */ - -/** - * \enum CborPrettyFlags - * The CborPrettyFlags enum contains flags that control the conversion of CBOR to text format. - * - * \value CborPrettyNumericEncodingIndicators Use numeric encoding indicators instead of textual for float and half-float. - * \value CborPrettyTextualEncodingIndicators Use textual encoding indicators for float ("f") and half-float ("f16"). - * \value CborPrettyIndicateIndeterminateLength (default) Indicate when a map or array has indeterminate length. - * \value CborPrettyIndicateOverlongNumbers Indicate when a number or length was encoded with more bytes than needed. - * \value CborPrettyShowStringFragments If the byte or text string is transmitted in chunks, show each individually. - * \value CborPrettyMergeStringFragment Merge all chunked byte or text strings and display them in a single entry. - * \value CborPrettyDefaultFlags Default conversion flags. - */ - -#ifndef CBOR_NO_FLOATING_POINT -static inline bool convertToUint64(double v, uint64_t *absolute) -{ - double supremum; - v = fabs(v); - - /* C11 standard section 6.3.1.4 "Real floating and integer" says: - * - * 1 When a finite value of real floating type is converted to an integer - * type other than _Bool, the fractional part is discarded (i.e., the - * value is truncated toward zero). If the value of the integral part - * cannot be represented by the integer type, the behavior is undefined. - * - * So we must perform a range check that v <= UINT64_MAX, but we can't use - * UINT64_MAX + 1.0 because the standard continues: - * - * 2 When a value of integer type is converted to a real floating type, if - * the value being converted can be represented exactly in the new type, - * it is unchanged. If the value being converted is in the range of - * values that can be represented but cannot be represented exactly, the - * result is either the nearest higher or nearest lower representable - * value, chosen in an implementation-defined manner. - */ - supremum = -2.0 * INT64_MIN; /* -2 * (- 2^63) == 2^64 */ - if (v >= supremum) - return false; - - /* Now we can convert, these two conversions cannot be UB */ - *absolute = v; - return *absolute == v; -} -#endif - -static void printRecursionLimit(CborStreamFunction stream, void *out) -{ - stream(out, ""); -} - -static CborError hexDump(CborStreamFunction stream, void *out, const void *ptr, size_t n) -{ - const uint8_t *buffer = (const uint8_t *)ptr; - CborError err = CborNoError; - while (n-- && !err) - err = stream(out, "%02" PRIx8, *buffer++); - - return err; -} - -/* This function decodes buffer as UTF-8 and prints as escaped UTF-16. - * On UTF-8 decoding error, it returns CborErrorInvalidUtf8TextString */ -static CborError utf8EscapedDump(CborStreamFunction stream, void *out, const void *ptr, size_t n) -{ - const uint8_t *buffer = (const uint8_t *)ptr; - const uint8_t * const end = buffer + n; - CborError err = CborNoError; - - while (buffer < end && !err) { - uint32_t uc = get_utf8(&buffer, end); - if (uc == ~0U) - return CborErrorInvalidUtf8TextString; - - if (uc < 0x80) { - /* single-byte UTF-8 */ - unsigned char escaped = (unsigned char)uc; - if (uc < 0x7f && uc >= 0x20 && uc != '\\' && uc != '"') { - err = stream(out, "%c", (char)uc); - continue; - } - - /* print as an escape sequence */ - switch (uc) { - case '"': - case '\\': - break; - case '\b': - escaped = 'b'; - break; - case '\f': - escaped = 'f'; - break; - case '\n': - escaped = 'n'; - break; - case '\r': - escaped = 'r'; - break; - case '\t': - escaped = 't'; - break; - default: - goto print_utf16; - } - err = stream(out, "\\%c", escaped); - continue; - } - - /* now print the sequence */ - if (uc > 0xffffU) { - /* needs surrogate pairs */ - err = stream(out, "\\u%04" PRIX32 "\\u%04" PRIX32, - (uc >> 10) + 0xd7c0, /* high surrogate */ - (uc % 0x0400) + 0xdc00); - } else { -print_utf16: - /* no surrogate pair needed */ - err = stream(out, "\\u%04" PRIX32, uc); - } - } - return err; -} - -static const char *resolve_indicator(const uint8_t *ptr, const uint8_t *end, int flags) -{ - static const char indicators[8][3] = { - "_0", "_1", "_2", "_3", - "", "", "", /* these are not possible */ - "_" - }; - const char *no_indicator = indicators[5]; /* empty string */ - uint8_t additional_information; - uint8_t expected_information; - uint64_t value; - CborError err; - - if (ptr == end) - return NULL; /* CborErrorUnexpectedEOF */ - - additional_information = (*ptr & SmallValueMask); - if (additional_information < Value8Bit) - return no_indicator; - - /* determine whether to show anything */ - if ((flags & CborPrettyIndicateIndeterminateLength) && - additional_information == IndefiniteLength) - return indicators[IndefiniteLength - Value8Bit]; - if ((flags & CborPrettyIndicateOverlongNumbers) == 0) - return no_indicator; - - err = _cbor_value_extract_number(&ptr, end, &value); - if (err) - return NULL; /* CborErrorUnexpectedEOF */ - - expected_information = Value8Bit - 1; - if (value >= Value8Bit) - ++expected_information; - if (value > 0xffU) - ++expected_information; - if (value > 0xffffU) - ++expected_information; - if (value > 0xffffffffU) - ++expected_information; - return expected_information == additional_information ? - no_indicator : - indicators[additional_information - Value8Bit]; -} - -static const char *get_indicator(const CborValue *it, int flags) -{ - return resolve_indicator(it->ptr, it->parser->end, flags); -} - -static CborError value_to_pretty(CborStreamFunction stream, void *out, CborValue *it, int flags, int recursionsLeft); -static CborError container_to_pretty(CborStreamFunction stream, void *out, CborValue *it, CborType containerType, - int flags, int recursionsLeft) -{ - const char *comma = ""; - CborError err = CborNoError; - - if (!recursionsLeft) { - printRecursionLimit(stream, out); - return err; /* do allow the dumping to continue */ - } - - while (!cbor_value_at_end(it) && !err) { - err = stream(out, "%s", comma); - comma = ", "; - - if (!err) - err = value_to_pretty(stream, out, it, flags, recursionsLeft); - - if (containerType == CborArrayType) - continue; - - /* map: that was the key, so get the value */ - if (!err) - err = stream(out, ": "); - if (!err) - err = value_to_pretty(stream, out, it, flags, recursionsLeft); - } - return err; -} - -static CborError value_to_pretty(CborStreamFunction stream, void *out, CborValue *it, int flags, int recursionsLeft) -{ - CborError err = CborNoError; - CborType type = cbor_value_get_type(it); - switch (type) { - case CborArrayType: - case CborMapType: { - /* recursive type */ - CborValue recursed; - const char *indicator = get_indicator(it, flags); - const char *space = *indicator ? " " : indicator; - - err = stream(out, "%c%s%s", type == CborArrayType ? '[' : '{', indicator, space); - if (err) - return err; - - err = cbor_value_enter_container(it, &recursed); - if (err) { - it->ptr = recursed.ptr; - return err; /* parse error */ - } - err = container_to_pretty(stream, out, &recursed, type, flags, recursionsLeft - 1); - if (err) { - it->ptr = recursed.ptr; - return err; /* parse error */ - } - err = cbor_value_leave_container(it, &recursed); - if (err) - return err; /* parse error */ - - return stream(out, type == CborArrayType ? "]" : "}"); - } - - case CborIntegerType: { - uint64_t val; - cbor_value_get_raw_integer(it, &val); /* can't fail */ - - if (cbor_value_is_unsigned_integer(it)) { - err = stream(out, "%" PRIu64, val); - } else { - /* CBOR stores the negative number X as -1 - X - * (that is, -1 is stored as 0, -2 as 1 and so forth) */ - if (++val) { /* unsigned overflow may happen */ - err = stream(out, "-%" PRIu64, val); - } else { - /* overflown - * 0xffff`ffff`ffff`ffff + 1 = - * 0x1`0000`0000`0000`0000 = 18446744073709551616 (2^64) */ - err = stream(out, "-18446744073709551616"); - } - } - if (!err) - err = stream(out, "%s", get_indicator(it, flags)); - break; - } - - case CborByteStringType: - case CborTextStringType: { - size_t n = 0; - const void *ptr; - bool showingFragments = (flags & CborPrettyShowStringFragments) && !cbor_value_is_length_known(it); - const char *separator = ""; - char close = '\''; - char open[3] = "h'"; - const char *indicator = NULL; - - if (type == CborTextStringType) { - close = open[0] = '"'; - open[1] = '\0'; - } - - if (showingFragments) { - err = stream(out, "(_ "); - if (!err) - err = _cbor_value_prepare_string_iteration(it); - } else { - err = stream(out, "%s", open); - } - - while (!err) { - if (showingFragments || indicator == NULL) { - /* any iteration, except the second for a non-chunked string */ - indicator = resolve_indicator(it->ptr, it->parser->end, flags); - } - - err = _cbor_value_get_string_chunk(it, &ptr, &n, it); - if (!ptr) - break; - - if (!err && showingFragments) - err = stream(out, "%s%s", separator, open); - if (!err) - err = (type == CborByteStringType ? - hexDump(stream, out, ptr, n) : - utf8EscapedDump(stream, out, ptr, n)); - if (!err && showingFragments) { - err = stream(out, "%c%s", close, indicator); - separator = ", "; - } - } - - if (!err) { - if (showingFragments) - err = stream(out, ")"); - else - err = stream(out, "%c%s", close, indicator); - } - return err; - } - - case CborTagType: { - CborTag tag; - cbor_value_get_tag(it, &tag); /* can't fail */ - err = stream(out, "%" PRIu64 "%s(", tag, get_indicator(it, flags)); - if (!err) - err = cbor_value_advance_fixed(it); - if (!err && recursionsLeft) - err = value_to_pretty(stream, out, it, flags, recursionsLeft - 1); - else if (!err) - printRecursionLimit(stream, out); - if (!err) - err = stream(out, ")"); - return err; - } - - case CborSimpleType: { - /* simple types can't fail and can't have overlong encoding */ - uint8_t simple_type; - cbor_value_get_simple_type(it, &simple_type); - err = stream(out, "simple(%" PRIu8 ")", simple_type); - break; - } - - case CborNullType: - err = stream(out, "null"); - break; - - case CborUndefinedType: - err = stream(out, "undefined"); - break; - - case CborBooleanType: { - bool val; - cbor_value_get_boolean(it, &val); /* can't fail */ - err = stream(out, val ? "true" : "false"); - break; - } - -#ifndef CBOR_NO_FLOATING_POINT - case CborDoubleType: { - const char *suffix; - double val; - int r; - uint64_t ival; - - if (false) { - float f; - case CborFloatType: - cbor_value_get_float(it, &f); - val = f; - suffix = flags & CborPrettyNumericEncodingIndicators ? "_2" : "f"; - } else if (false) { - uint16_t f16; - case CborHalfFloatType: -#ifndef CBOR_NO_HALF_FLOAT_TYPE - cbor_value_get_half_float(it, &f16); - val = decode_half(f16); - suffix = flags & CborPrettyNumericEncodingIndicators ? "_1" : "f16"; -#else - (void)f16; - err = CborErrorUnsupportedType; - break; -#endif - } else { - cbor_value_get_double(it, &val); - suffix = ""; - } - - if ((flags & CborPrettyNumericEncodingIndicators) == 0) { - r = fpclassify(val); - if (r == FP_NAN || r == FP_INFINITE) - suffix = ""; - } - - if (convertToUint64(val, &ival)) { - /* this double value fits in a 64-bit integer, so show it as such - * (followed by a floating point suffix, to disambiguate) */ - err = stream(out, "%s%" PRIu64 ".%s", val < 0 ? "-" : "", ival, suffix); - } else { - /* this number is definitely not a 64-bit integer */ - err = stream(out, "%." DBL_DECIMAL_DIG_STR "g%s", val, suffix); - } - break; - } -#else - case CborDoubleType: - case CborFloatType: - case CborHalfFloatType: - err = CborErrorUnsupportedType; - break; -#endif /* !CBOR_NO_FLOATING_POINT */ - - case CborInvalidType: - err = stream(out, "invalid"); - if (err) - return err; - return CborErrorUnknownType; - } - - if (!err) - err = cbor_value_advance_fixed(it); - return err; -} - -/** - * Converts the current CBOR type pointed by \a value to its textual - * representation and writes it to the stream by calling the \a streamFunction. - * If an error occurs, this function returns an error code similar to - * \ref CborParsing. - * - * The textual representation can be controlled by the \a flags parameter (see - * \ref CborPrettyFlags for more information). - * - * If no error ocurred, this function advances \a value to the next element. - * Often, concatenating the text representation of multiple elements can be - * done by appending a comma to the output stream in between calls to this - * function. - * - * The \a streamFunction function will be called with the \a token value as the - * first parameter and a printf-style format string as the second, with a variable - * number of further parameters. - * - * \sa cbor_value_to_pretty(), cbor_value_to_json_advance() - */ -CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *token, CborValue *value, int flags) -{ - return value_to_pretty(streamFunction, token, value, flags, CBOR_PARSER_MAX_RECURSIONS); -} - -#pragma GCC diagnostic pop - -/** @} */ diff --git a/src/cbor/lib/tinycbor/src/cborpretty_stdio.c b/src/cbor/lib/tinycbor/src/cborpretty_stdio.c deleted file mode 100644 index 0953e5e8..00000000 --- a/src/cbor/lib/tinycbor/src/cborpretty_stdio.c +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#include "cbor.h" -#include -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -static CborError cbor_fprintf(void *out, const char *fmt, ...) -{ - int n; - - va_list list; - va_start(list, fmt); - n = vfprintf((FILE *)out, fmt, list); - va_end(list); - - return n < 0 ? CborErrorIO : CborNoError; -} - -/** - * \fn CborError cbor_value_to_pretty(FILE *out, const CborValue *value) - * - * Converts the current CBOR type pointed to by \a value to its textual - * representation and writes it to the \a out stream. If an error occurs, this - * function returns an error code similar to CborParsing. - * - * \sa cbor_value_to_pretty_advance(), cbor_value_to_json_advance() - */ - -/** - * Converts the current CBOR type pointed to by \a value to its textual - * representation and writes it to the \a out stream. If an error occurs, this - * function returns an error code similar to CborParsing. - * - * If no error ocurred, this function advances \a value to the next element. - * Often, concatenating the text representation of multiple elements can be - * done by appending a comma to the output stream in between calls to this - * function. - * - * \sa cbor_value_to_pretty(), cbor_value_to_pretty_stream(), cbor_value_to_json_advance() - */ -CborError cbor_value_to_pretty_advance(FILE *out, CborValue *value) -{ - return cbor_value_to_pretty_stream(cbor_fprintf, out, value, CborPrettyDefaultFlags); -} - -/** - * Converts the current CBOR type pointed to by \a value to its textual - * representation and writes it to the \a out stream. If an error occurs, this - * function returns an error code similar to CborParsing. - * - * The textual representation can be controlled by the \a flags parameter (see - * CborPrettyFlags for more information). - * - * If no error ocurred, this function advances \a value to the next element. - * Often, concatenating the text representation of multiple elements can be - * done by appending a comma to the output stream in between calls to this - * function. - * - * \sa cbor_value_to_pretty_stream(), cbor_value_to_pretty(), cbor_value_to_json_advance() - */ -CborError cbor_value_to_pretty_advance_flags(FILE *out, CborValue *value, int flags) -{ - return cbor_value_to_pretty_stream(cbor_fprintf, out, value, flags); -} - -#pragma GCC diagnostic pop diff --git a/src/cbor/lib/tinycbor/src/cbortojson.c b/src/cbor/lib/tinycbor/src/cbortojson.c deleted file mode 100644 index ed6a1666..00000000 --- a/src/cbor/lib/tinycbor/src/cbortojson.c +++ /dev/null @@ -1,704 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#define _GNU_SOURCE 1 -#define _POSIX_C_SOURCE 200809L -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborjson.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" - -#include -#include -#include -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \defgroup CborToJson Converting CBOR to JSON - * \brief Group of functions used to convert CBOR to JSON. - * - * This group contains two functions that can be used to convert a \ref - * CborValue object to an equivalent JSON representation. This module attempts - * to follow the recommendations from RFC 7049 section 4.1 "Converting from - * CBOR to JSON", though it has a few differences. They are noted below. - * - * These functions produce a "minified" JSON output, with no spacing, - * indentation or line breaks. If those are necessary, they need to be applied - * in a post-processing phase. - * - * Note that JSON cannot support all CBOR types with fidelity, so the - * conversion is usually lossy. For that reason, TinyCBOR supports adding a set - * of metadata JSON values that can be used by a JSON-to-CBOR converter to - * restore the original data types. - * - * The TinyCBOR library does not provide a way to convert from JSON - * representation back to encoded form. However, it provides a tool called - * \c json2cbor which can be used for that purpose. That tool supports the - * metadata format that these functions may produce. - * - * Either of the functions in this section will attempt to convert exactly one - * CborValue object to JSON. Those functions may return any error documented - * for the functions for CborParsing. In addition, if the C standard library - * stream functions return with error, the text conversion will return with - * error CborErrorIO. - * - * These functions also perform UTF-8 validation in CBOR text strings. If they - * encounter a sequence of bytes that is not permitted in UTF-8, they will return - * CborErrorInvalidUtf8TextString. That includes encoding of surrogate points - * in UTF-8. - * - * \warning The metadata produced by these functions is not guaranteed to - * remain stable. A future update of TinyCBOR may produce different output for - * the same input and parsers may be unable to handle it. - * - * \sa CborParsing, CborPretty, cbor_parser_init() - */ - -/** - * \addtogroup CborToJson - * @{ - *

Conversion limitations

- * - * When converting from CBOR to JSON, there may be information loss. This - * section lists the possible scenarios. - * - * \par Number precision: - * ALL JSON numbers, due to its JavaScript heritage, are IEEE 754 - * double-precision floating point. This means JSON is not capable of - * representing all integers numbers outside the range [-(253)+1, - * 253-1] and is not capable of representing NaN or infinite. If the - * CBOR data contains a number outside the valid range, the conversion will - * lose precision. If the input was NaN or infinite, the result of the - * conversion will be the JSON null value. In addition, the distinction between - * half-, single- and double-precision is lost. - * - * \par - * If enabled, the original value and original type are stored in the metadata. - * - * \par Non-native types: - * CBOR's type system is richer than JSON's, which means some data values - * cannot be represented when converted to JSON. The conversion silently turns - * them into strings: CBOR simple types become "simple(nn)" where \c nn is the - * simple type's value, with the exception of CBOR undefined, which becomes - * "undefined", while CBOR byte strings are converted to an Base16, Base64, or - * Base64url encoding - * - * \par - * If enabled, the original type is stored in the metadata. - * - * \par Presence of tags: - * JSON has no support for tagged values, so by default tags are dropped when - * converting to JSON. However, if the CborConvertObeyByteStringTags option is - * active (default), then certain known tags are honored and are used to format - * the conversion of the tagged byte string to JSON. - * - * \par - * If the CborConvertTagsToObjects option is active, then the tag and the - * tagged value are converted to a JSON object. Otherwise, if enabled, the - * last (innermost) tag is stored in the metadata. - * - * \par Non-string keys in maps: - * JSON requires all Object keys to be strings, while CBOR does not. By - * default, if a non-string key is found, the conversion fails with error - * CborErrorJsonObjectKeyNotString. If the CborConvertStringifyMapKeys option - * is active, then the conversion attempts to create a string representation - * using CborPretty. Note that the \c json2cbor tool is not able to parse this - * back to the original form. - * - * \par Duplicate keys in maps: - * Neither JSON nor CBOR allow duplicated keys, but current TinyCBOR does not - * validate that this is the case. If there are duplicated keys in the input, - * they will be repeated in the output, which many JSON tools may flag as - * invalid. In addition to that, if the CborConvertStringifyMapKeys option is - * active, it is possible that a non-string key in a CBOR map will be converted - * to a string form that is identical to another key. - * - * \par - * When metadata support is active, the conversion will add extra key-value - * pairs to the JSON output so it can store the metadata. It is possible that - * the keys for the metadata clash with existing keys in the JSON map. - */ - -extern FILE *open_memstream(char **bufptr, size_t *sizeptr); - -enum ConversionStatusFlags { - TypeWasNotNative = 0x100, /* anything but strings, boolean, null, arrays and maps */ - TypeWasTagged = 0x200, - NumberPrecisionWasLost = 0x400, - NumberWasNaN = 0x800, - NumberWasInfinite = 0x1000, - NumberWasNegative = 0x2000, /* only used with NumberWasInifite or NumberWasTooBig */ - - FinalTypeMask = 0xff -}; - -typedef struct ConversionStatus { - CborTag lastTag; - uint64_t originalNumber; - int flags; -} ConversionStatus; - -static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType type, ConversionStatus *status); - -static CborError dump_bytestring_base16(char **result, CborValue *it) -{ - static const char characters[] = "0123456789abcdef"; - size_t i; - size_t n = 0; - uint8_t *buffer; - CborError err = cbor_value_calculate_string_length(it, &n); - if (err) - return err; - - /* a Base16 (hex) output is twice as big as our buffer */ - buffer = (uint8_t *)malloc(n * 2 + 1); - *result = (char *)buffer; - - /* let cbor_value_copy_byte_string know we have an extra byte for the terminating NUL */ - ++n; - err = cbor_value_copy_byte_string(it, buffer + n - 1, &n, it); - cbor_assert(err == CborNoError); - - for (i = 0; i < n; ++i) { - uint8_t byte = buffer[n + i]; - buffer[2*i] = characters[byte >> 4]; - buffer[2*i + 1] = characters[byte & 0xf]; - } - return CborNoError; -} - -static CborError generic_dump_base64(char **result, CborValue *it, const char alphabet[65]) -{ - size_t n = 0, i; - uint8_t *buffer, *out, *in; - CborError err = cbor_value_calculate_string_length(it, &n); - if (err) - return err; - - /* a Base64 output (untruncated) has 4 bytes for every 3 in the input */ - size_t len = (n + 5) / 3 * 4; - out = buffer = (uint8_t *)malloc(len + 1); - *result = (char *)buffer; - - /* we read our byte string at the tail end of the buffer - * so we can do an in-place conversion while iterating forwards */ - in = buffer + len - n; - - /* let cbor_value_copy_byte_string know we have an extra byte for the terminating NUL */ - ++n; - err = cbor_value_copy_byte_string(it, in, &n, it); - cbor_assert(err == CborNoError); - - uint_least32_t val = 0; - for (i = 0; n - i >= 3; i += 3) { - /* read 3 bytes x 8 bits = 24 bits */ - if (false) { -#ifdef __GNUC__ - } else if (i) { - __builtin_memcpy(&val, in + i - 1, sizeof(val)); - val = cbor_ntohl(val); -#endif - } else { - val = (in[i] << 16) | (in[i + 1] << 8) | in[i + 2]; - } - - /* write 4 chars x 6 bits = 24 bits */ - *out++ = alphabet[(val >> 18) & 0x3f]; - *out++ = alphabet[(val >> 12) & 0x3f]; - *out++ = alphabet[(val >> 6) & 0x3f]; - *out++ = alphabet[val & 0x3f]; - } - - /* maybe 1 or 2 bytes left */ - if (n - i) { - /* we can read in[i + 1] even if it's past the end of the string because - * we know (by construction) that it's a NUL byte */ -#ifdef __GNUC__ - uint16_t val16; - __builtin_memcpy(&val16, in + i, sizeof(val16)); - val = cbor_ntohs(val16); -#else - val = (in[i] << 8) | in[i + 1]; -#endif - val <<= 8; - - /* the 65th character in the alphabet is our filler: either '=' or '\0' */ - out[4] = '\0'; - out[3] = alphabet[64]; - if (n - i == 2) { - /* write the third char in 3 chars x 6 bits = 18 bits */ - out[2] = alphabet[(val >> 6) & 0x3f]; - } else { - out[2] = alphabet[64]; /* filler */ - } - out[1] = alphabet[(val >> 12) & 0x3f]; - out[0] = alphabet[(val >> 18) & 0x3f]; - } else { - out[0] = '\0'; - } - - return CborNoError; -} - -static CborError dump_bytestring_base64(char **result, CborValue *it) -{ - static const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" - "ghijklmn" "opqrstuv" "wxyz0123" "456789+/" "="; - return generic_dump_base64(result, it, alphabet); -} - -static CborError dump_bytestring_base64url(char **result, CborValue *it) -{ - static const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" - "ghijklmn" "opqrstuv" "wxyz0123" "456789-_"; - return generic_dump_base64(result, it, alphabet); -} - -static CborError add_value_metadata(FILE *out, CborType type, const ConversionStatus *status) -{ - int flags = status->flags; - if (flags & TypeWasTagged) { - /* extract the tagged type, which may be JSON native */ - type = flags & FinalTypeMask; - flags &= ~(FinalTypeMask | TypeWasTagged); - - if (fprintf(out, "\"tag\":\"%" PRIu64 "\"%s", status->lastTag, - flags & ~TypeWasTagged ? "," : "") < 0) - return CborErrorIO; - } - - if (!flags) - return CborNoError; - - /* print at least the type */ - if (fprintf(out, "\"t\":%d", type) < 0) - return CborErrorIO; - - if (flags & NumberWasNaN) - if (fprintf(out, ",\"v\":\"nan\"") < 0) - return CborErrorIO; - if (flags & NumberWasInfinite) - if (fprintf(out, ",\"v\":\"%sinf\"", flags & NumberWasNegative ? "-" : "") < 0) - return CborErrorIO; - if (flags & NumberPrecisionWasLost) - if (fprintf(out, ",\"v\":\"%c%" PRIx64 "\"", flags & NumberWasNegative ? '-' : '+', - status->originalNumber) < 0) - return CborErrorIO; - if (type == CborSimpleType) - if (fprintf(out, ",\"v\":%d", (int)status->originalNumber) < 0) - return CborErrorIO; - return CborNoError; -} - -static CborError find_tagged_type(CborValue *it, CborTag *tag, CborType *type) -{ - CborError err = CborNoError; - *type = cbor_value_get_type(it); - while (*type == CborTagType) { - cbor_value_get_tag(it, tag); /* can't fail */ - err = cbor_value_advance_fixed(it); - if (err) - return err; - - *type = cbor_value_get_type(it); - } - return err; -} - -static CborError tagged_value_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status) -{ - CborTag tag; - CborError err; - - if (flags & CborConvertTagsToObjects) { - cbor_value_get_tag(it, &tag); /* can't fail */ - err = cbor_value_advance_fixed(it); - if (err) - return err; - - if (fprintf(out, "{\"tag%" PRIu64 "\":", tag) < 0) - return CborErrorIO; - - CborType type = cbor_value_get_type(it); - err = value_to_json(out, it, flags, type, status); - if (err) - return err; - if (flags & CborConvertAddMetadata && status->flags) { - if (fprintf(out, ",\"tag%" PRIu64 "$cbor\":{", tag) < 0 || - add_value_metadata(out, type, status) != CborNoError || - fputc('}', out) < 0) - return CborErrorIO; - } - if (fputc('}', out) < 0) - return CborErrorIO; - status->flags = TypeWasNotNative | CborTagType; - return CborNoError; - } - - CborType type; - err = find_tagged_type(it, &status->lastTag, &type); - if (err) - return err; - tag = status->lastTag; - - /* special handling of byte strings? */ - if (type == CborByteStringType && (flags & CborConvertByteStringsToBase64Url) == 0 && - (tag == CborNegativeBignumTag || tag == CborExpectedBase16Tag || tag == CborExpectedBase64Tag)) { - char *str; - char *pre = ""; - - if (tag == CborNegativeBignumTag) { - pre = "~"; - err = dump_bytestring_base64url(&str, it); - } else if (tag == CborExpectedBase64Tag) { - err = dump_bytestring_base64(&str, it); - } else { /* tag == CborExpectedBase16Tag */ - err = dump_bytestring_base16(&str, it); - } - if (err) - return err; - err = fprintf(out, "\"%s%s\"", pre, str) < 0 ? CborErrorIO : CborNoError; - free(str); - status->flags = TypeWasNotNative | TypeWasTagged | CborByteStringType; - return err; - } - - /* no special handling */ - err = value_to_json(out, it, flags, type, status); - status->flags |= TypeWasTagged | type; - return err; -} - -static CborError stringify_map_key(char **key, CborValue *it, int flags, CborType type) -{ - (void)flags; /* unused */ - (void)type; /* unused */ -#ifdef WITHOUT_OPEN_MEMSTREAM - (void)key; /* unused */ - (void)it; /* unused */ - return CborErrorJsonNotImplemented; -#else - size_t size; - - FILE *memstream = open_memstream(key, &size); - if (memstream == NULL) - return CborErrorOutOfMemory; /* could also be EMFILE, but it's unlikely */ - CborError err = cbor_value_to_pretty_advance(memstream, it); - - if (unlikely(fclose(memstream) < 0 || *key == NULL)) - return CborErrorInternalError; - return err; -#endif -} - -static CborError array_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status) -{ - const char *comma = ""; - while (!cbor_value_at_end(it)) { - if (fprintf(out, "%s", comma) < 0) - return CborErrorIO; - comma = ","; - - CborError err = value_to_json(out, it, flags, cbor_value_get_type(it), status); - if (err) - return err; - } - return CborNoError; -} - -static CborError map_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status) -{ - const char *comma = ""; - CborError err; - while (!cbor_value_at_end(it)) { - char *key; - if (fprintf(out, "%s", comma) < 0) - return CborErrorIO; - comma = ","; - - CborType keyType = cbor_value_get_type(it); - if (likely(keyType == CborTextStringType)) { - size_t n = 0; - err = cbor_value_dup_text_string(it, &key, &n, it); - } else if (flags & CborConvertStringifyMapKeys) { - err = stringify_map_key(&key, it, flags, keyType); - } else { - return CborErrorJsonObjectKeyNotString; - } - if (err) - return err; - - /* first, print the key */ - if (fprintf(out, "\"%s\":", key) < 0) { - free(key); - return CborErrorIO; - } - - /* then, print the value */ - CborType valueType = cbor_value_get_type(it); - err = value_to_json(out, it, flags, valueType, status); - - /* finally, print any metadata we may have */ - if (flags & CborConvertAddMetadata) { - if (!err && keyType != CborTextStringType) { - if (fprintf(out, ",\"%s$keycbordump\":true", key) < 0) - err = CborErrorIO; - } - if (!err && status->flags) { - if (fprintf(out, ",\"%s$cbor\":{", key) < 0 || - add_value_metadata(out, valueType, status) != CborNoError || - fputc('}', out) < 0) - err = CborErrorIO; - } - } - - free(key); - if (err) - return err; - } - return CborNoError; -} - -static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType type, ConversionStatus *status) -{ - CborError err; - status->flags = 0; - - switch (type) { - case CborArrayType: - case CborMapType: { - /* recursive type */ - CborValue recursed; - err = cbor_value_enter_container(it, &recursed); - if (err) { - it->ptr = recursed.ptr; - return err; /* parse error */ - } - if (fputc(type == CborArrayType ? '[' : '{', out) < 0) - return CborErrorIO; - - err = (type == CborArrayType) ? - array_to_json(out, &recursed, flags, status) : - map_to_json(out, &recursed, flags, status); - if (err) { - it->ptr = recursed.ptr; - return err; /* parse error */ - } - - if (fputc(type == CborArrayType ? ']' : '}', out) < 0) - return CborErrorIO; - err = cbor_value_leave_container(it, &recursed); - if (err) - return err; /* parse error */ - - status->flags = 0; /* reset, there are never conversion errors for us */ - return CborNoError; - } - - case CborIntegerType: { - double num; /* JS numbers are IEEE double precision */ - uint64_t val; - cbor_value_get_raw_integer(it, &val); /* can't fail */ - num = (double)val; - - if (cbor_value_is_negative_integer(it)) { - num = -num - 1; /* convert to negative */ - if ((uint64_t)(-num - 1) != val) { - status->flags = NumberPrecisionWasLost | NumberWasNegative; - status->originalNumber = val; - } - } else { - if ((uint64_t)num != val) { - status->flags = NumberPrecisionWasLost; - status->originalNumber = val; - } - } - if (fprintf(out, "%.0f", num) < 0) /* this number has no fraction, so no decimal points please */ - return CborErrorIO; - break; - } - - case CborByteStringType: - case CborTextStringType: { - char *str; - if (type == CborByteStringType) { - err = dump_bytestring_base64url(&str, it); - status->flags = TypeWasNotNative; - } else { - size_t n = 0; - err = cbor_value_dup_text_string(it, &str, &n, it); - } - if (err) - return err; - err = (fprintf(out, "\"%s\"", str) < 0) ? CborErrorIO : CborNoError; - free(str); - return err; - } - - case CborTagType: - return tagged_value_to_json(out, it, flags, status); - - case CborSimpleType: { - uint8_t simple_type; - cbor_value_get_simple_type(it, &simple_type); /* can't fail */ - status->flags = TypeWasNotNative; - status->originalNumber = simple_type; - if (fprintf(out, "\"simple(%" PRIu8 ")\"", simple_type) < 0) - return CborErrorIO; - break; - } - - case CborNullType: - if (fprintf(out, "null") < 0) - return CborErrorIO; - break; - - case CborUndefinedType: - status->flags = TypeWasNotNative; - if (fprintf(out, "\"undefined\"") < 0) - return CborErrorIO; - break; - - case CborBooleanType: { - bool val; - cbor_value_get_boolean(it, &val); /* can't fail */ - if (fprintf(out, val ? "true" : "false") < 0) - return CborErrorIO; - break; - } - -#ifndef CBOR_NO_FLOATING_POINT - case CborDoubleType: { - double val; - if (false) { - float f; - case CborFloatType: - status->flags = TypeWasNotNative; - cbor_value_get_float(it, &f); - val = f; - } else if (false) { - uint16_t f16; - case CborHalfFloatType: -# ifndef CBOR_NO_HALF_FLOAT_TYPE - status->flags = TypeWasNotNative; - cbor_value_get_half_float(it, &f16); - val = decode_half(f16); -# else - (void)f16; - err = CborErrorUnsupportedType; - break; -# endif - } else { - cbor_value_get_double(it, &val); - } - - int r = fpclassify(val); - if (r == FP_NAN || r == FP_INFINITE) { - if (fprintf(out, "null") < 0) - return CborErrorIO; - status->flags |= r == FP_NAN ? NumberWasNaN : - NumberWasInfinite | (val < 0 ? NumberWasNegative : 0); - } else { - uint64_t ival = (uint64_t)fabs(val); - if ((double)ival == fabs(val)) { - /* print as integer so we get the full precision */ - r = fprintf(out, "%s%" PRIu64, val < 0 ? "-" : "", ival); - status->flags |= TypeWasNotNative; /* mark this integer number as a double */ - } else { - /* this number is definitely not a 64-bit integer */ - r = fprintf(out, "%." DBL_DECIMAL_DIG_STR "g", val); - } - if (r < 0) - return CborErrorIO; - } - break; - } -#else - case CborDoubleType: - case CborFloatType: - case CborHalfFloatType: - err = CborErrorUnsupportedType; - break; -#endif /* !CBOR_NO_FLOATING_POINT */ - - case CborInvalidType: - return CborErrorUnknownType; - } - - return cbor_value_advance_fixed(it); -} - -/** - * \enum CborToJsonFlags - * The CborToJsonFlags enum contains flags that control the conversion of CBOR to JSON. - * - * \value CborConvertAddMetadata Adds metadata to facilitate restoration of the original CBOR data. - * \value CborConvertTagsToObjects Converts CBOR tags to JSON objects - * \value CborConvertIgnoreTags (default) Ignore CBOR tags, except for byte strings - * \value CborConvertObeyByteStringTags (default) Honor formatting of CBOR byte strings if so tagged - * \value CborConvertByteStringsToBase64Url Force the conversion of all CBOR byte strings to Base64url encoding, despite any tags - * \value CborConvertRequireMapStringKeys (default) Require CBOR map keys to be strings, failing the conversion if they are not - * \value CborConvertStringifyMapKeys Convert non-string keys in CBOR maps to a string form - * \value CborConvertDefaultFlags Default conversion flags. - */ - -/** - * \fn CborError cbor_value_to_json(FILE *out, const CborValue *value, int flags) - * - * Converts the current CBOR type pointed to by \a value to JSON and writes that - * to the \a out stream. If an error occurs, this function returns an error - * code similar to CborParsing. The \a flags parameter indicates one or more of - * the flags from CborToJsonFlags that control the conversion. - * - * \sa cbor_value_to_json_advance(), cbor_value_to_pretty() - */ - -/** - * Converts the current CBOR type pointed to by \a value to JSON and writes that - * to the \a out stream. If an error occurs, this function returns an error - * code similar to CborParsing. The \a flags parameter indicates one or more of - * the flags from CborToJsonFlags that control the conversion. - * - * If no error ocurred, this function advances \a value to the next element. - * - * \sa cbor_value_to_json(), cbor_value_to_pretty_advance() - */ -CborError cbor_value_to_json_advance(FILE *out, CborValue *value, int flags) -{ - ConversionStatus status; - return value_to_json(out, value, flags, cbor_value_get_type(value), &status); -} - -#pragma GCC diagnostic pop - -/** @} */ diff --git a/src/cbor/lib/tinycbor/src/cborvalidation.c b/src/cbor/lib/tinycbor/src/cborvalidation.c deleted file mode 100644 index d9445ea2..00000000 --- a/src/cbor/lib/tinycbor/src/cborvalidation.c +++ /dev/null @@ -1,671 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" -#include "utf8_p.h" - -#include - -#ifndef CBOR_NO_FLOATING_POINT -# include -# include -#endif - - -#ifndef CBOR_PARSER_MAX_RECURSIONS -# define CBOR_PARSER_MAX_RECURSIONS 1024 -#endif - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \addtogroup CborParsing - * @{ - */ - -/** - * \enum CborValidationFlags - * The CborValidationFlags enum contains flags that control the validation of a - * CBOR stream. - * - * \value CborValidateBasic Validates only the syntactic correctedness of the stream. - * \value CborValidateCanonical Validates that the stream is in canonical format, according to - * RFC 7049 section 3.9. - * \value CborValidateStrictMode Performs strict validation, according to RFC 7049 section 3.10. - * \value CborValidateStrictest Attempt to perform the strictest validation we know of. - * - * \value CborValidateShortestIntegrals (Canonical) Validate that integral numbers and lengths are - * enconded in their shortest form possible. - * \value CborValidateShortestFloatingPoint (Canonical) Validate that floating-point numbers are encoded - * in their shortest form possible. - * \value CborValidateShortestNumbers (Canonical) Validate both integral and floating-point numbers - * are in their shortest form possible. - * \value CborValidateNoIndeterminateLength (Canonical) Validate that no string, array or map uses - * indeterminate length encoding. - * \value CborValidateMapIsSorted (Canonical & Strict mode) Validate that map keys appear in - * sorted order. - * \value CborValidateMapKeysAreUnique (Strict mode) Validate that map keys are unique. - * \value CborValidateTagUse (Strict mode) Validate that known tags are used with the - * correct types. This does not validate that the content of - * those types is syntactically correct. For example, this - * option validates that tag 1 (DateTimeString) is used with - * a Text String, but it does not validate that the string is - * a valid date/time representation. - * \value CborValidateUtf8 (Strict mode) Validate that text strings are appropriately - * encoded in UTF-8. - * \value CborValidateMapKeysAreString Validate that all map keys are text strings. - * \value CborValidateNoUndefined Validate that no elements of type "undefined" are present. - * \value CborValidateNoTags Validate that no tags are used. - * \value CborValidateFiniteFloatingPoint Validate that all floating point numbers are finite (no NaN or - * infinities are allowed). - * \value CborValidateCompleteData Validate that the stream is complete and there is no more data - * in the buffer. - * \value CborValidateNoUnknownSimpleTypesSA Validate that all Standards Action simple types are registered - * with IANA. - * \value CborValidateNoUnknownSimpleTypes Validate that all simple types used are registered with IANA. - * \value CborValidateNoUnknownTagsSA Validate that all Standard Actions tags are registered with IANA. - * \value CborValidateNoUnknownTagsSR Validate that all Standard Actions and Specification Required tags - * are registered with IANA (see below for limitations). - * \value CborValidateNoUnkonwnTags Validate that all tags are registered with IANA - * (see below for limitations). - * - * \par Simple type registry - * The CBOR specification requires that registration for use of the first 19 - * simple types must be done by way of Standards Action. The rest of the simple - * types only require a specification. The official list can be obtained from - * https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xhtml. - * - * \par - * There are no registered simple types recognized by this release of TinyCBOR - * (beyond those defined by RFC 7049). - * - * \par Tag registry - * The CBOR specification requires that registration for use of the first 23 - * tags must be done by way of Standards Action. The next up to tag 255 only - * require a specification. Finally, all other tags can be registered on a - * first-come-first-serve basis. The official list can be ontained from - * https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml. - * - * \par - * Given the variability of this list, TinyCBOR cannot recognize all tags - * registered with IANA. Instead, the implementation only recognizes tags - * that are backed by an RFC. - * - * \par - * These are the tags known to the current TinyCBOR release: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TagData ItemSemantics
0UTF-8 text stringStandard date/time string
1integerEpoch-based date/time
2byte stringPositive bignum
3byte stringNegative bignum
4arrayDecimal fraction
5arrayBigfloat
16arrayCOSE Single Recipient Encrypted Data Object (RFC 8152)
17arrayCOSE Mac w/o Recipients Object (RFC 8152)
18arrayCOSE Single Signer Data Object (RFC 8162)
21byte string, array, mapExpected conversion to base64url encoding
22byte string, array, mapExpected conversion to base64 encoding
23byte string, array, mapExpected conversion to base16 encoding
24byte stringEncoded CBOR data item
32UTF-8 text stringURI
33UTF-8 text stringbase64url
34UTF-8 text stringbase64
35UTF-8 text stringRegular expression
36UTF-8 text stringMIME message
96arrayCOSE Encrypted Data Object (RFC 8152)
97arrayCOSE MACed Data Object (RFC 8152)
98arrayCOSE Signed Data Object (RFC 8152)
55799anySelf-describe CBOR
- */ - -struct KnownTagData { uint32_t tag; uint32_t types; }; -static const struct KnownTagData knownTagData[] = { - { 0, (uint32_t)CborTextStringType }, - { 1, (uint32_t)(CborIntegerType+1) }, - { 2, (uint32_t)CborByteStringType }, - { 3, (uint32_t)CborByteStringType }, - { 4, (uint32_t)CborArrayType }, - { 5, (uint32_t)CborArrayType }, - { 16, (uint32_t)CborArrayType }, - { 17, (uint32_t)CborArrayType }, - { 18, (uint32_t)CborArrayType }, - { 21, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, - { 22, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, - { 23, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, - { 24, (uint32_t)CborByteStringType }, - { 32, (uint32_t)CborTextStringType }, - { 33, (uint32_t)CborTextStringType }, - { 34, (uint32_t)CborTextStringType }, - { 35, (uint32_t)CborTextStringType }, - { 36, (uint32_t)CborTextStringType }, - { 96, (uint32_t)CborArrayType }, - { 97, (uint32_t)CborArrayType }, - { 98, (uint32_t)CborArrayType }, - { 55799, 0U } -}; - -static CborError validate_value(CborValue *it, uint32_t flags, int recursionLeft); - -static inline CborError validate_utf8_string(const void *ptr, size_t n) -{ - const uint8_t *buffer = (const uint8_t *)ptr; - const uint8_t * const end = buffer + n; - while (buffer < end) { - uint32_t uc = get_utf8(&buffer, end); - if (uc == ~0U) - return CborErrorInvalidUtf8TextString; - } - return CborNoError; -} - -static inline CborError validate_simple_type(uint8_t simple_type, uint32_t flags) -{ - /* At current time, all known simple types are those from RFC 7049, - * which are parsed by the parser into different CBOR types. - * That means that if we've got here, the type is unknown */ - if (simple_type < 32) - return (flags & CborValidateNoUnknownSimpleTypesSA) ? CborErrorUnknownSimpleType : CborNoError; - return (flags & CborValidateNoUnknownSimpleTypes) == CborValidateNoUnknownSimpleTypes ? - CborErrorUnknownSimpleType : CborNoError; -} - -static inline CborError validate_number(const CborValue *it, CborType type, uint32_t flags) -{ - CborError err = CborNoError; - const uint8_t *ptr = it->ptr; - size_t bytesUsed, bytesNeeded; - uint64_t value; - - if ((flags & CborValidateShortestIntegrals) == 0) - return err; - if (type >= CborHalfFloatType && type <= CborDoubleType) - return err; /* checked elsewhere */ - - err = _cbor_value_extract_number(&ptr, it->parser->end, &value); - if (err) - return err; - - bytesUsed = (size_t)(ptr - it->ptr - 1); - bytesNeeded = 0; - if (value >= Value8Bit) - ++bytesNeeded; - if (value > 0xffU) - ++bytesNeeded; - if (value > 0xffffU) - bytesNeeded += 2; - if (value > 0xffffffffU) - bytesNeeded += 4; - if (bytesNeeded < bytesUsed) - return CborErrorOverlongEncoding; - return CborNoError; -} - -static inline CborError validate_tag(CborValue *it, CborTag tag, uint32_t flags, int recursionLeft) -{ - CborType type = cbor_value_get_type(it); - const size_t knownTagCount = sizeof(knownTagData) / sizeof(knownTagData[0]); - const struct KnownTagData *tagData = knownTagData; - const struct KnownTagData * const knownTagDataEnd = knownTagData + knownTagCount; - - if (!recursionLeft) - return CborErrorNestingTooDeep; - if (flags & CborValidateNoTags) - return CborErrorExcludedType; - - /* find the tag data, if any */ - for ( ; tagData != knownTagDataEnd; ++tagData) { - if (tagData->tag < tag) - continue; - if (tagData->tag > tag) - tagData = NULL; - break; - } - if (tagData == knownTagDataEnd) - tagData = NULL; - - if (flags & CborValidateNoUnknownTags && !tagData) { - /* tag not found */ - if (flags & CborValidateNoUnknownTagsSA && tag < 24) - return CborErrorUnknownTag; - if ((flags & CborValidateNoUnknownTagsSR) == CborValidateNoUnknownTagsSR && tag < 256) - return CborErrorUnknownTag; - if ((flags & CborValidateNoUnknownTags) == CborValidateNoUnknownTags) - return CborErrorUnknownTag; - } - - if (flags & CborValidateTagUse && tagData && tagData->types) { - uint32_t allowedTypes = tagData->types; - - /* correct Integer so it's not zero */ - if (type == CborIntegerType) - type = (CborType)(type + 1); - - while (allowedTypes) { - if ((uint8_t)(allowedTypes & 0xff) == type) - break; - allowedTypes >>= 8; - } - if (!allowedTypes) - return CborErrorInappropriateTagForType; - } - - return validate_value(it, flags, recursionLeft); -} - -#ifndef CBOR_NO_FLOATING_POINT -static inline CborError validate_floating_point(CborValue *it, CborType type, uint32_t flags) -{ - CborError err; - int r; - double val; - float valf; - uint16_t valf16; - - if (type != CborDoubleType) { - if (type == CborFloatType) { - err = cbor_value_get_float(it, &valf); - val = valf; - } else { -# ifdef CBOR_NO_HALF_FLOAT_TYPE - (void)valf16; - return CborErrorUnsupportedType; -# else - err = cbor_value_get_half_float(it, &valf16); - val = decode_half(valf16); -# endif - } - } else { - err = cbor_value_get_double(it, &val); - } - cbor_assert(err == CborNoError); /* can't fail */ - - r = fpclassify(val); - if (r == FP_NAN || r == FP_INFINITE) { - if (flags & CborValidateFiniteFloatingPoint) - return CborErrorExcludedValue; - if (flags & CborValidateShortestFloatingPoint) { - if (type == CborDoubleType) - return CborErrorOverlongEncoding; -# ifndef CBOR_NO_HALF_FLOAT_TYPE - if (type == CborFloatType) - return CborErrorOverlongEncoding; - if (r == FP_NAN && valf16 != 0x7e00) - return CborErrorImproperValue; - if (r == FP_INFINITE && valf16 != 0x7c00 && valf16 != 0xfc00) - return CborErrorImproperValue; -# endif - } - } - - if (flags & CborValidateShortestFloatingPoint && type > CborHalfFloatType) { - if (type == CborDoubleType) { - valf = (float)val; - if ((double)valf == val) - return CborErrorOverlongEncoding; - } -# ifndef CBOR_NO_HALF_FLOAT_TYPE - if (type == CborFloatType) { - valf16 = encode_half(valf); - if (valf == decode_half(valf16)) - return CborErrorOverlongEncoding; - } -# endif - } - - return CborNoError; -} -#endif - -static CborError validate_container(CborValue *it, int containerType, uint32_t flags, int recursionLeft) -{ - CborError err; - const uint8_t *previous = NULL; - const uint8_t *previous_end = NULL; - - if (!recursionLeft) - return CborErrorNestingTooDeep; - - while (!cbor_value_at_end(it)) { - const uint8_t *current = cbor_value_get_next_byte(it); - - if (containerType == CborMapType) { - if (flags & CborValidateMapKeysAreString) { - CborType type = cbor_value_get_type(it); - if (type == CborTagType) { - /* skip the tags */ - CborValue copy = *it; - err = cbor_value_skip_tag(©); - if (err) - return err; - type = cbor_value_get_type(©); - } - if (type != CborTextStringType) - return CborErrorMapKeyNotString; - } - } - - err = validate_value(it, flags, recursionLeft); - if (err) - return err; - - if (containerType != CborMapType) - continue; - - if (flags & CborValidateMapIsSorted) { - if (previous) { - uint64_t len1, len2; - const uint8_t *ptr; - - /* extract the two lengths */ - ptr = previous; - _cbor_value_extract_number(&ptr, it->parser->end, &len1); - ptr = current; - _cbor_value_extract_number(&ptr, it->parser->end, &len2); - - if (len1 > len2) - return CborErrorMapNotSorted; - if (len1 == len2) { - size_t bytelen1 = (size_t)(previous_end - previous); - size_t bytelen2 = (size_t)(it->ptr - current); - int r = memcmp(previous, current, bytelen1 <= bytelen2 ? bytelen1 : bytelen2); - - if (r == 0 && bytelen1 != bytelen2) - r = bytelen1 < bytelen2 ? -1 : +1; - if (r > 0) - return CborErrorMapNotSorted; - if (r == 0 && (flags & CborValidateMapKeysAreUnique) == CborValidateMapKeysAreUnique) - return CborErrorMapKeysNotUnique; - } - } - - previous = current; - previous_end = it->ptr; - } - - /* map: that was the key, so get the value */ - err = validate_value(it, flags, recursionLeft); - if (err) - return err; - } - return CborNoError; -} - -static CborError validate_value(CborValue *it, uint32_t flags, int recursionLeft) -{ - CborError err; - CborType type = cbor_value_get_type(it); - - if (cbor_value_is_length_known(it)) { - err = validate_number(it, type, flags); - if (err) - return err; - } else { - if (flags & CborValidateNoIndeterminateLength) - return CborErrorUnknownLength; - } - - switch (type) { - case CborArrayType: - case CborMapType: { - /* recursive type */ - CborValue recursed; - err = cbor_value_enter_container(it, &recursed); - if (!err) - err = validate_container(&recursed, type, flags, recursionLeft - 1); - if (err) { - it->ptr = recursed.ptr; - return err; - } - err = cbor_value_leave_container(it, &recursed); - if (err) - return err; - return CborNoError; - } - - case CborIntegerType: { - uint64_t val; - err = cbor_value_get_raw_integer(it, &val); - cbor_assert(err == CborNoError); /* can't fail */ - - break; - } - - case CborByteStringType: - case CborTextStringType: { - size_t n = 0; - const void *ptr; - - err = _cbor_value_prepare_string_iteration(it); - if (err) - return err; - - while (1) { - err = validate_number(it, type, flags); - if (err) - return err; - - err = _cbor_value_get_string_chunk(it, &ptr, &n, it); - if (err) - return err; - if (!ptr) - break; - - if (type == CborTextStringType && flags & CborValidateUtf8) { - err = validate_utf8_string(ptr, n); - if (err) - return err; - } - } - - return CborNoError; - } - - case CborTagType: { - CborTag tag; - err = cbor_value_get_tag(it, &tag); - cbor_assert(err == CborNoError); /* can't fail */ - - err = cbor_value_advance_fixed(it); - if (err) - return err; - err = validate_tag(it, tag, flags, recursionLeft - 1); - if (err) - return err; - - return CborNoError; - } - - case CborSimpleType: { - uint8_t simple_type; - err = cbor_value_get_simple_type(it, &simple_type); - cbor_assert(err == CborNoError); /* can't fail */ - err = validate_simple_type(simple_type, flags); - if (err) - return err; - break; - } - - case CborNullType: - case CborBooleanType: - break; - - case CborUndefinedType: - if (flags & CborValidateNoUndefined) - return CborErrorExcludedType; - break; - - case CborHalfFloatType: - case CborFloatType: - case CborDoubleType: { -#ifdef CBOR_NO_FLOATING_POINT - return CborErrorUnsupportedType; -#else - err = validate_floating_point(it, type, flags); - if (err) - return err; - break; -#endif /* !CBOR_NO_FLOATING_POINT */ - } - - case CborInvalidType: - return CborErrorUnknownType; - } - - err = cbor_value_advance_fixed(it); - return err; -} - -/** - * Performs a full validation, controlled by the \a flags options, of the CBOR - * stream pointed by \a it and returns the error it found. If no error was - * found, it returns CborNoError and the application can iterate over the items - * with certainty that no errors will appear during parsing. - * - * If \a flags is CborValidateBasic, the result should be the same as - * cbor_value_validate_basic(). - * - * This function has the same timing and memory requirements as - * cbor_value_advance() and cbor_value_validate_basic(). - * - * \sa CborValidationFlags, cbor_value_validate_basic(), cbor_value_advance() - */ -CborError cbor_value_validate(const CborValue *it, uint32_t flags) -{ - CborValue value = *it; - CborError err = validate_value(&value, flags, CBOR_PARSER_MAX_RECURSIONS); - if (err) - return err; - if (flags & CborValidateCompleteData && it->ptr != it->parser->end) - return CborErrorGarbageAtEnd; - return CborNoError; -} - -#pragma GCC diagnostic pop - -/** - * @} - */ diff --git a/src/cbor/lib/tinycbor/src/compilersupport_p.h b/src/cbor/lib/tinycbor/src/compilersupport_p.h deleted file mode 100644 index 2b9491d3..00000000 --- a/src/cbor/lib/tinycbor/src/compilersupport_p.h +++ /dev/null @@ -1,205 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#ifndef COMPILERSUPPORT_H -#define COMPILERSUPPORT_H - -#include "cbor.h" - -#ifndef _BSD_SOURCE -# define _BSD_SOURCE -#endif -#ifndef _DEFAULT_SOURCE -# define _DEFAULT_SOURCE -#endif -#ifndef assert -# include -#endif -#include -#include -#include - -#ifndef __cplusplus -# include -#endif - -#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L || __cpp_static_assert >= 200410 -# define cbor_static_assert(x) static_assert(x, #x) -#elif !defined(__cplusplus) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) && (__STDC_VERSION__ > 199901L) -# define cbor_static_assert(x) _Static_assert(x, #x) -#else -# define cbor_static_assert(x) ((void)sizeof(char[2*!!(x) - 1])) -#endif -#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) -/* inline is a keyword */ -#else -/* use the definition from cbor.h */ -# define inline CBOR_INLINE -#endif - -#ifdef NDEBUG -# define cbor_assert(cond) do { if (!(cond)) unreachable(); } while (0) -#else -# define cbor_assert(cond) assert(cond) -#endif - -#ifndef STRINGIFY -#define STRINGIFY(x) STRINGIFY2(x) -#endif -#define STRINGIFY2(x) #x - -#if !defined(UINT32_MAX) || !defined(INT64_MAX) -/* C89? We can define UINT32_MAX portably, but not INT64_MAX */ -# error "Your system has stdint.h but that doesn't define UINT32_MAX or INT64_MAX" -#endif - -#ifndef DBL_DECIMAL_DIG -/* DBL_DECIMAL_DIG is C11 */ -# define DBL_DECIMAL_DIG 17 -#endif -#define DBL_DECIMAL_DIG_STR STRINGIFY(DBL_DECIMAL_DIG) - -#if defined(__GNUC__) && defined(__i386__) && !defined(__iamcu__) -# define CBOR_INTERNAL_API_CC __attribute__((regparm(3))) -#elif defined(_MSC_VER) && defined(_M_IX86) -# define CBOR_INTERNAL_API_CC __fastcall -#else -# define CBOR_INTERNAL_API_CC -#endif - -#ifndef __has_builtin -# define __has_builtin(x) 0 -#endif - -#if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) || \ - (__has_builtin(__builtin_bswap64) && __has_builtin(__builtin_bswap32)) -# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define cbor_ntohll __builtin_bswap64 -# define cbor_htonll __builtin_bswap64 -# define cbor_ntohl __builtin_bswap32 -# define cbor_htonl __builtin_bswap32 -# ifdef __INTEL_COMPILER -# define cbor_ntohs _bswap16 -# define cbor_htons _bswap16 -# elif (__GNUC__ * 100 + __GNUC_MINOR__ >= 608) || __has_builtin(__builtin_bswap16) -# define cbor_ntohs __builtin_bswap16 -# define cbor_htons __builtin_bswap16 -# else -# define cbor_ntohs(x) (((uint16_t)x >> 8) | ((uint16_t)x << 8)) -# define cbor_htons cbor_ntohs -# endif -# else -# define cbor_ntohll -# define cbor_htonll -# define cbor_ntohl -# define cbor_htonl -# define cbor_ntohs -# define cbor_htons -# endif -#elif defined(__sun) -# include -#elif defined(_MSC_VER) -/* MSVC, which implies Windows, which implies little-endian and sizeof(long) == 4 */ -# include -# define cbor_ntohll _byteswap_uint64 -# define cbor_htonll _byteswap_uint64 -# define cbor_ntohl _byteswap_ulong -# define cbor_htonl _byteswap_ulong -# define cbor_ntohs _byteswap_ushort -# define cbor_htons _byteswap_ushort -#endif -#ifndef cbor_ntohs -# include -# define cbor_ntohs ntohs -# define cbor_htons htons -#endif -#ifndef cbor_ntohl -# include -# define cbor_ntohl ntohl -# define cbor_htonl htonl -#endif -#ifndef cbor_ntohll -# define cbor_ntohll ntohll -# define cbor_htonll htonll -/* ntohll isn't usually defined */ -# ifndef ntohll -# if (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ - (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) || \ - (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) || \ - (defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) || \ - defined(__ARMEB__) || defined(__MIPSEB__) || defined(__s390__) || defined(__sparc__) -# define ntohll -# define htonll -# elif (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ - (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || \ - (defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && BYTE_ORDER == LITTLE_ENDIAN) || \ - defined(_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPSEL__) || \ - defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) -# define ntohll(x) ((ntohl((uint32_t)(x)) * UINT64_C(0x100000000)) + (ntohl((x) >> 32))) -# define htonll ntohll -# else -# error "Unable to determine byte order!" -# endif -# endif -#endif - - -#ifdef __cplusplus -# define CONST_CAST(t, v) const_cast(v) -#else -/* C-style const_cast without triggering a warning with -Wcast-qual */ -# define CONST_CAST(t, v) (t)(uintptr_t)(v) -#endif - -#ifdef __GNUC__ -#ifndef likely -# define likely(x) __builtin_expect(!!(x), 1) -#endif -#ifndef unlikely -# define unlikely(x) __builtin_expect(!!(x), 0) -#endif -# define unreachable() __builtin_unreachable() -#elif defined(_MSC_VER) -# define likely(x) (x) -# define unlikely(x) (x) -# define unreachable() __assume(0) -#else -# define likely(x) (x) -# define unlikely(x) (x) -# define unreachable() do {} while (0) -#endif - -static inline bool add_check_overflow(size_t v1, size_t v2, size_t *r) -{ -#if ((defined(__GNUC__) && (__GNUC__ >= 5)) && !defined(__INTEL_COMPILER)) || __has_builtin(__builtin_add_overflow) - return __builtin_add_overflow(v1, v2, r); -#else - /* unsigned additions are well-defined */ - *r = v1 + v2; - return v1 > v1 + v2; -#endif -} - -#endif /* COMPILERSUPPORT_H */ - diff --git a/src/cbor/lib/tinycbor/src/open_memstream.c b/src/cbor/lib/tinycbor/src/open_memstream.c deleted file mode 100644 index b3e624d4..00000000 --- a/src/cbor/lib/tinycbor/src/open_memstream.c +++ /dev/null @@ -1,112 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#define _GNU_SOURCE 1 - -#include -#include -#include -#include -#include - -#include - -typedef ssize_t RetType; -typedef size_t LenType; - -#include "compilersupport_p.h" - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#pragma GCC diagnostic ignored "-Wreturn-type" -#pragma GCC diagnostic ignored "-Wunused-function" - -struct Buffer -{ - char **ptr; - size_t *len; - size_t alloc; -}; - -static RetType write_to_buffer(void *cookie, const char *data, LenType len) -{ - struct Buffer *b = (struct Buffer *)cookie; - char *ptr = *b->ptr; - size_t newsize; - - errno = EFBIG; - if (unlikely(add_check_overflow(*b->len, len, &newsize))) - return -1; - - if (newsize > b->alloc) { - /* make room */ - size_t newalloc = newsize + newsize / 2 + 1; /* give 50% more room */ - ptr = realloc(ptr, newalloc); - if (ptr == NULL) - return -1; - b->alloc = newalloc; - *b->ptr = ptr; - } - - memcpy(ptr + *b->len, data, len); - *b->len = newsize; - return len; -} - -static int close_buffer(void *cookie) -{ - struct Buffer *b = (struct Buffer *)cookie; - if (*b->ptr) - (*b->ptr)[*b->len] = '\0'; - free(b); - return 0; -} - -FILE *open_memstream(char **bufptr, size_t *lenptr) -{ - struct Buffer *b = (struct Buffer *)malloc(sizeof(struct Buffer)); - if (b == NULL) - return NULL; - b->alloc = 0; - b->len = lenptr; - b->ptr = bufptr; - *bufptr = NULL; - *lenptr = 0; - -#ifdef __APPLE__ - return funopen(b, NULL, write_to_buffer, NULL, close_buffer); -#elif __GLIBC__ - static const cookie_io_functions_t vtable = { - NULL, - write_to_buffer, - NULL, - close_buffer - }; - return fopencookie(b, "w", vtable); -#endif -} - -#pragma GCC diagnostic pop diff --git a/src/cbor/lib/tinycbor/src/tags.txt b/src/cbor/lib/tinycbor/src/tags.txt deleted file mode 100644 index ef78cfb5..00000000 --- a/src/cbor/lib/tinycbor/src/tags.txt +++ /dev/null @@ -1,23 +0,0 @@ -# Tag number; Tag ID; Applicable types (comma-separated); Semantics -0;DateTimeString;TextString;Standard date/time string -1;UnixTime_t;Integer;Epoch-based date/time -2;PositiveBignum;ByteString;Positive bignum -3;NegativeBignum;ByteString;Negative bignum -4;Decimal;Array;Decimal fraction -5;Bigfloat;Array;Bigfloat -16;COSE_Encrypt0;Array;COSE Single Recipient Encrypted Data Object (RFC 8152) -17;COSE_Mac0;Array;COSE Mac w/o Recipients Object (RFC 8152) -18;COSE_Sign1;Array;COSE Single Signer Data Object (RFC 8162) -21;ExpectedBase64url;ByteString,Array,Map;Expected conversion to base64url encoding -22;ExpectedBase64;ByteString,Array,Map;Expected conversion to base64 encoding -23;ExpectedBase16;ByteString,Array,Map;Expected conversion to base16 encoding -24;EncodedCbor;ByteString;Encoded CBOR data item -32;Url;TextString;URI -33;Base64url;TextString;base64url -34;Base64;TextString;base64 -35;RegularExpression;TextString;Regular expression -36;MimeMessage;TextString;MIME message -96;COSE_Encrypt;Array;COSE Encrypted Data Object (RFC 8152) -97;COSE_Mac;Array;COSE MACed Data Object (RFC 8152) -98;COSE_Sign;Array;COSE Signed Data Object (RFC 8152) -55799;Signature;;Self-describe CBOR diff --git a/src/cbor/lib/tinycbor/src/tinycbor-version.h b/src/cbor/lib/tinycbor/src/tinycbor-version.h deleted file mode 100644 index c57d7fa2..00000000 --- a/src/cbor/lib/tinycbor/src/tinycbor-version.h +++ /dev/null @@ -1,3 +0,0 @@ -#define TINYCBOR_VERSION_MAJOR 0 -#define TINYCBOR_VERSION_MINOR 5 -#define TINYCBOR_VERSION_PATCH 2 diff --git a/src/cbor/lib/tinycbor/src/utf8_p.h b/src/cbor/lib/tinycbor/src/utf8_p.h deleted file mode 100644 index 577e5404..00000000 --- a/src/cbor/lib/tinycbor/src/utf8_p.h +++ /dev/null @@ -1,104 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** 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. -** -****************************************************************************/ - -#ifndef CBOR_UTF8_H -#define CBOR_UTF8_H - -#include "compilersupport_p.h" - -#include - -static inline uint32_t get_utf8(const uint8_t **buffer, const uint8_t *end) -{ - int charsNeeded; - uint32_t uc, min_uc; - uint8_t b; - ptrdiff_t n = end - *buffer; - if (n == 0) - return ~0U; - - uc = *(*buffer)++; - if (uc < 0x80) { - /* single-byte UTF-8 */ - return uc; - } - - /* multi-byte UTF-8, decode it */ - if (unlikely(uc <= 0xC1)) - return ~0U; - if (uc < 0xE0) { - /* two-byte UTF-8 */ - charsNeeded = 2; - min_uc = 0x80; - uc &= 0x1f; - } else if (uc < 0xF0) { - /* three-byte UTF-8 */ - charsNeeded = 3; - min_uc = 0x800; - uc &= 0x0f; - } else if (uc < 0xF5) { - /* four-byte UTF-8 */ - charsNeeded = 4; - min_uc = 0x10000; - uc &= 0x07; - } else { - return ~0U; - } - - if (n < charsNeeded - 1) - return ~0U; - - /* first continuation character */ - b = *(*buffer)++; - if ((b & 0xc0) != 0x80) - return ~0U; - uc <<= 6; - uc |= b & 0x3f; - - if (charsNeeded > 2) { - /* second continuation character */ - b = *(*buffer)++; - if ((b & 0xc0) != 0x80) - return ~0U; - uc <<= 6; - uc |= b & 0x3f; - - if (charsNeeded > 3) { - /* third continuation character */ - b = *(*buffer)++; - if ((b & 0xc0) != 0x80) - return ~0U; - uc <<= 6; - uc |= b & 0x3f; - } - } - - /* overlong sequence? surrogate pair? out or range? */ - if (uc < min_uc || uc - 0xd800U < 2048U || uc > 0x10ffff) - return ~0U; - - return uc; -} - -#endif /* CBOR_UTF8_H */ diff --git a/src/property/Property.h b/src/property/Property.h index 71a8447c..991f545e 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -35,7 +35,7 @@ # include #include -#include "../cbor/lib/tinycbor/cbor-lib.h" +#include /****************************************************************************** CONST