diff --git a/LibCBOR/Include/CBOR/Decoder.hpp b/LibCBOR/Include/CBOR/Decoder.hpp index b552054..a135bda 100644 --- a/LibCBOR/Include/CBOR/Decoder.hpp +++ b/LibCBOR/Include/CBOR/Decoder.hpp @@ -23,29 +23,27 @@ namespace CBOR Item(Decoder &decoder); public: - bool Bool(); - Special Special(); + bool Bool (); + Special Special(); - std::int8_t Int8(); - std::int16_t Int16(); - std::int32_t Int32(); - std::int64_t Int64(); + std::int8_t Int8 (); + std::int16_t Int16 (); + std::int32_t Int32 (); + std::int64_t Int64 (); - std::uint8_t Uint8(); - std::uint16_t Uint16(); - std::uint32_t Uint32(); - std::uint64_t Uint64(); + std::uint8_t Uint8 (); + std::uint16_t Uint16 (); + std::uint32_t Uint32 (); + std::uint64_t Uint64 (); // Note(3011): float16_t is currently not supported - float Float(); - double Double(); + float Float (); + double Double (); - std::span Binary(); - std::string_view String(); - class Binary IndefiniteBinary(); - class String IndefiniteString(); - class Array Array(); - class Map Map(); + class Binary Binary (); + class String String (); + class Array Array (); + class Map Map (); private: friend class Decoder; @@ -82,13 +80,16 @@ namespace CBOR Binary(Decoder &decoder); public: + std::span Get(); + + void AllowIndefinite(); bool Done(); std::span Next(); - private: friend class Decoder; bool mHeaderParsed; + bool mIndefiniteAllowed; bool mDone; bool mCheckedDone; Decoder *mDecoder; @@ -100,13 +101,16 @@ namespace CBOR String(Decoder &decoder); public: + std::string_view Get(); + + void AllowIndefinite(); bool Done(); std::string_view Next(); - private: friend class Decoder; bool mHeaderParsed; + bool mIndefiniteAllowed; bool mDone; bool mCheckedDone; Decoder *mDecoder; @@ -157,29 +161,27 @@ namespace CBOR public: Decoder(std::span buffer); - bool Bool(); - Special Special(); + bool Bool (); + Special Special(); - std::int8_t Int8(); - std::int16_t Int16(); - std::int32_t Int32(); - std::int64_t Int64(); + std::int8_t Int8 (); + std::int16_t Int16 (); + std::int32_t Int32 (); + std::int64_t Int64 (); - std::uint8_t Uint8(); - std::uint16_t Uint16(); - std::uint32_t Uint32(); - std::uint64_t Uint64(); + std::uint8_t Uint8 (); + std::uint16_t Uint16 (); + std::uint32_t Uint32 (); + std::uint64_t Uint64 (); // Note(3011): float16_t is currently not supported - float Float(); - double Double(); + float Float (); + double Double (); - std::span Binary(); - std::string_view String(); - class Binary IndefiniteBinary(); - class String IndefiniteString(); - class Array Array(); - class Map Map(); + Binary Binary (); + String String (); + Array Array (); + Map Map (); private: friend class Binary; diff --git a/LibCBOR/Source/Decoder.cpp b/LibCBOR/Source/Decoder.cpp index 8cb2ca3..442ee1f 100644 --- a/LibCBOR/Source/Decoder.cpp +++ b/LibCBOR/Source/Decoder.cpp @@ -139,11 +139,11 @@ namespace CBOR 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) { - return std::to_underlying(position); + ArgumentPosition pos = GetArgumentPosition(header); + if (std::to_underlying(pos) <= 23) { + return std::to_underlying(pos); } - switch (position) { + switch (pos) { case ArgumentPosition::Next1B: return Consume1B(buffer, current); case ArgumentPosition::Next2B: @@ -416,26 +416,16 @@ namespace CBOR return mDecoder->Double(); } - std::span Item::Binary() + Binary Item::Binary() { return mDecoder->Binary(); } - std::string_view Item::String() + String Item::String() { return mDecoder->String(); } - Binary Item::IndefiniteBinary() - { - return mDecoder->IndefiniteBinary(); - } - - String Item::IndefiniteString() - { - return mDecoder->IndefiniteString(); - } - Array Item::Array() { return mDecoder->Array(); @@ -472,11 +462,44 @@ namespace CBOR Binary::Binary(Decoder &decoder) : mHeaderParsed(false) + , mIndefiniteAllowed(false) , mDone(false) , mCheckedDone(false) , mDecoder(&decoder) {} + std::span Binary::Get() + { + if (mDone) { + throw InvalidUsageError("this item has already been fully parsed"); + } + + if (mIndefiniteAllowed) { + throw InvalidUsageError("indefinite-length items have been explicitly enabled, " + "use the funcions for those instead"); + } + + std::uint8_t header = Consume1B(mDecoder->mBuffer, mDecoder->mCurrent); + MajorType major = GetMajorType(header); + mHeaderParsed = true; + if (major != MajorType::Binary) { + throw TypeMismatchError("binary", ToString(major)); + } + + if (GetArgumentPosition(header) == ArgumentPosition::Indefinite) { + throw IndefiniteLengthError(); + } + + mDone = true; + std::uint64_t arg = ArgumentValue(header, mDecoder->mBuffer, mDecoder->mCurrent); + return ExtractBinary(arg, mDecoder->mBuffer, mDecoder->mCurrent); + } + + void Binary::AllowIndefinite() + { + mIndefiniteAllowed = true; + } + bool Binary::Done() { if (!mHeaderParsed) { @@ -527,8 +550,8 @@ namespace CBOR std::uint8_t header = Consume1B(mDecoder->mBuffer, mDecoder->mCurrent); MajorType major = GetMajorType(header); - ArgumentPosition position = GetArgumentPosition(header); - if (major != MajorType::Binary || position == ArgumentPosition::Indefinite){ + ArgumentPosition pos = GetArgumentPosition(header); + if (major != MajorType::Binary || pos == ArgumentPosition::Indefinite){ throw MalformedDataError("an indefinite length string may only contain " "definite length strings"); } @@ -539,11 +562,44 @@ namespace CBOR String::String(Decoder &decoder) : mHeaderParsed(false) + , mIndefiniteAllowed(false) , mDone(false) , mCheckedDone(false) , mDecoder(&decoder) {} + std::string_view String::Get() + { + if (mDone) { + throw InvalidUsageError("this item has already been fully parsed"); + } + + if (mIndefiniteAllowed) { + throw InvalidUsageError("indefinite-length items have been explicitly enabled, " + "use the funcions for those instead"); + } + + std::uint8_t header = Consume1B(mDecoder->mBuffer, mDecoder->mCurrent); + mHeaderParsed = true; + MajorType major = GetMajorType(header); + if (major != MajorType::String) { + throw TypeMismatchError("string", ToString(major)); + } + + if (GetArgumentPosition(header) == ArgumentPosition::Indefinite) { + throw IndefiniteLengthError(); + } + + mDone = true; + std::uint64_t arg = ArgumentValue(header, mDecoder->mBuffer, mDecoder->mCurrent); + return ExtractString(arg, mDecoder->mBuffer, mDecoder->mCurrent); + } + + void String::AllowIndefinite() + { + mIndefiniteAllowed = true; + } + bool String::Done() { if (!mHeaderParsed) { @@ -594,8 +650,8 @@ namespace CBOR std::uint8_t header = Consume1B(mDecoder->mBuffer, mDecoder->mCurrent); MajorType major = GetMajorType(header); - ArgumentPosition position = GetArgumentPosition(header); - if (major != MajorType::String || position == ArgumentPosition::Indefinite){ + ArgumentPosition pos = GetArgumentPosition(header); + if (major != MajorType::String || pos == ArgumentPosition::Indefinite){ throw MalformedDataError("an indefinite length string may only contain " "definite length strings"); } @@ -846,44 +902,12 @@ namespace CBOR throw TypeMismatchError("double", ToString(major)); } - std::span Decoder::Binary() - { - std::uint8_t header = Consume1B(mBuffer, mCurrent); - MajorType major = GetMajorType(header); - if (major != MajorType::Binary) { - throw TypeMismatchError("binary", ToString(major)); - } - - if (GetArgumentPosition(header) == ArgumentPosition::Indefinite) { - throw IndefiniteLengthError(); - } - - std::uint64_t arg = ArgumentValue(header, mBuffer, mCurrent); - return ExtractBinary(arg, mBuffer, mCurrent); - } - - std::string_view Decoder::String() - { - std::uint8_t header = Consume1B(mBuffer, mCurrent); - MajorType major = GetMajorType(header); - if (major != MajorType::String) { - throw TypeMismatchError("string", ToString(major)); - } - - if (GetArgumentPosition(header) == ArgumentPosition::Indefinite) { - throw IndefiniteLengthError(); - } - - std::uint64_t arg = ArgumentValue(header, mBuffer, mCurrent); - return ExtractString(arg, mBuffer, mCurrent); - } - - Binary Decoder::IndefiniteBinary() + Binary Decoder::Binary() { return { *this }; } - String Decoder::IndefiniteString() + String Decoder::String() { return { *this }; } diff --git a/Tests/Main.cpp b/Tests/Main.cpp index cae2a7d..4dcd20e 100644 --- a/Tests/Main.cpp +++ b/Tests/Main.cpp @@ -59,10 +59,10 @@ SomeStruct Decode1(std::span buffer) CBOR::Map object = dec.Map(); while (!object.Done()) { CBOR::KeyValue kv = object.Next(); - std::string_view key = kv.Key().String(); + std::string_view key = kv.Key().String().Get(); CBOR::Item value = kv.Value(); if (key == "name") { - result.name = value.String(); + result.name = value.String().Get(); } else if (key == "speed") { result.speed = value.Double(); @@ -82,7 +82,7 @@ SomeStruct Decode1(std::span buffer) else if (key == "tools") { CBOR::Array tools = value.Array(); while(!tools.Done()) { - result.tools.push_back(std::string(tools.Next().String())); + result.tools.push_back(std::string(tools.Next().String().Get())); } } } @@ -98,10 +98,10 @@ SomeStruct Decode2(std::span buffer) CBOR::Map object = dec.Map(); while (!object.Done()) { CBOR::KeyValue kv = object.Next(); - std::string_view key = kv.Key().String(); + std::string_view key = kv.Key().String().Get(); CBOR::Item value = kv.Value(); if (key == "name") { - result.name = value.String(); + result.name = value.String().Get(); } else if (key == "speed") { result.speed = value.Double(); @@ -122,7 +122,8 @@ SomeStruct Decode2(std::span buffer) CBOR::Array tools = value.Array(); while(!tools.Done()) { result.tools.push_back(""); - CBOR::String tool = tools.Next().IndefiniteString(); + CBOR::String tool = tools.Next().String(); + tool.AllowIndefinite(); while (!tool.Done()) { result.tools.back().append(tool.Next()); }