From 52d441efa905d203ece3f7218c854efac372dda5 Mon Sep 17 00:00:00 2001 From: Thomas Saedt Date: Mon, 22 Nov 2021 21:00:11 +0100 Subject: [PATCH 1/8] build: add CMake support --- CMakeLists.txt | 17 +++++++++++++++++ {cborg => include/cborg}/Cbor.h | 0 {cborg => include/cborg}/CborBase.h | 0 {cborg => include/cborg}/Cbore.h | 0 {cborg => include/cborg}/Cborg.h | 0 {cborg => include/cborg}/CborgHeader.h | 0 6 files changed, 17 insertions(+) create mode 100644 CMakeLists.txt rename {cborg => include/cborg}/Cbor.h (100%) rename {cborg => include/cborg}/CborBase.h (100%) rename {cborg => include/cborg}/Cbore.h (100%) rename {cborg => include/cborg}/Cborg.h (100%) rename {cborg => include/cborg}/CborgHeader.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2e341a3 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,17 @@ +add_library(cborg-lib STATIC + source/CborBase.cpp + source/Cbore.cpp + source/Cborg.cpp + ) + +target_include_directories(cborg-lib PUBLIC include/) + +if (CMAKE_BUILD_TYPE MATCHES "Debug") + + add_executable(cborg-test + test/test.cpp) + + target_link_libraries(cborg-test PUBLIC + cborg-lib) + +endif () \ No newline at end of file diff --git a/cborg/Cbor.h b/include/cborg/Cbor.h similarity index 100% rename from cborg/Cbor.h rename to include/cborg/Cbor.h diff --git a/cborg/CborBase.h b/include/cborg/CborBase.h similarity index 100% rename from cborg/CborBase.h rename to include/cborg/CborBase.h diff --git a/cborg/Cbore.h b/include/cborg/Cbore.h similarity index 100% rename from cborg/Cbore.h rename to include/cborg/Cbore.h diff --git a/cborg/Cborg.h b/include/cborg/Cborg.h similarity index 100% rename from cborg/Cborg.h rename to include/cborg/Cborg.h diff --git a/cborg/CborgHeader.h b/include/cborg/CborgHeader.h similarity index 100% rename from cborg/CborgHeader.h rename to include/cborg/CborgHeader.h From fefa69302a5957ca64d539b51194ddd253d78675 Mon Sep 17 00:00:00 2001 From: Thomas Saedt Date: Mon, 22 Nov 2021 21:10:26 +0100 Subject: [PATCH 2/8] chore: implement some clang-tidy suggestions and format code --- source/CborBase.cpp | 439 +++++------ source/Cbore.cpp | 433 +++++------ source/Cborg.cpp | 1811 +++++++++++++++++++------------------------ 3 files changed, 1175 insertions(+), 1508 deletions(-) diff --git a/source/CborBase.cpp b/source/CborBase.cpp index 1eaef92..3256141 100644 --- a/source/CborBase.cpp +++ b/source/CborBase.cpp @@ -16,273 +16,234 @@ #include "cborg/CborBase.h" -#include #include +#include #include CborBase CborNull; -uint32_t CborBase::writeCBOR(uint8_t* destination, uint32_t maxLength) -{ - uint32_t written = 0; +uint32_t CborBase::writeCBOR(uint8_t* destination, uint32_t maxLength) { + uint32_t written = 0; - if (destination) - { - // write tag if set - if (tag != TypeUnassigned) - { - written += writeTypeAndValue(destination, maxLength, TypeTag, tag); - } + if (destination != nullptr) { + // write tag if set + if (tag != TypeUnassigned) { + written += writeTypeAndValue(destination, maxLength, TypeTag, tag); + } - if (written + 1 <= maxLength) - { - destination[written] = majorType << 5 | minorType; - written++; - } + if (written + 1 <= maxLength) { + destination[written] = majorType << 5 | minorType; + written++; } + } - return written; + return written; } -uint32_t CborBase::writeQueue(uint8_t* destination, uint32_t maxLength, std::list& queue) -{ - uint32_t written = 0; - - if (destination) - { - while (queue.size() > 0) - { - CborBase* currentObject = queue.back(); - queue.pop_back(); - - if (currentObject) - { - uint8_t type = currentObject->getType(); - - if (type == CborBase::TypeArray) - { - // write tag if set - uint32_t subtag = currentObject->getTag(); - if (subtag != TypeUnassigned) - { - written += writeTypeAndValue(&destination[written], maxLength - written, TypeTag, subtag); - } - - uint32_t items = currentObject->getSize(); - written += CborBase::writeTypeAndValue(&destination[written], maxLength - written, CborBase::TypeArray, items); - - // dump array to FILO queue - for (std::size_t idx = 0; idx < items; idx++) - { - queue.push_back(currentObject->at(items - 1 - idx)); - } - } - else if (type == CborBase::TypeMap) - { - // write tag if set - uint32_t subtag = currentObject->getTag(); - if (subtag != TypeUnassigned) - { - written += writeTypeAndValue(&destination[written], maxLength - written, TypeTag, subtag); - } - - uint32_t items = currentObject->getSize(); - written += CborBase::writeTypeAndValue(&destination[written], maxLength - written, CborBase::TypeMap, items); - - // dump map to FILO queue - for (std::size_t idx = 0; idx < items; idx++) - { - queue.push_back(currentObject->value(items - 1 - idx)); - queue.push_back(currentObject->key(items - 1 - idx)); - } - } - else - { - written += currentObject->writeCBOR(&destination[written], maxLength - written); - } - } +uint32_t CborBase::writeQueue(uint8_t* destination, uint32_t maxLength, + std::list& queue) { + uint32_t written = 0; + + if (destination) { + while (!queue.empty()) { + CborBase* current_object = queue.back(); + queue.pop_back(); + + if (current_object) { + uint8_t type = current_object->getType(); + + if (type == CborBase::TypeArray) { + // write tag if set + uint32_t subtag = current_object->getTag(); + if (subtag != TypeUnassigned) { + written += writeTypeAndValue(&destination[written], + maxLength - written, TypeTag, subtag); + } + + uint32_t items = current_object->getSize(); + written += CborBase::writeTypeAndValue(&destination[written], + maxLength - written, + CborBase::TypeArray, items); + + // dump array to FILO queue + for (std::size_t idx = 0; idx < items; idx++) { + queue.push_back(current_object->at(items - 1 - idx)); + } + } else if (type == CborBase::TypeMap) { + // write tag if set + uint32_t subtag = current_object->getTag(); + if (subtag != TypeUnassigned) { + written += writeTypeAndValue(&destination[written], + maxLength - written, TypeTag, subtag); + } + + uint32_t items = current_object->getSize(); + written += CborBase::writeTypeAndValue(&destination[written], + maxLength - written, + CborBase::TypeMap, items); + + // dump map to FILO queue + for (std::size_t idx = 0; idx < items; idx++) { + queue.push_back(current_object->value(items - 1 - idx)); + queue.push_back(current_object->key(items - 1 - idx)); + } + } else { + written += current_object->writeCBOR(&destination[written], + maxLength - written); } + } } + } - return written; + return written; } -void CborBase::printQueue(std::list queue) -{ - std::list progress; - uint32_t units = queue.size(); - uint32_t indentation = 1; - - while (queue.size() > 0) - { - CborBase* currentObject = queue.back(); - queue.pop_back(); - - if (currentObject) - { - units--; - - // indent - for (std::size_t idx = 0; idx < indentation; idx++) - { - printf("\t"); - } - - // - uint8_t type = currentObject->getType(); - - if (type == CborBase::TypeArray) - { - - // print tag if set - uint32_t subtag = currentObject->getTag(); - if (subtag != TypeUnassigned) - { - printf("[%" PRIu32 "] ", subtag); - } - - uint32_t items = currentObject->getSize(); - printf("Array: %" PRIu32 "\r\n", items); - - if (items > 0) - { - // dump array to FILO queue - for (std::size_t idx = 0; idx < items; idx++) - { - queue.push_back(currentObject->at(items - 1 - idx)); - } - - // fix indentation - progress.push_back(units); - units = items; - indentation++; - } - } - else if (type == CborBase::TypeMap) - { - // write tag if set - uint32_t subtag = currentObject->getTag(); - if (subtag != TypeUnassigned) - { - printf("[%" PRIu32 "] ", subtag); - } - - uint32_t items = currentObject->getSize(); - printf("Map: %" PRIu32 "\r\n", items); - - if (items > 0) - { - // dump map to FILO queue - for (std::size_t idx = 0; idx < items; idx++) - { - queue.push_back(currentObject->value(items - 1 - idx)); - queue.push_back(currentObject->key(items - 1 - idx)); - } - - // fix indentation - progress.push_back(units); - units = 2 * items; - indentation++; - } - } - else - { - currentObject->print(); - } - - while ((units == 0) && (progress.size() > 0)) - { - units = progress.back(); - progress.pop_back(); - indentation--; - } +void CborBase::printQueue(std::list queue) { + std::list progress; + uint32_t units = queue.size(); + uint32_t indentation = 1; + + while (!queue.empty()) { + CborBase* current_object = queue.back(); + queue.pop_back(); + + if (current_object) { + units--; + + // indent + for (std::size_t idx = 0; idx < indentation; idx++) { + printf("\t"); + } + + // + uint8_t type = current_object->getType(); + + if (type == CborBase::TypeArray) { + // print tag if set + uint32_t subtag = current_object->getTag(); + if (subtag != TypeUnassigned) { + printf("[%" PRIu32 "] ", subtag); + } + + uint32_t items = current_object->getSize(); + printf("Array: %" PRIu32 "\r\n", items); + + if (items > 0) { + // dump array to FILO queue + for (std::size_t idx = 0; idx < items; idx++) { + queue.push_back(current_object->at(items - 1 - idx)); + } + + // fix indentation + progress.push_back(units); + units = items; + indentation++; + } + } else if (type == CborBase::TypeMap) { + // write tag if set + uint32_t subtag = current_object->getTag(); + if (subtag != TypeUnassigned) { + printf("[%" PRIu32 "] ", subtag); + } + + uint32_t items = current_object->getSize(); + printf("Map: %" PRIu32 "\r\n", items); + + if (items > 0) { + // dump map to FILO queue + for (std::size_t idx = 0; idx < items; idx++) { + queue.push_back(current_object->value(items - 1 - idx)); + queue.push_back(current_object->key(items - 1 - idx)); + } + + // fix indentation + progress.push_back(units); + units = 2 * items; + indentation++; } + } else { + current_object->print(); + } + + while ((units == 0) && (!progress.empty())) { + units = progress.back(); + progress.pop_back(); + indentation--; + } } + } } -uint8_t CborBase::writeTypeAndValue(uint8_t* destination, uint32_t maxLength, uint8_t majorType, uint32_t value) -{ - if (destination) - { - if (majorType < TypeSpecial) - { - uint8_t majorTypeHigh = majorType << 5; - - // value fits in one byte - if (value <= 23) - { - if (maxLength >= 1) - { - destination[0] = majorTypeHigh | value; - - return 1; - } - } - // value fits in two bytes - else if (value <= 0xFF) - { - if (maxLength >= 2) - { - destination[0] = majorTypeHigh | 24; - destination[1] = value; - - return 2; - } - } - // value fits in three bytes - else if (value <= 0xFFFF) - { - if (maxLength >= 3) - { - destination[0] = majorTypeHigh | 25; - destination[1] = value >> 8; - destination[2] = value; - - return 3; - } - } - // value fits in four bytes - else - { - if (maxLength >= 5) - { - destination[0] = majorTypeHigh | 26; - destination[1] = value >> 24; - destination[2] = value >> 16; - destination[3] = value >> 8; - destination[4] = value; - - return 5; - } - } +uint8_t CborBase::writeTypeAndValue(uint8_t* destination, uint32_t maxLength, + uint8_t majorType, uint32_t value) { + if (destination != nullptr) { + if (majorType < TypeSpecial) { + uint8_t major_type_high = majorType << 5; + + // value fits in one byte + if (value <= 23) { + if (maxLength >= 1) { + destination[0] = major_type_high | value; + + return 1; + } + } + // value fits in two bytes + else if (value <= 0xFF) { + if (maxLength >= 2) { + destination[0] = major_type_high | 24; + destination[1] = value; + + return 2; } + } + // value fits in three bytes + else if (value <= 0xFFFF) { + if (maxLength >= 3) { + destination[0] = major_type_high | 25; + destination[1] = value >> 8; + destination[2] = value; + + return 3; + } + } + // value fits in four bytes + else { + if (maxLength >= 5) { + destination[0] = major_type_high | 26; + destination[1] = value >> 24; + destination[2] = value >> 16; + destination[3] = value >> 8; + destination[4] = value; + + return 5; + } + } } + } - return 0; + return 0; } -uint32_t CborBase::writeBytes(uint8_t* destination, uint32_t maxLength, const uint8_t* source, uint32_t length) -{ - if ((destination) && (source) && (length <= maxLength)) - { - for (std::size_t idx = 0; idx < length; idx++) - { - destination[idx] = source[idx]; - } - - return length; +uint32_t CborBase::writeBytes(uint8_t* destination, uint32_t maxLength, + const uint8_t* source, uint32_t length) { + if ((destination != nullptr) && (source != nullptr) && + (length <= maxLength)) { + for (std::size_t idx = 0; idx < length; idx++) { + destination[idx] = source[idx]; } - return 0; + return length; + } + + return 0; } -void CborBase::print() -{ - // write tag if set - if (tag != TypeUnassigned) - { - printf("(%" PRIu32 ") ", tag); - } +void CborBase::print() { + // write tag if set + if (tag != TypeUnassigned) { + printf("(%" PRIu32 ") ", tag); + } - printf("null\r\n"); + printf("null\r\n"); } diff --git a/source/Cbore.cpp b/source/Cbore.cpp index 59c3a35..8ab4d2f 100644 --- a/source/Cbore.cpp +++ b/source/Cbore.cpp @@ -15,59 +15,48 @@ */ #include "cborg/Cbore.h" -#include "cborg/Cborg.h" -#include -#include #include +#include + +#include + +#include "cborg/Cborg.h" #if 0 #include -#define DEBUG_PRINTF(...) { printf(__VA_ARGS__); } +#define DEBUG_PRINTF(...) \ + { printf(__VA_ARGS__); } #else #define DEBUG_PRINTF(...) #endif - -Cbore::Cbore() - : cbor(NULL), - currentLength(0), - maxLength(0) -{} +Cbore::Cbore() : cbor(nullptr), currentLength(0), maxLength(0) {} Cbore::Cbore(uint8_t* _cbor, std::size_t _length) - : cbor(_cbor), - currentLength(0), - maxLength(_length) -{} - -std::size_t Cbore::getLength() const -{ - return currentLength; -} + : cbor(_cbor), currentLength(0), maxLength(_length) {} + +std::size_t Cbore::getLength() const { return currentLength; } /*****************************************************************************/ /* Encoding */ /*****************************************************************************/ -Cbore& Cbore::tag(uint32_t tag) -{ - if ((cbor) && (itemSize(tag) <= (maxLength - currentLength))) - { - writeTypeAndValue(CborBase::TypeTag, tag); - } +Cbore& Cbore::tag(uint32_t tag) { + if ((cbor != nullptr) && (itemSize(tag) <= (maxLength - currentLength))) { + writeTypeAndValue(CborBase::TypeTag, tag); + } - return *this; + return *this; } -Cbore& Cbore::end() -{ - if ((cbor) && (currentLength < maxLength)) - { - cbor[currentLength++] = CborBase::TypeSpecial << 5 | CborBase::TypeIndefinite; - } +Cbore& Cbore::end() { + if ((cbor != nullptr) && (currentLength < maxLength)) { + cbor[currentLength++] = + CborBase::TypeSpecial << 5 | CborBase::TypeIndefinite; + } - return *this; + return *this; } /*************************************************************************/ @@ -75,25 +64,21 @@ Cbore& Cbore::end() /*************************************************************************/ // create indefinite array -Cbore& Cbore::array() -{ - if ((cbor) && (currentLength < maxLength)) - { - cbor[currentLength++] = CborBase::TypeArray << 5 | CborBase::TypeIndefinite; - } +Cbore& Cbore::array() { + if ((cbor != nullptr) && (currentLength < maxLength)) { + cbor[currentLength++] = CborBase::TypeArray << 5 | CborBase::TypeIndefinite; + } - return *this; + return *this; } // create arrray in array -Cbore& Cbore::array(std::size_t items) -{ - if ((cbor) && (itemSize(items) <= (maxLength - currentLength))) - { - writeTypeAndValue(CborBase::TypeArray, items); - } +Cbore& Cbore::array(std::size_t items) { + if ((cbor != nullptr) && (itemSize(items) <= (maxLength - currentLength))) { + writeTypeAndValue(CborBase::TypeArray, items); + } - return *this; + return *this; } /*************************************************************************/ @@ -101,55 +86,44 @@ Cbore& Cbore::array(std::size_t items) /*************************************************************************/ // insert integer -Cbore& Cbore::item(int32_t value) -{ - if (itemSize(value) <= (maxLength - currentLength)) - { - if (value < 0) - { - writeTypeAndValue(CborBase::TypeNegative, -1 - value); - } - else - { - writeTypeAndValue(CborBase::TypeUnsigned, value); - } +Cbore& Cbore::item(int32_t value) { + if (itemSize(value) <= (maxLength - currentLength)) { + if (value < 0) { + writeTypeAndValue(CborBase::TypeNegative, -1 - value); + } else { + writeTypeAndValue(CborBase::TypeUnsigned, value); } + } - return *this; + return *this; } // insert simple type -Cbore& Cbore::item(CborBase::SimpleType_t simpleType) -{ - if (currentLength < maxLength) - { - cbor[currentLength++] = CborBase::TypeSpecial << 5 | simpleType; - } +Cbore& Cbore::item(CborBase::SimpleType_t simpleType) { + if (currentLength < maxLength) { + cbor[currentLength++] = CborBase::TypeSpecial << 5 | simpleType; + } - return *this; + return *this; } -Cbore& Cbore::item(const uint8_t* bytes, std::size_t length) -{ - if ((itemSize(length) + length) <= (maxLength - currentLength)) - { - writeTypeAndValue(CborBase::TypeBytes, length); - writeBytes(bytes, length); - } +Cbore& Cbore::item(const uint8_t* bytes, std::size_t length) { + if ((itemSize(length) + length) <= (maxLength - currentLength)) { + writeTypeAndValue(CborBase::TypeBytes, length); + writeBytes(bytes, length); + } - return *this; + return *this; } // write string, length -Cbore& Cbore::item(const char* string, std::size_t length) -{ - if ((itemSize(length) + length) <= (maxLength - currentLength)) - { - writeTypeAndValue(CborBase::TypeString, length); - writeBytes((const uint8_t*) string, length); - } +Cbore& Cbore::item(const char* string, std::size_t length) { + if ((itemSize(length) + length) <= (maxLength - currentLength)) { + writeTypeAndValue(CborBase::TypeString, length); + writeBytes(reinterpret_cast(string), length); + } - return *this; + return *this; } /*************************************************************************/ @@ -157,25 +131,21 @@ Cbore& Cbore::item(const char* string, std::size_t length) /*************************************************************************/ // create indefinite map -Cbore& Cbore::map() -{ - if ((cbor) && (currentLength < maxLength)) - { - cbor[currentLength++] = CborBase::TypeMap << 5 | CborBase::TypeIndefinite; - } +Cbore& Cbore::map() { + if ((cbor != nullptr) && (currentLength < maxLength)) { + cbor[currentLength++] = CborBase::TypeMap << 5 | CborBase::TypeIndefinite; + } - return *this; + return *this; } // create map in array -Cbore& Cbore::map(std::size_t items) -{ - if ((cbor) && (itemSize(items) <= (maxLength - currentLength))) - { - writeTypeAndValue(CborBase::TypeMap, items); - } +Cbore& Cbore::map(std::size_t items) { + if ((cbor != nullptr) && (itemSize(items) <= (maxLength - currentLength))) { + writeTypeAndValue(CborBase::TypeMap, items); + } - return *this; + return *this; } /*************************************************************************/ @@ -183,205 +153,168 @@ Cbore& Cbore::map(std::size_t items) /*************************************************************************/ // insert key as integer -Cbore& Cbore::key(int32_t unit) -{ - if ((itemSize(unit)) <= (maxLength - currentLength)) - { - if (unit < 0) - { - writeTypeAndValue(CborBase::TypeNegative, -1 - unit); - } - else - { - writeTypeAndValue(CborBase::TypeUnsigned, unit); - } +Cbore& Cbore::key(int32_t unit) { + if ((itemSize(unit)) <= (maxLength - currentLength)) { + if (unit < 0) { + writeTypeAndValue(CborBase::TypeNegative, -1 - unit); + } else { + writeTypeAndValue(CborBase::TypeUnsigned, unit); } + } - return *this; + return *this; } // insert key as const char pointer with length -Cbore& Cbore::key(const char* unit, std::size_t length) -{ - if ((itemSize(length) + length) <= (maxLength - currentLength)) - { - writeTypeAndValue(CborBase::TypeString, length); - writeBytes((const uint8_t*) unit, length); - } +Cbore& Cbore::key(const char* unit, std::size_t length) { + if ((itemSize(length) + length) <= (maxLength - currentLength)) { + writeTypeAndValue(CborBase::TypeString, length); + writeBytes(reinterpret_cast(unit), length); + } - return *this; + return *this; } /*************************************************************************/ /* Map insertion - value */ /*************************************************************************/ -Cbore& Cbore::value(int32_t unit) -{ - if ((itemSize(unit)) <= (maxLength - currentLength)) - { - if (unit < 0) - { - writeTypeAndValue(CborBase::TypeNegative, -1 - unit); - } - else - { - writeTypeAndValue(CborBase::TypeUnsigned, unit); - } +Cbore& Cbore::value(int32_t unit) { + if ((itemSize(unit)) <= (maxLength - currentLength)) { + if (unit < 0) { + writeTypeAndValue(CborBase::TypeNegative, -1 - unit); + } else { + writeTypeAndValue(CborBase::TypeUnsigned, unit); } + } - return *this; + return *this; } -Cbore& Cbore::value(CborBase::SimpleType_t unit) -{ - if (currentLength < maxLength) - { - cbor[currentLength++] = CborBase::TypeSpecial << 5 | unit; - } +Cbore& Cbore::value(CborBase::SimpleType_t unit) { + if (currentLength < maxLength) { + cbor[currentLength++] = CborBase::TypeSpecial << 5 | unit; + } - return *this; + return *this; } -Cbore& Cbore::value(const uint8_t* unit, std::size_t length) -{ - if ((itemSize(length) + length) <= (maxLength - currentLength)) - { - writeTypeAndValue(CborBase::TypeBytes, length); - writeBytes(unit, length); - } +Cbore& Cbore::value(const uint8_t* unit, std::size_t length) { + if ((itemSize(length) + length) <= (maxLength - currentLength)) { + writeTypeAndValue(CborBase::TypeBytes, length); + writeBytes(unit, length); + } - return *this; + return *this; } -Cbore& Cbore::value(const char* unit, std::size_t length) -{ - if ((itemSize(length) + length) <= (maxLength - currentLength)) - { - writeTypeAndValue(CborBase::TypeString, length); - writeBytes((const uint8_t*) unit, length); - } +Cbore& Cbore::value(const char* unit, std::size_t length) { + if ((itemSize(length) + length) <= (maxLength - currentLength)) { + writeTypeAndValue(CborBase::TypeString, length); + writeBytes(reinterpret_cast(unit), length); + } - return *this; + return *this; } Cbore& Cbore::reset(bool resetBuffer) { - currentLength = 0; - if(resetBuffer) { - memset(cbor, 0x00, maxLength); - } + currentLength = 0; + if (resetBuffer) { + memset(cbor, 0x00, maxLength); + } - return *this; + return *this; } /*****************************************************************************/ /* Helper Functions */ /*****************************************************************************/ -uint8_t Cbore::itemSize(int32_t item) -{ - item = (item < 0) ? -1 - item : item; - - if (item <= 23) - { - return 1; - } - else if (item <= 0xFF) - { - return 2; - } - else if (item <= 0xFFFF) - { - return 3; - } - else - { - return 5; - } +uint8_t Cbore::itemSize(int32_t item) { + item = (item < 0) ? -1 - item : item; + + if (item <= 23) { + return 1; + } + if (item <= 0xFF) { + return 2; + } + if (item <= 0xFFFF) { + return 3; + } + return 5; } -uint8_t Cbore::writeTypeAndValue(CborBase::MajorType_t majorType, uint32_t value) -{ - if (cbor) - { - if (majorType < CborBase::TypeSpecial) - { - uint8_t majorTypeHigh = majorType << 5; - - uint32_t remainingLength = maxLength - currentLength; - - // value fits in one byte - if (value <= 23) - { - if (remainingLength >= 1) - { - cbor[currentLength++] = majorTypeHigh | value; - - return 1; - } - } - // value fits in two bytes - else if (value <= 0xFF) - { - if (remainingLength >= 2) - { - cbor[currentLength++] = majorTypeHigh | 24; - cbor[currentLength++] = value; - - return 2; - } - } - // value fits in three bytes - else if (value <= 0xFFFF) - { - if (remainingLength >= 3) - { - cbor[currentLength++] = majorTypeHigh | 25; - cbor[currentLength++] = value >> 8; - cbor[currentLength++] = value; - - return 3; - } - } - // value fits in four bytes - else - { - if (remainingLength >= 5) - { - cbor[currentLength++] = majorTypeHigh | 26; - cbor[currentLength++] = value >> 24; - cbor[currentLength++] = value >> 16; - cbor[currentLength++] = value >> 8; - cbor[currentLength++] = value; - - return 5; - } - } +uint8_t Cbore::writeTypeAndValue(CborBase::MajorType_t majorType, + uint32_t value) { + if (cbor != nullptr) { + if (majorType < CborBase::TypeSpecial) { + uint8_t major_type_high = majorType << 5; + + uint32_t remaining_length = maxLength - currentLength; + + // value fits in one byte + if (value <= 23) { + if (remaining_length >= 1) { + cbor[currentLength++] = major_type_high | value; + + return 1; + } + } + // value fits in two bytes + else if (value <= 0xFF) { + if (remaining_length >= 2) { + cbor[currentLength++] = major_type_high | 24; + cbor[currentLength++] = value; + + return 2; + } + } + // value fits in three bytes + else if (value <= 0xFFFF) { + if (remaining_length >= 3) { + cbor[currentLength++] = major_type_high | 25; + cbor[currentLength++] = value >> 8; + cbor[currentLength++] = value; + + return 3; } + } + // value fits in four bytes + else { + if (remaining_length >= 5) { + cbor[currentLength++] = major_type_high | 26; + cbor[currentLength++] = value >> 24; + cbor[currentLength++] = value >> 16; + cbor[currentLength++] = value >> 8; + cbor[currentLength++] = value; + + return 5; + } + } } + } - return 0; + return 0; } -uint32_t Cbore::writeBytes(const uint8_t* source, uint32_t length) -{ - if ((cbor) && (source) && (length <= (maxLength - currentLength))) - { - memcpy(&cbor[currentLength], source, length); - currentLength += length; +uint32_t Cbore::writeBytes(const uint8_t* source, uint32_t length) { + if ((cbor != nullptr) && (source != nullptr) && + (length <= (maxLength - currentLength))) { + memcpy(&cbor[currentLength], source, length); + currentLength += length; - return length; - } + return length; + } - return 0; + return 0; } /*****************************************************************************/ /* Debug related */ /*****************************************************************************/ -void Cbore::print() const -{ - Cborg decoder(cbor, maxLength); - decoder.print(); +void Cbore::print() const { + Cborg decoder(cbor, maxLength); + decoder.print(); } diff --git a/source/Cborg.cpp b/source/Cborg.cpp index 2116439..f6b4a36 100644 --- a/source/Cborg.cpp +++ b/source/Cborg.cpp @@ -16,1151 +16,924 @@ #include "cborg/Cborg.h" -#include #include -#include + #include +#include +#include #if 0 #include -#define DEBUG_PRINTF(...) { printf(__VA_ARGS__); } +#define DEBUG_PRINTF(...) \ + { printf(__VA_ARGS__); } #else #define DEBUG_PRINTF(...) #endif -template -typename std::enable_if::value, T>::type maxOf(T /* var_to_maximize */) { - return std::numeric_limits::max(); +template +typename std::enable_if::value, T>::type maxOf( + T /* var_to_maximize */) { + return std::numeric_limits::max(); } -Cborg::Cborg() - : cbor(NULL), - maxLength(0) -{} +Cborg::Cborg() : cbor(nullptr), maxLength(0) {} Cborg::Cborg(const uint8_t* _cbor, std::size_t _length) - : cbor(_cbor), - maxLength(_length) -{} - - -bool Cborg::getCBOR(const uint8_t** pointer, uint32_t* length) -{ - // decode current header - CborgHeader head; - head.decode(cbor); - - uint8_t type = head.getMajorType(); - uint8_t simple = head.getMinorType(); - - *pointer = cbor; - - if (type == CborBase::TypeUnassigned) - { - return false; - } - else if ((type == CborBase::TypeMap) || (type == CborBase::TypeArray) - || (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - && (simple == CborBase::TypeIndefinite))) - { - // list keeps track of the current level - std::list list; - - // skip first header - std::size_t progress = head.getLength(); - uint32_t units = head.getValue(); - - // maps contain key-value pairs, double the number of units in container - if (type == CborBase::TypeMap) - { - units *= 2; - } - else if (simple == CborBase::TypeIndefinite) - { - units = maxOf(units); - } - - // iterate through cbor encoded buffer - // stop when maximum length is reached or - // the current container is finished - while (progress < maxLength) - { - // decrement unit count unless set to indefinite - if (units != maxOf(units)) - { - units--; - } - - // decode header for cbor object currently pointed to - head.decode(&cbor[progress]); + : cbor(_cbor), maxLength(_length) {} - type = head.getMajorType(); - simple = head.getMinorType(); +bool Cborg::getCBOR(const uint8_t** pointer, uint32_t* length) { + // decode current header + CborgHeader head; + head.decode(cbor); - // if object is a container type (map or array), push remaining units onto the stack (list) - // and set units to the number of elements in the new container. - if (type == CborBase::TypeMap) - { - if (simple == CborBase::TypeIndefinite) - { - list.push_back(units); - units = maxOf(units); - } - else if (head.getValue() > 0) - { - list.push_back(units); - units = 2 * head.getValue(); - } - } - else if (type == CborBase::TypeArray) - { - if (simple == CborBase::TypeIndefinite) - { - list.push_back(units); - units = maxOf(units); - } - else if (head.getValue() > 0) - { - list.push_back(units); - units = head.getValue(); - } - } - else if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - && (simple == CborBase::TypeIndefinite)) - { - list.push_back(units); - units = maxOf(units); - } + uint8_t type = head.getMajorType(); + uint8_t simple = head.getMinorType(); - // increment progress based on cbor object size - if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - && (simple != CborBase::TypeIndefinite)) - { - progress += head.getLength() + head.getValue(); - } - else - { - progress += head.getLength(); - } + *pointer = cbor; - // finished processing all elements in the current container object - // step back up one level by popping remaining elements from the stack (list) - // do it in a while loop since we might have to step back up multiple times - while ((units == 0) || ((type == CborBase::TypeSpecial) && (simple == CborBase::TypeIndefinite))) - { - type = CborBase::TypeSpecial; - simple = CborBase::TypeNull; - - if (list.size() > 0) - { - // pop from stack - units = list.back(); - list.pop_back(); - } - else - { - // stack is empty, means we have reached the end of the current container - *length = progress; + if (type == CborBase::TypeUnassigned) { + return false; + } + if ((type == CborBase::TypeMap) || (type == CborBase::TypeArray) || + (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) && + (simple == CborBase::TypeIndefinite))) { + // list keeps track of the current level + std::list list; - return true; - } - } - } + // skip first header + std::size_t progress = head.getLength(); + uint32_t units = head.getValue(); - return false; - } - else if ((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - { - // return header and length - *length = head.getLength() + head.getValue(); + // maps contain key-value pairs, double the number of units in container + if (type == CborBase::TypeMap) { + units *= 2; + } else if (simple == CborBase::TypeIndefinite) { + units = maxOf(units); } - else - { - // return header - *length = head.getLength(); + + // iterate through cbor encoded buffer + // stop when maximum length is reached or + // the current container is finished + while (progress < maxLength) { + // decrement unit count unless set to indefinite + if (units != maxOf(units)) { + units--; + } + + // decode header for cbor object currently pointed to + head.decode(&cbor[progress]); + + type = head.getMajorType(); + simple = head.getMinorType(); + + // if object is a container type (map or array), push remaining units onto + // the stack (list) and set units to the number of elements in the new + // container. + if (type == CborBase::TypeMap) { + if (simple == CborBase::TypeIndefinite) { + list.push_back(units); + units = maxOf(units); + } else if (head.getValue() > 0) { + list.push_back(units); + units = 2 * head.getValue(); + } + } else if (type == CborBase::TypeArray) { + if (simple == CborBase::TypeIndefinite) { + list.push_back(units); + units = maxOf(units); + } else if (head.getValue() > 0) { + list.push_back(units); + units = head.getValue(); + } + } else if (((type == CborBase::TypeBytes) || + (type == CborBase::TypeString)) && + (simple == CborBase::TypeIndefinite)) { + list.push_back(units); + units = maxOf(units); + } + + // increment progress based on cbor object size + if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) && + (simple != CborBase::TypeIndefinite)) { + progress += head.getLength() + head.getValue(); + } else { + progress += head.getLength(); + } + + // finished processing all elements in the current container object + // step back up one level by popping remaining elements from the stack + // (list) do it in a while loop since we might have to step back up + // multiple times + while ((units == 0) || ((type == CborBase::TypeSpecial) && + (simple == CborBase::TypeIndefinite))) { + type = CborBase::TypeSpecial; + simple = CborBase::TypeNull; + + if (!list.empty()) { + // pop from stack + units = list.back(); + list.pop_back(); + } else { + // stack is empty, means we have reached the end of the current + // container + *length = progress; + + return true; + } + } } - return true; + return false; + } + if ((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) { + // return header and length + *length = head.getLength() + head.getValue(); + } else { + // return header + *length = head.getLength(); + } + + return true; } -uint32_t Cborg::getCBORLength() -{ - // decode current header - CborgHeader head; - head.decode(cbor); +uint32_t Cborg::getCBORLength() { + // decode current header + CborgHeader head; + head.decode(cbor); + + uint8_t type = head.getMajorType(); + uint8_t simple = head.getMinorType(); + + if (type == CborBase::TypeUnassigned) { + return 0; + } + if ((type == CborBase::TypeMap) || (type == CborBase::TypeArray) || + (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) && + (simple == CborBase::TypeIndefinite))) { + // list keeps track of the current level + std::list list; - uint8_t type = head.getMajorType(); - uint8_t simple = head.getMinorType(); + // skip first header + std::size_t progress = head.getLength(); + uint32_t units = head.getValue(); - if (type == CborBase::TypeUnassigned) - { - return 0; + // maps contain key-value pairs, double the number of units in container + if (type == CborBase::TypeMap) { + units *= 2; + } else if (simple == CborBase::TypeIndefinite) { + units = maxOf(units); } - else if ((type == CborBase::TypeMap) || (type == CborBase::TypeArray) - || (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - && (simple == CborBase::TypeIndefinite))) - { - // list keeps track of the current level - std::list list; - - // skip first header - std::size_t progress = head.getLength(); - uint32_t units = head.getValue(); - - // maps contain key-value pairs, double the number of units in container - if (type == CborBase::TypeMap) - { - units *= 2; - } - else if (simple == CborBase::TypeIndefinite) - { - units = maxOf(units); - } - - // iterate through cbor encoded buffer - // stop when maximum length is reached or - // the current container is finished - while (progress < maxLength) - { - // decrement unit count unless set to indefinite - if (units != maxOf(units)) - { - units--; - } - - // decode header for cbor object currently pointed to - head.decode(&cbor[progress]); - - type = head.getMajorType(); - simple = head.getMinorType(); - - // if object is a container type (map or array), push remaining units onto the stack (list) - // and set units to the number of elements in the new container. - if (type == CborBase::TypeMap) - { - if (simple == CborBase::TypeIndefinite) - { - list.push_back(units); - units = maxOf(units); - } - else if (head.getValue() > 0) - { - list.push_back(units); - units = 2 * head.getValue(); - } - } - else if (type == CborBase::TypeArray) - { - if (simple == CborBase::TypeIndefinite) - { - list.push_back(units); - units = maxOf(units); - } - else if (head.getValue() > 0) - { - list.push_back(units); - units = head.getValue(); - } - } - else if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - && (simple == CborBase::TypeIndefinite)) - { - list.push_back(units); - units = maxOf(units); - } - // increment progress based on cbor object size - if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - && (simple != CborBase::TypeIndefinite)) - { - progress += head.getLength() + head.getValue(); - } - else - { - progress += head.getLength(); - } + // iterate through cbor encoded buffer + // stop when maximum length is reached or + // the current container is finished + while (progress < maxLength) { + // decrement unit count unless set to indefinite + if (units != maxOf(units)) { + units--; + } + + // decode header for cbor object currently pointed to + head.decode(&cbor[progress]); + + type = head.getMajorType(); + simple = head.getMinorType(); + + // if object is a container type (map or array), push remaining units onto + // the stack (list) and set units to the number of elements in the new + // container. + if (type == CborBase::TypeMap) { + if (simple == CborBase::TypeIndefinite) { + list.push_back(units); + units = maxOf(units); + } else if (head.getValue() > 0) { + list.push_back(units); + units = 2 * head.getValue(); + } + } else if (type == CborBase::TypeArray) { + if (simple == CborBase::TypeIndefinite) { + list.push_back(units); + units = maxOf(units); + } else if (head.getValue() > 0) { + list.push_back(units); + units = head.getValue(); + } + } else if (((type == CborBase::TypeBytes) || + (type == CborBase::TypeString)) && + (simple == CborBase::TypeIndefinite)) { + list.push_back(units); + units = maxOf(units); + } + + // increment progress based on cbor object size + if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) && + (simple != CborBase::TypeIndefinite)) { + progress += head.getLength() + head.getValue(); + } else { + progress += head.getLength(); + } + + // finished processing all elements in the current container object + // step back up one level by popping remaining elements from the stack + // (list) do it in a while loop since we might have to step back up + // multiple times + while ((units == 0) || ((type == CborBase::TypeSpecial) && + (simple == CborBase::TypeIndefinite))) { + type = CborBase::TypeSpecial; + simple = CborBase::TypeNull; + + if (!list.empty()) { + // pop from stack + units = list.back(); + list.pop_back(); + } else { + // stack is empty, means we have reached the end of the current + // container + return progress; + } + } + } - // finished processing all elements in the current container object - // step back up one level by popping remaining elements from the stack (list) - // do it in a while loop since we might have to step back up multiple times - while ((units == 0) || ((type == CborBase::TypeSpecial) && (simple == CborBase::TypeIndefinite))) - { - type = CborBase::TypeSpecial; - simple = CborBase::TypeNull; - - if (list.size() > 0) - { - // pop from stack - units = list.back(); - list.pop_back(); - } - else - { - // stack is empty, means we have reached the end of the current container - return progress; - } - } - } + return progress; + } + if ((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) { + // return header and length + return head.getLength() + head.getValue(); + } - return progress; - } - else if ((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - { - // return header and length - return head.getLength() + head.getValue(); - } - else - { - // return header - return head.getLength(); - } + // return header + return head.getLength(); } -Cborg Cborg::find(int32_t key) const -{ - CborgHeader head; - head.decode(cbor); +Cborg Cborg::find(int32_t key) const { + CborgHeader head; + head.decode(cbor); - uint8_t type = head.getMajorType(); - uint8_t simple = head.getMinorType(); + uint8_t type = head.getMajorType(); + uint8_t simple = head.getMinorType(); - uint32_t units = 2 * head.getValue(); - units = (simple == CborBase::TypeIndefinite) ? maxOf(units) : units; + uint32_t units = 2 * head.getValue(); + units = (simple == CborBase::TypeIndefinite) ? maxOf(units) : units; - // only continue if type is Cbor Map and the map is not empty - if ((type != CborBase::TypeMap) || (units == 0)) - { - return Cborg(NULL, 0); - } + // only continue if type is Cbor Map and the map is not empty + if ((type != CborBase::TypeMap) || (units == 0)) { + return {nullptr, 0}; + } - // got map, look for key - std::list list; - bool gotKey = false; - - // skip map header - std::size_t progress = head.getLength(); + // got map, look for key + std::list list; + bool got_key = false; - // iterate through cbor encoded buffer - // stop when maximum length is reached or - // the current map is finished - while (progress < maxLength) - { - // decrement unit count unless set to indefinite - if (units != maxOf(units)) - { - units--; - } + // skip map header + std::size_t progress = head.getLength(); - // decode header for cbor object currently pointed to - head.decode(&cbor[progress]); + // iterate through cbor encoded buffer + // stop when maximum length is reached or + // the current map is finished + while (progress < maxLength) { + // decrement unit count unless set to indefinite + if (units != maxOf(units)) { + units--; + } - type = head.getMajorType(); - simple = head.getMinorType(); + // decode header for cbor object currently pointed to + head.decode(&cbor[progress]); + + type = head.getMajorType(); + simple = head.getMinorType(); + + // if object is a container type (map or array), push remaining units onto + // the stack (list) and set units to the number of elements in the new + // container. + if (type == CborBase::TypeMap) { + got_key = false; + + if (simple == CborBase::TypeIndefinite) { + list.push_back(units); + units = maxOf(units); + } else if (head.getValue() > 0) { + list.push_back(units); + units = 2 * head.getValue(); + } + } else if (type == CborBase::TypeArray) { + got_key = false; + + if (simple == CborBase::TypeIndefinite) { + list.push_back(units); + units = maxOf(units); + } else if (head.getValue() > 0) { + list.push_back(units); + units = head.getValue(); + } + } else if (((type == CborBase::TypeBytes) || + (type == CborBase::TypeString)) && + (simple == CborBase::TypeIndefinite)) { + got_key = false; + + list.push_back(units); + units = maxOf(units); + } else { + // object is not a container type + // if object is on the same level as the top level map then process + // content otherwise igonre and move on + if (list.empty()) { + // if previous object was a key, this is a value. Skip it. + if (got_key) { + got_key = false; + } else { + // assume keys are cbor integers. + bool found = false; + + if (type == CborBase::TypeUnsigned) { + if (static_cast(head.getValue()) == key) { + found = true; + } + } else if (type == CborBase::TypeNegative) { + if ((-1 - static_cast(head.getValue())) == key) { + found = true; + } + } + + if (found) { + // update progress to point to next object + progress += head.getLength(); - // if object is a container type (map or array), push remaining units onto the stack (list) - // and set units to the number of elements in the new container. - if (type == CborBase::TypeMap) - { - gotKey = false; + // return new Cborg object based on object pointer and max length + return {&cbor[progress], maxLength - progress}; + } - if (simple == CborBase::TypeIndefinite) - { - list.push_back(units); - units = maxOf(units); - } - else if (head.getValue() > 0) - { - list.push_back(units); - units = 2 * head.getValue(); - } - } - else if (type == CborBase::TypeArray) - { - gotKey = false; - - if (simple == CborBase::TypeIndefinite) - { - list.push_back(units); - units = maxOf(units); - } - else if (head.getValue() > 0) - { - list.push_back(units); - units = head.getValue(); - } - } - else if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - && (simple == CborBase::TypeIndefinite)) - { - gotKey = false; - - list.push_back(units); - units = maxOf(units); - } - else - { - // object is not a container type - // if object is on the same level as the top level map then process content - // otherwise igonre and move on - if (list.size() == 0) - { - // if previous object was a key, this is a value. Skip it. - if (gotKey) - { - gotKey = false; - } - else - { - // assume keys are cbor integers. - bool found = false; - - if (type == CborBase::TypeUnsigned) - { - if ((int32_t) head.getValue() == key) - { - found = true; - } - } - else if (type == CborBase::TypeNegative) - { - if ((-1 - (int32_t) head.getValue()) == key) - { - found = true; - } - } - - if (found) - { - // update progress to point to next object - progress += head.getLength(); - - // return new Cborg object based on object pointer and max length - return Cborg(&cbor[progress], maxLength - progress); - } - - // this object is a key, but the key didn't match - // signal that the next object is a value - gotKey = true; - } - } + // this object is a key, but the key didn't match + // signal that the next object is a value + got_key = true; } + } + } - // increment progress based on cbor object size - if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - && (simple != CborBase::TypeIndefinite)) - { - progress += head.getLength() + head.getValue(); - } - else - { - progress += head.getLength(); - } + // increment progress based on cbor object size + if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) && + (simple != CborBase::TypeIndefinite)) { + progress += head.getLength() + head.getValue(); + } else { + progress += head.getLength(); + } - // finished processing all elements in the current container object - // step back up one level by popping remaining elements from the stack (list) - // do it in a while loop since we might have to step back up multiple times - while ((units == 0) || ((type == CborBase::TypeSpecial) && (simple == CborBase::TypeIndefinite))) - { - type = CborBase::TypeSpecial; - simple = CborBase::TypeNull; - - if (list.size() > 0) - { - // pop from stack - units = list.back(); - list.pop_back(); - } - else - { - // stack is empty, means we have reached the end of the current container - // return a Cbor null object - return Cborg(NULL, 0); - } - } + // finished processing all elements in the current container object + // step back up one level by popping remaining elements from the stack + // (list) do it in a while loop since we might have to step back up multiple + // times + while ((units == 0) || ((type == CborBase::TypeSpecial) && + (simple == CborBase::TypeIndefinite))) { + type = CborBase::TypeSpecial; + simple = CborBase::TypeNull; + + if (!list.empty()) { + // pop from stack + units = list.back(); + list.pop_back(); + } else { + // stack is empty, means we have reached the end of the current + // container return a Cbor null object + return {nullptr, 0}; + } } + } - // key not found, retun null object - return Cborg(NULL, 0); + // key not found, retun null object + return {nullptr, 0}; } -Cborg Cborg::find(const char* key, std::size_t keyLength) const -{ - CborgHeader head; - head.decode(cbor); +Cborg Cborg::find(const char* key, std::size_t keyLength) const { + CborgHeader head; + head.decode(cbor); - uint8_t type = head.getMajorType(); - uint8_t simple = head.getMinorType(); + uint8_t type = head.getMajorType(); + uint8_t simple = head.getMinorType(); - uint32_t units = 2 * head.getValue(); - units = (simple == CborBase::TypeIndefinite) ? maxOf(units) : units; + uint32_t units = 2 * head.getValue(); + units = (simple == CborBase::TypeIndefinite) ? maxOf(units) : units; - // only continue if type is Cbor Map, key is not NULL, and the map is not empty - if ((type != CborBase::TypeMap) || (key == NULL) || (units == 0)) - { - return Cborg(NULL, 0); - } + // only continue if type is Cbor Map, key is not NULL, and the map is not + // empty + if ((type != CborBase::TypeMap) || (key == nullptr) || (units == 0)) { + return {nullptr, 0}; + } - // got map, look for key - std::list list; - bool gotKey = false; + // got map, look for key + std::list list; + bool got_key = false; - // skip map header - std::size_t progress = head.getLength(); - - // iterate through cbor encoded buffer - // stop when maximum length is reached or - // the current map is finished - while (progress < maxLength) - { - // decrement unit count unless set to indefinite - if (units != maxOf(units)) - { - units--; - } + // skip map header + std::size_t progress = head.getLength(); - // decode header for cbor object currently pointed to - head.decode(&cbor[progress]); + // iterate through cbor encoded buffer + // stop when maximum length is reached or + // the current map is finished + while (progress < maxLength) { + // decrement unit count unless set to indefinite + if (units != maxOf(units)) { + units--; + } - type = head.getMajorType(); - simple = head.getMinorType(); + // decode header for cbor object currently pointed to + head.decode(&cbor[progress]); + + type = head.getMajorType(); + simple = head.getMinorType(); + + // if object is a container type (map or array), push remaining units onto + // the stack (list) and set units to the number of elements in the new + // container. + if (type == CborBase::TypeMap) { + got_key = false; + + if (simple == CborBase::TypeIndefinite) { + list.push_back(units); + units = maxOf(units); + } else if (head.getValue() > 0) { + list.push_back(units); + units = 2 * head.getValue(); + } + } else if (type == CborBase::TypeArray) { + got_key = false; + + if (simple == CborBase::TypeIndefinite) { + list.push_back(units); + units = maxOf(units); + } else if (head.getValue() > 0) { + list.push_back(units); + units = head.getValue(); + } + } else if (((type == CborBase::TypeBytes) || + (type == CborBase::TypeString)) && + (simple == CborBase::TypeIndefinite)) { + got_key = false; + + list.push_back(units); + units = maxOf(units); + } else { + // object is not a container type + // if object is on the same level as the top level map then process + // content otherwise igonre and move on + if (list.empty()) { + // if previous object was a key, this is a value. Skip it. + if (got_key) { + got_key = false; + } else { + // if object is a string and the length matches the key length + // do a byte-by-byte comparison + if (type == CborBase::TypeString) { + if (head.getValue() == keyLength) { + bool found = true; + + for (std::size_t idx = 0; idx < keyLength; idx++) { + // break out of loop if string is different from the key + if (key[idx] != cbor[progress + head.getLength() + idx]) { + found = false; + break; + } + } - // if object is a container type (map or array), push remaining units onto the stack (list) - // and set units to the number of elements in the new container. - if (type == CborBase::TypeMap) - { - gotKey = false; + if (found) { + // update progress to point to next object + progress += head.getLength() + head.getValue(); - if (simple == CborBase::TypeIndefinite) - { - list.push_back(units); - units = maxOf(units); + // return new Cborg object based on object pointer and max + // length + return {&cbor[progress], maxLength - progress}; + } } - else if (head.getValue() > 0) - { - list.push_back(units); - units = 2 * head.getValue(); - } - } - else if (type == CborBase::TypeArray) - { - gotKey = false; - - if (simple == CborBase::TypeIndefinite) - { - list.push_back(units); - units = maxOf(units); - } - else if (head.getValue() > 0) - { - list.push_back(units); - units = head.getValue(); - } - } - else if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - && (simple == CborBase::TypeIndefinite)) - { - gotKey = false; + } - list.push_back(units); - units = maxOf(units); - } - else - { - // object is not a container type - // if object is on the same level as the top level map then process content - // otherwise igonre and move on - if (list.size() == 0) - { - // if previous object was a key, this is a value. Skip it. - if (gotKey) - { - gotKey = false; - } - else - { - // if object is a string and the length matches the key length - // do a byte-by-byte comparison - if (type == CborBase::TypeString) - { - if (head.getValue() == keyLength) - { - bool found = true; - - for (std::size_t idx = 0; idx < keyLength; idx++) - { - // break out of loop if string is different from the key - if (key[idx] != cbor[progress + head.getLength() + idx]) - { - found = false; - break; - } - } - - if (found) - { - // update progress to point to next object - progress += head.getLength() + head.getValue(); - - // return new Cborg object based on object pointer and max length - return Cborg(&cbor[progress], maxLength - progress); - } - } - } - - // this object is a key, but the key didn't match - // signal that the next object is a value - gotKey = true; - } - } + // this object is a key, but the key didn't match + // signal that the next object is a value + got_key = true; } + } + } - // increment progress based on cbor object size - if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - && (simple != CborBase::TypeIndefinite)) - { - progress += head.getLength() + head.getValue(); - } - else - { - progress += head.getLength(); - } + // increment progress based on cbor object size + if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) && + (simple != CborBase::TypeIndefinite)) { + progress += head.getLength() + head.getValue(); + } else { + progress += head.getLength(); + } - // finished processing all elements in the current container object - // step back up one level by popping remaining elements from the stack (list) - // do it in a while loop since we might have to step back up multiple times - while ((units == 0) || ((type == CborBase::TypeSpecial) && (simple == CborBase::TypeIndefinite))) - { - type = CborBase::TypeSpecial; - simple = CborBase::TypeNull; - - if (list.size() > 0) - { - // pop from stack - units = list.back(); - list.pop_back(); - } - else - { - // stack is empty, means we have reached the end of the current container - // return a Cbor null object - return Cborg(NULL, 0); - } - } + // finished processing all elements in the current container object + // step back up one level by popping remaining elements from the stack + // (list) do it in a while loop since we might have to step back up multiple + // times + while ((units == 0) || ((type == CborBase::TypeSpecial) && + (simple == CborBase::TypeIndefinite))) { + type = CborBase::TypeSpecial; + simple = CborBase::TypeNull; + + if (!list.empty()) { + // pop from stack + units = list.back(); + list.pop_back(); + } else { + // stack is empty, means we have reached the end of the current + // container return a Cbor null object + return {nullptr, 0}; + } } + } - // key not found, retun null object - return Cborg(NULL, 0); + // key not found, retun null object + return {nullptr, 0}; } -Cborg Cborg::at(std::size_t index) const -{ - CborgHeader head; - head.decode(cbor); - - uint8_t type = head.getMajorType(); - uint8_t simple = head.getMinorType(); - - // set units to elements in array - int32_t units = head.getValue(); - units = (simple == CborBase::TypeIndefinite) ? maxOf(units) : units; - - // only continue if container is Cbor Map, not empty, and index is within bounds - if ((type != CborBase::TypeArray) || (units == 0) || ((int32_t) index >= units)) - { - return Cborg(NULL, 0); +Cborg Cborg::at(std::size_t index) const { + CborgHeader head; + head.decode(cbor); + + uint8_t type = head.getMajorType(); + uint8_t simple = head.getMinorType(); + + // set units to elements in array + int32_t units = head.getValue(); + units = (simple == CborBase::TypeIndefinite) ? maxOf(units) : units; + + // only continue if container is Cbor Map, not empty, and index is within + // bounds + if ((type != CborBase::TypeArray) || (units == 0) || + (static_cast(index) >= units)) { + return {nullptr, 0}; + } + + // got array, look for index + std::list list; + std::size_t currentIndex = 0; + + // skip array header + std::size_t progress = head.getLength(); + + // iterate through cbor encoded buffer + // stop when maximum length is reached or + // the current array is finished + while (progress < maxLength) { + // compare current array index with the one sought for and return if found + if (currentIndex == index) { + return {&cbor[progress], maxLength - progress}; } - // got array, look for index - std::list list; - std::size_t currentIndex = 0; - - // skip array header - std::size_t progress = head.getLength(); - - // iterate through cbor encoded buffer - // stop when maximum length is reached or - // the current array is finished - while (progress < maxLength) - { - // compare current array index with the one sought for and return if found - if (currentIndex == index) - { - return Cborg(&cbor[progress], maxLength - progress); - } - else - { - // decrement unit count unless set to indefinite - if (units != maxOf(units)) - { - units--; - } - - // decode header for cbor object currently pointed to - head.decode(&cbor[progress]); - - type = head.getMajorType(); - simple = head.getMinorType(); + // decrement unit count unless set to indefinite + if (units != maxOf(units)) { + units--; + } - // if object is a container type (map or array), push remaining units onto the stack (list) - // and set units to the number of elements in the new container. - if (type == CborBase::TypeMap) - { - if (simple == CborBase::TypeIndefinite) - { - list.push_back(units); - units = maxOf(units); - } - else if (head.getValue() > 0) - { - list.push_back(units); - units = 2 * head.getValue(); - } - } - else if (type == CborBase::TypeArray) - { - if (simple == CborBase::TypeIndefinite) - { - list.push_back(units); - units = maxOf(units); - } - else if (head.getValue() > 0) - { - list.push_back(units); - units = head.getValue(); - } - } - else if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - && (simple == CborBase::TypeIndefinite)) - { - list.push_back(units); - units = maxOf(units); - } + // decode header for cbor object currently pointed to + head.decode(&cbor[progress]); + + type = head.getMajorType(); + simple = head.getMinorType(); + + // if object is a container type (map or array), push remaining units onto + // the stack (list) and set units to the number of elements in the new + // container. + if (type == CborBase::TypeMap) { + if (simple == CborBase::TypeIndefinite) { + list.push_back(units); + units = maxOf(units); + } else if (head.getValue() > 0) { + list.push_back(units); + units = 2 * head.getValue(); + } + } else if (type == CborBase::TypeArray) { + if (simple == CborBase::TypeIndefinite) { + list.push_back(units); + units = maxOf(units); + } else if (head.getValue() > 0) { + list.push_back(units); + units = head.getValue(); + } + } else if (((type == CborBase::TypeBytes) || + (type == CborBase::TypeString)) && + (simple == CborBase::TypeIndefinite)) { + list.push_back(units); + units = maxOf(units); + } - // increment progress based on cbor object size - if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - && (simple != CborBase::TypeIndefinite)) - { - progress += head.getLength() + head.getValue(); - } - else - { - progress += head.getLength(); - } + // increment progress based on cbor object size + if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) && + (simple != CborBase::TypeIndefinite)) { + progress += head.getLength() + head.getValue(); + } else { + progress += head.getLength(); + } - // finished processing all elements in the current container object - // step back up one level by popping remaining elements from the stack (list) - // do it in a while loop since we might have to step back up multiple times - while ((units == 0) || ((type == CborBase::TypeSpecial) && (simple == CborBase::TypeIndefinite))) - { - type = CborBase::TypeSpecial; - simple = CborBase::TypeNull; - - if (list.size() > 0) - { - // pop from stack - units = list.back(); - list.pop_back(); - } - else - { - // stack is empty, means we have reached the end of the current container - // return a Cbor null object - return Cborg(NULL, 0); - } - } + // finished processing all elements in the current container object + // step back up one level by popping remaining elements from the stack + // (list) do it in a while loop since we might have to step back up multiple + // times + while ((units == 0) || ((type == CborBase::TypeSpecial) && + (simple == CborBase::TypeIndefinite))) { + type = CborBase::TypeSpecial; + simple = CborBase::TypeNull; + + if (!list.empty()) { + // pop from stack + units = list.back(); + list.pop_back(); + } else { + // stack is empty, means we have reached the end of the current + // container return a Cbor null object + return {nullptr, 0}; + } + } - // if element is on the top level, increment index counter - if (list.size() == 0) - { - currentIndex++; - } - } + // if element is on the top level, increment index counter + if (list.empty()) { + currentIndex++; } + } - // index not found, return null object - return Cborg(NULL, 0); + // index not found, return null object + return {nullptr, 0}; } -uint32_t Cborg::getSize() const -{ - CborgHeader head; - head.decode(cbor); +uint32_t Cborg::getSize() const { + CborgHeader head; + head.decode(cbor); - uint8_t type = head.getMajorType(); - uint8_t simple = head.getMinorType(); + uint8_t type = head.getMajorType(); + uint8_t simple = head.getMinorType(); - if ((type == CborBase::TypeMap) - || (type == CborBase::TypeArray) - || (type == CborBase::TypeString) - || (type == CborBase::TypeBytes)) - { - if (simple == CborBase::TypeIndefinite) - { - return std::numeric_limits::max(); - } - else - { - return head.getValue(); - } - } - else - { - return 0; + if ((type == CborBase::TypeMap) || (type == CborBase::TypeArray) || + (type == CborBase::TypeString) || (type == CborBase::TypeBytes)) { + if (simple == CborBase::TypeIndefinite) { + return std::numeric_limits::max(); } + return head.getValue(); + } + return 0; } +bool Cborg::getUnsigned(uint32_t* integer) const { + CborgHeader head; + head.decode(cbor); -bool Cborg::getUnsigned(uint32_t* integer) const -{ - CborgHeader head; - head.decode(cbor); - - if (head.getMajorType() == CborBase::TypeUnsigned) - { - *integer = head.getValue(); + if (head.getMajorType() == CborBase::TypeUnsigned) { + *integer = head.getValue(); - return true; - } - else - { - return false; - } + return true; + } + return false; } -bool Cborg::getNegative(int32_t* integer) const -{ - CborgHeader head; - head.decode(cbor); +bool Cborg::getNegative(int32_t* integer) const { + CborgHeader head; + head.decode(cbor); - if (head.getMajorType() == CborBase::TypeNegative) - { - *integer = -1 - head.getValue(); + if (head.getMajorType() == CborBase::TypeNegative) { + *integer = -1 - head.getValue(); - return true; - } - else - { - return false; - } + return true; + } + return false; } -bool Cborg::getBytes(const uint8_t** pointer, uint32_t* length) const -{ - CborgHeader head; - head.decode(cbor); +bool Cborg::getBytes(const uint8_t** pointer, uint32_t* length) const { + CborgHeader head; + head.decode(cbor); - if (head.getMajorType() == CborBase::TypeBytes) - { - *pointer = &cbor[head.getLength()]; - *length = head.getValue(); + if (head.getMajorType() == CborBase::TypeBytes) { + *pointer = &cbor[head.getLength()]; + *length = head.getValue(); - return true; - } - else - { - return false; - } + return true; + } + return false; } -bool Cborg::getString(const char** pointer, uint32_t* length) const -{ - CborgHeader head; - head.decode(cbor); +bool Cborg::getString(const char** pointer, uint32_t* length) const { + CborgHeader head; + head.decode(cbor); - if (head.getMajorType() == CborBase::TypeString) - { - *pointer = (const char*) &cbor[head.getLength()]; - *length = head.getValue(); + if (head.getMajorType() == CborBase::TypeString) { + *pointer = reinterpret_cast(&cbor[head.getLength()]); + *length = head.getValue(); - return true; - } - else - { - return false; - } + return true; + } + return false; } -bool Cborg::getString(std::string& str) const -{ - CborgHeader head; - head.decode(cbor); +bool Cborg::getString(std::string& str) const { + CborgHeader head; + head.decode(cbor); - if (head.getMajorType() == CborBase::TypeString) - { - str.assign((const char*) &cbor[head.getLength()], head.getValue()); + if (head.getMajorType() == CborBase::TypeString) { + str.assign(reinterpret_cast(&cbor[head.getLength()]), + head.getValue()); - return true; - } - else - { - return false; - } + return true; + } + return false; } /*****************************************************************************/ /* Header related */ /*****************************************************************************/ -uint32_t Cborg::getTag() const -{ - CborgHeader head; - head.decode(cbor); +uint32_t Cborg::getTag() const { + CborgHeader head; + head.decode(cbor); - return head.getTag(); + return head.getTag(); } -uint8_t Cborg::getType() const -{ - CborgHeader head; - head.decode(cbor); +uint8_t Cborg::getType() const { + CborgHeader head; + head.decode(cbor); - return head.getMajorType(); + return head.getMajorType(); } -uint8_t Cborg::getMinorType() const -{ - CborgHeader head; - head.decode(cbor); +uint8_t Cborg::getMinorType() const { + CborgHeader head; + head.decode(cbor); - return head.getMinorType(); + return head.getMinorType(); } - /*****************************************************************************/ /* Debug related */ /*****************************************************************************/ -void Cborg::print() const -{ - CborgHeader head; - std::size_t progress = 0; - - std::list list; - uint32_t units = 1; - - while (progress < maxLength) - { - // decrement unit count unless set to indefinite - if (units != maxOf(units)) - { - units--; - } - - head.decode(&cbor[progress]); - - /* semantic tag */ - uint32_t tag = head.getTag(); - uint8_t type = head.getMajorType(); - uint8_t simple = head.getMinorType(); - - if ((type != CborBase::TypeSpecial) || (simple != CborBase::TypeIndefinite)) - { - for (std::size_t indent = 0; indent < list.size(); indent++) - { - printf("\t"); - } - } +void Cborg::print() const { + CborgHeader head; + std::size_t progress = 0; - if (tag != CborBase::TypeUnassigned) - { - printf("[%" PRIu32 "] ", tag); - } + std::list list; + uint32_t units = 1; - /* container object */ - if (type == CborBase::TypeMap) - { - if (simple == CborBase::TypeIndefinite) - { - printf("Map:\r\n"); + while (progress < maxLength) { + // decrement unit count unless set to indefinite + if (units != maxOf(units)) { + units--; + } - list.push_back(units); - units = maxOf(units); - } - else if (head.getValue() > 0) - { - printf("Map: %" PRIu32 "\r\n", head.getValue()); + head.decode(&cbor[progress]); - list.push_back(units); - units = 2 * head.getValue(); - } - } - else if (type == CborBase::TypeArray) - { - if (simple == CborBase::TypeIndefinite) - { - printf("Array:\r\n"); - - list.push_back(units); - units = maxOf(units); - } - else if (head.getValue() > 0) - { - printf("Array: %" PRIu32 "\r\n", head.getValue()); + /* semantic tag */ + uint32_t tag = head.getTag(); + uint8_t type = head.getMajorType(); + uint8_t simple = head.getMinorType(); - list.push_back(units); - units = head.getValue(); - } - } - else if ((type == CborBase::TypeBytes) && (simple == CborBase::TypeIndefinite)) - { - printf("Bytes:\r\n"); + if ((type != CborBase::TypeSpecial) || + (simple != CborBase::TypeIndefinite)) { + for (std::size_t indent = 0; indent < list.size(); indent++) { + printf("\t"); + } + } - list.push_back(units); - units = maxOf(units); - } - else if ((type == CborBase::TypeString) && (simple == CborBase::TypeIndefinite)) - { - printf("String:\r\n"); + if (tag != CborBase::TypeUnassigned) { + printf("[%" PRIu32 "] ", tag); + } - list.push_back(units); - units = maxOf(units); - } - else - { - switch(type) - { - case CborBase::TypeUnsigned: - { - Cborg object(&cbor[progress], maxLength - progress); - uint32_t integer = 0; - bool result = object.getUnsigned(&integer); - - if (result) - { - printf("%" PRIu32 "\r\n", integer); - } - else - { - printf("\r\n"); - } - } - break; - - case CborBase::TypeNegative: - { - Cborg object(&cbor[progress], maxLength - progress); - int32_t integer = 0; - bool result = object.getNegative(&integer); - - if (result) - { - printf("%" PRId32 "\r\n", integer); - } - else - { - printf("\r\n"); - } - } - break; - - case CborBase::TypeBytes: - { - Cborg object(&cbor[progress], maxLength - progress); - const uint8_t* pointer; - uint32_t length; - - bool result = object.getBytes(&pointer, &length); - - if (result) - { - for (std::size_t idx = 0; idx < length; idx++) - { - printf("%02X", pointer[idx]); - } - } - printf("\r\n"); - } - break; - - case CborBase::TypeString: - { - Cborg object(&cbor[progress], maxLength - progress); - const char* pointer; - uint32_t length; - - bool result = object.getString(&pointer, &length); - - if (result) - { - for (std::size_t idx = 0; idx < length; idx++) - { - printf("%c", pointer[idx]); - } - } - printf("\r\n"); - } - break; - - case CborBase::TypeSpecial: - { - if (simple == CborBase::TypeTrue) - { - printf("true\r\n"); - } - else if (simple == CborBase::TypeFalse) - { - printf("false\r\n"); - } - else if (simple == CborBase::TypeNull) - { - printf("null\r\n"); - } - else if (simple == CborBase::TypeUndefined) - { - printf("undefined\r\n"); - } - else if (simple == CborBase::TypeHalfFloat) - { - printf("half float\r\n"); - } - else if (simple == CborBase::TypeSingleFloat) - { - printf("single float\r\n"); - } - else if (simple == CborBase::TypeDoubleFloat) - { - printf("double float\r\n"); - } - } - break; - - default: - printf("error\r\n"); - return; - break; - } - } + /* container object */ + if (type == CborBase::TypeMap) { + if (simple == CborBase::TypeIndefinite) { + printf("Map:\r\n"); + + list.push_back(units); + units = maxOf(units); + } else if (head.getValue() > 0) { + printf("Map: %" PRIu32 "\r\n", head.getValue()); + + list.push_back(units); + units = 2 * head.getValue(); + } + } else if (type == CborBase::TypeArray) { + if (simple == CborBase::TypeIndefinite) { + printf("Array:\r\n"); + + list.push_back(units); + units = maxOf(units); + } else if (head.getValue() > 0) { + printf("Array: %" PRIu32 "\r\n", head.getValue()); + + list.push_back(units); + units = head.getValue(); + } + } else if ((type == CborBase::TypeBytes) && + (simple == CborBase::TypeIndefinite)) { + printf("Bytes:\r\n"); + + list.push_back(units); + units = maxOf(units); + } else if ((type == CborBase::TypeString) && + (simple == CborBase::TypeIndefinite)) { + printf("String:\r\n"); + + list.push_back(units); + units = maxOf(units); + } else { + switch (type) { + case CborBase::TypeUnsigned: { + Cborg object(&cbor[progress], maxLength - progress); + uint32_t integer = 0; + bool result = object.getUnsigned(&integer); + + if (result) { + printf("%" PRIu32 "\r\n", integer); + } else { + printf("\r\n"); + } + } break; + + case CborBase::TypeNegative: { + Cborg object(&cbor[progress], maxLength - progress); + int32_t integer = 0; + bool result = object.getNegative(&integer); + + if (result) { + printf("%" PRId32 "\r\n", integer); + } else { + printf("\r\n"); + } + } break; + + case CborBase::TypeBytes: { + Cborg object(&cbor[progress], maxLength - progress); + const uint8_t* pointer; + uint32_t length; + + bool result = object.getBytes(&pointer, &length); + + if (result) { + for (std::size_t idx = 0; idx < length; idx++) { + printf("%02X", pointer[idx]); + } + } + printf("\r\n"); + } break; + + case CborBase::TypeString: { + Cborg object(&cbor[progress], maxLength - progress); + const char* pointer; + uint32_t length; + + bool result = object.getString(&pointer, &length); + + if (result) { + for (std::size_t idx = 0; idx < length; idx++) { + printf("%c", pointer[idx]); + } + } + printf("\r\n"); + } break; + + case CborBase::TypeSpecial: { + if (simple == CborBase::TypeTrue) { + printf("true\r\n"); + } else if (simple == CborBase::TypeFalse) { + printf("false\r\n"); + } else if (simple == CborBase::TypeNull) { + printf("null\r\n"); + } else if (simple == CborBase::TypeUndefined) { + printf("undefined\r\n"); + } else if (simple == CborBase::TypeHalfFloat) { + printf("half float\r\n"); + } else if (simple == CborBase::TypeSingleFloat) { + printf("single float\r\n"); + } else if (simple == CborBase::TypeDoubleFloat) { + printf("double float\r\n"); + } + } break; + + default: + printf("error\r\n"); + return; + break; + } + } - // increment progress based on cbor object size - if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) - && (simple != CborBase::TypeIndefinite)) - { - progress += head.getLength() + head.getValue(); - } - else - { - progress += head.getLength(); - } + // increment progress based on cbor object size + if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) && + (simple != CborBase::TypeIndefinite)) { + progress += head.getLength() + head.getValue(); + } else { + progress += head.getLength(); + } - // finished processing all elements in the current container object - // step back up one level by popping remaining elements from the stack (list) - // do it in a while loop since we might have to step back up multiple times - while ((units == 0) || ((type == CborBase::TypeSpecial) && (simple == CborBase::TypeIndefinite))) - { - type = CborBase::TypeSpecial; - simple = CborBase::TypeNull; - - if (list.size() > 0) - { - units = list.back(); - list.pop_back(); - } - else - { - return; - } - } + // finished processing all elements in the current container object + // step back up one level by popping remaining elements from the stack + // (list) do it in a while loop since we might have to step back up multiple + // times + while ((units == 0) || ((type == CborBase::TypeSpecial) && + (simple == CborBase::TypeIndefinite))) { + type = CborBase::TypeSpecial; + simple = CborBase::TypeNull; + + if (!list.empty()) { + units = list.back(); + list.pop_back(); + } else { + return; + } } + } } - - From 87c51c11e4ec163bb34a17de0fedd7da2e930fca Mon Sep 17 00:00:00 2001 From: Thomas Saedt Date: Tue, 23 Nov 2021 09:44:58 +0100 Subject: [PATCH 3/8] feat: add support for bool, uint32 and timestamp --- include/cborg/CborBase.h | 229 ++++++++++++++++++--------------------- include/cborg/Cbore.h | 208 ++++++++++++++++++----------------- include/cborg/Cborg.h | 2 + source/Cbore.cpp | 51 +++++++-- source/Cborg.cpp | 12 ++ 5 files changed, 269 insertions(+), 233 deletions(-) diff --git a/include/cborg/CborBase.h b/include/cborg/CborBase.h index e9de110..097fa9a 100644 --- a/include/cborg/CborBase.h +++ b/include/cborg/CborBase.h @@ -14,139 +14,120 @@ * limitations under the License. */ - #ifndef __CBOR_BASE_H__ #define __CBOR_BASE_H__ #include +#include + #include #include -#include - class CborBase; extern CborBase CborNull; -class CborBase -{ -public: - typedef enum { - TypeUnsigned = 0x00, - TypeNegative = 0x01, - TypeBytes = 0x02, - TypeString = 0x03, - TypeArray = 0x04, - TypeMap = 0x05, - TypeTag = 0x06, - TypeSpecial = 0x07, - TypeRaw = 0xFE, - TypeUnassigned = 0xFF - } MajorType_t; - - typedef enum { - TypeFalse = 0x14, - TypeTrue = 0x15, - TypeNull = 0x16, - TypeUndefined = 0x17, - TypeUnknown = 0x18, - TypeHalfFloat = 0x19, - TypeSingleFloat = 0x1A, - TypeDoubleFloat = 0x1B, - TypeIndefinite = 0x1F - } SimpleType_t; - - CborBase(MajorType_t _majorType = TypeSpecial, SimpleType_t _minorType = TypeNull) - : majorType(_majorType), - minorType(_minorType), - tag(TypeUnassigned) - {} - - virtual ~CborBase() {}; - - /*************************************************************************/ - /* Encode */ - /*************************************************************************/ - - virtual uint32_t writeCBOR(uint8_t* destination, uint32_t maxLength); - - /*************************************************************************/ - /* Mutators */ - /*************************************************************************/ - - uint8_t getType() const - { - return majorType; - } - - void setTag(uint32_t _tag) - { - tag = _tag; - } - - uint32_t getTag() const - { - return tag; - } - - /*************************************************************************/ - /* Container */ - /*************************************************************************/ - - virtual uint32_t getLength() const - { - return 0; - } - - virtual uint32_t getSize() const - { - return 0; - } - - /*************************************************************************/ - /* Array */ - /*************************************************************************/ - - virtual CborBase* at(std::size_t index) - { - (void) index; - - return &CborNull; - } - - /*************************************************************************/ - /* Map */ - /*************************************************************************/ - - virtual CborBase* key(std::size_t index) - { - (void) index; - - return &CborNull; - } - - virtual CborBase* value(std::size_t index) - { - (void) index; - - return &CborNull; - } - - /*************************************************************************/ - /* Debug */ - /*************************************************************************/ - - virtual void print(); - -protected: - static uint32_t writeQueue(uint8_t* destination, uint32_t maxLength, std::list& queue); - static uint8_t writeTypeAndValue(uint8_t* destination, uint32_t maxLength, uint8_t majorType, uint32_t value); - static uint32_t writeBytes(uint8_t* destination, uint32_t maxLength, const uint8_t* source, uint32_t length); - static void printQueue(std::list queue); - -protected: - uint8_t majorType; - uint8_t minorType; - uint32_t tag; +class CborBase { + public: + using MajorType_t = enum { + TypeUnsigned = 0x00, + TypeNegative = 0x01, + TypeBytes = 0x02, + TypeString = 0x03, + TypeArray = 0x04, + TypeMap = 0x05, + TypeTag = 0x06, + TypeSpecial = 0x07, + TypeRaw = 0xFE, + TypeUnassigned = 0xFF + }; + + using SimpleType_t = enum { + TypeFalse = 0x14, + TypeTrue = 0x15, + TypeNull = 0x16, + TypeUndefined = 0x17, + TypeUnknown = 0x18, + TypeHalfFloat = 0x19, + TypeSingleFloat = 0x1A, + TypeDoubleFloat = 0x1B, + TypeIndefinite = 0x1F + }; + + CborBase(MajorType_t _majorType = TypeSpecial, + SimpleType_t _minorType = TypeNull) + : majorType(_majorType), minorType(_minorType), tag(TypeUnassigned) {} + + virtual ~CborBase(){}; + + /*************************************************************************/ + /* Encode */ + /*************************************************************************/ + + virtual uint32_t writeCBOR(uint8_t* destination, uint32_t maxLength); + + /*************************************************************************/ + /* Mutators */ + /*************************************************************************/ + + uint8_t getType() const { return majorType; } + + void setTag(uint32_t _tag) { tag = _tag; } + + uint32_t getTag() const { return tag; } + + /*************************************************************************/ + /* Container */ + /*************************************************************************/ + + virtual uint32_t getLength() const { return 0; } + + virtual uint32_t getSize() const { return 0; } + + /*************************************************************************/ + /* Array */ + /*************************************************************************/ + + virtual CborBase* at(std::size_t index) { + (void)index; + + return &CborNull; + } + + /*************************************************************************/ + /* Map */ + /*************************************************************************/ + + virtual CborBase* key(std::size_t index) { + (void)index; + + return &CborNull; + } + + virtual CborBase* value(std::size_t index) { + (void)index; + + return &CborNull; + } + + /*************************************************************************/ + /* Debug */ + /*************************************************************************/ + + virtual void print(); + + protected: + static uint32_t writeQueue(uint8_t* destination, uint32_t maxLength, + std::list& queue); + static uint8_t writeTypeAndValue(uint8_t* destination, uint32_t maxLength, + uint8_t majorType, uint32_t value); + static uint32_t writeBytes(uint8_t* destination, uint32_t maxLength, + const uint8_t* source, uint32_t length); + static void printQueue(std::list queue); + + protected: + uint8_t majorType; + uint8_t minorType; + uint32_t tag; }; -#endif // __CBOR_BASE_H__ +#endif // __CBOR_BASE_H__ diff --git a/include/cborg/Cbore.h b/include/cborg/Cbore.h index e83cc61..6fd0990 100644 --- a/include/cborg/Cbore.h +++ b/include/cborg/Cbore.h @@ -18,149 +18,153 @@ #define __CBORE_H__ #include + +#include #include -#include "cborg/CborgHeader.h" #include "cborg/CborBase.h" +#include "cborg/CborgHeader.h" +class Cbore { + public: + Cbore(); -class Cbore -{ -public: - Cbore(); + Cbore(uint8_t* cbor, std::size_t maxLength); - Cbore(uint8_t* cbor, std::size_t maxLength); + std::size_t getLength() const; - std::size_t getLength() const; + /* Encode methods */ + Cbore& tag(uint32_t tag); - /* Encode methods */ - Cbore& tag(uint32_t tag); + // end indefinite map/array + Cbore& end(); - // end indefinite map/array - Cbore& end(); + /*************************************************************************/ + /* Array creation */ + /*************************************************************************/ - /*************************************************************************/ - /* Array creation */ - /*************************************************************************/ + // create indefinite map + Cbore& array(); - // create indefinite map - Cbore& array(); + // create array with size + Cbore& array(std::size_t items); - // create array with size - Cbore& array(std::size_t items); + /*************************************************************************/ + /* Array insertion */ + /*************************************************************************/ - /*************************************************************************/ - /* Array insertion */ - /*************************************************************************/ + // write + Cbore& item(int32_t value); + Cbore& item(uint32_t value); - // write - Cbore& item(int32_t value); + // write + Cbore& item(bool value); - // write - Cbore& item(CborBase::SimpleType_t simpleType); + // write + Cbore& item(std::chrono::system_clock::time_point unixTimeStamp); - // write - template - Cbore& item(const char (&string)[I]) - { - if ((itemSize(I) + I) <= (maxLength - currentLength)) - { - writeTypeAndValue(CborBase::TypeString, I - 1); - writeBytes((const uint8_t*) string, I - 1); - } + // write + Cbore& item(CborBase::SimpleType_t simpleType); - return *this; + // write + template + Cbore& item(const char (&string)[I]) { + if ((itemSize(static_cast(I)) + I) <= + (maxLength - currentLength)) { + writeTypeAndValue(CborBase::TypeString, I - 1); + writeBytes(static_cast(string), I - 1); } - // write bytes, length - Cbore& item(const uint8_t* bytes, std::size_t length); + return *this; + } - // write string, length - Cbore& item(const char* string, std::size_t length); + // write bytes, length + Cbore& item(const uint8_t* bytes, std::size_t length); - /*************************************************************************/ - /* Map creation */ - /*************************************************************************/ + // write string, length + Cbore& item(const char* string, std::size_t length); - // create indefinite map - Cbore& map(); + /*************************************************************************/ + /* Map creation */ + /*************************************************************************/ - // create map with size - Cbore& map(std::size_t items); + // create indefinite map + Cbore& map(); - /*************************************************************************/ - /* Map insertion - key */ - /*************************************************************************/ + // create map with size + Cbore& map(std::size_t items); - // insert key as integer - Cbore& key(int32_t unit); + /*************************************************************************/ + /* Map insertion - key */ + /*************************************************************************/ - // insert key as const char array - template - Cbore& key(const char (&unit)[I]) - { - if ((itemSize(I) + I) <= (maxLength - currentLength)) - { - writeTypeAndValue(CborBase::TypeString, I - 1); - writeBytes((const uint8_t*) unit, I - 1); - } + // insert key as integer + Cbore& key(int32_t unit); - return *this; + // insert key as const char array + template + Cbore& key(const char (&unit)[I]) { + if ((itemSize(static_cast(I)) + I) <= + (maxLength - currentLength)) { + writeTypeAndValue(CborBase::TypeString, I - 1); + writeBytes(static_cast(unit), I - 1); } - // insert key as const char pointer with length - Cbore& key(const char* unit, std::size_t length); + return *this; + } - /*************************************************************************/ - /* Map insertion - value */ - /*************************************************************************/ + // insert key as const char pointer with length + Cbore& key(const char* unit, std::size_t length); - // insert value as integer - Cbore& value(int32_t unit); + /*************************************************************************/ + /* Map insertion - value */ + /*************************************************************************/ - // insert value as simple type - Cbore& value(CborBase::SimpleType_t value); + // insert value as integer + Cbore& value(int32_t unit); - // insert value as const char array - template - Cbore& value(const char (&unit)[I]) - { - if ((itemSize(I) + I) <= (maxLength - currentLength)) - { - writeTypeAndValue(CborBase::TypeString, I - 1); - writeBytes((const uint8_t*) unit, I - 1); - } + // insert value as simple type + Cbore& value(CborBase::SimpleType_t value); - return *this; + // insert value as const char array + template + Cbore& value(const char (&unit)[I]) { + if ((itemSize(static_cast(I)) + I) <= + (maxLength - currentLength)) { + writeTypeAndValue(CborBase::TypeString, I - 1); + writeBytes(static_cast(unit), I - 1); } - // insert value as byte array with length - Cbore& value(const uint8_t* unit, std::size_t length); + return *this; + } + + // insert value as byte array with length + Cbore& value(const uint8_t* unit, std::size_t length); - // insert value as const char pointer with length - Cbore& value(const char* unit, std::size_t length); + // insert value as const char pointer with length + Cbore& value(const char* unit, std::size_t length); - /*************************************************************************/ - /* Reset */ - /*************************************************************************/ - Cbore& reset(bool resetBuffer); + /*************************************************************************/ + /* Reset */ + /*************************************************************************/ + Cbore& reset(bool resetBuffer); - /*************************************************************************/ - /* Debug */ - /*************************************************************************/ + /*************************************************************************/ + /* Debug */ + /*************************************************************************/ - /* debug */ - void print() const; + /* debug */ + void print() const; -private: - uint8_t itemSize(int32_t item); - uint8_t writeTypeAndValue(CborBase::MajorType_t majorType, uint32_t value); - uint32_t writeBytes(const uint8_t* source, uint32_t length); + private: + uint8_t itemSize(int32_t item); + uint8_t itemSize(uint32_t item); + uint8_t writeTypeAndValue(CborBase::MajorType_t majorType, uint32_t value); + uint32_t writeBytes(const uint8_t* source, uint32_t length); -private: - uint8_t* cbor; - std::size_t currentLength; - std::size_t maxLength; + uint8_t* cbor; + std::size_t currentLength; + std::size_t maxLength; }; -#endif // __CBORE_H__ +#endif // __CBORE_H__ diff --git a/include/cborg/Cborg.h b/include/cborg/Cborg.h index 1ebb2a8..69d88da 100644 --- a/include/cborg/Cborg.h +++ b/include/cborg/Cborg.h @@ -52,6 +52,8 @@ class Cborg bool getUnsigned(uint32_t*) const; bool getNegative(int32_t*) const; + bool getTimeStamp(time_t*) const; + bool getBytes(const uint8_t** pointer, uint32_t* length) const; bool getString(const char** pointer, uint32_t* length) const; bool getString(std::string& str) const; diff --git a/source/Cbore.cpp b/source/Cbore.cpp index 8ab4d2f..e88d427 100644 --- a/source/Cbore.cpp +++ b/source/Cbore.cpp @@ -74,7 +74,8 @@ Cbore& Cbore::array() { // create arrray in array Cbore& Cbore::array(std::size_t items) { - if ((cbor != nullptr) && (itemSize(items) <= (maxLength - currentLength))) { + if ((cbor != nullptr) && (itemSize(static_cast(items)) <= + (maxLength - currentLength))) { writeTypeAndValue(CborBase::TypeArray, items); } @@ -98,6 +99,32 @@ Cbore& Cbore::item(int32_t value) { return *this; } +Cbore& Cbore::item(uint32_t value) { + if (itemSize(value) <= (maxLength - currentLength)) { + writeTypeAndValue(CborBase::TypeUnsigned, value); + } + + return *this; +} + +Cbore& Cbore::item(bool value) { + if (value) { + return this->value(CborBase::TypeTrue); + } + return this->value(CborBase::TypeFalse); +} + +Cbore& Cbore::item(std::chrono::system_clock::time_point unixTimeStamp) { + time_t time_stamp = std::chrono::system_clock::to_time_t(unixTimeStamp); + if (itemSize(static_cast(time_stamp)) <= + (maxLength - currentLength)) { + writeTypeAndValue(CborBase::TypeTag, 1); + writeTypeAndValue(CborBase::TypeUnsigned, time_stamp); + } + + return *this; +} + // insert simple type Cbore& Cbore::item(CborBase::SimpleType_t simpleType) { if (currentLength < maxLength) { @@ -108,7 +135,8 @@ Cbore& Cbore::item(CborBase::SimpleType_t simpleType) { } Cbore& Cbore::item(const uint8_t* bytes, std::size_t length) { - if ((itemSize(length) + length) <= (maxLength - currentLength)) { + if ((itemSize(static_cast(length)) + length) <= + (maxLength - currentLength)) { writeTypeAndValue(CborBase::TypeBytes, length); writeBytes(bytes, length); } @@ -118,7 +146,8 @@ Cbore& Cbore::item(const uint8_t* bytes, std::size_t length) { // write string, length Cbore& Cbore::item(const char* string, std::size_t length) { - if ((itemSize(length) + length) <= (maxLength - currentLength)) { + if ((itemSize(static_cast(length)) + length) <= + (maxLength - currentLength)) { writeTypeAndValue(CborBase::TypeString, length); writeBytes(reinterpret_cast(string), length); } @@ -141,7 +170,8 @@ Cbore& Cbore::map() { // create map in array Cbore& Cbore::map(std::size_t items) { - if ((cbor != nullptr) && (itemSize(items) <= (maxLength - currentLength))) { + if ((cbor != nullptr) && (itemSize(static_cast(items)) <= + (maxLength - currentLength))) { writeTypeAndValue(CborBase::TypeMap, items); } @@ -167,7 +197,8 @@ Cbore& Cbore::key(int32_t unit) { // insert key as const char pointer with length Cbore& Cbore::key(const char* unit, std::size_t length) { - if ((itemSize(length) + length) <= (maxLength - currentLength)) { + if ((itemSize(static_cast(length)) + length) <= + (maxLength - currentLength)) { writeTypeAndValue(CborBase::TypeString, length); writeBytes(reinterpret_cast(unit), length); } @@ -200,7 +231,8 @@ Cbore& Cbore::value(CborBase::SimpleType_t unit) { } Cbore& Cbore::value(const uint8_t* unit, std::size_t length) { - if ((itemSize(length) + length) <= (maxLength - currentLength)) { + if ((itemSize(static_cast(length)) + length) <= + (maxLength - currentLength)) { writeTypeAndValue(CborBase::TypeBytes, length); writeBytes(unit, length); } @@ -209,7 +241,8 @@ Cbore& Cbore::value(const uint8_t* unit, std::size_t length) { } Cbore& Cbore::value(const char* unit, std::size_t length) { - if ((itemSize(length) + length) <= (maxLength - currentLength)) { + if ((itemSize(static_cast(length)) + length) <= + (maxLength - currentLength)) { writeTypeAndValue(CborBase::TypeString, length); writeBytes(reinterpret_cast(unit), length); } @@ -233,6 +266,10 @@ Cbore& Cbore::reset(bool resetBuffer) { uint8_t Cbore::itemSize(int32_t item) { item = (item < 0) ? -1 - item : item; + return (itemSize(static_cast(item))); +} + +uint8_t Cbore::itemSize(uint32_t item) { if (item <= 23) { return 1; } diff --git a/source/Cborg.cpp b/source/Cborg.cpp index f6b4a36..0ee9e12 100644 --- a/source/Cborg.cpp +++ b/source/Cborg.cpp @@ -682,6 +682,18 @@ bool Cborg::getUnsigned(uint32_t* integer) const { return false; } +bool Cborg::getTimeStamp(time_t* timeStamp) const { + CborgHeader head; + head.decode(cbor); + + if (head.getMajorType() == CborBase::TypeUnsigned && head.getTag() == 1) { + *timeStamp = head.getValue(); + + return true; + } + return false; +} + bool Cborg::getNegative(int32_t* integer) const { CborgHeader head; head.decode(cbor); From 408212916cbad9a5cb328efca8eb50e0fc432456 Mon Sep 17 00:00:00 2001 From: Thomas Saedt Date: Tue, 23 Nov 2021 12:19:41 +0100 Subject: [PATCH 4/8] feat: make maps iterable --- CMakeLists.txt | 9 +++++ include/cborg/Cbore.h | 27 ++++++++++--- include/cborg/Cborg.h | 90 ++++++++++++++++++++++++----------------- source/Cbore.cpp | 55 ++++++++++++++++++++++++- source/Cborg.cpp | 93 ++++++++++++++++++++++++++++++++++++++----- 5 files changed, 221 insertions(+), 53 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e341a3..275bf49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,12 @@ +file(GLOB_RECURSE cbor_sources "*.cpp") + +set_property( + SOURCE ${cbor_sources} + APPEND + PROPERTY COMPILE_FLAGS + "-std=c++17") + + add_library(cborg-lib STATIC source/CborBase.cpp source/Cbore.cpp diff --git a/include/cborg/Cbore.h b/include/cborg/Cbore.h index 6fd0990..beb12a0 100644 --- a/include/cborg/Cbore.h +++ b/include/cborg/Cbore.h @@ -21,6 +21,7 @@ #include #include +#include #include "cborg/CborBase.h" #include "cborg/CborgHeader.h" @@ -72,7 +73,7 @@ class Cbore { if ((itemSize(static_cast(I)) + I) <= (maxLength - currentLength)) { writeTypeAndValue(CborBase::TypeString, I - 1); - writeBytes(static_cast(string), I - 1); + writeBytes(reinterpret_cast(string), I - 1); } return *this; @@ -100,6 +101,7 @@ class Cbore { // insert key as integer Cbore& key(int32_t unit); + Cbore& key(uint32_t unit); // insert key as const char array template @@ -107,7 +109,7 @@ class Cbore { if ((itemSize(static_cast(I)) + I) <= (maxLength - currentLength)) { writeTypeAndValue(CborBase::TypeString, I - 1); - writeBytes(static_cast(unit), I - 1); + writeBytes(reinterpret_cast(unit), I - 1); } return *this; @@ -116,23 +118,30 @@ class Cbore { // insert key as const char pointer with length Cbore& key(const char* unit, std::size_t length); + // insert key as string view + Cbore& key(std::string_view str); + /*************************************************************************/ /* Map insertion - value */ /*************************************************************************/ // insert value as integer Cbore& value(int32_t unit); + Cbore& value(uint32_t unit); // insert value as simple type Cbore& value(CborBase::SimpleType_t value); + // insert value as simple bool + Cbore& value(bool value); + // insert value as const char array template Cbore& value(const char (&unit)[I]) { if ((itemSize(static_cast(I)) + I) <= (maxLength - currentLength)) { writeTypeAndValue(CborBase::TypeString, I - 1); - writeBytes(static_cast(unit), I - 1); + writeBytes(reinterpret_cast(unit), I - 1); } return *this; @@ -144,6 +153,16 @@ class Cbore { // insert value as const char pointer with length Cbore& value(const char* unit, std::size_t length); + // insert value as string view + Cbore& value(std::string_view unit); + + // get the size of an item (used to calculate buffer size) + static uint8_t itemSize(int32_t item); + static uint8_t itemSize(uint32_t item); + static uint8_t itemSize(std::size_t item); + static uint8_t itemSizeBool(); + static size_t itemSize(std::string_view str); + /*************************************************************************/ /* Reset */ /*************************************************************************/ @@ -157,8 +176,6 @@ class Cbore { void print() const; private: - uint8_t itemSize(int32_t item); - uint8_t itemSize(uint32_t item); uint8_t writeTypeAndValue(CborBase::MajorType_t majorType, uint32_t value); uint32_t writeBytes(const uint8_t* source, uint32_t length); diff --git a/include/cborg/Cborg.h b/include/cborg/Cborg.h index 69d88da..15ebf65 100644 --- a/include/cborg/Cborg.h +++ b/include/cborg/Cborg.h @@ -18,57 +18,75 @@ #define __CBORG_H__ #include + #include #include -#include "cborg/CborgHeader.h" #include "cborg/CborBase.h" +#include "cborg/CborgHeader.h" + +class Cborg { + public: + Cborg(); + Cborg(const uint8_t* cbor, std::size_t maxLength); + + bool isNull(); + + /* Decode methods */ + bool getCBOR(const uint8_t** pointer, uint32_t* length); + uint32_t getCBORLength(); + + /* map functions */ + template + Cborg find(const char (&key)[I]) { + return find(key, I - 1); + } + + Cborg find(int32_t key) const; + Cborg find(const char* key, std::size_t keyLength) const; -class Cborg -{ -public: - Cborg(); - Cborg(const uint8_t* cbor, std::size_t maxLength); + Cborg getKey(); + bool getKey(std::string& str); + bool getKey(int32_t& str); + bool getKey(uint32_t& str); - /* Decode methods */ - bool getCBOR(const uint8_t** pointer, uint32_t* length); - uint32_t getCBORLength(); + Cborg getValue(); + bool getValueUnsigned(uint32_t& value); + bool getValueNegative(int32_t& value); + bool getValueSigned(int32_t& value); - /* map functions */ - template - Cborg find(const char (&key)[I]) - { - return find(key, I - 1); - } + bool getValueTimeStamp(time_t& value); - Cborg find(int32_t key) const; - Cborg find(const char* key, std::size_t keyLength) const; + bool getValueBytes(const uint8_t** pointer, uint32_t* length); + bool getValueString(const char** pointer, uint32_t* length); + bool getValueString(std::string& str); - Cborg at(std::size_t index) const; + [[nodiscard]] Cborg at(std::size_t index) const; - uint32_t getSize() const; + [[nodiscard]] uint32_t getSize() const; - /* non-container functions */ - bool getUnsigned(uint32_t*) const; - bool getNegative(int32_t*) const; + /* non-container functions */ + bool getUnsigned(uint32_t&) const; + bool getNegative(int32_t&) const; + bool getSigned(int32_t&) const; - bool getTimeStamp(time_t*) const; + bool getTimeStamp(time_t&) const; - bool getBytes(const uint8_t** pointer, uint32_t* length) const; - bool getString(const char** pointer, uint32_t* length) const; - bool getString(std::string& str) const; + bool getBytes(const uint8_t** pointer, uint32_t* length) const; + bool getString(const char** pointer, uint32_t* length) const; + bool getString(std::string& str) const; - /* pass through to header */ - uint32_t getTag() const; - uint8_t getType() const; - uint8_t getMinorType() const; + /* pass through to header */ + uint32_t getTag() const; + uint8_t getType() const; + uint8_t getMinorType() const; - /* debug */ - void print() const; + /* debug */ + void print() const; -private: - const uint8_t* cbor; - std::size_t maxLength; + private: + const uint8_t* cbor; + std::size_t maxLength; }; -#endif // __CBORG_H__ +#endif // __CBORG_H__ diff --git a/source/Cbore.cpp b/source/Cbore.cpp index e88d427..add18cb 100644 --- a/source/Cbore.cpp +++ b/source/Cbore.cpp @@ -109,9 +109,9 @@ Cbore& Cbore::item(uint32_t value) { Cbore& Cbore::item(bool value) { if (value) { - return this->value(CborBase::TypeTrue); + return this->item(CborBase::TypeTrue); } - return this->value(CborBase::TypeFalse); + return this->item(CborBase::TypeFalse); } Cbore& Cbore::item(std::chrono::system_clock::time_point unixTimeStamp) { @@ -195,6 +195,14 @@ Cbore& Cbore::key(int32_t unit) { return *this; } +Cbore& Cbore::key(uint32_t unit) { + if ((itemSize(unit)) <= (maxLength - currentLength)) { + writeTypeAndValue(CborBase::TypeUnsigned, unit); + } + + return *this; +} + // insert key as const char pointer with length Cbore& Cbore::key(const char* unit, std::size_t length) { if ((itemSize(static_cast(length)) + length) <= @@ -206,6 +214,15 @@ Cbore& Cbore::key(const char* unit, std::size_t length) { return *this; } +Cbore& Cbore::key(std::string_view str) { + if ((itemSize(str)) <= (maxLength - currentLength)) { + writeTypeAndValue(CborBase::TypeString, str.size()); + writeBytes(reinterpret_cast(str.data()), str.size()); + } + + return *this; +} + /*************************************************************************/ /* Map insertion - value */ /*************************************************************************/ @@ -222,6 +239,14 @@ Cbore& Cbore::value(int32_t unit) { return *this; } +Cbore& Cbore::value(uint32_t unit) { + if ((itemSize(unit)) <= (maxLength - currentLength)) { + writeTypeAndValue(CborBase::TypeUnsigned, unit); + } + + return *this; +} + Cbore& Cbore::value(CborBase::SimpleType_t unit) { if (currentLength < maxLength) { cbor[currentLength++] = CborBase::TypeSpecial << 5 | unit; @@ -230,6 +255,13 @@ Cbore& Cbore::value(CborBase::SimpleType_t unit) { return *this; } +Cbore& Cbore::value(bool unit) { + if (unit) { + return value(CborBase::TypeTrue); + } + return value(CborBase::TypeFalse); +} + Cbore& Cbore::value(const uint8_t* unit, std::size_t length) { if ((itemSize(static_cast(length)) + length) <= (maxLength - currentLength)) { @@ -250,6 +282,16 @@ Cbore& Cbore::value(const char* unit, std::size_t length) { return *this; } +Cbore& Cbore::value(std::string_view unit) { + if ((itemSize(unit.size())) <= + (maxLength - currentLength)) { + writeTypeAndValue(CborBase::TypeString, unit.size()); + writeBytes(reinterpret_cast(unit.data()), unit.size()); + } + + return *this; +} + Cbore& Cbore::reset(bool resetBuffer) { currentLength = 0; if (resetBuffer) { @@ -282,6 +324,14 @@ uint8_t Cbore::itemSize(uint32_t item) { return 5; } +uint8_t Cbore::itemSize(std::size_t item) { + return itemSize(static_cast(item)); +} + +size_t Cbore::itemSize(std::string_view str) { + return (itemSize(str.size()) + str.size()); +} + uint8_t Cbore::writeTypeAndValue(CborBase::MajorType_t majorType, uint32_t value) { if (cbor != nullptr) { @@ -355,3 +405,4 @@ void Cbore::print() const { Cborg decoder(cbor, maxLength); decoder.print(); } +uint8_t Cbore::itemSizeBool() { return 1; } diff --git a/source/Cborg.cpp b/source/Cborg.cpp index 0ee9e12..91ee0b0 100644 --- a/source/Cborg.cpp +++ b/source/Cborg.cpp @@ -544,6 +544,11 @@ Cborg Cborg::find(const char* key, std::size_t keyLength) const { return {nullptr, 0}; } +Cborg Cborg::getKey() { return *this; } +bool Cborg::getKey(std::string& str) { return getString(str); } +bool Cborg::getKey(int32_t& integer) { return getSigned(integer); } +bool Cborg::getKey(uint32_t& integer) { return getUnsigned(integer); } + Cborg Cborg::at(std::size_t index) const { CborgHeader head; head.decode(cbor); @@ -553,12 +558,18 @@ Cborg Cborg::at(std::size_t index) const { // set units to elements in array int32_t units = head.getValue(); + + if (type == CborBase::TypeMap) { + units *= 2; // double units for map type as we need to iterate both keys + // and values. + } + units = (simple == CborBase::TypeIndefinite) ? maxOf(units) : units; // only continue if container is Cbor Map, not empty, and index is within // bounds - if ((type != CborBase::TypeArray) || (units == 0) || - (static_cast(index) >= units)) { + if ((type != CborBase::TypeArray && type != CborBase::TypeMap) || + (units == 0) || (static_cast(index) >= units)) { return {nullptr, 0}; } @@ -670,39 +681,57 @@ uint32_t Cborg::getSize() const { return 0; } -bool Cborg::getUnsigned(uint32_t* integer) const { +bool Cborg::getUnsigned(uint32_t& integer) const { CborgHeader head; head.decode(cbor); if (head.getMajorType() == CborBase::TypeUnsigned) { - *integer = head.getValue(); + integer = head.getValue(); return true; } return false; } -bool Cborg::getTimeStamp(time_t* timeStamp) const { +bool Cborg::getTimeStamp(time_t& timeStamp) const { CborgHeader head; head.decode(cbor); if (head.getMajorType() == CborBase::TypeUnsigned && head.getTag() == 1) { - *timeStamp = head.getValue(); + timeStamp = head.getValue(); + + return true; + } + return false; +} + +bool Cborg::getNegative(int32_t& integer) const { + CborgHeader head; + head.decode(cbor); + + if (head.getMajorType() == CborBase::TypeNegative) { + integer = static_cast(-1) - + static_cast(head.getValue()); return true; } return false; } -bool Cborg::getNegative(int32_t* integer) const { +bool Cborg::getSigned(int32_t& integer) const { CborgHeader head; head.decode(cbor); if (head.getMajorType() == CborBase::TypeNegative) { - *integer = -1 - head.getValue(); + integer = static_cast(-1) - + static_cast(head.getValue()); return true; } + if (head.getMajorType() == CborBase::TypeUnsigned) { + integer = static_cast(head.getValue()); + return true; + } return false; } @@ -847,7 +876,7 @@ void Cborg::print() const { case CborBase::TypeUnsigned: { Cborg object(&cbor[progress], maxLength - progress); uint32_t integer = 0; - bool result = object.getUnsigned(&integer); + bool result = object.getUnsigned(integer); if (result) { printf("%" PRIu32 "\r\n", integer); @@ -859,7 +888,7 @@ void Cborg::print() const { case CborBase::TypeNegative: { Cborg object(&cbor[progress], maxLength - progress); int32_t integer = 0; - bool result = object.getNegative(&integer); + bool result = object.getNegative(integer); if (result) { printf("%" PRId32 "\r\n", integer); @@ -949,3 +978,47 @@ void Cborg::print() const { } } } +bool Cborg::getValueUnsigned(uint32_t& value) { + return getValue().getUnsigned(value); +} + +bool Cborg::getValueNegative(int32_t& value) { + return getValue().getNegative(value); +} +bool Cborg::getValueSigned(int32_t& value) { + return getValue().getSigned(value); +} +bool Cborg::getValueTimeStamp(time_t& value) { + return getValue().getTimeStamp(value); +} +bool Cborg::getValueBytes(const uint8_t** pointer, uint32_t* length) { + return getValue().getBytes(pointer, length); +} +bool Cborg::getValueString(const char** pointer, uint32_t* length) { + return getValue().getString(pointer, length); +} +bool Cborg::getValueString(std::string& str) { + return getValue().getValueString(str); +} + +Cborg Cborg::getValue() { + CborgHeader head; + std::size_t progress = 0; + /* semantic tag */ + uint32_t tag = head.getTag(); + uint8_t type = head.getMajorType(); + uint8_t simple = head.getMinorType(); + // increment progress based on cbor object size + if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) && + (simple != CborBase::TypeIndefinite)) { + progress += head.getLength() + head.getValue(); + } else { + progress += head.getLength(); + } + if (progress >= maxLength) { + return {nullptr, 0}; + } + return {&cbor[progress], maxLength - progress}; +} + +bool Cborg::isNull() { return (cbor == nullptr); } From fc39c4dc6c96312b49492e12c4fefb00a9ef7c2b Mon Sep 17 00:00:00 2001 From: Thomas Saedt Date: Tue, 23 Nov 2021 12:48:26 +0100 Subject: [PATCH 5/8] feat: more optimized iteration for maps and arrays --- include/cborg/Cborg.h | 14 ++++-- source/Cborg.cpp | 112 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 120 insertions(+), 6 deletions(-) diff --git a/include/cborg/Cborg.h b/include/cborg/Cborg.h index 15ebf65..a5b79cc 100644 --- a/include/cborg/Cborg.h +++ b/include/cborg/Cborg.h @@ -29,6 +29,7 @@ class Cborg { public: Cborg(); Cborg(const uint8_t* cbor, std::size_t maxLength); + Cborg(const uint8_t* cbor, std::size_t maxLength, std::int32_t _arrayUnits); bool isNull(); @@ -38,19 +39,19 @@ class Cborg { /* map functions */ template - Cborg find(const char (&key)[I]) { + [[nodiscard]] Cborg find(const char (&key)[I]) { return find(key, I - 1); } - Cborg find(int32_t key) const; - Cborg find(const char* key, std::size_t keyLength) const; + [[nodiscard]] Cborg find(int32_t key) const; + [[nodiscard]] Cborg find(const char* key, std::size_t keyLength) const; - Cborg getKey(); + [[nodiscard]] Cborg getKey(); bool getKey(std::string& str); bool getKey(int32_t& str); bool getKey(uint32_t& str); - Cborg getValue(); + [[nodiscard]] Cborg getValue(); bool getValueUnsigned(uint32_t& value); bool getValueNegative(int32_t& value); bool getValueSigned(int32_t& value); @@ -62,6 +63,8 @@ class Cborg { bool getValueString(std::string& str); [[nodiscard]] Cborg at(std::size_t index) const; + [[nodiscard]] Cborg nextArrayItem(std::size_t index = 1) const; + [[nodiscard]] Cborg nextMapItem(std::size_t index = 1) const; [[nodiscard]] uint32_t getSize() const; @@ -87,6 +90,7 @@ class Cborg { private: const uint8_t* cbor; std::size_t maxLength; + std::int32_t _arrayUnits = std::numeric_limits::max(); }; #endif // __CBORG_H__ diff --git a/source/Cborg.cpp b/source/Cborg.cpp index 91ee0b0..4c94e0d 100644 --- a/source/Cborg.cpp +++ b/source/Cborg.cpp @@ -41,6 +41,10 @@ Cborg::Cborg() : cbor(nullptr), maxLength(0) {} Cborg::Cborg(const uint8_t* _cbor, std::size_t _length) : cbor(_cbor), maxLength(_length) {} +Cborg::Cborg(const uint8_t* _cbor, std::size_t _length, + std::int32_t _arrayUnits) + : cbor(_cbor), maxLength(_length), _arrayUnits(_arrayUnits) {} + bool Cborg::getCBOR(const uint8_t** pointer, uint32_t* length) { // decode current header CborgHeader head; @@ -586,7 +590,7 @@ Cborg Cborg::at(std::size_t index) const { while (progress < maxLength) { // compare current array index with the one sought for and return if found if (currentIndex == index) { - return {&cbor[progress], maxLength - progress}; + return {&cbor[progress], maxLength - progress, units}; } // decrement unit count unless set to indefinite @@ -664,6 +668,112 @@ Cborg Cborg::at(std::size_t index) const { return {nullptr, 0}; } +Cborg Cborg::nextMapItem(std::size_t index) const { + return nextArrayItem(index * 2); +} + +Cborg Cborg::nextArrayItem(std::size_t index) const { + CborgHeader head; + head.decode(cbor); + + // set units to elements in array + int32_t units = _arrayUnits; // head.getValue(); + + if (units == 0) { + return {nullptr, 0}; + } + + // got array, look for index + std::list list; + std::size_t current_index = 0; + + // skip array header + std::size_t progress = 0; + + // iterate through cbor encoded buffer + // stop when maximum length is reached or + // the current map is finished + while (progress < maxLength) { + // compare current array index with the one sought for and return if found + if (current_index == index) { + return {&cbor[progress], maxLength - progress, units}; + } + + // decrement unit count unless set to indefinite + if (units != maxOf(units)) { + units--; + } + + // decode header for cbor object currently pointed to + head.decode(&cbor[progress]); + + uint8_t type = head.getMajorType(); + uint8_t simple = head.getMinorType(); + + // if object is a container type (map or array), push remaining units onto + // the stack (list) and set units to the number of elements in the new + // container. + if (type == CborBase::TypeMap) { + if (simple == CborBase::TypeIndefinite) { + list.push_back(units); + units = maxOf(units); + } else if (head.getValue() > 0) { + list.push_back(units); + units = 2 * head.getValue(); + } + } else if (type == CborBase::TypeArray) { + if (simple == CborBase::TypeIndefinite) { + list.push_back(units); + units = maxOf(units); + } else if (head.getValue() > 0) { + list.push_back(units); + units = head.getValue(); + } + } else if (((type == CborBase::TypeBytes) || + (type == CborBase::TypeString)) && + (simple == CborBase::TypeIndefinite)) { + list.push_back(units); + units = maxOf(units); + } + + // increment progress based on cbor object size + if (((type == CborBase::TypeBytes) || (type == CborBase::TypeString)) && + (simple != CborBase::TypeIndefinite)) { + progress += head.getLength() + head.getValue(); + } else { + progress += head.getLength(); + } + + // finished processing all elements in the current container object + // step back up one level by popping remaining elements from the stack + // (list) do it in a while loop since we might have to step back up multiple + // times + while ((units == 0) || ((type == CborBase::TypeSpecial) && + (simple == CborBase::TypeIndefinite))) { + type = CborBase::TypeSpecial; + simple = CborBase::TypeNull; + + if (!list.empty()) { + // pop from stack + units = list.back(); + list.pop_back(); + } else { + // stack is empty, means we have reached the end of the current + // container return a Cbor null object + return {nullptr, 0}; + } + } + + // if element is on the top level, increment index counter + if (list.empty()) { + current_index++; + } + } + + // index not found, return null object + return {nullptr, 0}; +} + uint32_t Cborg::getSize() const { CborgHeader head; head.decode(cbor); From 9eaa3f102a5887f39aff0dc7a891c8be7ca5128a Mon Sep 17 00:00:00 2001 From: Thomas Saedt Date: Tue, 23 Nov 2021 16:00:26 +0100 Subject: [PATCH 6/8] fix: size_t being a uin32_t on some platforms --- include/cborg/Cbore.h | 16 +++++++++++----- source/Cbore.cpp | 9 ++++----- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/include/cborg/Cbore.h b/include/cborg/Cbore.h index beb12a0..1073bd4 100644 --- a/include/cborg/Cbore.h +++ b/include/cborg/Cbore.h @@ -141,7 +141,7 @@ class Cbore { if ((itemSize(static_cast(I)) + I) <= (maxLength - currentLength)) { writeTypeAndValue(CborBase::TypeString, I - 1); - writeBytes(reinterpret_cast(unit), I - 1); + writeBytes(reinterpret_cast(unit), I - 1); } return *this; @@ -157,10 +157,16 @@ class Cbore { Cbore& value(std::string_view unit); // get the size of an item (used to calculate buffer size) - static uint8_t itemSize(int32_t item); - static uint8_t itemSize(uint32_t item); - static uint8_t itemSize(std::size_t item); - static uint8_t itemSizeBool(); + static std::uint8_t itemSize(int32_t item); + static std::uint8_t itemSize(uint32_t item); + + template >> // NOLINT + static std::uint8_t itemSize(std::size_t item) { + return itemSize(static_cast(item)); + }; + + static std::uint8_t itemSizeBool(); static size_t itemSize(std::string_view str); /*************************************************************************/ diff --git a/source/Cbore.cpp b/source/Cbore.cpp index add18cb..39d2f64 100644 --- a/source/Cbore.cpp +++ b/source/Cbore.cpp @@ -283,8 +283,7 @@ Cbore& Cbore::value(const char* unit, std::size_t length) { } Cbore& Cbore::value(std::string_view unit) { - if ((itemSize(unit.size())) <= - (maxLength - currentLength)) { + if ((itemSize(unit.size())) <= (maxLength - currentLength)) { writeTypeAndValue(CborBase::TypeString, unit.size()); writeBytes(reinterpret_cast(unit.data()), unit.size()); } @@ -324,9 +323,9 @@ uint8_t Cbore::itemSize(uint32_t item) { return 5; } -uint8_t Cbore::itemSize(std::size_t item) { - return itemSize(static_cast(item)); -} +// uint8_t Cbore::itemSize(std::size_t item) { +// return itemSize(static_cast(item)); +// } size_t Cbore::itemSize(std::string_view str) { return (itemSize(str.size()) + str.size()); From 7078678f81322713a04c412af4e964bae99705fc Mon Sep 17 00:00:00 2001 From: Thomas Saedt Date: Wed, 24 Nov 2021 10:17:16 +0100 Subject: [PATCH 7/8] feat: add bool and getType functions --- include/cborg/Cborg.h | 8 +++++--- source/Cborg.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/include/cborg/Cborg.h b/include/cborg/Cborg.h index a5b79cc..ba5c958 100644 --- a/include/cborg/Cborg.h +++ b/include/cborg/Cborg.h @@ -78,11 +78,13 @@ class Cborg { bool getBytes(const uint8_t** pointer, uint32_t* length) const; bool getString(const char** pointer, uint32_t* length) const; bool getString(std::string& str) const; + bool getBool(bool& bl) const; /* pass through to header */ - uint32_t getTag() const; - uint8_t getType() const; - uint8_t getMinorType() const; + [[nodiscard]] std::uint32_t getTag() const; + [[nodiscard]] std::uint8_t getType() const; + [[nodiscard]] std::uint8_t getMajorType() const; + [[nodiscard]] std::uint8_t getMinorType() const; /* debug */ void print() const; diff --git a/source/Cborg.cpp b/source/Cborg.cpp index 4c94e0d..7351cf2 100644 --- a/source/Cborg.cpp +++ b/source/Cborg.cpp @@ -884,6 +884,23 @@ bool Cborg::getString(std::string& str) const { return false; } +bool Cborg::getBool(bool& bl) const { + CborgHeader head; + head.decode(cbor); + + if (head.getMajorType() == CborBase::TypeSpecial || + head.getMinorType() == CborBase::TypeTrue) { + bl = true; + return true; + } + if (head.getMajorType() == CborBase::TypeSpecial || + head.getMinorType() == CborBase::TypeFalse) { + bl = false; + return true; + } + return false; +} + /*****************************************************************************/ /* Header related */ /*****************************************************************************/ @@ -899,6 +916,17 @@ uint8_t Cborg::getType() const { CborgHeader head; head.decode(cbor); + std::uint8_t type = head.getMajorType(); + if (type == CborBase::TypeSpecial) { + type = head.getMinorType(); + } + return type; +} + +uint8_t Cborg::getMajorType() const { + CborgHeader head; + head.decode(cbor); + return head.getMajorType(); } @@ -1113,6 +1141,7 @@ bool Cborg::getValueString(std::string& str) { Cborg Cborg::getValue() { CborgHeader head; + head.decode(cbor); std::size_t progress = 0; /* semantic tag */ uint32_t tag = head.getTag(); From c5ab4e0388c2c019616eaf08284ba0b240f4a222 Mon Sep 17 00:00:00 2001 From: Thomas Saedt Date: Thu, 2 Dec 2021 14:05:41 +0100 Subject: [PATCH 8/8] fix: compile include issues --- include/cborg/Cborg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/cborg/Cborg.h b/include/cborg/Cborg.h index ba5c958..8183eb4 100644 --- a/include/cborg/Cborg.h +++ b/include/cborg/Cborg.h @@ -17,9 +17,9 @@ #ifndef __CBORG_H__ #define __CBORG_H__ -#include - #include +#include +#include #include #include "cborg/CborBase.h"