Streamline parsing of fixed length strings and blobs

This commit is contained in:
TennesseeTrash 2025-09-19 02:06:37 +02:00
parent 257be2e57a
commit bec16e493f
3 changed files with 90 additions and 117 deletions

View file

@ -23,27 +23,29 @@ namespace CBOR
Item(Decoder &decoder); Item(Decoder &decoder);
public: public:
bool Bool (); bool Bool();
Special Special(); Special Special();
std::int8_t Int8 (); std::int8_t Int8();
std::int16_t Int16 (); std::int16_t Int16();
std::int32_t Int32 (); std::int32_t Int32();
std::int64_t Int64 (); std::int64_t Int64();
std::uint8_t Uint8 (); std::uint8_t Uint8();
std::uint16_t Uint16 (); std::uint16_t Uint16();
std::uint32_t Uint32 (); std::uint32_t Uint32();
std::uint64_t Uint64 (); std::uint64_t Uint64();
// Note(3011): float16_t is currently not supported // Note(3011): float16_t is currently not supported
float Float (); float Float();
double Double (); double Double();
class Binary Binary (); std::span<std::uint8_t> Binary();
class String String (); std::string_view String();
class Array Array (); class Binary IndefiniteBinary();
class Map Map (); class String IndefiniteString();
class Array Array();
class Map Map();
private: private:
friend class Decoder; friend class Decoder;
@ -80,16 +82,13 @@ namespace CBOR
Binary(Decoder &decoder); Binary(Decoder &decoder);
public: public:
std::span<std::uint8_t> Get();
void AllowIndefinite();
bool Done(); bool Done();
std::span<std::uint8_t> Next(); std::span<std::uint8_t> Next();
private: private:
friend class Decoder; friend class Decoder;
bool mHeaderParsed; bool mHeaderParsed;
bool mIndefiniteAllowed;
bool mDone; bool mDone;
bool mCheckedDone; bool mCheckedDone;
Decoder *mDecoder; Decoder *mDecoder;
@ -101,16 +100,13 @@ namespace CBOR
String(Decoder &decoder); String(Decoder &decoder);
public: public:
std::string_view Get();
void AllowIndefinite();
bool Done(); bool Done();
std::string_view Next(); std::string_view Next();
private: private:
friend class Decoder; friend class Decoder;
bool mHeaderParsed; bool mHeaderParsed;
bool mIndefiniteAllowed;
bool mDone; bool mDone;
bool mCheckedDone; bool mCheckedDone;
Decoder *mDecoder; Decoder *mDecoder;
@ -161,27 +157,29 @@ namespace CBOR
public: public:
Decoder(std::span<std::uint8_t> buffer); Decoder(std::span<std::uint8_t> buffer);
bool Bool (); bool Bool();
Special Special(); Special Special();
std::int8_t Int8 (); std::int8_t Int8();
std::int16_t Int16 (); std::int16_t Int16();
std::int32_t Int32 (); std::int32_t Int32();
std::int64_t Int64 (); std::int64_t Int64();
std::uint8_t Uint8 (); std::uint8_t Uint8();
std::uint16_t Uint16 (); std::uint16_t Uint16();
std::uint32_t Uint32 (); std::uint32_t Uint32();
std::uint64_t Uint64 (); std::uint64_t Uint64();
// Note(3011): float16_t is currently not supported // Note(3011): float16_t is currently not supported
float Float (); float Float();
double Double (); double Double();
Binary Binary (); std::span<std::uint8_t> Binary();
String String (); std::string_view String();
Array Array (); class Binary IndefiniteBinary();
Map Map (); class String IndefiniteString();
class Array Array();
class Map Map();
private: private:
friend class Binary; friend class Binary;

View file

