diff options
author | Max Bires <jbires@google.com> | 2020-04-09 23:40:02 +0000 |
---|---|---|
committer | Max Bires <jbires@google.com> | 2020-04-09 23:40:02 +0000 |
commit | af2e2a6c6d9dc174ac4d65766ba0ebc3f553afaf (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /include/cppbor | |
parent | a7b145a6a5d05b89e9769ffea84d1068ef32bd4e (diff) | |
download | libcppbor-af2e2a6c6d9dc174ac4d65766ba0ebc3f553afaf.tar.gz |
Revert "Adding the initial commit for libcppbor"
This reverts commit a7b145a6a5d05b89e9769ffea84d1068ef32bd4e.
Reason for revert: Need to submit with altered binary names
Change-Id: I73a6e442fdbd955bbbd9ab03a7c3096deabbc786
Diffstat (limited to 'include/cppbor')
-rw-r--r-- | include/cppbor/cppbor.h | 827 | ||||
-rw-r--r-- | include/cppbor/cppbor_parse.h | 133 |
2 files changed, 0 insertions, 960 deletions
diff --git a/include/cppbor/cppbor.h b/include/cppbor/cppbor.h deleted file mode 100644 index 8fb7cc6..0000000 --- a/include/cppbor/cppbor.h +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include <cstdint> -#include <functional> -#include <iterator> -#include <memory> -#include <numeric> -#include <string> -#include <vector> - -namespace cppbor { - -enum MajorType : uint8_t { - UINT = 0 << 5, - NINT = 1 << 5, - BSTR = 2 << 5, - TSTR = 3 << 5, - ARRAY = 4 << 5, - MAP = 5 << 5, - SEMANTIC = 6 << 5, - SIMPLE = 7 << 5, -}; - -enum SimpleType { - BOOLEAN, - NULL_T, // Only two supported, as yet. -}; - -enum SpecialAddlInfoValues : uint8_t { - FALSE = 20, - TRUE = 21, - NULL_V = 22, - ONE_BYTE_LENGTH = 24, - TWO_BYTE_LENGTH = 25, - FOUR_BYTE_LENGTH = 26, - EIGHT_BYTE_LENGTH = 27, -}; - -class Item; -class Uint; -class Nint; -class Int; -class Tstr; -class Bstr; -class Simple; -class Bool; -class Array; -class Map; -class Null; -class Semantic; - -/** - * Returns the size of a CBOR header that contains the additional info value addlInfo. - */ -size_t headerSize(uint64_t addlInfo); - -/** - * Encodes a CBOR header with the specified type and additional info into the range [pos, end). - * Returns a pointer to one past the last byte written, or nullptr if there isn't sufficient space - * to write the header. - */ -uint8_t* encodeHeader(MajorType type, uint64_t addlInfo, uint8_t* pos, const uint8_t* end); - -using EncodeCallback = std::function<void(uint8_t)>; - -/** - * Encodes a CBOR header with the specified type and additional info, passing each byte in turn to - * encodeCallback. - */ -void encodeHeader(MajorType type, uint64_t addlInfo, EncodeCallback encodeCallback); - -/** - * Encodes a CBOR header witht he specified type and additional info, writing each byte to the - * provided OutputIterator. - */ -template <typename OutputIterator, - typename = std::enable_if_t<std::is_base_of_v< - std::output_iterator_tag, - typename std::iterator_traits<OutputIterator>::iterator_category>>> -void encodeHeader(MajorType type, uint64_t addlInfo, OutputIterator iter) { - return encodeHeader(type, addlInfo, [&](uint8_t v) { *iter++ = v; }); -} - -/** - * Item represents a CBOR-encodeable data item. Item is an abstract interface with a set of virtual - * methods that allow encoding of the item or conversion to the appropriate derived type. - */ -class Item { - public: - virtual ~Item() {} - - /** - * Returns the CBOR type of the item. - */ - virtual MajorType type() const = 0; - - // These methods safely downcast an Item to the appropriate subclass. - virtual const Int* asInt() const { return nullptr; } - virtual const Uint* asUint() const { return nullptr; } - virtual const Nint* asNint() const { return nullptr; } - virtual const Tstr* asTstr() const { return nullptr; } - virtual const Bstr* asBstr() const { return nullptr; } - virtual const Simple* asSimple() const { return nullptr; } - virtual const Map* asMap() const { return nullptr; } - virtual const Array* asArray() const { return nullptr; } - virtual const Semantic* asSemantic() const { return nullptr; } - - /** - * Returns true if this is a "compound" item, i.e. one that contains one or more other items. - */ - virtual bool isCompound() const { return false; } - - bool operator==(const Item& other) const&; - bool operator!=(const Item& other) const& { return !(*this == other); } - - /** - * Returns the number of bytes required to encode this Item into CBOR. Note that if this is a - * complex Item, calling this method will require walking the whole tree. - */ - virtual size_t encodedSize() const = 0; - - /** - * Encodes the Item into buffer referenced by range [*pos, end). Returns a pointer to one past - * the last position written. Returns nullptr if there isn't enough space to encode. - */ - virtual uint8_t* encode(uint8_t* pos, const uint8_t* end) const = 0; - - /** - * Encodes the Item by passing each encoded byte to encodeCallback. - */ - virtual void encode(EncodeCallback encodeCallback) const = 0; - - /** - * Clones the Item - */ - virtual std::unique_ptr<Item> clone() const = 0; - - /** - * Encodes the Item into the provided OutputIterator. - */ - template <typename OutputIterator, - typename = typename std::iterator_traits<OutputIterator>::iterator_category> - void encode(OutputIterator i) const { - return encode([&](uint8_t v) { *i++ = v; }); - } - - /** - * Encodes the Item into a new std::vector<uint8_t>. - */ - std::vector<uint8_t> encode() const { - std::vector<uint8_t> retval; - retval.reserve(encodedSize()); - encode(std::back_inserter(retval)); - return retval; - } - - /** - * Encodes the Item into a new std::string. - */ - std::string toString() const { - std::string retval; - retval.reserve(encodedSize()); - encode([&](uint8_t v) { retval.push_back(v); }); - return retval; - } - - /** - * Encodes only the header of the Item. - */ - inline uint8_t* encodeHeader(uint64_t addlInfo, uint8_t* pos, const uint8_t* end) const { - return ::cppbor::encodeHeader(type(), addlInfo, pos, end); - } - - /** - * Encodes only the header of the Item. - */ - inline void encodeHeader(uint64_t addlInfo, EncodeCallback encodeCallback) const { - ::cppbor::encodeHeader(type(), addlInfo, encodeCallback); - } -}; - -/** - * Int is an abstraction that allows Uint and Nint objects to be manipulated without caring about - * the sign. - */ -class Int : public Item { - public: - bool operator==(const Int& other) const& { return value() == other.value(); } - - virtual int64_t value() const = 0; - - const Int* asInt() const override { return this; } -}; - -/** - * Uint is a concrete Item that implements CBOR major type 0. - */ -class Uint : public Int { - public: - static constexpr MajorType kMajorType = UINT; - - explicit Uint(uint64_t v) : mValue(v) {} - - bool operator==(const Uint& other) const& { return mValue == other.mValue; } - - MajorType type() const override { return kMajorType; } - const Uint* asUint() const override { return this; } - - size_t encodedSize() const override { return headerSize(mValue); } - - int64_t value() const override { return mValue; } - uint64_t unsignedValue() const { return mValue; } - - using Item::encode; - uint8_t* encode(uint8_t* pos, const uint8_t* end) const override { - return encodeHeader(mValue, pos, end); - } - void encode(EncodeCallback encodeCallback) const override { - encodeHeader(mValue, encodeCallback); - } - - virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Uint>(mValue); } - - private: - uint64_t mValue; -}; - -/** - * Nint is a concrete Item that implements CBOR major type 1. - - * Note that it is incapable of expressing the full range of major type 1 values, becaue it can only - * express values that fall into the range [std::numeric_limits<int64_t>::min(), -1]. It cannot - * express values in the range [std::numeric_limits<int64_t>::min() - 1, - * -std::numeric_limits<uint64_t>::max()]. - */ -class Nint : public Int { - public: - static constexpr MajorType kMajorType = NINT; - - explicit Nint(int64_t v); - - bool operator==(const Nint& other) const& { return mValue == other.mValue; } - - MajorType type() const override { return kMajorType; } - const Nint* asNint() const override { return this; } - size_t encodedSize() const override { return headerSize(addlInfo()); } - - int64_t value() const override { return mValue; } - - using Item::encode; - uint8_t* encode(uint8_t* pos, const uint8_t* end) const override { - return encodeHeader(addlInfo(), pos, end); - } - void encode(EncodeCallback encodeCallback) const override { - encodeHeader(addlInfo(), encodeCallback); - } - - virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Nint>(mValue); } - - private: - uint64_t addlInfo() const { return -1ll - mValue; } - - int64_t mValue; -}; - -/** - * Bstr is a concrete Item that implements major type 2. - */ -class Bstr : public Item { - public: - static constexpr MajorType kMajorType = BSTR; - - // Construct from a vector - explicit Bstr(std::vector<uint8_t> v) : mValue(std::move(v)) {} - - // Construct from a string - explicit Bstr(const std::string& v) - : mValue(reinterpret_cast<const uint8_t*>(v.data()), - reinterpret_cast<const uint8_t*>(v.data()) + v.size()) {} - - // Construct from a pointer/size pair - explicit Bstr(const std::pair<const uint8_t*, size_t>& buf) - : mValue(buf.first, buf.first + buf.second) {} - - // Construct from a pair of iterators - template <typename I1, typename I2, - typename = typename std::iterator_traits<I1>::iterator_category, - typename = typename std::iterator_traits<I2>::iterator_category> - explicit Bstr(const std::pair<I1, I2>& pair) : mValue(pair.first, pair.second) {} - - // Construct from an iterator range. - template <typename I1, typename I2, - typename = typename std::iterator_traits<I1>::iterator_category, - typename = typename std::iterator_traits<I2>::iterator_category> - Bstr(I1 begin, I2 end) : mValue(begin, end) {} - - bool operator==(const Bstr& other) const& { return mValue == other.mValue; } - - MajorType type() const override { return kMajorType; } - const Bstr* asBstr() const override { return this; } - size_t encodedSize() const override { return headerSize(mValue.size()) + mValue.size(); } - using Item::encode; - uint8_t* encode(uint8_t* pos, const uint8_t* end) const override; - void encode(EncodeCallback encodeCallback) const override { - encodeHeader(mValue.size(), encodeCallback); - encodeValue(encodeCallback); - } - - const std::vector<uint8_t>& value() const { return mValue; } - - virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Bstr>(mValue); } - - private: - void encodeValue(EncodeCallback encodeCallback) const; - - std::vector<uint8_t> mValue; -}; - -/** - * Bstr is a concrete Item that implements major type 3. - */ -class Tstr : public Item { - public: - static constexpr MajorType kMajorType = TSTR; - - // Construct from a string - explicit Tstr(std::string v) : mValue(std::move(v)) {} - - // Construct from a string_view - explicit Tstr(const std::string_view& v) : mValue(v) {} - - // Construct from a C string - explicit Tstr(const char* v) : mValue(std::string(v)) {} - - // Construct from a pair of iterators - template <typename I1, typename I2, - typename = typename std::iterator_traits<I1>::iterator_category, - typename = typename std::iterator_traits<I2>::iterator_category> - explicit Tstr(const std::pair<I1, I2>& pair) : mValue(pair.first, pair.second) {} - - // Construct from an iterator range - template <typename I1, typename I2, - typename = typename std::iterator_traits<I1>::iterator_category, - typename = typename std::iterator_traits<I2>::iterator_category> - Tstr(I1 begin, I2 end) : mValue(begin, end) {} - - bool operator==(const Tstr& other) const& { return mValue == other.mValue; } - - MajorType type() const override { return kMajorType; } - const Tstr* asTstr() const override { return this; } - size_t encodedSize() const override { return headerSize(mValue.size()) + mValue.size(); } - using Item::encode; - uint8_t* encode(uint8_t* pos, const uint8_t* end) const override; - void encode(EncodeCallback encodeCallback) const override { - encodeHeader(mValue.size(), encodeCallback); - encodeValue(encodeCallback); - } - - const std::string& value() const { return mValue; } - - virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Tstr>(mValue); } - - private: - void encodeValue(EncodeCallback encodeCallback) const; - - std::string mValue; -}; - -/** - * CompoundItem is an abstract Item that provides common functionality for Items that contain other - * items, i.e. Arrays (CBOR type 4) and Maps (CBOR type 5). - */ -class CompoundItem : public Item { - public: - bool operator==(const CompoundItem& other) const&; - - virtual size_t size() const { return mEntries.size(); } - - bool isCompound() const override { return true; } - - size_t encodedSize() const override { - return std::accumulate(mEntries.begin(), mEntries.end(), headerSize(size()), - [](size_t sum, auto& entry) { return sum + entry->encodedSize(); }); - } - - using Item::encode; // Make base versions visible. - uint8_t* encode(uint8_t* pos, const uint8_t* end) const override; - void encode(EncodeCallback encodeCallback) const override; - - virtual uint64_t addlInfo() const = 0; - - protected: - std::vector<std::unique_ptr<Item>> mEntries; -}; - -/* - * Array is a concrete Item that implements CBOR major type 4. - * - * Note that Arrays are not copyable. This is because copying them is expensive and making them - * move-only ensures that they're never copied accidentally. If you actually want to copy an Array, - * use the clone() method. - */ -class Array : public CompoundItem { - public: - static constexpr MajorType kMajorType = ARRAY; - - Array() = default; - Array(const Array& other) = delete; - Array(Array&&) = default; - Array& operator=(const Array&) = delete; - Array& operator=(Array&&) = default; - - /** - * Construct an Array from a variable number of arguments of different types. See - * details::makeItem below for details on what types may be provided. In general, this accepts - * all of the types you'd expect and doest the things you'd expect (integral values are addes as - * Uint or Nint, std::string and char* are added as Tstr, bools are added as Bool, etc.). - */ - template <typename... Args, typename Enable> - Array(Args&&... args); - - /** - * Append a single element to the Array, of any compatible type. - */ - template <typename T> - Array& add(T&& v) &; - template <typename T> - Array&& add(T&& v) &&; - - const std::unique_ptr<Item>& operator[](size_t index) const { return mEntries[index]; } - std::unique_ptr<Item>& operator[](size_t index) { return mEntries[index]; } - - MajorType type() const override { return kMajorType; } - const Array* asArray() const override { return this; } - - virtual std::unique_ptr<Item> clone() const override; - - uint64_t addlInfo() const override { return size(); } -}; - -/* - * Map is a concrete Item that implements CBOR major type 5. - * - * Note that Maps are not copyable. This is because copying them is expensive and making them - * move-only ensures that they're never copied accidentally. If you actually want to copy a - * Map, use the clone() method. - */ -class Map : public CompoundItem { - public: - static constexpr MajorType kMajorType = MAP; - - Map() = default; - Map(const Map& other) = delete; - Map(Map&&) = default; - Map& operator=(const Map& other) = delete; - Map& operator=(Map&&) = default; - - /** - * Construct a Map from a variable number of arguments of different types. An even number of - * arguments must be provided (this is verified statically). See details::makeItem below for - * details on what types may be provided. In general, this accepts all of the types you'd - * expect and doest the things you'd expect (integral values are addes as Uint or Nint, - * std::string and char* are added as Tstr, bools are added as Bool, etc.). - */ - template <typename... Args, typename Enable> - Map(Args&&... args); - - /** - * Append a key/value pair to the Map, of any compatible types. - */ - template <typename Key, typename Value> - Map& add(Key&& key, Value&& value) &; - template <typename Key, typename Value> - Map&& add(Key&& key, Value&& value) &&; - - size_t size() const override { - assertInvariant(); - return mEntries.size() / 2; - } - - template <typename Key, typename Enable> - std::pair<std::unique_ptr<Item>&, bool> get(Key key); - - std::pair<const std::unique_ptr<Item>&, const std::unique_ptr<Item>&> operator[]( - size_t index) const { - assertInvariant(); - return {mEntries[index * 2], mEntries[index * 2 + 1]}; - } - - std::pair<std::unique_ptr<Item>&, std::unique_ptr<Item>&> operator[](size_t index) { - assertInvariant(); - return {mEntries[index * 2], mEntries[index * 2 + 1]}; - } - - MajorType type() const override { return kMajorType; } - const Map* asMap() const override { return this; } - - virtual std::unique_ptr<Item> clone() const override; - - uint64_t addlInfo() const override { return size(); } - - private: - void assertInvariant() const; -}; - -class Semantic : public CompoundItem { - public: - static constexpr MajorType kMajorType = SEMANTIC; - - template <typename T> - explicit Semantic(uint64_t value, T&& child); - - Semantic(const Semantic& other) = delete; - Semantic(Semantic&&) = default; - Semantic& operator=(const Semantic& other) = delete; - Semantic& operator=(Semantic&&) = default; - - size_t size() const override { - assertInvariant(); - return 1; - } - - size_t encodedSize() const override { - return std::accumulate(mEntries.begin(), mEntries.end(), headerSize(mValue), - [](size_t sum, auto& entry) { return sum + entry->encodedSize(); }); - } - - MajorType type() const override { return kMajorType; } - const Semantic* asSemantic() const override { return this; } - - const std::unique_ptr<Item>& child() const { - assertInvariant(); - return mEntries[0]; - } - - std::unique_ptr<Item>& child() { - assertInvariant(); - return mEntries[0]; - } - - uint64_t value() const { return mValue; } - - uint64_t addlInfo() const override { return value(); } - - virtual std::unique_ptr<Item> clone() const override { - assertInvariant(); - return std::make_unique<Semantic>(mValue, mEntries[0]->clone()); - } - - protected: - Semantic() = default; - Semantic(uint64_t value) : mValue(value) {} - uint64_t mValue; - - private: - void assertInvariant() const; -}; - -/** - * Simple is abstract Item that implements CBOR major type 7. It is intended to be subclassed to - * create concrete Simple types. At present only Bool is provided. - */ -class Simple : public Item { - public: - static constexpr MajorType kMajorType = SIMPLE; - - bool operator==(const Simple& other) const&; - - virtual SimpleType simpleType() const = 0; - MajorType type() const override { return kMajorType; } - - const Simple* asSimple() const override { return this; } - - virtual const Bool* asBool() const { return nullptr; }; - virtual const Null* asNull() const { return nullptr; }; -}; - -/** - * Bool is a concrete type that implements CBOR major type 7, with additional item values for TRUE - * and FALSE. - */ -class Bool : public Simple { - public: - static constexpr SimpleType kSimpleType = BOOLEAN; - - explicit Bool(bool v) : mValue(v) {} - - bool operator==(const Bool& other) const& { return mValue == other.mValue; } - - SimpleType simpleType() const override { return kSimpleType; } - const Bool* asBool() const override { return this; } - - size_t encodedSize() const override { return 1; } - - using Item::encode; - uint8_t* encode(uint8_t* pos, const uint8_t* end) const override { - return encodeHeader(mValue ? TRUE : FALSE, pos, end); - } - void encode(EncodeCallback encodeCallback) const override { - encodeHeader(mValue ? TRUE : FALSE, encodeCallback); - } - - bool value() const { return mValue; } - - virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Bool>(mValue); } - - private: - bool mValue; -}; - -/** - * Null is a concrete type that implements CBOR major type 7, with additional item value for NULL - */ -class Null : public Simple { - public: - static constexpr SimpleType kSimpleType = NULL_T; - - explicit Null() {} - - SimpleType simpleType() const override { return kSimpleType; } - const Null* asNull() const override { return this; } - - size_t encodedSize() const override { return 1; } - - using Item::encode; - uint8_t* encode(uint8_t* pos, const uint8_t* end) const override { - return encodeHeader(NULL_V, pos, end); - } - void encode(EncodeCallback encodeCallback) const override { - encodeHeader(NULL_V, encodeCallback); - } - - virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Null>(); } -}; - -template <typename T> -std::unique_ptr<T> downcastItem(std::unique_ptr<Item>&& v) { - static_assert(std::is_base_of_v<Item, T> && !std::is_abstract_v<T>, - "returned type is not an Item or is an abstract class"); - if (v && T::kMajorType == v->type()) { - if constexpr (std::is_base_of_v<Simple, T>) { - if (T::kSimpleType != v->asSimple()->simpleType()) { - return nullptr; - } - } - return std::unique_ptr<T>(static_cast<T*>(v.release())); - } else { - return nullptr; - } -} - -/** - * Details. Mostly you shouldn't have to look below, except perhaps at the docstring for makeItem. - */ -namespace details { - -template <typename T, typename V, typename Enable = void> -struct is_iterator_pair_over : public std::false_type {}; - -template <typename I1, typename I2, typename V> -struct is_iterator_pair_over< - std::pair<I1, I2>, V, - typename std::enable_if_t<std::is_same_v<V, typename std::iterator_traits<I1>::value_type>>> - : public std::true_type {}; - -template <typename T, typename V, typename Enable = void> -struct is_unique_ptr_of_subclass_of_v : public std::false_type {}; - -template <typename T, typename P> -struct is_unique_ptr_of_subclass_of_v<T, std::unique_ptr<P>, - typename std::enable_if_t<std::is_base_of_v<T, P>>> - : public std::true_type {}; - -/* check if type is one of std::string (1), std::string_view (2), null-terminated char* (3) or pair - * of iterators (4)*/ -template <typename T, typename Enable = void> -struct is_text_type_v : public std::false_type {}; - -template <typename T> -struct is_text_type_v< - T, typename std::enable_if_t< - /* case 1 */ // - std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, std::string> - /* case 2 */ // - || std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, std::string_view> - /* case 3 */ // - || std::is_same_v<std::remove_cv_t<std::decay_t<T>>, char*> // - || std::is_same_v<std::remove_cv_t<std::decay_t<T>>, const char*> - /* case 4 */ - || details::is_iterator_pair_over<T, char>::value>> : public std::true_type {}; - -/** - * Construct a unique_ptr<Item> from many argument types. Accepts: - * - * (a) booleans; - * (b) integers, all sizes and signs; - * (c) text strings, as defined by is_text_type_v above; - * (d) byte strings, as std::vector<uint8_t>(d1), pair of iterators (d2) or pair<uint8_t*, size_T> - * (d3); and - * (e) Item subclass instances, including Array and Map. Items may be provided by naked pointer - * (e1), unique_ptr (e2), reference (e3) or value (e3). If provided by reference or value, will - * be moved if possible. If provided by pointer, ownership is taken. - * (f) null pointer; - */ -template <typename T> -std::unique_ptr<Item> makeItem(T v) { - Item* p = nullptr; - if constexpr (/* case a */ std::is_same_v<T, bool>) { - p = new Bool(v); - } else if constexpr (/* case b */ std::is_integral_v<T>) { // b - if (v < 0) { - p = new Nint(v); - } else { - p = new Uint(static_cast<uint64_t>(v)); - } - } else if constexpr (/* case c */ // - details::is_text_type_v<T>::value) { - p = new Tstr(v); - } else if constexpr (/* case d1 */ // - std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, - std::vector<uint8_t>> - /* case d2 */ // - || details::is_iterator_pair_over<T, uint8_t>::value - /* case d3 */ // - || std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, - std::pair<uint8_t*, size_t>>) { - p = new Bstr(v); - } else if constexpr (/* case e1 */ // - std::is_pointer_v<T> && - std::is_base_of_v<Item, std::remove_pointer_t<T>>) { - p = v; - } else if constexpr (/* case e2 */ // - details::is_unique_ptr_of_subclass_of_v<Item, T>::value) { - p = v.release(); - } else if constexpr (/* case e3 */ // - std::is_base_of_v<Item, T>) { - p = new T(std::move(v)); - } else if constexpr (/* case f */ std::is_null_pointer_v<T>) { - p = new Null(); - } else { - // It's odd that this can't be static_assert(false), since it shouldn't be evaluated if one - // of the above ifs matches. But static_assert(false) always triggers. - static_assert(std::is_same_v<T, bool>, "makeItem called with unsupported type"); - } - return std::unique_ptr<Item>(p); -} - -} // namespace details - -template <typename... Args, - /* Prevent use as copy ctor */ typename = std::enable_if_t< - (sizeof...(Args)) != 1 || - !(std::is_same_v<Array, std::remove_cv_t<std::remove_reference_t<Args>>> || ...)>> -Array::Array(Args&&... args) { - mEntries.reserve(sizeof...(args)); - (mEntries.push_back(details::makeItem(std::forward<Args>(args))), ...); -} - -template <typename T> -Array& Array::add(T&& v) & { - mEntries.push_back(details::makeItem(std::forward<T>(v))); - return *this; -} - -template <typename T> -Array&& Array::add(T&& v) && { - mEntries.push_back(details::makeItem(std::forward<T>(v))); - return std::move(*this); -} - -template <typename... Args, - /* Prevent use as copy ctor */ typename = std::enable_if_t<(sizeof...(Args)) != 1>> -Map::Map(Args&&... args) { - static_assert((sizeof...(Args)) % 2 == 0, "Map must have an even number of entries"); - mEntries.reserve(sizeof...(args)); - (mEntries.push_back(details::makeItem(std::forward<Args>(args))), ...); -} - -template <typename Key, typename Value> -Map& Map::add(Key&& key, Value&& value) & { - mEntries.push_back(details::makeItem(std::forward<Key>(key))); - mEntries.push_back(details::makeItem(std::forward<Value>(value))); - return *this; -} - -template <typename Key, typename Value> -Map&& Map::add(Key&& key, Value&& value) && { - this->add(std::forward<Key>(key), std::forward<Value>(value)); - return std::move(*this); -} - -template <typename Key, typename = std::enable_if_t<std::is_integral_v<Key> || - details::is_text_type_v<Key>::value>> -std::pair<std::unique_ptr<Item>&, bool> Map::get(Key key) { - assertInvariant(); - auto keyItem = details::makeItem(key); - for (size_t i = 0; i < mEntries.size(); i += 2) { - if (*keyItem == *mEntries[i]) { - return {mEntries[i + 1], true}; - } - } - return {keyItem, false}; -} - -template <typename T> -Semantic::Semantic(uint64_t value, T&& child) : mValue(value) { - mEntries.reserve(1); - mEntries.push_back(details::makeItem(std::forward<T>(child))); -} - -} // namespace cppbor diff --git a/include/cppbor/cppbor_parse.h b/include/cppbor/cppbor_parse.h deleted file mode 100644 index 1b10ce1..0000000 --- a/include/cppbor/cppbor_parse.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "cppbor.h" - -namespace cppbor { - -using ParseResult = std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */, - std::string /* errMsg */>; - -/** - * Parse the first CBOR data item (possibly compound) from the range [begin, end). - * - * Returns a tuple of Item pointer, buffer pointer and error message. If parsing is successful, the - * Item pointer is non-null, the buffer pointer points to the first byte after the - * successfully-parsed item and the error message string is empty. If parsing fails, the Item - * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte - * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is - * too large for the remining buffer, etc.) and the string contains an error message describing the - * problem encountered. - */ -ParseResult parse(const uint8_t* begin, const uint8_t* end); - -/** - * Parse the first CBOR data item (possibly compound) from the byte vector. - * - * Returns a tuple of Item pointer, buffer pointer and error message. If parsing is successful, the - * Item pointer is non-null, the buffer pointer points to the first byte after the - * successfully-parsed item and the error message string is empty. If parsing fails, the Item - * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte - * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is - * too large for the remining buffer, etc.) and the string contains an error message describing the - * problem encountered. - */ -inline ParseResult parse(const std::vector<uint8_t>& encoding) { - return parse(encoding.data(), encoding.data() + encoding.size()); -} - -/** - * Parse the first CBOR data item (possibly compound) from the range [begin, begin + size). - * - * Returns a tuple of Item pointer, buffer pointer and error message. If parsing is successful, the - * Item pointer is non-null, the buffer pointer points to the first byte after the - * successfully-parsed item and the error message string is empty. If parsing fails, the Item - * pointer is null, the buffer pointer points to the first byte that was unparseable (the first byte - * of a data item header that is malformed in some way, e.g. an invalid value, or a length that is - * too large for the remining buffer, etc.) and the string contains an error message describing the - * problem encountered. - */ -inline ParseResult parse(const uint8_t* begin, size_t size) { - return parse(begin, begin + size); -} - -class ParseClient; - -/** - * Parse the CBOR data in the range [begin, end) in streaming fashion, calling methods on the - * provided ParseClient when elements are found. - */ -void parse(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient); - -/** - * Parse the CBOR data in the vector in streaming fashion, calling methods on the - * provided ParseClient when elements are found. - */ -inline void parse(const std::vector<uint8_t>& encoding, ParseClient* parseClient) { - return parse(encoding.data(), encoding.data() + encoding.size(), parseClient); -} - -/** - * A pure interface that callers of the streaming parse functions must implement. - */ -class ParseClient { - public: - virtual ~ParseClient() {} - - /** - * Called when an item is found. The Item pointer points to the found item; use type() and - * the appropriate as*() method to examine the value. hdrBegin points to the first byte of the - * header, valueBegin points to the first byte of the value and end points one past the end of - * the item. In the case of header-only items, such as integers, and compound items (ARRAY, - * MAP or SEMANTIC) whose end has not yet been found, valueBegin and end are equal and point to - * the byte past the header. - * - * Note that for compound types (ARRAY, MAP, and SEMANTIC), the Item will have no content. For - * Map and Array items, the size() method will return a correct value, but the index operators - * are unsafe, and the object cannot be safely compared with another Array/Map. - * - * The method returns a ParseClient*. In most cases "return this;" will be the right answer, - * but a different ParseClient may be returned, which the parser will begin using. If the method - * returns nullptr, parsing will be aborted immediately. - */ - virtual ParseClient* item(std::unique_ptr<Item>& item, const uint8_t* hdrBegin, - const uint8_t* valueBegin, const uint8_t* end) = 0; - - /** - * Called when the end of a compound item (MAP or ARRAY) is found. The item argument will be - * the same one passed to the item() call -- and may be empty if item() moved its value out. - * hdrBegin, valueBegin and end point to the beginning of the item header, the beginning of the - * first contained value, and one past the end of the last contained value, respectively. - * - * Note that the Item will have no content. - * - * As with item(), itemEnd() can change the ParseClient by returning a different one, or end the - * parsing by returning nullptr; - */ - virtual ParseClient* itemEnd(std::unique_ptr<Item>& item, const uint8_t* hdrBegin, - const uint8_t* valueBegin, const uint8_t* end) = 0; - - /** - * Called when parsing encounters an error. position is set to the first unparsed byte (one - * past the last successfully-parsed byte) and errorMessage contains an message explaining what - * sort of error occurred. - */ - virtual void error(const uint8_t* position, const std::string& errorMessage) = 0; -}; - -} // namespace cppbor |