General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

384 rivejä
10 KiB

4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
4 vuotta sitten
  1. #pragma once
  2. #include <gp/bitops.hpp>
  3. #include <gp/optional.hpp>
  4. #include <gp/pair.hpp>
  5. #include <gp/variant.hpp>
  6. #include <gp/vector.hpp>
  7. namespace gp {
  8. enum class cbor_type : uint8_t {
  9. uint = 0,
  10. nint = 1,
  11. bstr = 2,
  12. tstr = 3,
  13. list = 4,
  14. hmap = 5,
  15. tags = 6,
  16. oths = 7
  17. };
  18. enum class cbor_oths : uint8_t {
  19. value_false = 20,
  20. value_true = 21,
  21. value_null = 22,
  22. value_undefined = 23,
  23. byte = 24,
  24. word = 25,
  25. dword = 26,
  26. qword = 27,
  27. terminator = 31
  28. };
  29. enum class cbor_tags {
  30. datetime = 0,
  31. unix_time = 1,
  32. ubignum = 2,
  33. nbignum = 3,
  34. decimal = 4,
  35. bigfloat = 5,
  36. cose_encrypt0 = 16,
  37. cose_mac0 = 17,
  38. cose_sign1 = 18,
  39. expected_base64url = 21,
  40. expected_base64 = 22,
  41. expected_base16 = 23,
  42. encoded_cbor = 24,
  43. url = 32,
  44. base64url = 33,
  45. base64 = 34,
  46. regexp = 35,
  47. mime = 36,
  48. cose_encrypt = 96,
  49. cose_mac = 97,
  50. cose_sign = 98,
  51. signature = 55799
  52. };
  53. struct cbor_number final {
  54. bool sign;
  55. uint64_t value;
  56. bool is_negative() {
  57. return sign;
  58. }
  59. cbor_number(int64_t v)
  60. : sign{v < 0}
  61. , value{uint64_t((sign ? -1 : 1) * v)}
  62. {}
  63. cbor_number(bool s, uint64_t v)
  64. : sign{s}
  65. , value{v}
  66. {}
  67. };
  68. struct ieee754_hf final {
  69. uint16_t sign : 1;
  70. uint16_t exponent : 5;
  71. uint16_t mantissa : 10;
  72. };
  73. using cbor_floating_point = gp::fixed_variant<
  74. ieee754_hf,
  75. float,
  76. double
  77. >;
  78. struct undefined_t final {};
  79. template<typename T>
  80. using cbor_composite = gp::fixed_variant<
  81. undefined_t,
  82. cbor_number,
  83. gp::vector<std::byte>,
  84. bool,
  85. gp::vector<T>,
  86. gp::vector<gp::pair<T, T>>,
  87. gp::nullopt_t,
  88. cbor_floating_point
  89. >;
  90. class cbor_value {
  91. cbor_composite<cbor_value> contents;
  92. gp::reference_wrapper<allocator> alloc;
  93. public:
  94. cbor_value(allocator& alloc_v)
  95. : contents(cbor_composite<cbor_value>(undefined_t{}))
  96. , alloc(alloc_v)
  97. {}
  98. cbor_value(cbor_number number, allocator& alloc_v)
  99. : contents(number)
  100. , alloc(alloc_v)
  101. {}
  102. cbor_value(cbor_composite<cbor_value> val, allocator& alloc_v)
  103. : contents(val)
  104. , alloc(alloc_v)
  105. {}
  106. cbor_value(const cbor_value& oth)
  107. : contents(oth.contents)
  108. , alloc(oth.alloc)
  109. {}
  110. cbor_value(cbor_value&& oth)
  111. : contents(gp::move(oth.contents))
  112. , alloc(gp::move(oth.alloc))
  113. {}
  114. cbor_value& operator=(cbor_value& value) {
  115. contents = value.contents;
  116. alloc = value.alloc;
  117. return *this;
  118. }
  119. cbor_value& operator=(cbor_value&& value) {
  120. gp::swap(contents, value.contents);
  121. gp::swap(alloc, value.alloc);
  122. return *this;
  123. }
  124. cbor_value& operator=(cbor_composite<cbor_value>& value) {
  125. contents = value;
  126. return *this;
  127. }
  128. template<typename T>
  129. cbor_value& operator=(T& value) {
  130. contents = value;
  131. return *this;
  132. }
  133. template<typename T>
  134. cbor_value& operator=(T&& value) {
  135. contents = gp::move(value);
  136. return *this;
  137. }
  138. auto new_array() {
  139. return gp::vector<cbor_value>{alloc};
  140. }
  141. auto new_object() {
  142. return gp::vector<gp::pair<cbor_value, cbor_value>>{alloc};
  143. }
  144. static gp::pair<cbor_value, gp::buffer<std::byte>::associated_iterator> decode(allocator& alloc, gp::buffer<std::byte> src) {
  145. #define ERROR return {cbor_value{undefined_t{}, alloc}, src.begin()}
  146. if(src.size()==0) ERROR;
  147. auto discriminant = (cbor_type)(((uint8_t)*src.begin()) >> 5);
  148. auto local = uint8_t(((uint8_t)*src.begin()) & 0b00011111);
  149. switch(discriminant) {
  150. case cbor_type::uint:
  151. case cbor_type::nint: {
  152. if(local <= 23) {
  153. return {cbor_value{cbor_number{(bool)discriminant, local}, alloc}, src.begin()+1};
  154. } else {
  155. switch((cbor_oths)local) {
  156. case cbor_oths::byte: {
  157. if(src.size()<2) ERROR;
  158. return {
  159. cbor_value{
  160. cbor_number{(bool)discriminant, (uint8_t)*(src.begin()+1)},
  161. alloc
  162. },
  163. src.begin()+2
  164. };
  165. }
  166. case cbor_oths::word: {
  167. if(src.size()<3) ERROR;
  168. return {
  169. cbor_value{
  170. cbor_number{(bool)discriminant, uint16_t(*(gp::endian_wrapper<uint16_t, endian::big>*)(src.begin().data))},
  171. alloc
  172. },
  173. src.begin()+3
  174. };
  175. }
  176. case cbor_oths::dword: {
  177. if(src.size()<5) ERROR;
  178. return {
  179. cbor_value{
  180. cbor_number{(bool)discriminant, uint32_t(*(gp::endian_wrapper<uint32_t, endian::big>*)(src.begin().data))},
  181. alloc
  182. },
  183. src.begin()+5
  184. };
  185. }
  186. case cbor_oths::qword: {
  187. if(src.size()<9) ERROR;
  188. return {
  189. cbor_value{
  190. cbor_number{(bool)discriminant, uint64_t(*(gp::endian_wrapper<uint64_t, endian::big>*)(src.begin().data))},
  191. alloc
  192. },
  193. src.begin()+9
  194. };
  195. }
  196. default: {
  197. ERROR;
  198. }
  199. }
  200. }
  201. }
  202. case cbor_type::bstr: {
  203. }
  204. case cbor_type::tstr: {
  205. ERROR;
  206. }
  207. case cbor_type::list: {
  208. }
  209. case cbor_type::hmap: {
  210. }
  211. case cbor_type::tags: {
  212. }
  213. case cbor_type::oths: {
  214. }
  215. }
  216. ERROR;
  217. }
  218. static auto encode_float(buffer<std::byte> dest, cbor_floating_point& value) {
  219. switch(value.type()) {
  220. case cbor_floating_point::alt<ieee754_hf>():{
  221. if(dest.size() < 3) return dest.begin();
  222. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::word);
  223. (dest.slice_start(3).slice_end(2).cast<gp::endian_wrapper<ieee754_hf, gp::endian::big>>())[0] = value.value<ieee754_hf>();
  224. return dest.begin()+3;
  225. }
  226. case cbor_floating_point::alt<float>():{
  227. if(dest.size() < 5) return dest.begin();
  228. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::dword);
  229. (dest.slice_start(5).slice_end(4).cast<gp::endian_wrapper<float, gp::endian::big>>())[0] = value.value<float>();
  230. return dest.begin()+5;
  231. }
  232. case cbor_floating_point::alt<double>():{
  233. if(dest.size() < 9) return dest.begin();
  234. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::qword);
  235. (dest.slice_start(9).slice_end(8).cast<gp::endian_wrapper<double, gp::endian::big>>())[0] = value.value<double>();
  236. return dest.begin()+9;
  237. }
  238. default: return dest.begin();
  239. }
  240. }
  241. static auto encode_length(buffer<std::byte> dest, cbor_type major, uint64_t value) {
  242. auto num = value;
  243. if(value <= 23) {
  244. if(dest.size() < 1) return dest.begin();
  245. dest[0] = std::byte(((uint8_t)major << 5u) + value);
  246. return dest.begin()+1;
  247. } else if(value <= 255) {
  248. if(dest.size() < 2) return dest.begin();
  249. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::byte);
  250. dest[1] = std::byte(value);
  251. return dest.begin() + 2;
  252. } else if(value <= 65535) {
  253. if(dest.size() < 3) return dest.begin();
  254. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::word);
  255. (dest.slice_start(3).slice_end(2).cast<gp::endian_wrapper<uint16_t, gp::endian::big>>())[0] = num;
  256. return dest.begin()+3;
  257. } else if(value <= 4294967295) {
  258. if(dest.size() < 5) return dest.begin();
  259. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::dword);
  260. (dest.slice_start(5).slice_end(4).cast<gp::endian_wrapper<uint32_t, gp::endian::big>>())[0] = num;
  261. return dest.begin()+5;
  262. } else {
  263. if(dest.size() < 9) return dest.begin();
  264. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::qword);
  265. (dest.slice_start(9).slice_end(8).cast<gp::endian_wrapper<uint64_t, gp::endian::big>>())[0] = num;
  266. return dest.begin()+9;
  267. }
  268. }
  269. auto encode(buffer<std::byte> dest) {
  270. switch(contents.type()) {
  271. case cbor_composite<cbor_value>::alt<undefined_t>(): {
  272. if(dest.size() < 1) return dest.begin();
  273. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_undefined);
  274. return dest.begin()+1;
  275. }
  276. case cbor_composite<cbor_value>::alt<cbor_number>(): {
  277. auto& ref = contents.value<cbor_number>();
  278. return encode_length(
  279. dest,
  280. ref.is_negative() ? cbor_type::nint : cbor_type::uint,
  281. ref.value
  282. );
  283. }
  284. case cbor_composite<cbor_value>::alt<gp::vector<std::byte>>(): {
  285. auto& ref = contents.value<gp::vector<std::byte>>();
  286. auto it = encode_length(
  287. dest,
  288. cbor_type::bstr,
  289. ref.size()
  290. );
  291. if(it == dest.begin()) return it;
  292. for(auto a : ref) {
  293. *(it++) = a;
  294. }
  295. return it;
  296. }
  297. case cbor_composite<cbor_value>::alt<bool>(): {
  298. if(dest.size() < 1) return dest.begin();
  299. if(contents.value<bool>())
  300. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_true);
  301. else
  302. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_false);
  303. return dest.begin()+1;
  304. }
  305. case cbor_composite<cbor_value>::alt<gp::vector<cbor_value>>(): {
  306. auto& ary = contents.value<gp::vector<cbor_value>>();
  307. auto it_begin = encode_length(dest, cbor_type::list, ary.size());
  308. if(it_begin == dest.begin()) return dest.begin();
  309. for(auto& elem : ary) {
  310. auto slice = dest.slice_end(dest.size() - (it_begin - dest.begin()));
  311. auto it = elem.encode(slice);
  312. if(it == it_begin)
  313. return dest.begin();
  314. it_begin = it;
  315. }
  316. return it_begin;
  317. }
  318. case cbor_composite<cbor_value>::alt<gp::vector<gp::pair<cbor_value, cbor_value>>>(): {
  319. auto& ary = contents.value<gp::vector<gp::pair<cbor_value,cbor_value>>>();
  320. auto it_begin = encode_length(dest, cbor_type::hmap, ary.size());
  321. if(it_begin == dest.begin()) return dest.begin();
  322. for(auto& elem : ary) {
  323. auto slice = dest.slice_end(dest.size() - (it_begin - dest.begin()));
  324. auto it = elem.first.encode(slice);
  325. if(it == it_begin) return dest.begin();
  326. it_begin = it;
  327. slice = dest.slice_end(dest.size() - (it_begin - dest.begin()));
  328. it = elem.second.encode(slice);
  329. if(it == it_begin) return dest.begin();
  330. it_begin = it;
  331. }
  332. return it_begin;
  333. }
  334. case cbor_composite<cbor_value>::alt<gp::nullopt_t>(): {
  335. if(dest.size() < 1) return dest.begin();
  336. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_null);
  337. return dest.begin()+1;
  338. }
  339. case cbor_composite<cbor_value>::alt<cbor_floating_point>(): {
  340. return encode_float(dest, contents.value<cbor_floating_point>());
  341. }
  342. default: return dest.begin();
  343. }
  344. }
  345. };
  346. }