ソースを参照

Can encode most basic (non recursive) value into cbor

cbor
Ludovic 'Archivist' Lagouardette 3年前
コミット
38fe6839e7
3個のファイルの変更109行の追加21行の削除
  1. +101
    -15
      include/gp/enveloppe/cbor.hpp
  2. +1
    -1
      include/gp/variant.hpp
  3. +7
    -5
      tests/cbor_test.cpp

+ 101
- 15
include/gp/enveloppe/cbor.hpp ファイルの表示

@ -1,13 +1,14 @@
#pragma once
#include <gp/pair.hpp>
#include <gp/bitops.hpp>
#include <gp/optional.hpp>
#include <gp/pair.hpp>
#include <gp/variant.hpp>
#include <gp/vector.hpp>
namespace gp {
enum class cbor_type {
enum class cbor_type o">: uint8_t {
uint = 0,
nint = 1,
bstr = 2,
@ -18,7 +19,7 @@ namespace gp {
oths = 7
};
enum class cbor_oths {
enum class cbor_oths o">: uint8_t {
value_false = 20,
value_true = 21,
value_null = 22,
@ -55,16 +56,19 @@ namespace gp {
signature = 55799
};
using cbor_number = gp::fixed_variant<
int8_t,
uint8_t,
int16_t,
uint16_t,
int32_t,
uint32_t,
int64_t,
uint64_t
>;
struct cbor_number final {
bool sign;
uint64_t value;
bool is_negative() {
return sign;
}
cbor_number(int64_t v)
: sign{v < 0}
, value{uint64_t((sign ? -1 : 1) * v)}
{}
};
using cbor_floating_point = gp::fixed_variant<
float,
@ -75,13 +79,13 @@ namespace gp {
template<typename T>
using cbor_composite = gp::fixed_variant<
undefined_t,
cbor_number,
gp::buffer<std::byte>,
bool,
gp::vector<T>,
gp::vector<gp::pair<T, T>>,
gp::nullopt_t,
undefined_t,
cbor_floating_point
>;
@ -140,7 +144,6 @@ namespace gp {
return *this;
}
auto new_array() {
return gp::vector<cbor_value>{alloc};
}
@ -148,5 +151,88 @@ namespace gp {
auto new_object() {
return gp::vector<gp::pair<cbor_value, cbor_value>>{alloc};
}
static auto encode_length(buffer<std::byte> dest, cbor_type major, uint64_t value) {
auto num = value;
if(value <= 23) {
if(dest.size() < 1) return dest.begin();
dest[0] = std::byte(((uint8_t)major << 5u) + value);
return dest.begin()+1;
} else if(value <= 255) {
if(dest.size() < 2) return dest.begin();
dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::byte);
dest[1] = std::byte(value);
return dest.begin() + 2;
} else if(value <= 65535) {
if(dest.size() < 3) return dest.begin();
dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::word);
(dest.slice_start(3).slice_end(2).cast<gp::endian_wrapper<uint16_t, gp::endian::big>>())[0] = num.value;
return dest.begin()+3;
} else if(value <= 4294967295) {
if(dest.size() < 5) return dest.begin();
dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::dword);
(dest.slice_start(5).slice_end(4).cast<gp::endian_wrapper<uint32_t, gp::endian::big>>())[0] = num.value;
return dest.begin()+5;
} else {
if(dest.size() < 9) return dest.begin();
dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::qword);
(dest.slice_start(9).slice_end(8).cast<gp::endian_wrapper<uint64_t, gp::endian::big>>())[0] = num.value;
return dest.begin()+9;
}
}
auto encode(buffer<std::byte> dest) {
switch(contents.type()) {
case cbor_composite<cbor_value>::alt<undefined_t>(): {
if(dest.size() < 1) return dest.begin();
dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_undefined);
return dest.begin()+1;
}
case cbor_composite<cbor_value>::alt<cbor_number>(): {
auto& ref = contents.value<cbor_number>();
return encode_length(
dest,
ref.is_negative() ? cbor_type::nint : cbor_type::uint,
ref.value
);
}
case cbor_composite<cbor_value>::alt<gp::buffer<std::byte>>(): {
auto& ref = contents.value<gp::buffer<std::byte>>();
auto it = encode_length(
dest,
cbor_type::bstr,
ref.size()
);
if(it == dest.begin()) return it;
for(auto a : ref) {
*(it++) = a;
}
return it;
}
case cbor_composite<cbor_value>::alt<bool>(): {
if(dest.size() < 1) return dest.begin();
if(contents.value<bool>())
dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_true);
else
dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_false);
return dest.begin()+1;
}
case cbor_composite<cbor_value>::alt<gp::vector<cbor_value>>(): {
}
case cbor_composite<cbor_value>::alt<gp::vector<gp::pair<cbor_value, cbor_value>>>(): {
}
case cbor_composite<cbor_value>::alt<gp::nullopt_t>(): {
if(dest.size() < 1) return dest.begin();
dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_null);
return dest.begin()+1;
}
case cbor_composite<cbor_value>::alt<cbor_floating_point>(): {
}
}
}
};
}

+ 1
- 1
include/gp/variant.hpp ファイルの表示

@ -98,7 +98,7 @@ namespace gp{
}
template<typename U>
constexpr size_t alt() const {
constexpr k">static size_t alt() {
return r_index_of<U, T...>::value;
}

+ 7
- 5
tests/cbor_test.cpp ファイルの表示

@ -12,11 +12,6 @@ struct cbor_test : public test_scaffold {
virtual int run() {
gp::array<char, 4096> store;
gp::arena alloc{&*store.begin(), store.size()};
/*gp::cbor_value data{alloc};
auto gen = data.new_object();
gen.push_back(gp::make_pair(gp::cbor_value{uint8_t(12), alloc}, gp::cbor_value{int32_t(-98), alloc}));
gen.push_back(gp::make_pair(gp::cbor_value{uint8_t(13), alloc}, gp::cbor_value{uint32_t(98), alloc}));
data = gen;*/
using some_int = gp::fixed_variant<int, unsigned int, long long>;
{
@ -58,6 +53,13 @@ struct cbor_test : public test_scaffold {
gp_config::assertion(vec[0].is_a<unsigned int>(), "vec0 got wrong type assigned");
gp_config::assertion(vec[1].is_a<int>(), "vec1 got wrong type assigned");
}
{
gp::cbor_value data{alloc};
auto gen = data.new_object();
gen.push_back(gp::make_pair(gp::cbor_value{uint8_t(12), alloc}, gp::cbor_value{int32_t(-98), alloc}));
gen.push_back(gp::make_pair(gp::cbor_value{uint8_t(13), alloc}, gp::cbor_value{uint32_t(98), alloc}));
data = gen;
}
return 0;
}

読み込み中…
キャンセル
保存