General Purpose library for Freestanding C++ and POSIX systems
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

509 řádky
14 KiB

před 4 roky
před 4 roky
před 4 roky
před 4 roky
před 4 roky
před 4 roky
před 4 roky
před 4 roky
před 4 roky
před 4 roky
před 4 roky
před 4 roky
před 4 roky
před 4 roky
před 4 roky
  1. #pragma once
  2. #include <gp/algorithm/repeat.hpp>
  3. #include <gp/bitops.hpp>
  4. #include <gp/optional.hpp>
  5. #include <gp/pair.hpp>
  6. #include <gp/variant.hpp>
  7. #include <gp/vector.hpp>
  8. namespace gp {
  9. enum class cbor_type : uint8_t {
  10. uint = 0,
  11. nint = 1,
  12. bstr = 2,
  13. tstr = 3,
  14. list = 4,
  15. hmap = 5,
  16. tags = 6,
  17. oths = 7
  18. };
  19. enum class cbor_oths : uint8_t {
  20. value_false = 20,
  21. value_true = 21,
  22. value_null = 22,
  23. value_undefined = 23,
  24. byte = 24,
  25. word = 25,
  26. dword = 26,
  27. qword = 27,
  28. terminator = 31
  29. };
  30. enum class cbor_tags {
  31. datetime = 0,
  32. unix_time = 1,
  33. ubignum = 2,
  34. nbignum = 3,
  35. decimal = 4,
  36. bigfloat = 5,
  37. cose_encrypt0 = 16,
  38. cose_mac0 = 17,
  39. cose_sign1 = 18,
  40. expected_base64url = 21,
  41. expected_base64 = 22,
  42. expected_base16 = 23,
  43. encoded_cbor = 24,
  44. url = 32,
  45. base64url = 33,
  46. base64 = 34,
  47. regexp = 35,
  48. mime = 36,
  49. cose_encrypt = 96,
  50. cose_mac = 97,
  51. cose_sign = 98,
  52. signature = 55799
  53. };
  54. struct cbor_number final {
  55. bool sign;
  56. uint64_t value;
  57. bool is_negative() {
  58. return sign;
  59. }
  60. cbor_number(int64_t v)
  61. : sign{v < 0}
  62. , value{uint64_t((sign ? -1 : 1) * v)}
  63. {}
  64. cbor_number(bool s, uint64_t v)
  65. : sign{s}
  66. , value{v}
  67. {}
  68. };
  69. struct ieee754_hf final {
  70. uint16_t sign : 1;
  71. uint16_t exponent : 5;
  72. uint16_t mantissa : 10;
  73. };
  74. using cbor_floating_point = gp::fixed_variant<
  75. ieee754_hf,
  76. float,
  77. double
  78. >;
  79. struct undefined_t final {};
  80. template<typename T>
  81. using cbor_composite = gp::fixed_variant<
  82. undefined_t,
  83. cbor_number,
  84. gp::vector<std::byte>,
  85. bool,
  86. gp::vector<T>,
  87. gp::vector<gp::pair<T, T>>,
  88. gp::nullopt_t,
  89. cbor_floating_point
  90. >;
  91. class cbor_value {
  92. cbor_composite<cbor_value> contents;
  93. gp::reference_wrapper<allocator> alloc;
  94. public:
  95. cbor_value(allocator& alloc_v)
  96. : contents(cbor_composite<cbor_value>(undefined_t{}))
  97. , alloc(alloc_v)
  98. {}
  99. cbor_value(cbor_number number, allocator& alloc_v)
  100. : contents(number)
  101. , alloc(alloc_v)
  102. {}
  103. cbor_value(cbor_composite<cbor_value> val, allocator& alloc_v)
  104. : contents(val)
  105. , alloc(alloc_v)
  106. {}
  107. cbor_value(const cbor_value& oth)
  108. : contents(oth.contents)
  109. , alloc(oth.alloc)
  110. {}
  111. cbor_value(cbor_value&& oth)
  112. : contents(gp::move(oth.contents))
  113. , alloc(gp::move(oth.alloc))
  114. {}
  115. cbor_value& operator=(cbor_value& value) {
  116. contents = value.contents;
  117. alloc = value.alloc;
  118. return *this;
  119. }
  120. cbor_value& operator=(cbor_value&& value) {
  121. gp::swap(contents, value.contents);
  122. gp::swap(alloc, value.alloc);
  123. return *this;
  124. }
  125. cbor_value& operator=(cbor_composite<cbor_value>& value) {
  126. contents = value;
  127. return *this;
  128. }
  129. template<typename T>
  130. cbor_value& operator=(T& value) {
  131. contents = value;
  132. return *this;
  133. }
  134. template<typename T>
  135. cbor_value& operator=(T&& value) {
  136. contents = gp::move(value);
  137. return *this;
  138. }
  139. auto new_array() {
  140. return gp::vector<cbor_value>{alloc};
  141. }
  142. auto new_object() {
  143. return gp::vector<gp::pair<cbor_value, cbor_value>>{alloc};
  144. }
  145. static gp::pair<uint64_t, gp::buffer<std::byte>::associated_iterator> decode_integer(gp::buffer<std::byte> src) {
  146. #define ERROR return {0, src.begin()}
  147. auto local = (uint8_t)0b00011111 & (uint8_t)src[0];
  148. if(local <= 23) {
  149. return {local, src.begin()+1};
  150. } else {
  151. switch((cbor_oths)local) {
  152. case cbor_oths::byte: {
  153. if(src.size()<2) ERROR;
  154. return {
  155. (uint8_t)*(src.begin()+1),
  156. src.begin()+2
  157. };
  158. }
  159. case cbor_oths::word: {
  160. if(src.size()<3) ERROR;
  161. return {
  162. uint16_t(*(gp::endian_wrapper<uint16_t, endian::big>*)(src.begin().data)),
  163. src.begin()+3
  164. };
  165. }
  166. case cbor_oths::dword: {
  167. if(src.size()<5) ERROR;
  168. return {
  169. uint32_t(*(gp::endian_wrapper<uint32_t, endian::big>*)(src.begin().data)),
  170. src.begin()+5
  171. };
  172. }
  173. case cbor_oths::qword: {
  174. if(src.size()<9) ERROR;
  175. return {
  176. uint64_t(*(gp::endian_wrapper<uint64_t, endian::big>*)(src.begin().data)),
  177. src.begin()+9
  178. };
  179. }
  180. default: {
  181. ERROR;
  182. }
  183. }
  184. }
  185. #undef ERROR
  186. }
  187. static gp::pair<cbor_value, gp::buffer<std::byte>::associated_iterator> decode(allocator& alloc, gp::buffer<std::byte> src) {
  188. #define ERROR return {cbor_value{undefined_t{}, alloc}, src.begin()}
  189. if(src.size()==0) ERROR;
  190. auto discriminant = (cbor_type)(((uint8_t)*src.begin()) >> 5);
  191. auto local = uint8_t(((uint8_t)*src.begin()) & 0b00011111);
  192. switch(discriminant) {
  193. case cbor_type::uint:
  194. case cbor_type::nint: {
  195. auto nb = decode_integer(src);
  196. return {cbor_value{cbor_number{(bool)discriminant, nb.first}, alloc}, nb.second};
  197. }
  198. case cbor_type::bstr: {
  199. gp::vector<std::byte> str{alloc};
  200. if(local == 31) {
  201. auto sub = src.slice_end(src.size() - 1);
  202. if(!sub.size()) ERROR;
  203. while((uint8_t)sub[0] && 0b00011111 != 31) {
  204. auto len = decode_integer(sub);
  205. if(len.second == sub.begin()) ERROR;
  206. str.reserve(str.size() + len.first);
  207. auto end = (len.second + len.first);
  208. if(len.first + (len.second - src.begin()) > src.size()) ERROR;
  209. for(auto it = len.second; it != end; it++) {
  210. str.push_back(*it);
  211. }
  212. sub = sub.slice_end(sub.size() - (len.first + (len.second - sub.begin())));
  213. }
  214. return {cbor_value{str, alloc}, sub.begin()+1};
  215. } else if(auto len = decode_integer(src); len.second != src.begin()) {
  216. str.reserve(len.first);
  217. auto end = (len.second + len.first);
  218. if(len.first + (len.second - src.begin()) > src.size()) ERROR;
  219. for(auto it = len.second; it != end; it++) {
  220. str.push_back(*it);
  221. }
  222. return {cbor_value{str, alloc}, end};
  223. }
  224. ERROR;
  225. }
  226. case cbor_type::tstr: {
  227. ERROR;
  228. }
  229. case cbor_type::list: {
  230. gp::vector<cbor_value> list{alloc};
  231. if(local == 31) {
  232. // TODO: Add the indefinite length version
  233. } else if(auto len = decode_integer(src); len.second != src.begin()) {
  234. auto sub = src.slice_end(src.size()-(len.second - src.begin()));
  235. while(len.first--) {
  236. auto tmp = decode(alloc, sub);
  237. if(tmp.second == sub.begin()) ERROR;
  238. list.push_back(tmp.first);
  239. sub = sub.slice_end(sub.size() - (tmp.second - sub.begin()));
  240. }
  241. return {cbor_value{list, alloc}, sub.begin()};
  242. }
  243. ERROR;
  244. }
  245. case cbor_type::hmap: {
  246. gp::vector<gp::pair<cbor_value, cbor_value>> list{alloc};
  247. if(local == 31) {
  248. // TODO: Add the indefinite length version
  249. } else if(auto len = decode_integer(src); len.second != src.begin()) {
  250. auto sub = src.slice_end(src.size()-(len.second - src.begin()));
  251. while(len.first--) {
  252. auto tmpl = decode(alloc, sub);
  253. if(tmpl.second == sub.begin()) ERROR;
  254. sub = sub.slice_end(sub.size() - (tmpl.second - sub.begin()));
  255. auto tmpr = decode(alloc, sub);
  256. if(tmpr.second == sub.begin()) ERROR;
  257. list.push_back(gp::make_pair(
  258. tmpl.first,
  259. tmpr.first
  260. ));
  261. sub = sub.slice_end(sub.size() - (tmpr.second - sub.begin()));
  262. }
  263. return {cbor_value{list, alloc}, sub.begin()};
  264. }
  265. ERROR;
  266. }
  267. case cbor_type::tags: {
  268. }
  269. case cbor_type::oths: {
  270. switch((cbor_oths)local) {
  271. case cbor_oths::value_false: {
  272. return {
  273. cbor_value{
  274. cbor_composite<cbor_value>(false),
  275. alloc
  276. },
  277. src.begin()+1
  278. };
  279. }
  280. case cbor_oths::value_true: {
  281. return {
  282. cbor_value{
  283. cbor_composite<cbor_value>(true),
  284. alloc
  285. },
  286. src.begin()+1
  287. };
  288. }
  289. case cbor_oths::value_null: {
  290. return {
  291. cbor_value{
  292. cbor_composite<cbor_value>(nullopt),
  293. alloc
  294. },
  295. src.begin()+1
  296. };
  297. }
  298. case cbor_oths::value_undefined: {
  299. return {
  300. cbor_value{
  301. cbor_composite<cbor_value>(undefined_t{}),
  302. alloc
  303. },
  304. src.begin()+1
  305. };
  306. }
  307. case cbor_oths::word: {
  308. if(src.size()<3) ERROR;
  309. return {
  310. cbor_value{
  311. cbor_floating_point{(ieee754_hf)(*(gp::endian_wrapper<ieee754_hf, endian::big>*)(src.begin().data))},
  312. alloc
  313. },
  314. src.begin()+3
  315. };
  316. }
  317. case cbor_oths::dword: {
  318. if(src.size()<5) ERROR;
  319. return {
  320. cbor_value{
  321. cbor_floating_point{float(*(gp::endian_wrapper<float, endian::big>*)(src.begin().data))},
  322. alloc
  323. },
  324. src.begin()+5
  325. };
  326. }
  327. case cbor_oths::qword: {
  328. if(src.size()<9) ERROR;
  329. return {
  330. cbor_value{
  331. cbor_floating_point{double(*(gp::endian_wrapper<double, endian::big>*)(src.begin().data))},
  332. alloc
  333. },
  334. src.begin()+9
  335. };
  336. }
  337. default: {
  338. ERROR;
  339. }
  340. }
  341. }
  342. }
  343. ERROR;
  344. #undef ERROR
  345. }
  346. static auto encode_float(buffer<std::byte> dest, cbor_floating_point& value) {
  347. switch(value.type()) {
  348. case cbor_floating_point::alt<ieee754_hf>():{
  349. if(dest.size() < 3) return dest.begin();
  350. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::word);
  351. (dest.slice_start(3).slice_end(2).cast<gp::endian_wrapper<ieee754_hf, gp::endian::big>>())[0] = value.value<ieee754_hf>();
  352. return dest.begin()+3;
  353. }
  354. case cbor_floating_point::alt<float>():{
  355. if(dest.size() < 5) return dest.begin();
  356. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::dword);
  357. (dest.slice_start(5).slice_end(4).cast<gp::endian_wrapper<float, gp::endian::big>>())[0] = value.value<float>();
  358. return dest.begin()+5;
  359. }
  360. case cbor_floating_point::alt<double>():{
  361. if(dest.size() < 9) return dest.begin();
  362. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::qword);
  363. (dest.slice_start(9).slice_end(8).cast<gp::endian_wrapper<double, gp::endian::big>>())[0] = value.value<double>();
  364. return dest.begin()+9;
  365. }
  366. default: return dest.begin();
  367. }
  368. }
  369. static auto encode_length(buffer<std::byte> dest, cbor_type major, uint64_t value) {
  370. auto num = value;
  371. if(value <= 23) {
  372. if(dest.size() < 1) return dest.begin();
  373. dest[0] = std::byte(((uint8_t)major << 5u) + value);
  374. return dest.begin()+1;
  375. } else if(value <= 255) {
  376. if(dest.size() < 2) return dest.begin();
  377. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::byte);
  378. dest[1] = std::byte(value);
  379. return dest.begin() + 2;
  380. } else if(value <= 65535) {
  381. if(dest.size() < 3) return dest.begin();
  382. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::word);
  383. (dest.slice_start(3).slice_end(2).cast<gp::endian_wrapper<uint16_t, gp::endian::big>>())[0] = num;
  384. return dest.begin()+3;
  385. } else if(value <= 4294967295) {
  386. if(dest.size() < 5) return dest.begin();
  387. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::dword);
  388. (dest.slice_start(5).slice_end(4).cast<gp::endian_wrapper<uint32_t, gp::endian::big>>())[0] = num;
  389. return dest.begin()+5;
  390. } else {
  391. if(dest.size() < 9) return dest.begin();
  392. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::qword);
  393. (dest.slice_start(9).slice_end(8).cast<gp::endian_wrapper<uint64_t, gp::endian::big>>())[0] = num;
  394. return dest.begin()+9;
  395. }
  396. }
  397. auto encode(buffer<std::byte> dest) {
  398. switch(contents.type()) {
  399. case cbor_composite<cbor_value>::alt<undefined_t>(): {
  400. if(dest.size() < 1) return dest.begin();
  401. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_undefined);
  402. return dest.begin()+1;
  403. }
  404. case cbor_composite<cbor_value>::alt<cbor_number>(): {
  405. auto& ref = contents.value<cbor_number>();
  406. return encode_length(
  407. dest,
  408. ref.is_negative() ? cbor_type::nint : cbor_type::uint,
  409. ref.value
  410. );
  411. }
  412. case cbor_composite<cbor_value>::alt<gp::vector<std::byte>>(): {
  413. auto& ref = contents.value<gp::vector<std::byte>>();
  414. auto it = encode_length(
  415. dest,
  416. cbor_type::bstr,
  417. ref.size()
  418. );
  419. if(it == dest.begin()) return it;
  420. for(auto a : ref) {
  421. *(it++) = a;
  422. }
  423. return it;
  424. }
  425. case cbor_composite<cbor_value>::alt<bool>(): {
  426. if(dest.size() < 1) return dest.begin();
  427. if(contents.value<bool>())
  428. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_true);
  429. else
  430. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_false);
  431. return dest.begin()+1;
  432. }
  433. case cbor_composite<cbor_value>::alt<gp::vector<cbor_value>>(): {
  434. auto& ary = contents.value<gp::vector<cbor_value>>();
  435. auto it_begin = encode_length(dest, cbor_type::list, ary.size());
  436. if(it_begin == dest.begin()) return dest.begin();
  437. for(auto& elem : ary) {
  438. auto slice = dest.slice_end(dest.size() - (it_begin - dest.begin()));
  439. auto it = elem.encode(slice);
  440. if(it == it_begin)
  441. return dest.begin();
  442. it_begin = it;
  443. }
  444. return it_begin;
  445. }
  446. case cbor_composite<cbor_value>::alt<gp::vector<gp::pair<cbor_value, cbor_value>>>(): {
  447. auto& ary = contents.value<gp::vector<gp::pair<cbor_value,cbor_value>>>();
  448. auto it_begin = encode_length(dest, cbor_type::hmap, ary.size());
  449. if(it_begin == dest.begin()) return dest.begin();
  450. for(auto& elem : ary) {
  451. auto slice = dest.slice_end(dest.size() - (it_begin - dest.begin()));
  452. auto it = elem.first.encode(slice);
  453. if(it == it_begin) return dest.begin();
  454. it_begin = it;
  455. slice = dest.slice_end(dest.size() - (it_begin - dest.begin()));
  456. it = elem.second.encode(slice);
  457. if(it == it_begin) return dest.begin();
  458. it_begin = it;
  459. }
  460. return it_begin;
  461. }
  462. case cbor_composite<cbor_value>::alt<gp::nullopt_t>(): {
  463. if(dest.size() < 1) return dest.begin();
  464. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_null);
  465. return dest.begin()+1;
  466. }
  467. case cbor_composite<cbor_value>::alt<cbor_floating_point>(): {
  468. return encode_float(dest, contents.value<cbor_floating_point>());
  469. }
  470. default: return dest.begin();
  471. }
  472. }
  473. };
  474. }