0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-01 01:28:54 +02:00

ircd: Move preliminary cbor into directory.

This commit is contained in:
Jason Volk 2018-08-09 01:24:12 -07:00
parent 7404aa0581
commit 9aedac4461
4 changed files with 860 additions and 271 deletions

View file

@ -1,173 +0,0 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#pragma once
#define HAVE_IRCD_CBOR_H
/// Concise Binary Object Representation (RFC7049)
///
namespace ircd::cbor
{
IRCD_EXCEPTION(ircd::error, error);
IRCD_EXCEPTION(error, type_error);
IRCD_EXCEPTION(error, parse_error);
IRCD_EXCEPTION(parse_error, buffer_underrun);
union primitive;
union positive;
union negative;
struct binary;
struct string;
struct array;
struct object;
struct tag;
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
{
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, ///< 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
};

309
include/ircd/cbor/cbor.h Normal file
View file

@ -0,0 +1,309 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#pragma once
#define HAVE_IRCD_CBOR_H
/// Concise Binary Object Representation (RFC7049)
///
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 positive;
struct negative;
struct binary;
struct string;
struct array;
struct object;
struct tag;
struct primitive;
enum major :uint8_t;
enum minor :uint8_t;
struct head;
struct item;
string_view reflect(const enum major &);
enum major major(const const_buffer &);
}
/// Item head.
///
/// This object represents the head byte and any following-integer bytes under
/// its const_buffer. If the major type has a payload, it starts immediately
/// following the end of this object's buffer. The first byte of this object's
/// buffer is the leading head byte. This object's buffer will never be empty()
/// unless it's default-initialized (i.e not pointing at anything).
///
/// This is used to query information about the item from the head data.
///
struct ircd::cbor::head
:const_buffer
{
static uint8_t major(const uint8_t &); // Major type
static uint8_t minor(const uint8_t &); // Minor type
static size_t length(const uint8_t &); // (1 + size(following()))
// Member ops when buffer has >= 1 byte
const uint8_t &leading() const; // Reference the leading byte
enum major major() const; // major(leading())
enum minor minor() const; // minor(leading())
size_t length() const; // length(leading())
// Get bytes following leading byte based on major/minor
const_buffer following() const;
template<class T> const T &following() const;
// Construct from at least first byte of item or more
head(const const_buffer &);
head() = default;
head(head &&) = default;
head(const head &) = default;
};
/// Abstract item
///
struct ircd::cbor::item
:const_buffer
{
operator head() const;
const_buffer value() const;
item(const const_buffer &buf);
item() = default;
};
/// Positive integer item.
///
/// Represents a positive integer item. This is a buffer spanning the item,
/// which is same span as the cbor::head buffer because positive integer items
/// only have a payload of an integer item within or following the leading head
/// byte.
///
/// The integer value is returned through the cast operator.
///
struct ircd::cbor::positive
:item
{
uint64_t value() const;
operator uint64_t() const;
positive(const head &);
positive() = default;
};
/// Negative integer item.
///
/// This is similar to cbor::positive except that the integer returned is signed
/// and computed from 1 - cbor::positive(buf).
///
struct ircd::cbor::negative
:positive
{
int64_t value() const;
operator int64_t() const;
negative(const head &);
negative() = default;
};
/// Binary buffer item
///
///
struct ircd::cbor::binary
:positive
{
const_buffer value() const;
binary(const const_buffer &);
};
struct ircd::cbor::string
:binary
{
string_view value() const;
explicit operator string_view() const;
string(const const_buffer &);
};
struct ircd::cbor::array
:item
{
struct const_iterator;
size_t count() const;
const_buffer value() const;
const_iterator begin() const;
const_iterator end() const;
item operator[](size_t i) const;
array(const const_buffer &);
};
struct ircd::cbor::array::const_iterator
{
cbor::array array;
const_buffer state;
public:
bool operator!() const
{
return ircd::empty(state);
}
explicit operator bool() const
{
return !operator!();
}
const const_buffer &operator*() const
{
return state;
}
const const_buffer *operator->() const
{
return &state;
}
const_iterator &operator++();
const_iterator(const cbor::array &);
};
struct ircd::cbor::object
:item
{
struct member;
struct const_iterator;
size_t count() const;
const_buffer value() const;
member operator[](const string_view &name) const;
object(const const_buffer &);
};
struct ircd::cbor::object::member
:std::pair<item, item>
{
using std::pair<item, item>::pair;
};
struct ircd::cbor::object::const_iterator
{
cbor::object object;
member state;
public:
bool operator!() const
{
return ircd::empty(state.first);
}
explicit operator bool() const
{
return !operator!();
}
const member &operator*() const
{
return state;
}
const member *operator->() const
{
return &state;
}
const_iterator &operator++();
const_iterator(const cbor::object &);
};
/*
union ircd::cbor::primitive
{
bool ud;
bool nul;
bool boolean;
float fsingle;
double fdouble;
};
struct ircd::cbor::item
:const_buffer
{
item(const const_buffer &);
item() = default;
friend enum major major(const item &);
};
struct ircd::cbor::binary
:const_buffer
{
binary(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 &);
};
*/
enum ircd::cbor::major
:uint8_t
{
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::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
};