@ -416,16 +416,26 @@ namespace CBOR
return mDecoder->Double(); return mDecoder->Double();
} }
Binary Item::Binary() std::span<std::uint8_t> Item::Binary()
{ {
return mDecoder->Binary(); return mDecoder->Binary();
} }
String Item::String() std::string_view Item::String()
{ {
return mDecoder->String(); return mDecoder->String();
} }
Binary Item::IndefiniteBinary()
{
return mDecoder->IndefiniteBinary();
}
String Item::IndefiniteString()
{
return mDecoder->IndefiniteString();
}
Array Item::Array() Array Item::Array()
{ {
return mDecoder->Array(); return mDecoder->Array();
@ -462,44 +472,11 @@ namespace CBOR
Binary::Binary(Decoder &decoder) Binary::Binary(Decoder &decoder)
: mHeaderParsed(false) : mHeaderParsed(false)
, mIndefiniteAllowed(false)
, mDone(false) , mDone(false)
, mCheckedDone(false) , mCheckedDone(false)
, mDecoder(&decoder) , mDecoder(&decoder)
{} {}
std::span<std::uint8_t> 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() bool Binary::Done()
{ {
if (!mHeaderParsed) { if (!mHeaderParsed) {
@ -562,44 +539,11 @@ namespace CBOR
String::String(Decoder &decoder) String::String(Decoder &decoder)
: mHeaderParsed(false) : mHeaderParsed(false)
, mIndefiniteAllowed(false)
, mDone(false) , mDone(false)
, mCheckedDone(false) , mCheckedDone(false)
, mDecoder(&decoder) , 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() bool String::Done()
{ {
if (!mHeaderParsed) { if (!mHeaderParsed) {
@ -902,12 +846,44 @@ namespace CBOR
throw TypeMismatchError("double", ToString(major)); throw TypeMismatchError("double", ToString(major));
} }
Binary Decoder::Binary() std::span<std::uint8_t> 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()
{ {
return { *this }; return { *this };
} }
String Decoder::String() String Decoder::IndefiniteString()
{ {
return { *this }; return { *this };
} }

View file

@ -59,10 +59,10 @@ SomeStruct Decode1(std::span<std::uint8_t> buffer)
CBOR::Map object = dec.Map(); CBOR::Map object = dec.Map();
while (!object.Done()) { while (!object.Done()) {
CBOR::KeyValue kv = object.Next(); CBOR::KeyValue kv = object.Next();
std::string_view key = kv.Key().String().Get(); std::string_view key = kv.Key().String();
CBOR::Item value = kv.Value(); CBOR::Item value = kv.Value();
if (key == "name") { if (key == "name") {
result.name = value.String().Get(); result.name = value.String();
} }
else if (key == "speed") { else if (key == "speed") {
result.speed = value.Double(); result.speed = value.Double();
@ -82,7 +82,7 @@ SomeStruct Decode1(std::span<std::uint8_t> buffer)
else if (key == "tools") { else if (key == "tools") {
CBOR::Array tools = value.Array(); CBOR::Array tools = value.Array();
while(!tools.Done()) { while(!tools.Done()) {
result.tools.push_back(std::string(tools.Next().String().Get())); result.tools.push_back(std::string(tools.Next().String()));
} }
} }
} }
@ -98,10 +98,10 @@ SomeStruct Decode2(std::span<std::uint8_t> buffer)
CBOR::Map object = dec.Map(); CBOR::Map object = dec.Map();
while (!object.Done()) { while (!object.Done()) {
CBOR::KeyValue kv = object.Next(); CBOR::KeyValue kv = object.Next();
std::string_view key = kv.Key().String().Get(); std::string_view key = kv.Key().String();
CBOR::Item value = kv.Value(); CBOR::Item value = kv.Value();
if (key == "name") { if (key == "name") {
result.name = value.String().Get(); result.name = value.String();
} }
else if (key == "speed") { else if (key == "speed") {
result.speed = value.Double(); result.speed = value.Double();
@ -122,8 +122,7 @@ SomeStruct Decode2(std::span<std::uint8_t> buffer)
CBOR::Array tools = value.Array(); CBOR::Array tools = value.Array();
while(!tools.Done()) { while(!tools.Done()) {
result.tools.push_back(""); result.tools.push_back("");
CBOR::String tool = tools.Next().String(); CBOR::String tool = tools.Next().IndefiniteString();
tool.AllowIndefinite();
while (!tool.Done()) { while (!tool.Done()) {
result.tools.back().append(tool.Next()); result.tools.back().append(tool.Next());
} }