From f383ea9f662565b66b9bebefe52444b94ecf76da Mon Sep 17 00:00:00 2001 From: TennesseeTrash Date: Fri, 26 Sep 2025 01:52:23 +0200 Subject: [PATCH 1/5] Add the ability to print a nearly arbitrary CBOR encoded value --- LibCBOR/CMakeLists.txt | 1 + LibCBOR/Include/CBOR/Decoder.hpp | 54 +++++++---- LibCBOR/Include/CBOR/Printer.hpp | 12 +++ LibCBOR/Source/Decoder.cpp | 157 ++++++++++++++++++++++++++----- LibCBOR/Source/Printer.cpp | 146 ++++++++++++++++++++++++++++ Tests/Main.cpp | 5 + 6 files changed, 332 insertions(+), 43 deletions(-) create mode 100644 LibCBOR/Include/CBOR/Printer.hpp create mode 100644 LibCBOR/Source/Printer.cpp diff --git a/LibCBOR/CMakeLists.txt b/LibCBOR/CMakeLists.txt index 76fda8d..03af6a0 100644 --- a/LibCBOR/CMakeLists.txt +++ b/LibCBOR/CMakeLists.txt @@ -25,4 +25,5 @@ target_sources(LibCBOR "Source/Core.cpp" "Source/Decoder.cpp" "Source/Encoder.cpp" + "Source/Printer.cpp" ) diff --git a/LibCBOR/Include/CBOR/Decoder.hpp b/LibCBOR/Include/CBOR/Decoder.hpp index 40b2096..9d36d69 100644 --- a/LibCBOR/Include/CBOR/Decoder.hpp +++ b/LibCBOR/Include/CBOR/Decoder.hpp @@ -3,6 +3,7 @@ #include "Core.hpp" +#include #include #include @@ -20,6 +21,13 @@ namespace CBOR Item(class Decoder &decoder); public: + static constexpr + std::uint64_t ArgumentIndefinite = std::numeric_limits::max(); + + MajorType GetMajor() const; + MinorType GetMinor() const; + std::uint64_t GetArgument() const; + bool Bool(); Special Special(); @@ -37,13 +45,13 @@ namespace CBOR float Float(); double Double(); - std::span Binary(); - std::string_view String(); - class Binary IndefiniteBinary(); - class String IndefiniteString(); - class Array Array(); - class Map Map(); - class TaggedItem TaggedItem(); + std::span Binary(); + std::string_view String(); + class Binary IndefiniteBinary(); + class String IndefiniteString(); + class Array Array(); + class Map Map(); + class TaggedItem TaggedItem(); private: friend class Decoder; @@ -102,8 +110,8 @@ namespace CBOR Binary(class Decoder &decoder); public: - bool Done(); - std::span Next(); + bool Done(); + std::span Next(); private: friend class Decoder; @@ -175,7 +183,14 @@ namespace CBOR class Decoder { public: - Decoder(std::span buffer); + Decoder(std::span buffer); + + static constexpr + std::uint64_t ArgumentIndefinite = std::numeric_limits::max(); + + MajorType GetMajor() const; + MinorType GetMinor() const; + std::uint64_t GetArgument() const; bool Bool(); Special Special(); @@ -194,14 +209,15 @@ namespace CBOR float Float(); double Double(); - std::span Binary(); - std::string_view String(); - class Binary IndefiniteBinary(); - class String IndefiniteString(); - class Array Array(); - class Map Map(); - class TaggedItem TaggedItem(); + std::span Binary(); + std::string_view String(); + class Binary IndefiniteBinary(); + class String IndefiniteString(); + class Array Array(); + class Map Map(); + class TaggedItem TaggedItem(); + class Item AsItem(); private: friend class Binary; friend class String; @@ -209,8 +225,8 @@ namespace CBOR friend class Map; friend class TaggedItem; - std::size_t mCurrent; - std::span mBuffer; + std::size_t mCurrent; + std::span mBuffer; }; } diff --git a/LibCBOR/Include/CBOR/Printer.hpp b/LibCBOR/Include/CBOR/Printer.hpp new file mode 100644 index 0000000..8efe7df --- /dev/null +++ b/LibCBOR/Include/CBOR/Printer.hpp @@ -0,0 +1,12 @@ +#ifndef LIBCBOR_PRINTER_HPP +#define LIBCBOR_PRINTER_HPP + +#include +#include + +namespace CBOR +{ + void Print(std::ostream &out, std::span buffer); +} + +#endif // LIBCBOR_PRINTER_HPP diff --git a/LibCBOR/Source/Decoder.cpp b/LibCBOR/Source/Decoder.cpp index c0dce05..c15bbb3 100644 --- a/LibCBOR/Source/Decoder.cpp +++ b/LibCBOR/Source/Decoder.cpp @@ -57,7 +57,7 @@ namespace CBOR { static constexpr std::size_t Indefinite = std::numeric_limits::max(); - std::size_t SpaceLeft(std::span buffer, std::size_t offset) + std::size_t SpaceLeft(std::span buffer, std::size_t offset) { if (offset >= buffer.size()) { return 0; @@ -65,7 +65,7 @@ namespace CBOR return buffer.size() - offset; } - void EnsureEnoughSpace(std::span buffer, std::size_t offset, + void EnsureEnoughSpace(std::span buffer, std::size_t offset, std::size_t spaceRequired) { if (SpaceLeft(buffer, offset) < spaceRequired) { @@ -75,19 +75,13 @@ namespace CBOR } } - std::uint8_t Read1B(std::span buffer, std::size_t current) + std::uint8_t Read1B(std::span buffer, std::size_t current) { EnsureEnoughSpace(buffer, current, 1); return buffer[current]; } - std::uint8_t Consume1B(std::span buffer, std::size_t ¤t) - { - EnsureEnoughSpace(buffer, current, 1); - return buffer[current++]; - } - - std::uint16_t Consume2B(std::span buffer, std::size_t ¤t) + std::uint16_t Read2B(std::span buffer, std::size_t current) { EnsureEnoughSpace(buffer, current, 2); std::uint16_t result = 0; @@ -96,7 +90,7 @@ namespace CBOR return NetworkToHost(result); } - std::uint32_t Consume4B(std::span buffer, std::size_t ¤t) + std::uint32_t Read4B(std::span buffer, std::size_t current) { EnsureEnoughSpace(buffer, current, 4); std::uint32_t result = 0; @@ -107,7 +101,48 @@ namespace CBOR return NetworkToHost(result); } - std::uint64_t Consume8B(std::span buffer, std::size_t ¤t) + std::uint64_t Read8B(std::span buffer, std::size_t current) + { + EnsureEnoughSpace(buffer, current, 8); + std::uint64_t result = 0; + result |= std::uint64_t(buffer[current++]) ; + result |= std::uint64_t(buffer[current++]) << 8; + result |= std::uint64_t(buffer[current++]) << 16; + result |= std::uint64_t(buffer[current++]) << 24; + result |= std::uint64_t(buffer[current++]) << 32; + result |= std::uint64_t(buffer[current++]) << 40; + result |= std::uint64_t(buffer[current++]) << 48; + result |= std::uint64_t(buffer[current++]) << 56; + return NetworkToHost(result); + } + + std::uint8_t Consume1B(std::span buffer, std::size_t ¤t) + { + EnsureEnoughSpace(buffer, current, 1); + return buffer[current++]; + } + + std::uint16_t Consume2B(std::span buffer, std::size_t ¤t) + { + EnsureEnoughSpace(buffer, current, 2); + std::uint16_t result = 0; + result |= std::uint16_t(buffer[current++]) ; + result |= std::uint16_t(buffer[current++]) << 8; + return NetworkToHost(result); + } + + std::uint32_t Consume4B(std::span buffer, std::size_t ¤t) + { + EnsureEnoughSpace(buffer, current, 4); + std::uint32_t result = 0; + result |= std::uint32_t(buffer[current++]) ; + result |= std::uint32_t(buffer[current++]) << 8; + result |= std::uint32_t(buffer[current++]) << 16; + result |= std::uint32_t(buffer[current++]) << 24; + return NetworkToHost(result); + } + + std::uint64_t Consume8B(std::span buffer, std::size_t ¤t) { EnsureEnoughSpace(buffer, current, 8); std::uint64_t result = 0; @@ -137,7 +172,8 @@ namespace CBOR return ArgumentPosition(header & std::to_underlying(ArgumentPosition::PositionMask)); } - std::uint64_t ArgumentValue(std::uint8_t header, std::span buffer, std::size_t ¤t) + std::uint64_t ArgumentValue(std::uint8_t header, std::span buffer, + std::size_t ¤t) { ArgumentPosition position = GetArgumentPosition(header); if (std::to_underlying(position) <= 23) { @@ -158,8 +194,30 @@ namespace CBOR } } + std::uint64_t ReadArgumentValue(std::uint8_t header, std::span buffer, + std::size_t current) + { + ArgumentPosition position = GetArgumentPosition(header); + if (std::to_underlying(position) <= 23) { + return std::to_underlying(position); + } + switch (position) { + case ArgumentPosition::Next1B: + return Read1B(buffer, current); + case ArgumentPosition::Next2B: + return Read2B(buffer, current); + case ArgumentPosition::Next4B: + return Read4B(buffer, current); + case ArgumentPosition::Next8B: + return Read8B(buffer, current); + default: + throw MalformedDataError("argument position is reserved for future use, incorrect, " + "or the parser is out of date"); + } + } + template - T ExtractUnsigned(std::span buffer, std::size_t ¤t) + T ExtractUnsigned(std::span buffer, std::size_t ¤t) { static constexpr std::uint64_t maxValue = std::numeric_limits::max(); @@ -214,7 +272,8 @@ namespace CBOR // Note(3011): In this case it includes zero, even though zero is not technically positive. template - T SignedPositive(std::uint8_t header, std::span buffer, std::size_t ¤t) + T SignedPositive(std::uint8_t header, std::span buffer, + std::size_t ¤t) { static constexpr std::uint64_t maxValue = std::numeric_limits::max(); @@ -266,7 +325,8 @@ namespace CBOR } template - T SignedNegative(std::uint8_t header, std::span buffer, std::size_t ¤t) + T SignedNegative(std::uint8_t header, std::span buffer, + std::size_t ¤t) { static constexpr auto actualMin = std::numeric_limits::min(); static constexpr std::uint64_t minValue = -std::int64_t(actualMin + 1); @@ -319,7 +379,7 @@ namespace CBOR } template - T ExtractSigned(std::span buffer, std::size_t ¤t) + T ExtractSigned(std::span buffer, std::size_t ¤t) { std::uint8_t header = Consume1B(buffer, current); MajorType major = GetMajorType(header); @@ -335,15 +395,17 @@ namespace CBOR } } - std::span ExtractBinary(std::size_t size, std::span buffer, std::size_t ¤t) + std::span + ExtractBinary(std::size_t size, std::span buffer, std::size_t ¤t) { EnsureEnoughSpace(buffer, current, size); - std::span result(buffer.data() + current, size); + std::span result(buffer.data() + current, size); current += size; return result; } - std::string_view ExtractString(std::size_t size, std::span buffer, std::size_t ¤t) + std::string_view ExtractString(std::size_t size, std::span buffer, + std::size_t ¤t) { EnsureEnoughSpace(buffer, current, size); std::string_view result(reinterpret_cast(buffer.data() + current), size); @@ -356,6 +418,21 @@ namespace CBOR : mDecoder(&decoder) {} + MajorType Item::GetMajor() const + { + return mDecoder->GetMajor(); + } + + MinorType Item::GetMinor() const + { + return mDecoder->GetMinor(); + } + + std::uint64_t Item::GetArgument() const + { + return mDecoder->GetArgument(); + } + bool Item::Bool() { return mDecoder->Bool(); @@ -416,7 +493,7 @@ namespace CBOR return mDecoder->Double(); } - std::span Item::Binary() + std::span Item::Binary() { return mDecoder->Binary(); } @@ -531,7 +608,7 @@ namespace CBOR return mDone; } - std::span Binary::Next() + std::span Binary::Next() { if (!mHeaderParsed) { std::uint8_t header = Consume1B(mDecoder->mBuffer, mDecoder->mCurrent); @@ -767,10 +844,37 @@ namespace CBOR return KeyValue(*mDecoder); } - Decoder::Decoder(std::span buffer) + Decoder::Decoder(std::span buffer) : mCurrent(0), mBuffer(buffer) {} + MajorType Decoder::GetMajor() const + { + std::uint8_t header = Read1B(mBuffer, mCurrent); + return GetMajorType(header); + } + + MinorType Decoder::GetMinor() const + { + std::uint8_t header = Read1B(mBuffer, mCurrent); + if (GetMajorType(header) != MajorType::Other) { + throw InvalidUsageError("use the GetArgument function instead"); + } + return GetMinorType(header); + } + + std::uint64_t Decoder::GetArgument() const + { + std::uint8_t header = Read1B(mBuffer, mCurrent); + if (GetMajorType(header) != MajorType::Other) { + throw InvalidUsageError("use the GetMinor function instead"); + } + if (GetArgumentPosition(header) == ArgumentPosition::Indefinite) { + return Decoder::ArgumentIndefinite; + } + return ReadArgumentValue(header, mBuffer, mCurrent); + } + bool Decoder::Bool() { std::uint8_t header = Consume1B(mBuffer, mCurrent); @@ -881,7 +985,7 @@ namespace CBOR throw TypeMismatchError("double", ToString(major)); } - std::span Decoder::Binary() + std::span Decoder::Binary() { std::uint8_t header = Consume1B(mBuffer, mCurrent); MajorType major = GetMajorType(header); @@ -937,4 +1041,9 @@ namespace CBOR { return { *this }; } + + Item Decoder::AsItem() + { + return { *this }; + } } diff --git a/LibCBOR/Source/Printer.cpp b/LibCBOR/Source/Printer.cpp new file mode 100644 index 0000000..89716c3 --- /dev/null +++ b/LibCBOR/Source/Printer.cpp @@ -0,0 +1,146 @@ +#include "Printer.hpp" + +#include "Core.hpp" +#include "Decoder.hpp" + +#include +#include + +namespace CBOR +{ + namespace + { + void Print(std::ostream &out, std::size_t depth, CBOR::Item item); + + char AsChar(std::uint8_t nibble) + { + if (nibble < 10) { + return nibble + '0'; + } + if (nibble < 16) { + return nibble + 'A'; + } + return 'X'; + } + + std::string AsString(std::uint8_t byte) + { + std::string result; + result.push_back(AsChar((byte >> 4) & 15)); + result.push_back(AsChar((byte ) & 15)); + return result; + } + + void PrintBinary(std::ostream &out, CBOR::Binary binary) + { + out << "b\""; + while (!binary.Done()) { + std::span chunk = binary.Next(); + for (std::uint8_t byte: chunk) { + out << AsString(byte); + } + } + out << '\"'; + } + + void PrintString(std::ostream &out, CBOR::String string) + { + out << '\"'; + while (!string.Done()) { + out << string.Next(); + } + out << '\"'; + } + + void PrintArray(std::ostream &out, std::size_t depth, CBOR::Array array) + { + out << "[\n"; + while (!array.Done()) { + out << std::string((depth + 1) * 4, ' '); + Print(out, depth + 1, array.Next()); + out << ",\n"; + } + out << std::string(depth * 4, ' ') << "]"; + } + + void PrintMap(std::ostream &out, std::size_t depth, CBOR::Map map) + { + out << "{\n"; + while (!map.Done()) { + CBOR::KeyValue kv = map.Next(); + out << std::string((depth + 1) * 4, ' '); + Print(out, depth + 1, kv.Key()); + out << ": "; + Print(out, depth + 1, kv.Value()); + out << ",\n"; + } + out << std::string(depth * 4, ' ') << "}"; + } + + void PrintTagged(std::ostream &out, std::size_t depth, CBOR::TaggedItem item) + { + out << item.Tag(); + out << '('; + Print(out, depth, item.Item()); + out << ')'; + } + + void Print(std::ostream &out, std::size_t depth, CBOR::Item item) + { + switch (item.GetMajor()) { + case MajorType::Unsigned: + out << item.Uint64(); + break; + case MajorType::Negative: + out << item.Int64(); + break; + case MajorType::Binary: + PrintBinary(out, item.IndefiniteBinary()); + break; + case MajorType::String: + PrintString(out, item.IndefiniteString()); + break; + case MajorType::Array: + PrintArray(out, depth, item.Array()); + break; + case MajorType::Map: + PrintMap(out, depth, item.Map()); + break; + case MajorType::Tag: + PrintTagged(out, depth, item.TaggedItem()); + break; + case MajorType::Other: + switch (item.GetMinor()) { + case MinorType::False: + out << "false"; + break; + case MinorType::True: + out << "true"; + break; + case MinorType::Null: + out << "null"; + break; + case MinorType::Undefined: + out << "undefined"; + break; + case MinorType::Float: + std::print(out, "{:.6f}", item.Float()); + break; + case MinorType::Double: + std::print(out, "{:.15f}", item.Double()); + break; + default: + out << "invalid_value"; + break; + } + } + } + } + + void Print(std::ostream &out, std::span buffer) + { + CBOR::Decoder dec(buffer); + Print(out, 0, dec.AsItem()); + out << '\n'; + } +} diff --git a/Tests/Main.cpp b/Tests/Main.cpp index 5b51912..e0424ef 100644 --- a/Tests/Main.cpp +++ b/Tests/Main.cpp @@ -1,7 +1,9 @@ #include "CBOR/Decoder.hpp" #include "CBOR/Encoder.hpp" +#include "Cbor/Printer.hpp" #include #include +#include #include #include #include @@ -206,6 +208,9 @@ int main() SomeStruct result1 = Decode1(std::span(buffer.data(), encodedSize)); SomeStruct result2 = Decode2(std::span(buffer.data(), encodedSize)); + std::println("JSON-esque serialization:"); + CBOR::Print(std::cout, std::span(buffer.data(), encodedSize)); + Compare(expected, result1); Compare(expected, result2); std::println("The test has been completed successfully."); From 9bda00793d2ed25e9e55766e12753299a825a951 Mon Sep 17 00:00:00 2001 From: TennesseeTrash Date: Fri, 26 Sep 2025 01:54:28 +0200 Subject: [PATCH 2/5] Add the ability to print a nested item --- LibCBOR/Include/CBOR/Printer.hpp | 3 +++ LibCBOR/Source/Printer.cpp | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/LibCBOR/Include/CBOR/Printer.hpp b/LibCBOR/Include/CBOR/Printer.hpp index 8efe7df..a944b58 100644 --- a/LibCBOR/Include/CBOR/Printer.hpp +++ b/LibCBOR/Include/CBOR/Printer.hpp @@ -1,12 +1,15 @@ #ifndef LIBCBOR_PRINTER_HPP #define LIBCBOR_PRINTER_HPP +#include "Decoder.hpp" + #include #include namespace CBOR { void Print(std::ostream &out, std::span buffer); + void Print(std::ostream &out, CBOR::Item item); } #endif // LIBCBOR_PRINTER_HPP diff --git a/LibCBOR/Source/Printer.cpp b/LibCBOR/Source/Printer.cpp index 89716c3..f537da6 100644 --- a/LibCBOR/Source/Printer.cpp +++ b/LibCBOR/Source/Printer.cpp @@ -143,4 +143,9 @@ namespace CBOR Print(out, 0, dec.AsItem()); out << '\n'; } + + void Print(std::ostream &out, CBOR::Item item) + { + Print(out, 0, std::move(item)); + } } From d5680eaccb52da5bd1fecad44db8e488b9d146a0 Mon Sep 17 00:00:00 2001 From: TennesseeTrash Date: Fri, 26 Sep 2025 02:06:11 +0200 Subject: [PATCH 3/5] Add trailing newline to item print --- LibCBOR/Source/Printer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/LibCBOR/Source/Printer.cpp b/LibCBOR/Source/Printer.cpp index f537da6..49a1e70 100644 --- a/LibCBOR/Source/Printer.cpp +++ b/LibCBOR/Source/Printer.cpp @@ -147,5 +147,6 @@ namespace CBOR void Print(std::ostream &out, CBOR::Item item) { Print(out, 0, std::move(item)); + out << '\n'; } } From ca8750aab2ec52857f9eb0b93e6debee83b96269 Mon Sep 17 00:00:00 2001 From: TennesseeTrash Date: Fri, 26 Sep 2025 02:16:52 +0200 Subject: [PATCH 4/5] Refactors - Refer to std::span as Buffer - Refer to std::span as ConstBuffer - Use more consistent naming for members These were mostly added so the function prototypes look a bit better. --- LibCBOR/Include/CBOR/Core.hpp | 4 ++ LibCBOR/Include/CBOR/Decoder.hpp | 41 +++++++------- LibCBOR/Include/CBOR/Encoder.hpp | 16 +++--- LibCBOR/Include/CBOR/Printer.hpp | 6 +- LibCBOR/Source/Decoder.cpp | 53 ++++++++---------- LibCBOR/Source/Encoder.cpp | 94 ++++++++++++++++---------------- LibCBOR/Source/Printer.cpp | 2 +- 7 files changed, 106 insertions(+), 110 deletions(-) diff --git a/LibCBOR/Include/CBOR/Core.hpp b/LibCBOR/Include/CBOR/Core.hpp index ab39203..08fc5f3 100644 --- a/LibCBOR/Include/CBOR/Core.hpp +++ b/LibCBOR/Include/CBOR/Core.hpp @@ -3,6 +3,7 @@ #include #include +#include #include namespace CBOR @@ -148,6 +149,9 @@ namespace CBOR public: using std::runtime_error::runtime_error; }; + + using Buffer = std::span; + using ConstBuffer = std::span; } #endif // LIBCBOR_CORE_HPP diff --git a/LibCBOR/Include/CBOR/Decoder.hpp b/LibCBOR/Include/CBOR/Decoder.hpp index 9d36d69..9c3d1e2 100644 --- a/LibCBOR/Include/CBOR/Decoder.hpp +++ b/LibCBOR/Include/CBOR/Decoder.hpp @@ -4,7 +4,6 @@ #include "Core.hpp" #include -#include #include namespace CBOR @@ -45,13 +44,13 @@ namespace CBOR float Float(); double Double(); - std::span Binary(); - std::string_view String(); - class Binary IndefiniteBinary(); - class String IndefiniteString(); - class Array Array(); - class Map Map(); - class TaggedItem TaggedItem(); + ConstBuffer Binary(); + std::string_view String(); + class Binary IndefiniteBinary(); + class String IndefiniteString(); + class Array Array(); + class Map Map(); + class TaggedItem TaggedItem(); private: friend class Decoder; @@ -110,8 +109,8 @@ namespace CBOR Binary(class Decoder &decoder); public: - bool Done(); - std::span Next(); + bool Done(); + ConstBuffer Next(); private: friend class Decoder; @@ -183,7 +182,7 @@ namespace CBOR class Decoder { public: - Decoder(std::span buffer); + Decoder(ConstBuffer buffer); static constexpr std::uint64_t ArgumentIndefinite = std::numeric_limits::max(); @@ -209,15 +208,15 @@ namespace CBOR float Float(); double Double(); - std::span Binary(); - std::string_view String(); - class Binary IndefiniteBinary(); - class String IndefiniteString(); - class Array Array(); - class Map Map(); - class TaggedItem TaggedItem(); + ConstBuffer Binary(); + std::string_view String(); + class Binary IndefiniteBinary(); + class String IndefiniteString(); + class Array Array(); + class Map Map(); + class TaggedItem TaggedItem(); - class Item AsItem(); + class Item AsItem(); private: friend class Binary; friend class String; @@ -225,8 +224,8 @@ namespace CBOR friend class Map; friend class TaggedItem; - std::size_t mCurrent; - std::span mBuffer; + std::size_t mCurrent; + ConstBuffer mBuffer; }; } diff --git a/LibCBOR/Include/CBOR/Encoder.hpp b/LibCBOR/Include/CBOR/Encoder.hpp index ac63692..9b22bde 100644 --- a/LibCBOR/Include/CBOR/Encoder.hpp +++ b/LibCBOR/Include/CBOR/Encoder.hpp @@ -21,7 +21,7 @@ namespace CBOR class EncoderBuffer { public: - EncoderBuffer(std::span buffer); + EncoderBuffer(Buffer buffer); EncoderBuffer(std::vector &buffer); template @@ -39,7 +39,7 @@ namespace CBOR void Write(std::uint16_t value); void Write(std::uint32_t value); void Write(std::uint64_t value); - void Write(std::span value); + void Write(Buffer value); void Write(std::string_view value); std::size_t Size() const; @@ -51,14 +51,14 @@ namespace CBOR void Write(std::uint16_t value); void Write(std::uint32_t value); void Write(std::uint64_t value); - void Write(std::span value); + void Write(Buffer value); void Write(std::string_view value); std::size_t Size() const; void EnsureSpace(std::size_t size) const; - std::size_t Current; - std::span Buffer; + std::size_t mCurrent; + Buffer mBuffer; }; struct DynamicBuffer @@ -67,12 +67,12 @@ namespace CBOR void Write(std::uint16_t value); void Write(std::uint32_t value); void Write(std::uint64_t value); - void Write(std::span value); + void Write(Buffer value); void Write(std::string_view value); std::size_t Size() const; - std::vector *Buffer; + std::vector *mBuffer; }; using BufferType = std::variant; @@ -108,7 +108,7 @@ namespace CBOR void Encode(float value); void Encode(double value); - void Encode(std::span value); + void Encode(Buffer value); void Encode(const char *value); void Encode(std::string_view value); diff --git a/LibCBOR/Include/CBOR/Printer.hpp b/LibCBOR/Include/CBOR/Printer.hpp index a944b58..b4550ea 100644 --- a/LibCBOR/Include/CBOR/Printer.hpp +++ b/LibCBOR/Include/CBOR/Printer.hpp @@ -1,15 +1,15 @@ #ifndef LIBCBOR_PRINTER_HPP #define LIBCBOR_PRINTER_HPP +#include "Core.hpp" #include "Decoder.hpp" #include -#include namespace CBOR { - void Print(std::ostream &out, std::span buffer); - void Print(std::ostream &out, CBOR::Item item); + void Print(std::ostream &out, ConstBuffer buffer); + void Print(std::ostream &out, Item item); } #endif // LIBCBOR_PRINTER_HPP diff --git a/LibCBOR/Source/Decoder.cpp b/LibCBOR/Source/Decoder.cpp index c15bbb3..706efb0 100644 --- a/LibCBOR/Source/Decoder.cpp +++ b/LibCBOR/Source/Decoder.cpp @@ -57,7 +57,7 @@ namespace CBOR { static constexpr std::size_t Indefinite = std::numeric_limits::max(); - std::size_t SpaceLeft(std::span buffer, std::size_t offset) + std::size_t SpaceLeft(ConstBuffer buffer, std::size_t offset) { if (offset >= buffer.size()) { return 0; @@ -65,8 +65,7 @@ namespace CBOR return buffer.size() - offset; } - void EnsureEnoughSpace(std::span buffer, std::size_t offset, - std::size_t spaceRequired) + void EnsureEnoughSpace(ConstBuffer buffer, std::size_t offset, std::size_t spaceRequired) { if (SpaceLeft(buffer, offset) < spaceRequired) { using namespace std::string_view_literals; @@ -75,13 +74,13 @@ namespace CBOR } } - std::uint8_t Read1B(std::span buffer, std::size_t current) + std::uint8_t Read1B(ConstBuffer buffer, std::size_t current) { EnsureEnoughSpace(buffer, current, 1); return buffer[current]; } - std::uint16_t Read2B(std::span buffer, std::size_t current) + std::uint16_t Read2B(ConstBuffer buffer, std::size_t current) { EnsureEnoughSpace(buffer, current, 2); std::uint16_t result = 0; @@ -90,7 +89,7 @@ namespace CBOR return NetworkToHost(result); } - std::uint32_t Read4B(std::span buffer, std::size_t current) + std::uint32_t Read4B(ConstBuffer buffer, std::size_t current) { EnsureEnoughSpace(buffer, current, 4); std::uint32_t result = 0; @@ -101,7 +100,7 @@ namespace CBOR return NetworkToHost(result); } - std::uint64_t Read8B(std::span buffer, std::size_t current) + std::uint64_t Read8B(ConstBuffer buffer, std::size_t current) { EnsureEnoughSpace(buffer, current, 8); std::uint64_t result = 0; @@ -116,13 +115,13 @@ namespace CBOR return NetworkToHost(result); } - std::uint8_t Consume1B(std::span buffer, std::size_t ¤t) + std::uint8_t Consume1B(ConstBuffer buffer, std::size_t ¤t) { EnsureEnoughSpace(buffer, current, 1); return buffer[current++]; } - std::uint16_t Consume2B(std::span buffer, std::size_t ¤t) + std::uint16_t Consume2B(ConstBuffer buffer, std::size_t ¤t) { EnsureEnoughSpace(buffer, current, 2); std::uint16_t result = 0; @@ -131,7 +130,7 @@ namespace CBOR return NetworkToHost(result); } - std::uint32_t Consume4B(std::span buffer, std::size_t ¤t) + std::uint32_t Consume4B(ConstBuffer buffer, std::size_t ¤t) { EnsureEnoughSpace(buffer, current, 4); std::uint32_t result = 0; @@ -142,7 +141,7 @@ namespace CBOR return NetworkToHost(result); } - std::uint64_t Consume8B(std::span buffer, std::size_t ¤t) + std::uint64_t Consume8B(ConstBuffer buffer, std::size_t ¤t) { EnsureEnoughSpace(buffer, current, 8); std::uint64_t result = 0; @@ -172,8 +171,7 @@ namespace CBOR return ArgumentPosition(header & std::to_underlying(ArgumentPosition::PositionMask)); } - std::uint64_t ArgumentValue(std::uint8_t header, std::span buffer, - std::size_t ¤t) + std::uint64_t ArgumentValue(std::uint8_t header, ConstBuffer buffer, std::size_t ¤t) { ArgumentPosition position = GetArgumentPosition(header); if (std::to_underlying(position) <= 23) { @@ -194,8 +192,7 @@ namespace CBOR } } - std::uint64_t ReadArgumentValue(std::uint8_t header, std::span buffer, - std::size_t current) + std::uint64_t ReadArgumentValue(std::uint8_t header, ConstBuffer buffer, std::size_t current) { ArgumentPosition position = GetArgumentPosition(header); if (std::to_underlying(position) <= 23) { @@ -217,7 +214,7 @@ namespace CBOR } template - T ExtractUnsigned(std::span buffer, std::size_t ¤t) + T ExtractUnsigned(ConstBuffer buffer, std::size_t ¤t) { static constexpr std::uint64_t maxValue = std::numeric_limits::max(); @@ -272,8 +269,7 @@ namespace CBOR // Note(3011): In this case it includes zero, even though zero is not technically positive. template - T SignedPositive(std::uint8_t header, std::span buffer, - std::size_t ¤t) + T SignedPositive(std::uint8_t header, ConstBuffer buffer, std::size_t ¤t) { static constexpr std::uint64_t maxValue = std::numeric_limits::max(); @@ -325,8 +321,7 @@ namespace CBOR } template - T SignedNegative(std::uint8_t header, std::span buffer, - std::size_t ¤t) + T SignedNegative(std::uint8_t header, ConstBuffer buffer, std::size_t ¤t) { static constexpr auto actualMin = std::numeric_limits::min(); static constexpr std::uint64_t minValue = -std::int64_t(actualMin + 1); @@ -379,7 +374,7 @@ namespace CBOR } template - T ExtractSigned(std::span buffer, std::size_t ¤t) + T ExtractSigned(ConstBuffer buffer, std::size_t ¤t) { std::uint8_t header = Consume1B(buffer, current); MajorType major = GetMajorType(header); @@ -395,17 +390,15 @@ namespace CBOR } } - std::span - ExtractBinary(std::size_t size, std::span buffer, std::size_t ¤t) + ConstBuffer ExtractBinary(std::size_t size, ConstBuffer buffer, std::size_t ¤t) { EnsureEnoughSpace(buffer, current, size); - std::span result(buffer.data() + current, size); + ConstBuffer result(buffer.data() + current, size); current += size; return result; } - std::string_view ExtractString(std::size_t size, std::span buffer, - std::size_t ¤t) + std::string_view ExtractString(std::size_t size, ConstBuffer buffer, std::size_t ¤t) { EnsureEnoughSpace(buffer, current, size); std::string_view result(reinterpret_cast(buffer.data() + current), size); @@ -493,7 +486,7 @@ namespace CBOR return mDecoder->Double(); } - std::span Item::Binary() + ConstBuffer Item::Binary() { return mDecoder->Binary(); } @@ -608,7 +601,7 @@ namespace CBOR return mDone; } - std::span Binary::Next() + ConstBuffer Binary::Next() { if (!mHeaderParsed) { std::uint8_t header = Consume1B(mDecoder->mBuffer, mDecoder->mCurrent); @@ -844,7 +837,7 @@ namespace CBOR return KeyValue(*mDecoder); } - Decoder::Decoder(std::span buffer) + Decoder::Decoder(ConstBuffer buffer) : mCurrent(0), mBuffer(buffer) {} @@ -985,7 +978,7 @@ namespace CBOR throw TypeMismatchError("double", ToString(major)); } - std::span Decoder::Binary() + ConstBuffer Decoder::Binary() { std::uint8_t header = Consume1B(mBuffer, mCurrent); MajorType major = GetMajorType(header); diff --git a/LibCBOR/Source/Encoder.cpp b/LibCBOR/Source/Encoder.cpp index e61a8ac..f21a177 100644 --- a/LibCBOR/Source/Encoder.cpp +++ b/LibCBOR/Source/Encoder.cpp @@ -76,16 +76,16 @@ namespace CBOR } } - EncoderBuffer::EncoderBuffer(std::span buffer) - : mBuffer(FixedBuffer { .Current = 0, .Buffer = buffer, }) + EncoderBuffer::EncoderBuffer(Buffer buffer) + : mBuffer(FixedBuffer { .mCurrent = 0, .mBuffer = buffer, }) {} EncoderBuffer::EncoderBuffer(std::vector &buffer) - : mBuffer(DynamicBuffer { .Buffer = &buffer }) + : mBuffer(DynamicBuffer { .mBuffer = &buffer }) {} EncoderBuffer::EncoderBuffer(EncoderBuffer &&other) - : mBuffer(std::exchange(other.mBuffer, FixedBuffer { .Current = 0, .Buffer = {}, })) + : mBuffer(std::exchange(other.mBuffer, FixedBuffer { .mCurrent = 0, .mBuffer = {}, })) {} void EncoderBuffer::Write(std::uint8_t value) @@ -120,7 +120,7 @@ namespace CBOR }, mBuffer); } - void EncoderBuffer::Write(std::span value) + void EncoderBuffer::Write(Buffer value) { std::visit(Overload { [value] (FixedBuffer &buffer) { buffer.Write(value); }, @@ -147,7 +147,7 @@ namespace CBOR void EncoderBuffer::FixedBuffer::Write(std::uint8_t value) { EnsureSpace(1); - Buffer[Current++] = value; + mBuffer[mCurrent++] = value; } void EncoderBuffer::FixedBuffer::Write(std::uint16_t value) @@ -155,8 +155,8 @@ namespace CBOR EnsureSpace(2); static constexpr std::uint16_t mask = 0x00'FF; std::uint16_t network = HostToNetwork(value); - Buffer[Current++] = static_cast((network ) & mask); - Buffer[Current++] = static_cast((network >> 8) & mask); + mBuffer[mCurrent++] = static_cast((network ) & mask); + mBuffer[mCurrent++] = static_cast((network >> 8) & mask); } void EncoderBuffer::FixedBuffer::Write(std::uint32_t value) @@ -164,10 +164,10 @@ namespace CBOR EnsureSpace(4); static constexpr std::uint32_t mask = 0x00'00'00'FF; std::uint32_t network = HostToNetwork(value); - Buffer[Current++] = static_cast((network ) & mask); - Buffer[Current++] = static_cast((network >> 8) & mask); - Buffer[Current++] = static_cast((network >> 16) & mask); - Buffer[Current++] = static_cast((network >> 24) & mask); + mBuffer[mCurrent++] = static_cast((network ) & mask); + mBuffer[mCurrent++] = static_cast((network >> 8) & mask); + mBuffer[mCurrent++] = static_cast((network >> 16) & mask); + mBuffer[mCurrent++] = static_cast((network >> 24) & mask); } void EncoderBuffer::FixedBuffer::Write(std::uint64_t value) @@ -175,33 +175,33 @@ namespace CBOR EnsureSpace(8); static constexpr std::uint64_t mask = 0x00'00'00'00'00'00'00'FF; std::uint64_t network = HostToNetwork(value); - Buffer[Current++] = static_cast((network ) & mask); - Buffer[Current++] = static_cast((network >> 8) & mask); - Buffer[Current++] = static_cast((network >> 16) & mask); - Buffer[Current++] = static_cast((network >> 24) & mask); - Buffer[Current++] = static_cast((network >> 32) & mask); - Buffer[Current++] = static_cast((network >> 40) & mask); - Buffer[Current++] = static_cast((network >> 48) & mask); - Buffer[Current++] = static_cast((network >> 56) & mask); + mBuffer[mCurrent++] = static_cast((network ) & mask); + mBuffer[mCurrent++] = static_cast((network >> 8) & mask); + mBuffer[mCurrent++] = static_cast((network >> 16) & mask); + mBuffer[mCurrent++] = static_cast((network >> 24) & mask); + mBuffer[mCurrent++] = static_cast((network >> 32) & mask); + mBuffer[mCurrent++] = static_cast((network >> 40) & mask); + mBuffer[mCurrent++] = static_cast((network >> 48) & mask); + mBuffer[mCurrent++] = static_cast((network >> 56) & mask); } - void EncoderBuffer::FixedBuffer::Write(std::span value) + void EncoderBuffer::FixedBuffer::Write(Buffer value) { EnsureSpace(value.size()); - std::memcpy(Buffer.data() + Current, value.data(), value.size()); - Current += value.size(); + std::memcpy(mBuffer.data() + mCurrent, value.data(), value.size()); + mCurrent += value.size(); } void EncoderBuffer::FixedBuffer::Write(std::string_view value) { EnsureSpace(value.size()); - std::memcpy(Buffer.data() + Current, value.data(), value.size()); - Current += value.size(); + std::memcpy(mBuffer.data() + mCurrent, value.data(), value.size()); + mCurrent += value.size(); } void EncoderBuffer::FixedBuffer::EnsureSpace(std::size_t size) const { - std::size_t spaceLeft = Current > Buffer.size() ? 0 : Buffer.size() - Current; + std::size_t spaceLeft = mCurrent > mBuffer.size() ? 0 : mBuffer.size() - mCurrent; if (size > spaceLeft) { throw NotEnoughSpace(spaceLeft, size); @@ -210,59 +210,59 @@ namespace CBOR std::size_t EncoderBuffer::FixedBuffer::Size() const { - return Current; + return mCurrent; } void EncoderBuffer::DynamicBuffer::Write(std::uint8_t value) { - Buffer->push_back(value); + mBuffer->push_back(value); } void EncoderBuffer::DynamicBuffer::Write(std::uint16_t value) { static constexpr std::uint16_t mask = 0x00'FF; std::uint16_t network = HostToNetwork(value); - Buffer->push_back(static_cast((network ) & mask)); - Buffer->push_back(static_cast((network >> 8) & mask)); + mBuffer->push_back(static_cast((network ) & mask)); + mBuffer->push_back(static_cast((network >> 8) & mask)); } void EncoderBuffer::DynamicBuffer::Write(std::uint32_t value) { static constexpr std::uint32_t mask = 0x00'00'00'FF; std::uint32_t network = HostToNetwork(value); - Buffer->push_back(static_cast((network ) & mask)); - Buffer->push_back(static_cast((network >> 8) & mask)); - Buffer->push_back(static_cast((network >> 16) & mask)); - Buffer->push_back(static_cast((network >> 24) & mask)); + mBuffer->push_back(static_cast((network ) & mask)); + mBuffer->push_back(static_cast((network >> 8) & mask)); + mBuffer->push_back(static_cast((network >> 16) & mask)); + mBuffer->push_back(static_cast((network >> 24) & mask)); } void EncoderBuffer::DynamicBuffer::Write(std::uint64_t value) { static constexpr std::uint64_t mask = 0x00'00'00'00'00'00'00'FF; std::uint64_t network = HostToNetwork(value); - Buffer->push_back(static_cast((network ) & mask)); - Buffer->push_back(static_cast((network >> 8) & mask)); - Buffer->push_back(static_cast((network >> 16) & mask)); - Buffer->push_back(static_cast((network >> 24) & mask)); - Buffer->push_back(static_cast((network >> 32) & mask)); - Buffer->push_back(static_cast((network >> 40) & mask)); - Buffer->push_back(static_cast((network >> 48) & mask)); - Buffer->push_back(static_cast((network >> 56) & mask)); + mBuffer->push_back(static_cast((network ) & mask)); + mBuffer->push_back(static_cast((network >> 8) & mask)); + mBuffer->push_back(static_cast((network >> 16) & mask)); + mBuffer->push_back(static_cast((network >> 24) & mask)); + mBuffer->push_back(static_cast((network >> 32) & mask)); + mBuffer->push_back(static_cast((network >> 40) & mask)); + mBuffer->push_back(static_cast((network >> 48) & mask)); + mBuffer->push_back(static_cast((network >> 56) & mask)); } - void EncoderBuffer::DynamicBuffer::Write(std::span value) + void EncoderBuffer::DynamicBuffer::Write(Buffer value) { - Buffer->append_range(value); + mBuffer->append_range(value); } void EncoderBuffer::DynamicBuffer::Write(std::string_view value) { - Buffer->append_range(value); + mBuffer->append_range(value); } std::size_t EncoderBuffer::DynamicBuffer::Size() const { - return Buffer->size(); + return mBuffer->size(); } BasicEncoder::BasicEncoder(EncoderBuffer buffer) @@ -447,7 +447,7 @@ namespace CBOR mBuffer.Write(std::bit_cast(value)); } - void BasicEncoder::Encode(std::span value) + void BasicEncoder::Encode(Buffer value) { WriteHeader(mBuffer, MajorType::Binary, value.size()); mBuffer.Write(value); diff --git a/LibCBOR/Source/Printer.cpp b/LibCBOR/Source/Printer.cpp index 49a1e70..bcc10bf 100644 --- a/LibCBOR/Source/Printer.cpp +++ b/LibCBOR/Source/Printer.cpp @@ -137,7 +137,7 @@ namespace CBOR } } - void Print(std::ostream &out, std::span buffer) + void Print(std::ostream &out, ConstBuffer buffer) { CBOR::Decoder dec(buffer); Print(out, 0, dec.AsItem()); From e06b85632aa48c173a42d4f34e79cc1ad9b2280c Mon Sep 17 00:00:00 2001 From: TennesseeTrash Date: Fri, 26 Sep 2025 02:54:05 +0200 Subject: [PATCH 5/5] Make all decoder components move-only --- LibCBOR/Include/CBOR/Decoder.hpp | 55 ++++++++++++++ LibCBOR/Source/Decoder.cpp | 118 +++++++++++++++++++++++++++++++ Tests/Main.cpp | 2 +- 3 files changed, 174 insertions(+), 1 deletion(-) diff --git a/LibCBOR/Include/CBOR/Decoder.hpp b/LibCBOR/Include/CBOR/Decoder.hpp index 9c3d1e2..b3c957e 100644 --- a/LibCBOR/Include/CBOR/Decoder.hpp +++ b/LibCBOR/Include/CBOR/Decoder.hpp @@ -19,7 +19,14 @@ namespace CBOR private: Item(class Decoder &decoder); + Item(const Item &) = delete; + Item &operator=(const Item &) = delete; + public: + Item(Item &&other); + Item &operator=(Item &&other); + ~Item() = default; + static constexpr std::uint64_t ArgumentIndefinite = std::numeric_limits::max(); @@ -66,7 +73,14 @@ namespace CBOR private: TaggedItem(class Decoder &decoder); + TaggedItem(const TaggedItem &) = delete; + TaggedItem &operator=(const TaggedItem &) = delete; + public: + TaggedItem(TaggedItem &&other); + TaggedItem &operator=(TaggedItem &&other); + ~TaggedItem() = default; + std::uint64_t Tag(); Item Item(); @@ -87,7 +101,14 @@ namespace CBOR private: KeyValue(class Decoder &decoder); + KeyValue(const KeyValue &) = delete; + KeyValue &operator=(const KeyValue &) = delete; + public: + KeyValue(KeyValue &&other); + KeyValue &operator=(KeyValue &&other); + ~KeyValue() = default; + Item Key(); Item Value(); private: @@ -108,7 +129,14 @@ namespace CBOR private: Binary(class Decoder &decoder); + Binary(const Binary &) = delete; + Binary &operator=(const Binary &) = delete; + public: + Binary(Binary &&other); + Binary &operator=(Binary &&other); + ~Binary() = default; + bool Done(); ConstBuffer Next(); @@ -126,7 +154,14 @@ namespace CBOR private: String(class Decoder &decoder); + String(const String &) = delete; + String &operator=(const String &) = delete; + public: + String(String &&other); + String &operator=(String &&other); + ~String() = default; + bool Done(); std::string_view Next(); @@ -144,7 +179,14 @@ namespace CBOR private: Array(class Decoder &decoder); + Array(const Array &) = delete; + Array &operator=(const Array &) = delete; + public: + Array(Array &&other); + Array &operator=(Array &&other); + ~Array() = default; + bool Done(); Item Next(); @@ -164,7 +206,14 @@ namespace CBOR private: Map(class Decoder &decoder); + Map(const Map &) = delete; + Map &operator=(const Map &) = delete; + public: + Map(Map &&other); + Map &operator=(Map &&other); + ~Map() = default; + bool Done(); KeyValue Next(); @@ -184,6 +233,12 @@ namespace CBOR public: Decoder(ConstBuffer buffer); + Decoder(const Decoder &) = delete; + Decoder &operator=(const Decoder &) = delete; + Decoder(Decoder &&other); + Decoder &operator=(Decoder &&other); + ~Decoder() = default; + static constexpr std::uint64_t ArgumentIndefinite = std::numeric_limits::max(); diff --git a/LibCBOR/Source/Decoder.cpp b/LibCBOR/Source/Decoder.cpp index 706efb0..dae31e0 100644 --- a/LibCBOR/Source/Decoder.cpp +++ b/LibCBOR/Source/Decoder.cpp @@ -411,6 +411,16 @@ namespace CBOR : mDecoder(&decoder) {} + Item::Item(Item &&other) + : mDecoder(std::exchange(other.mDecoder, nullptr)) + {} + + Item &Item::operator=(Item &&other) + { + mDecoder = std::exchange(other.mDecoder, nullptr); + return *this; + } + MajorType Item::GetMajor() const { return mDecoder->GetMajor(); @@ -525,6 +535,18 @@ namespace CBOR : mState(State::Initial), mDecoder(&decoder) {} + TaggedItem::TaggedItem(TaggedItem &&other) + : mState(std::exchange(other.mState, State::Done)) + , mDecoder(std::exchange(other.mDecoder, nullptr)) + {} + + TaggedItem &TaggedItem::operator=(TaggedItem &&other) + { + mState = std::exchange(other.mState, State::Done); + mDecoder = std::exchange(other.mDecoder, nullptr); + return *this; + } + std::uint64_t TaggedItem::Tag() { if (mState != State::Initial) { @@ -555,6 +577,18 @@ namespace CBOR : mState(State::Initial), mDecoder(&decoder) {} + KeyValue::KeyValue(KeyValue &&other) + : mState(std::exchange(other.mState, State::Done)) + , mDecoder(std::exchange(other.mDecoder, nullptr)) + {} + + KeyValue &KeyValue::operator=(KeyValue &&other) + { + mState = std::exchange(other.mState, State::Done); + mDecoder = std::exchange(other.mDecoder, nullptr); + return *this; + } + Item KeyValue::Key() { if (mState != State::Initial) { @@ -582,6 +616,22 @@ namespace CBOR , mDecoder(&decoder) {} + Binary::Binary(Binary &&other) + : mHeaderParsed(std::exchange(other.mHeaderParsed, true)) + , mDone(std::exchange(other.mDone, true)) + , mCheckedDone(std::exchange(other.mCheckedDone, true)) + , mDecoder(std::exchange(other.mDecoder, nullptr)) + {} + + Binary &Binary::operator=(Binary &&other) + { + mHeaderParsed = std::exchange(other.mHeaderParsed, true); + mDone = std::exchange(other.mDone, true); + mCheckedDone = std::exchange(other.mCheckedDone, true); + mDecoder = std::exchange(other.mDecoder, nullptr); + return *this; + } + bool Binary::Done() { if (!mHeaderParsed) { @@ -649,6 +699,22 @@ namespace CBOR , mDecoder(&decoder) {} + String::String(String &&other) + : mHeaderParsed(std::exchange(other.mHeaderParsed, true)) + , mDone(std::exchange(other.mDone, true)) + , mCheckedDone(std::exchange(other.mCheckedDone, true)) + , mDecoder(std::exchange(other.mDecoder, nullptr)) + {} + + String &String::operator=(String &&other) + { + mHeaderParsed = std::exchange(other.mHeaderParsed, true); + mDone = std::exchange(other.mDone, true); + mCheckedDone = std::exchange(other.mCheckedDone, true); + mDecoder = std::exchange(other.mDecoder, nullptr); + return *this; + } + bool String::Done() { if (!mHeaderParsed) { @@ -718,6 +784,26 @@ namespace CBOR , mDecoder(&decoder) {} + Array::Array(Array &&other) + : mHeaderParsed(std::exchange(other.mHeaderParsed, true)) + , mDone(std::exchange(other.mDone, true)) + , mCheckedDone(std::exchange(other.mCheckedDone, true)) + , mCurrent(std::exchange(other.mCurrent, 0)) + , mSize(std::exchange(other.mSize, 0)) + , mDecoder(std::exchange(other.mDecoder, nullptr)) + {} + + Array &Array::operator=(Array &&other) + { + mHeaderParsed = std::exchange(other.mHeaderParsed, true); + mDone = std::exchange(other.mDone, true); + mCheckedDone = std::exchange(other.mCheckedDone, true); + mCurrent = std::exchange(other.mCurrent, 0); + mSize = std::exchange(other.mSize, 0); + mDecoder = std::exchange(other.mDecoder, nullptr); + return *this; + } + bool Array::Done() { if (!mHeaderParsed) { @@ -782,6 +868,26 @@ namespace CBOR , mDecoder(&decoder) {} + Map::Map(Map &&other) + : mHeaderParsed(std::exchange(other.mHeaderParsed, true)) + , mDone(std::exchange(other.mDone, true)) + , mCheckedDone(std::exchange(other.mCheckedDone, true)) + , mCurrent(std::exchange(other.mCurrent, 0)) + , mSize(std::exchange(other.mSize, 0)) + , mDecoder(std::exchange(other.mDecoder, nullptr)) + {} + + Map &Map::operator=(Map &&other) + { + mHeaderParsed = std::exchange(other.mHeaderParsed, true); + mDone = std::exchange(other.mDone, true); + mCheckedDone = std::exchange(other.mCheckedDone, true); + mCurrent = std::exchange(other.mCurrent, 0); + mSize = std::exchange(other.mSize, 0); + mDecoder = std::exchange(other.mDecoder, nullptr); + return *this; + } + bool Map::Done() { if (!mHeaderParsed) { @@ -841,6 +947,18 @@ namespace CBOR : mCurrent(0), mBuffer(buffer) {} + Decoder::Decoder(Decoder &&other) + : mCurrent(std::exchange(other.mCurrent, 0)) + , mBuffer(std::exchange(other.mBuffer, {})) + {} + + Decoder &Decoder::operator=(Decoder &&other) + { + mCurrent = std::exchange(other.mCurrent, 0); + mBuffer = std::exchange(other.mBuffer, {}); + return *this; + } + MajorType Decoder::GetMajor() const { std::uint8_t header = Read1B(mBuffer, mCurrent); diff --git a/Tests/Main.cpp b/Tests/Main.cpp index e0424ef..67653a7 100644 --- a/Tests/Main.cpp +++ b/Tests/Main.cpp @@ -1,6 +1,6 @@ #include "CBOR/Decoder.hpp" #include "CBOR/Encoder.hpp" -#include "Cbor/Printer.hpp" +#include "CBOR/Printer.hpp" #include #include #include