View file

@ -54,7 +54,7 @@ namespace ircd
#include "parse.h"
#include "rfc1459.h"
#include "json/json.h"
#include "cbor.h"
#include "cbor/cbor.h"
#include "openssl.h"
#include "http.h"
#include "fmt.h"

View file

@ -8,73 +8,486 @@
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
namespace ircd::cbor
//
// object
//
ircd::cbor::object::object(const const_buffer &buf)
:item{buf}
{
const head &head{*this};
if(unlikely(head.major() != major::OBJECT))
throw type_error
{
"Supplied item is a '%s' and not an OBJECT", reflect(head.major())
};
}
ircd::cbor::object::member
ircd::cbor::object::operator[](const string_view &name)
const
{
const_iterator it{*this};
for(; it; ++it)
{
const string item{it->first};
if(item.value() == name)
return *it;
}
throw std::out_of_range
{
"object member not found"
};
}
ircd::const_buffer
ircd::cbor::object::value()
const
{
return {};
}
size_t
ircd::cbor::object::count()
const
{
const head &head{*this};
const positive &positive{head};
return uint64_t(positive);
}
//
// object::const_iterator
//
ircd::cbor::object::const_iterator::const_iterator(const cbor::object &object)
:object{object}
,state{[this]() -> member
{
if(!this->object.count())
return {};
const const_buffer &obuf{this->object};
const head &head{obuf};
const_buffer key
{
ircd::data(obuf) + head.length(), ircd::end(obuf)
};
const cbor::head &keyhead{key};
switch(keyhead.major())
{
case major::POSITIVE:
case major::NEGATIVE:
case major::TAG:
case major::PRIMITIVE:
{
std::get<1>(key) = std::get<0>(key) + keyhead.length();
break;
}
case major::BINARY:
case major::STRING:
{
const cbor::positive keypositive(keyhead);
std::get<1>(key) = std::get<0>(key) + keyhead.length() + uint64_t(keypositive);
break;
}
case major::ARRAY:
case major::OBJECT:
default: throw type_error
{
"Unknown major type; length of value unknown"
};
}
const_buffer val
{
ircd::end(key), ircd::end(obuf)
};
const cbor::head &valhead{val};
switch(valhead.major())
{
case major::POSITIVE:
case major::NEGATIVE:
case major::TAG:
case major::PRIMITIVE:
{
std::get<1>(val) = std::get<0>(val) + valhead.length();
break;
}
case major::BINARY:
case major::STRING:
{
const cbor::positive valpositive(valhead);
std::get<1>(val) = std::get<0>(val) + valhead.length() + uint64_t(valpositive);
break;
}
case major::ARRAY:
case major::OBJECT:
default: throw type_error
{
"Unknown major type; length of value unknown"
};
}
return { key, val };
}()}
{
const const_buffer &obuf{this->object};
if(unlikely(data(state.first) > data(obuf) + size(obuf)))
throw buffer_underrun
{
"Object iteration leads beyond the supplied object buffer"
};
}
ircd::cbor::object::const_iterator &
ircd::cbor::object::const_iterator::operator++()
{
return *this;
}
//
// array
//
ircd::cbor::array::array(const const_buffer &buf)
:item{buf}
{
const head &head{*this};
if(unlikely(head.major() != major::ARRAY))
throw type_error
{
"Supplied item is a '%s' and not an ARRAY", reflect(head.major())
};
}
ircd::cbor::item
ircd::cbor::array::operator[](size_t i)
const
{
const_iterator it{*this};
for(; it && i > 0; --i, ++it);
return *it;
}
ircd::cbor::array::const_iterator
ircd::cbor::array::begin()
const
{
const_iterator ret(*this);
if(!this->count())
return ret;
const const_buffer &abuf{*this};
const head &head{abuf};
ret.state = { ircd::data(abuf) + head.length(), ircd::end(abuf) };
const cbor::head &elemhead{ret.state};
switch(elemhead.major())
{
case major::POSITIVE:
case major::NEGATIVE:
case major::TAG:
case major::PRIMITIVE:
{
std::get<1>(ret.state) = std::get<0>(ret.state) + elemhead.length();
break;
}
case major::BINARY:
case major::STRING:
{
const cbor::positive elempositive(elemhead);
std::get<1>(ret.state) = std::get<0>(ret.state) + elemhead.length() + uint64_t(elempositive);
break;
}
case major::ARRAY:
case major::OBJECT:
default: throw type_error
{
"Unknown major type; length of value unknown"
};
}
if(unlikely(data(ret.state) > data(abuf) + size(abuf)))
throw buffer_underrun
{
"Array iteration leads beyond the supplied array buffer"
};
return ret;
}
ircd::cbor::array::const_iterator
ircd::cbor::array::end()
const
{
return {*this};
}
ircd::const_buffer
ircd::cbor::array::value()
const
{
return {};
}
size_t
ircd::cbor::array::count()
const
{
const head &head{*this};
const positive &positive{head};
return uint64_t(positive);
}
//
// array::const_iterator
//
ircd::cbor::array::const_iterator::const_iterator(const cbor::array &array)
:array{array}
{
}
ircd::cbor::array::const_iterator &
ircd::cbor::array::const_iterator::operator++()
{
const const_buffer &buf{this->array};
state =
{
data(state) + size(state), data(buf) + size(buf)
};
if(data(state) == data(buf) + size(buf))
return *this;
assert(!!state);
const head &head{state};
switch(head.major())
{
case major::POSITIVE:
case major::NEGATIVE:
case major::TAG:
case major::PRIMITIVE:
{
std::get<1>(state) = std::get<0>(state) + head.length();
break;
}
case major::BINARY:
case major::STRING:
{
const positive positive(head);
std::get<1>(state) = std::get<0>(state) + head.length() + uint64_t(positive);
break;
}
case major::ARRAY:
case major::OBJECT:
default: throw type_error
{
"Unknown major type; length of value unknown"
};
}
if(unlikely(data(state) > data(buf) + size(buf)))
throw buffer_underrun
{
"Array iteration leads beyond the supplied array buffer"
};
return *this;
}
//
// string
//
ircd::cbor::string::string(const item &item)
:string_view{[&item]
ircd::cbor::string::string(const const_buffer &buf)
:binary{buf}
{
const item::header header(item);
return string_view
const head &head{*this};
if(unlikely(head.major() != major::STRING))
throw type_error
{
"Supplied item is a '%s' and not a STRING",
reflect(head.major())
};
}
ircd::cbor::string::operator
string_view()
const
{
return value();
}
ircd::string_view
ircd::cbor::string::value()
const
{
const binary &bin{*this};
return string_view{bin.value()};
}
//
// binary
//
ircd::cbor::binary::binary(const const_buffer &buf)
:positive
{
buf
}
{
item &item{*this};
const head &head{item};
if(unlikely(head.major() != major::BINARY && head.major() != major::STRING))
throw type_error
{
"Supplied item is a '%s' and not a BINARY or STRING",
reflect(head.major())
};
const_buffer &itembuf{item};
itembuf = value();
if(unlikely(size(itembuf) > size(buf)))
throw buffer_underrun
{
"Length of binary data item (%zu) exceeds supplied buffer (%zu)",
size(itembuf),
size(buf)
};
}
ircd::const_buffer
ircd::cbor::binary::value()
const
{
const item &item{*this};
const const_buffer &buf{item};
const head head{item};
const positive &positive{*this};
const uint64_t length{positive};
return const_buffer
{
ircd::buffer::data(item) + header.header_size(), header.value_count()
ircd::data(buf) + head.length(), length
};
}()}
}
//
// negative
//
ircd::cbor::negative::negative(const head &head)
:positive{head}
{
}
ircd::cbor::negative::operator
int64_t()
const
{
return value();
}
int64_t
ircd::cbor::negative::value()
const
{
const positive positive(*this);
const uint64_t &val(positive);
return 1 - val;
}
//
// positive
//
ircd::cbor::positive::positive(const head &head)
:item{head}
{
}
ircd::cbor::positive::operator
uint64_t()
const
{
return value();
}
uint64_t
ircd::cbor::positive::value()
const
{
const head &head{*this};
if(head.minor() > 23) switch(head.minor())
{
case minor::U8: return head.following<uint8_t>();
case minor::U16: return ntoh(head.following<uint16_t>());
case minor::U32: return ntoh(head.following<uint32_t>());
case minor::U64: return ntoh(head.following<uint64_t>());
default: throw parse_error
{
"Unknown minor type; length of value unknown"
};
}
else return head.minor();
}
//
// 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]
:const_buffer{buf}
{}
ircd::const_buffer
ircd::cbor::item::value()
const
{
return const_buffer{buf};
}()}
return {};
}
ircd::cbor::item::operator
ircd::cbor::head()
const
{
const const_buffer &buf(*this);
return cbor::head{buf};
}
//
// item::header
// head
//
ircd::cbor::item::header::header(const const_buffer &buf)
/// Given a buffer of CBOR this function parses the head data and maintains
/// a const_buffer span of the head. The span includes the leading head byte
/// and one or more integer bytes following the leading byte. If the major
/// type found in this head has a data payload which is not a following-integer
/// then that data starts directly after this head buffer ends.
///
/// The argument buffer must be at least one byte and must at least cover the
/// following-integer bytes (and can also be as large as possible).
///
ircd::cbor::head::head(const const_buffer &buf)
:const_buffer{[&buf]
{
if(unlikely(size(buf) < sizeof(uint8_t)))
@ -101,73 +514,76 @@ ircd::cbor::item::header::header(const const_buffer &buf)
};
}
size_t
ircd::cbor::item::header::value_count()
/// Pun a reference to the integer contained by the bytes following the head.
/// If there are no bytes following the head because the integer is contained
/// as bits packed into the leading head byte, this function will throw.
///
template<class T>
const T &
ircd::cbor::head::following()
const
{
switch(major(leading()))
{
case BINARY:
case STRING:
case ARRAY:
case OBJECT:
if(unlikely(size(following()) < sizeof(T)))
throw buffer_underrun
{
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"
"Buffer following header is too small (%zu) for type requiring %zu",
size(following()),
sizeof(T)
};
}
return *reinterpret_cast<const T *>(data(following()));
}
/// Return buffer spanning the integer bytes following this head. This may be
/// an empty buffer if the integer byte is packed into bits of the leading
/// byte (denoted by minor()).
ircd::const_buffer
ircd::cbor::head::following()
const
{
return { data(*this) + 1, length() - 1 };
}
/// Extract the length of the head from the buffer (requires 1 byte of buffer)
size_t
ircd::cbor::item::header::header_size()
ircd::cbor::head::length()
const
{
return length(leading());
}
ircd::const_buffer
ircd::cbor::item::header::following()
/// Extract the minor type from the reference to the leading byte in the head.
enum ircd::cbor::minor
ircd::cbor::head::minor()
const
{
return { data(*this) + 1, header_size() - 1 };
return static_cast<enum minor>(minor(leading()));
}
/// Extract the major type from the reference to the leading byte in the head.
enum ircd::cbor::major
ircd::cbor::head::major()
const
{
return static_cast<enum major>(major(leading()));
}
/// Reference the leading byte of the head.
const uint8_t &
ircd::cbor::item::header::leading()
ircd::cbor::head::leading()
const
{
assert(size(*this) >= sizeof(uint8_t));
return *reinterpret_cast<const uint8_t *>(data(*this));
}
/// Extract length of head from leading head byte (arg); this is the length of
/// the integer following the leading head byte plus the one leading head
/// byte. This length covers all bytes which come before item payload bytes
/// (when such a payload exists). If this length is 1 then no integer bytes
/// are following the leading head byte. The length/returned value is never 0.
size_t
ircd::cbor::item::header::length(const uint8_t &a)
ircd::cbor::head::length(const uint8_t &a)
{
switch(major(a))
{
@ -181,11 +597,11 @@ ircd::cbor::item::header::length(const uint8_t &a)
{
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
case minor::U8: return 2;
case minor::U16: return 3;
case minor::U32: return 5;
case minor::U64: return 9;
default: throw type_error
{
"Unknown minor type (%u); length of header unknown", minor(a)
};
@ -200,11 +616,11 @@ ircd::cbor::item::header::length(const uint8_t &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
case UD: return 1;
case minor::F16: return 3;
case minor::F32: return 5;
case minor::F64: return 9;
default: throw type_error
{
"Unknown primitive minor type (%u); length of header unknown", minor(a)
};
@ -219,16 +635,53 @@ ircd::cbor::item::header::length(const uint8_t &a)
}
}
/// Extract major type from leading head byte (arg)
uint8_t
ircd::cbor::item::header::major(const uint8_t &a)
ircd::cbor::head::major(const uint8_t &a)
{
// shift for higher 3 bits only
static const int &shift(5);
return a >> shift;
}
/// Extract minor type from leading head byte (arg)
uint8_t
ircd::cbor::item::header::minor(const uint8_t &a)
ircd::cbor::head::minor(const uint8_t &a)
{
static const uint8_t &mask(0x1F);
// mask of lower 5 bits only
static const uint8_t &mask
{
uint8_t(0xFF) >> 3
};
return a & mask;
}
//
// cbor.h
//
enum ircd::cbor::major
ircd::cbor::major(const const_buffer &buf)
{
const head head(buf);
return head.major();
}
ircd::string_view
ircd::cbor::reflect(const enum major &major)
{
switch(major)
{
case major::POSITIVE: return "POSITIVE";
case major::NEGATIVE: return "NEGATIVE";
case major::BINARY: return "BINARY";
case major::STRING: return "STRING";
case major::ARRAY: return "ARRAY";
case major::OBJECT: return "OBJECT";
case major::TAG: return "TAG";
case major::PRIMITIVE: return "PRIMITIVE";
}
return "??????";
}