mirror of
https://github.com/matrix-construct/construct
synced 2024-12-26 15:33:54 +01:00
ircd::cbor: checkpoint; item header size and value counter gauge.
This commit is contained in:
parent
5e8c1ad52d
commit
b6f7a64c4c
2 changed files with 347 additions and 31 deletions
|
@ -16,59 +16,158 @@
|
|||
namespace ircd::cbor
|
||||
{
|
||||
IRCD_EXCEPTION(ircd::error, error);
|
||||
IRCD_EXCEPTION(error, type_error);
|
||||
IRCD_EXCEPTION(error, parse_error);
|
||||
IRCD_EXCEPTION(parse_error, buffer_underrun);
|
||||
|
||||
struct item;
|
||||
|
||||
struct positive;
|
||||
struct negative;
|
||||
union primitive;
|
||||
union positive;
|
||||
union negative;
|
||||
struct binary;
|
||||
struct string;
|
||||
struct array;
|
||||
struct object;
|
||||
struct tag;
|
||||
struct primitive;
|
||||
|
||||
struct item;
|
||||
}
|
||||
|
||||
struct ircd::cbor::item
|
||||
:const_buffer
|
||||
{
|
||||
enum major :uint8_t;
|
||||
enum minor :uint8_t;
|
||||
struct header;
|
||||
struct value;
|
||||
|
||||
item(const const_buffer &buf);
|
||||
item() = default;
|
||||
|
||||
friend string_view reflect(const major &);
|
||||
friend enum major major(const item &);
|
||||
};
|
||||
|
||||
struct ircd::cbor::item::header
|
||||
:const_buffer
|
||||
{
|
||||
uint8_t major :3;
|
||||
uint8_t minor :5;
|
||||
static uint8_t major(const uint8_t &);
|
||||
static uint8_t minor(const uint8_t &);
|
||||
static size_t length(const uint8_t &);
|
||||
|
||||
const uint8_t &leading() const;
|
||||
const_buffer following() const;
|
||||
size_t header_size() const;
|
||||
size_t value_count() const;
|
||||
|
||||
header(const const_buffer &);
|
||||
header() = default;
|
||||
};
|
||||
|
||||
struct ircd::cbor::string
|
||||
:string_view
|
||||
{
|
||||
using string_view::string_view;
|
||||
string(const item &);
|
||||
};
|
||||
|
||||
union ircd::cbor::positive
|
||||
{
|
||||
uint8_t u8;
|
||||
uint16_t u16;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
};
|
||||
|
||||
/*
|
||||
union ircd::cbor::primitive
|
||||
{
|
||||
bool ud;
|
||||
bool nul;
|
||||
bool boolean;
|
||||
float fsingle;
|
||||
double fdouble;
|
||||
};
|
||||
|
||||
union ircd::cbor::negative
|
||||
{
|
||||
int8_t u8;
|
||||
int16_t u16;
|
||||
int32_t u32;
|
||||
int64_t u64;
|
||||
};
|
||||
|
||||
struct ircd::cbor::binary
|
||||
:const_buffer
|
||||
{
|
||||
using const_buffer::const_buffer;
|
||||
binary(const item &);
|
||||
};
|
||||
|
||||
struct ircd::cbor::array
|
||||
:const_buffer
|
||||
{
|
||||
using const_buffer::const_buffer;
|
||||
array(const item &);
|
||||
};
|
||||
|
||||
struct ircd::cbor::object
|
||||
:const_buffer
|
||||
{
|
||||
using member = std::pair<item, item>;
|
||||
|
||||
using const_buffer::const_buffer;
|
||||
object(const item &);
|
||||
};
|
||||
|
||||
struct ircd::cbor::tag
|
||||
:const_buffer
|
||||
{
|
||||
using const_buffer::const_buffer;
|
||||
tag(const item &);
|
||||
};
|
||||
|
||||
struct ircd::cbor::value
|
||||
{
|
||||
item::header header; union
|
||||
{
|
||||
cbor::primitive primitive;
|
||||
cbor::positive positive;
|
||||
cbor::negative negative;
|
||||
cbor::binary binary;
|
||||
cbor::string string;
|
||||
cbor::value *array;
|
||||
cbor::object::member *object;
|
||||
};
|
||||
};
|
||||
*/
|
||||
|
||||
enum ircd::cbor::item::major
|
||||
:uint8_t
|
||||
{
|
||||
POSITIVE = 0,
|
||||
NEGATIVE = 1,
|
||||
BINARY = 2,
|
||||
STRING = 3,
|
||||
ARRAY = 4,
|
||||
OBJECT = 5,
|
||||
TAG = 6,
|
||||
PRIMITIVE = 7,
|
||||
POSITIVE = 0, ///< Z*
|
||||
NEGATIVE = 1, ///< Z-
|
||||
BINARY = 2, ///< Raw byte sequence
|
||||
STRING = 3, ///< UTF-8 character sequence
|
||||
ARRAY = 4, ///< Array of items
|
||||
OBJECT = 5, ///< Dictionary of items
|
||||
TAG = 6, ///< CBOR extensions (IANA registered)
|
||||
PRIMITIVE = 7, ///< Literals / floats
|
||||
};
|
||||
|
||||
enum ircd::cbor::item::minor
|
||||
:uint8_t
|
||||
{
|
||||
FALSE = 20, ///< False
|
||||
TRUE = 21, ///< True
|
||||
NUL = 22, ///< Null
|
||||
UD = 23, ///< Undefined value
|
||||
U8 = 24, ///< 8 bits follow
|
||||
U16 = 25, ///< 16 bits follow
|
||||
F16 = 25, ///< IEEE754 half-precision (16 bits follow)
|
||||
U32 = 26, ///< 32 bits follow
|
||||
F32 = 26, ///< IEEE754 single-precision (32 bits follow)
|
||||
U64 = 27, ///< 64 bits follow
|
||||
F64 = 27, ///< IEEE754 double-precision (64 bits follow)
|
||||
STREAM = 31, ///< Variable length (terminated by BREAK)
|
||||
BREAK = 31, ///< Terminator code
|
||||
FALSE = 20, ///< False
|
||||
TRUE = 21, ///< True
|
||||
NUL = 22, ///< Null
|
||||
UD = 23, ///< Undefined value
|
||||
U8 = 24, ///< 8 bits follow
|
||||
U16 = 25, ///< 16 bits follow
|
||||
F16 = 25, ///< IEEE754 half-precision (16 bits follow)
|
||||
U32 = 26, ///< 32 bits follow
|
||||
F32 = 26, ///< IEEE754 single-precision (32 bits follow)
|
||||
U64 = 27, ///< 64 bits follow
|
||||
F64 = 27, ///< IEEE754 double-precision (64 bits follow)
|
||||
STREAM = 31, ///< Variable length (terminated by BREAK)
|
||||
BREAK = 31, ///< Terminator code
|
||||
};
|
||||
|
|
223
ircd/cbor.cc
223
ircd/cbor.cc
|
@ -8,10 +8,227 @@
|
|||
// copyright notice and this permission notice is present in all copies. The
|
||||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
static_assert(sizeof(ircd::cbor::item::header) == 1);
|
||||
static_assert(std::is_standard_layout<ircd::cbor::item::header>());
|
||||
|
||||
namespace ircd::cbor
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// string
|
||||
//
|
||||
|
||||
ircd::cbor::string::string(const item &item)
|
||||
:string_view{[&item]
|
||||
{
|
||||
const item::header header(item);
|
||||
return string_view
|
||||
{
|
||||
ircd::buffer::data(item) + header.header_size(), header.value_count()
|
||||
};
|
||||
}()}
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// item
|
||||
//
|
||||
|
||||
enum ircd::cbor::item::major
|
||||
ircd::cbor::major(const item &item)
|
||||
{
|
||||
const item::header &header(item);
|
||||
return static_cast<item::major>(item::header::major(header.leading()));
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::cbor::reflect(const item::major &major)
|
||||
{
|
||||
switch(major)
|
||||
{
|
||||
case item::major::POSITIVE: return "POSITIVE";
|
||||
case item::major::NEGATIVE: return "NEGATIVE";
|
||||
case item::major::BINARY: return "BINARY";
|
||||
case item::major::STRING: return "STRING";
|
||||
case item::major::ARRAY: return "ARRAY";
|
||||
case item::major::OBJECT: return "OBJECT";
|
||||
case item::major::TAG: return "TAG";
|
||||
case item::major::PRIMITIVE: return "PRIMITIVE";
|
||||
}
|
||||
|
||||
return "??????";
|
||||
}
|
||||
|
||||
//
|
||||
// item::item
|
||||
//
|
||||
|
||||
ircd::cbor::item::item(const const_buffer &buf)
|
||||
:const_buffer{[&buf]
|
||||
{
|
||||
return const_buffer{buf};
|
||||
}()}
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// item::header
|
||||
//
|
||||
|
||||
ircd::cbor::item::header::header(const const_buffer &buf)
|
||||
:const_buffer{[&buf]
|
||||
{
|
||||
if(unlikely(size(buf) < sizeof(uint8_t)))
|
||||
throw buffer_underrun
|
||||
{
|
||||
"Item buffer is too small to contain a header"
|
||||
};
|
||||
|
||||
const uint8_t &leading
|
||||
{
|
||||
*reinterpret_cast<const uint8_t *>(data(buf))
|
||||
};
|
||||
|
||||
return const_buffer
|
||||
{
|
||||
data(buf), length(leading)
|
||||
};
|
||||
}()}
|
||||
{
|
||||
if(unlikely(size(*this) > size(buf)))
|
||||
throw buffer_underrun
|
||||
{
|
||||
"Item buffer is too small to contain full header"
|
||||
};
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::cbor::item::header::value_count()
|
||||
const
|
||||
{
|
||||
switch(major(leading()))
|
||||
{
|
||||
case BINARY:
|
||||
case STRING:
|
||||
case ARRAY:
|
||||
case OBJECT:
|
||||
{
|
||||
if(minor(leading()) <= 23)
|
||||
return minor(leading());
|
||||
|
||||
const auto *const positive
|
||||
{
|
||||
reinterpret_cast<const cbor::positive *>(data(following()))
|
||||
};
|
||||
|
||||
switch(minor(leading()))
|
||||
{
|
||||
case item::minor::U8: return ntoh(positive->u8);
|
||||
case item::minor::U16: return ntoh(positive->u16);
|
||||
case item::minor::U32: return ntoh(positive->u32);
|
||||
case item::minor::U64: return ntoh(positive->u64);
|
||||
default: throw parse_error
|
||||
{
|
||||
"Unknown value length from minor data"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
case TAG: return 1; // Indicates 1 item is content
|
||||
case POSITIVE: return 0; // No content
|
||||
case NEGATIVE: return 0; // No content
|
||||
case PRIMITIVE: return 0; // No content
|
||||
default: throw type_error
|
||||
{
|
||||
"Unknown major type; length of value unknown"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::cbor::item::header::header_size()
|
||||
const
|
||||
{
|
||||
return length(leading());
|
||||
}
|
||||
|
||||
ircd::const_buffer
|
||||
ircd::cbor::item::header::following()
|
||||
const
|
||||
{
|
||||
return { data(*this) + 1, header_size() - 1 };
|
||||
}
|
||||
|
||||
const uint8_t &
|
||||
ircd::cbor::item::header::leading()
|
||||
const
|
||||
{
|
||||
assert(size(*this) >= sizeof(uint8_t));
|
||||
return *reinterpret_cast<const uint8_t *>(data(*this));
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::cbor::item::header::length(const uint8_t &a)
|
||||
{
|
||||
switch(major(a))
|
||||
{
|
||||
case POSITIVE:
|
||||
case NEGATIVE:
|
||||
case BINARY:
|
||||
case STRING:
|
||||
case ARRAY:
|
||||
case OBJECT:
|
||||
case TAG:
|
||||
{
|
||||
if(minor(a) > 23) switch(minor(a))
|
||||
{
|
||||
case item::minor::U8: return 2;
|
||||
case item::minor::U16: return 3;
|
||||
case item::minor::U32: return 5;
|
||||
case item::minor::U64: return 9;
|
||||
default: throw type_error
|
||||
{
|
||||
"Unknown minor type (%u); length of header unknown", minor(a)
|
||||
};
|
||||
}
|
||||
else return 1;
|
||||
}
|
||||
|
||||
case PRIMITIVE:
|
||||
{
|
||||
if(minor(a) > 23) switch(minor(a))
|
||||
{
|
||||
case FALSE:
|
||||
case TRUE:
|
||||
case NUL:
|
||||
case UD: return 1;
|
||||
case item::minor::F16: return 3;
|
||||
case item::minor::F32: return 5;
|
||||
case item::minor::F64: return 9;
|
||||
default: throw type_error
|
||||
{
|
||||
"Unknown primitive minor type (%u); length of header unknown", minor(a)
|
||||
};
|
||||
}
|
||||
else return 1;
|
||||
}
|
||||
|
||||
default: throw type_error
|
||||
{
|
||||
"Unknown major type; length of header unknown"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ircd::cbor::item::header::major(const uint8_t &a)
|
||||
{
|
||||
static const int &shift(5);
|
||||
return a >> shift;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ircd::cbor::item::header::minor(const uint8_t &a)
|
||||
{
|
||||
static const uint8_t &mask(0x1F);
|
||||
return a & mask;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue