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.

642 regels
18 KiB

3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
3 jaren geleden
  1. #pragma once
  2. #include <gp/algorithms/repeat.hpp>
  3. #include <gp/math/boolean/bitops.hpp>
  4. #include <gp/functional/optional.hpp>
  5. #include <gp/utils/pair.hpp>
  6. #include <gp/functional/variant.hpp>
  7. #include <gp/containers/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. // TODO: support for denormalized values and NaNs
  74. operator float() {
  75. auto a = (uint32_t)((sign<<16) | ((exponent+0x1C000)<<13) | (mantissa<<13));
  76. return *(float*)&a;
  77. }
  78. operator double() {
  79. return (float)*this;
  80. }
  81. };
  82. struct cbor_floating_point final {
  83. using backing = gp::fixed_variant<
  84. ieee754_hf,
  85. float,
  86. double
  87. >;
  88. backing contents;
  89. cbor_floating_point(backing& p)
  90. : contents{p}{}
  91. cbor_floating_point(ieee754_hf p)
  92. : contents{p}{}
  93. cbor_floating_point(float p)
  94. : contents{p}{}
  95. cbor_floating_point(double p)
  96. : contents{p}{}
  97. operator ieee754_hf() {
  98. return contents.value<ieee754_hf>();
  99. }
  100. operator float() {
  101. switch(contents.type()) {
  102. case backing::alt<ieee754_hf>():
  103. return contents.value<ieee754_hf>();
  104. case backing::alt<float>():
  105. return contents.value<float>();
  106. default:
  107. gp_config::assertion(false,"this code should never be reached");
  108. return std::numeric_limits<float>::quiet_NaN();
  109. }
  110. }
  111. operator double() {
  112. switch(contents.type()) {
  113. case backing::alt<ieee754_hf>():
  114. return contents.value<ieee754_hf>();
  115. case backing::alt<float>():
  116. return contents.value<float>();
  117. case backing::alt<double>():
  118. return contents.value<double>();
  119. default:
  120. gp_config::assertion(false,"this code should never be reached");
  121. return std::numeric_limits<double>::quiet_NaN();
  122. }
  123. }
  124. };
  125. struct undefined_t final {};
  126. template<typename T>
  127. using cbor_composite = gp::fixed_variant<
  128. gp::undefined_t,
  129. cbor_number,
  130. gp::vector<std::byte>,
  131. bool,
  132. gp::vector<T>,
  133. gp::vector<gp::pair<T, T>>,
  134. gp::nullopt_t,
  135. cbor_floating_point
  136. >;
  137. class cbor_value {
  138. cbor_composite<cbor_value> contents;
  139. gp::reference_wrapper<allocator> alloc;
  140. public:
  141. cbor_value(allocator& alloc_v)
  142. : contents()
  143. , alloc(alloc_v)
  144. {}
  145. cbor_value(cbor_number number, allocator& alloc_v)
  146. : contents(number)
  147. , alloc(alloc_v)
  148. {}
  149. cbor_value(cbor_composite<cbor_value> val, allocator& alloc_v)
  150. : contents(val)
  151. , alloc(alloc_v)
  152. {}
  153. cbor_value(const cbor_value& oth)
  154. : contents(oth.contents)
  155. , alloc(oth.alloc)
  156. {}
  157. cbor_value(cbor_value&& oth)
  158. : contents(gp::move(oth.contents))
  159. , alloc(gp::move(oth.alloc))
  160. {}
  161. cbor_value& operator=(cbor_value& value) {
  162. contents = value.contents;
  163. alloc = value.alloc;
  164. return *this;
  165. }
  166. cbor_value& operator=(cbor_value&& value) {
  167. gp::swap(contents, value.contents);
  168. gp::swap(alloc, value.alloc);
  169. return *this;
  170. }
  171. cbor_value& operator=(cbor_composite<cbor_value>& value) {
  172. contents = value;
  173. return *this;
  174. }
  175. template<typename T>
  176. cbor_value& operator=(T& value) {
  177. contents = value;
  178. return *this;
  179. }
  180. template<typename T>
  181. cbor_value& operator=(T&& value) {
  182. contents = gp::move(value);
  183. return *this;
  184. }
  185. auto new_array() {
  186. return gp::vector<cbor_value>{alloc};
  187. }
  188. auto new_object() {
  189. return gp::vector<gp::pair<cbor_value, cbor_value>>{alloc};
  190. }
  191. static gp::pair<uint64_t, gp::buffer<std::byte>::associated_iterator> decode_integer(gp::buffer<std::byte> src) {
  192. #define ERROR return {0, src.begin()}
  193. auto local = (uint8_t)0b00011111 & (uint8_t)src[0];
  194. if(local <= 23) {
  195. return {local, src.begin()+1};
  196. } else {
  197. switch((cbor_oths)local) {
  198. case cbor_oths::byte: {
  199. if(src.size()<2) ERROR;
  200. return {
  201. (uint8_t)*(src.begin()+1),
  202. src.begin()+2
  203. };
  204. }
  205. case cbor_oths::word: {
  206. if(src.size()<3) ERROR;
  207. return {
  208. uint16_t(*(src.slice_start(3).slice_end(2).cast<gp::endian_wrapper<uint16_t, endian::big>>().begin().data)),
  209. src.begin()+3
  210. };
  211. }
  212. case cbor_oths::dword: {
  213. if(src.size()<5) ERROR;
  214. return {
  215. uint32_t(*(src.slice_start(5).slice_end(4).cast<gp::endian_wrapper<uint32_t, endian::big>>().begin().data)),
  216. src.begin()+5
  217. };
  218. }
  219. case cbor_oths::qword: {
  220. if(src.size()<9) ERROR;
  221. return {
  222. uint64_t(*(src.slice_start(9).slice_end(8).cast<gp::endian_wrapper<uint64_t, endian::big>>().begin().data)),
  223. src.begin()+9
  224. };
  225. }
  226. default: {
  227. ERROR;
  228. }
  229. }
  230. }
  231. #undef ERROR
  232. }
  233. template<typename U>
  234. bool is_a() {
  235. if constexpr (
  236. std::is_same_v<U, uint8_t>
  237. || std::is_same_v<U, uint16_t>
  238. || std::is_same_v<U, uint32_t>
  239. || std::is_same_v<U, uint64_t>
  240. || std::is_same_v<U, int8_t>
  241. || std::is_same_v<U, int16_t>
  242. || std::is_same_v<U, int32_t>
  243. || std::is_same_v<U, int64_t>
  244. ) {
  245. if(contents.is_a<cbor_number>())
  246. {
  247. auto& v = contents.value<cbor_number>();
  248. if(!std::is_signed_v<U> && v.is_negative()) return false;
  249. if(
  250. std::numeric_limits<int64_t>::max()<v.value
  251. && (
  252. !std::is_same_v<U, uint64_t>
  253. || v.is_negative()
  254. )
  255. ) return false;
  256. int64_t signed_v = (v.is_negative() ? -1 : 1 ) * v.value;
  257. if(
  258. std::numeric_limits<U>::min() <= signed_v
  259. && std::numeric_limits<U>::max() >= signed_v
  260. ) return true;
  261. return false;
  262. } else return false;
  263. } else if constexpr (
  264. std::is_same_v<U, ieee754_hf>
  265. || std::is_same_v<U, float>
  266. || std::is_same_v<U, double>
  267. ) {
  268. auto& v = contents.value<cbor_floating_point>();
  269. switch(v.contents.type()) {
  270. case cbor_floating_point::backing::alt<ieee754_hf>():
  271. return std::is_same_v<U, ieee754_hf>;
  272. case cbor_floating_point::backing::alt<float>():
  273. return std::is_same_v<U, float> || std::is_same_v<U, ieee754_hf>;
  274. case cbor_floating_point::backing::alt<double>():
  275. return std::is_same_v<U, double> || std::is_same_v<U, float> || std::is_same_v<U, ieee754_hf>;
  276. default:
  277. return false;
  278. }
  279. } else {
  280. return contents.is_a<U>();
  281. }
  282. }
  283. template<typename U>
  284. U get_value() {
  285. gp_config::assertion(is_a<U>(), "can't convert value legally");
  286. if constexpr (
  287. std::is_same_v<U, uint8_t>
  288. || std::is_same_v<U, uint16_t>
  289. || std::is_same_v<U, uint32_t>
  290. || std::is_same_v<U, uint64_t>
  291. || std::is_same_v<U, int8_t>
  292. || std::is_same_v<U, int16_t>
  293. || std::is_same_v<U, int32_t>
  294. || std::is_same_v<U, int64_t>
  295. ) {
  296. auto& v = contents.value<cbor_number>();
  297. return (v.is_negative() ? -1 : 1 ) * v.value;
  298. } else if constexpr (
  299. std::is_same_v<U, ieee754_hf>
  300. || std::is_same_v<U, float>
  301. || std::is_same_v<U, double>
  302. ) {
  303. auto& v = contents.value<cbor_floating_point>();
  304. return v;
  305. } else {
  306. return contents.value<U>();
  307. }
  308. }
  309. static gp::pair<cbor_value, gp::buffer<std::byte>::associated_iterator> decode(allocator& alloc, gp::buffer<std::byte> src) {
  310. #define ERROR return {cbor_value{alloc}, src.begin()}
  311. if(src.size()==0) ERROR;
  312. auto discriminant = (cbor_type)(((uint8_t)*src.begin()) >> 5);
  313. auto local = uint8_t(((uint8_t)*src.begin()) & 0b00011111);
  314. switch(discriminant) {
  315. case cbor_type::uint:
  316. case cbor_type::nint: {
  317. auto nb = decode_integer(src);
  318. return {cbor_value{cbor_number{(bool)discriminant, nb.first}, alloc}, nb.second};
  319. }
  320. case cbor_type::bstr: {
  321. gp::vector<std::byte> str{alloc};
  322. if(local == 31) {
  323. auto sub = src.slice_end(src.size() - 1);
  324. if(!sub.size()) ERROR;
  325. while((uint8_t)sub[0] && 0b00011111 != 31) {
  326. auto len = decode_integer(sub);
  327. if(len.second == sub.begin()) ERROR;
  328. str.reserve(str.size() + len.first);
  329. auto end = (len.second + len.first);
  330. if(len.first + (len.second - src.begin()) > src.size()) ERROR;
  331. for(auto it = len.second; it != end; it++) {
  332. str.push_back(*it);
  333. }
  334. sub = sub.slice_end(sub.size() - (len.first + (len.second - sub.begin())));
  335. }
  336. return {cbor_value{str, alloc}, sub.begin()+1};
  337. } else if(auto len = decode_integer(src); len.second != src.begin()) {
  338. str.reserve(len.first);
  339. auto end = (len.second + len.first);
  340. if(len.first + (len.second - src.begin()) > src.size()) ERROR;
  341. for(auto it = len.second; it != end; it++) {
  342. str.push_back(*it);
  343. }
  344. return {cbor_value{str, alloc}, end};
  345. }
  346. ERROR;
  347. }
  348. case cbor_type::tstr: {
  349. ERROR;
  350. }
  351. case cbor_type::list: {
  352. gp::vector<cbor_value> list{alloc};
  353. if(local == 31) {
  354. // TODO: Add the indefinite length version
  355. } else if(auto len = decode_integer(src); len.second != src.begin()) {
  356. auto sub = src.slice_end(src.size()-(len.second - src.begin()));
  357. while(len.first--) {
  358. auto tmp = decode(alloc, sub);
  359. if(tmp.second == sub.begin()) ERROR;
  360. list.push_back(tmp.first);
  361. sub = sub.slice_end(sub.size() - (tmp.second - sub.begin()));
  362. }
  363. return {cbor_value{list, alloc}, sub.begin()};
  364. }
  365. ERROR;
  366. }
  367. case cbor_type::hmap: {
  368. gp::vector<gp::pair<cbor_value, cbor_value>> list{alloc};
  369. if(local == 31) {
  370. // TODO: Add the indefinite length version
  371. } else if(auto len = decode_integer(src); len.second != src.begin()) {
  372. auto sub = src.slice_end(src.size()-(len.second - src.begin()));
  373. while(len.first--) {
  374. auto tmpl = decode(alloc, sub);
  375. if(tmpl.second == sub.begin()) ERROR;
  376. sub = sub.slice_end(sub.size() - (tmpl.second - sub.begin()));
  377. auto tmpr = decode(alloc, sub);
  378. if(tmpr.second == sub.begin()) ERROR;
  379. list.push_back(gp::make_pair(
  380. tmpl.first,
  381. tmpr.first
  382. ));
  383. sub = sub.slice_end(sub.size() - (tmpr.second - sub.begin()));
  384. }
  385. return {cbor_value{list, alloc}, sub.begin()};
  386. }
  387. ERROR;
  388. }
  389. case cbor_type::tags: {
  390. // TODO: add tag decoding methods
  391. }
  392. case cbor_type::oths: {
  393. switch((cbor_oths)local) {
  394. case cbor_oths::value_false: {
  395. return {
  396. cbor_value{
  397. cbor_composite<cbor_value>(false),
  398. alloc
  399. },
  400. src.begin()+1
  401. };
  402. }
  403. case cbor_oths::value_true: {
  404. return {
  405. cbor_value{
  406. cbor_composite<cbor_value>(true),
  407. alloc
  408. },
  409. src.begin()+1
  410. };
  411. }
  412. case cbor_oths::value_null: {
  413. return {
  414. cbor_value{
  415. cbor_composite<cbor_value>(nullopt),
  416. alloc
  417. },
  418. src.begin()+1
  419. };
  420. }
  421. case cbor_oths::value_undefined: {
  422. return {
  423. cbor_value{
  424. cbor_composite<cbor_value>(undefined_t{}),
  425. alloc
  426. },
  427. src.begin()+1
  428. };
  429. }
  430. case cbor_oths::word: {
  431. if(src.size()<3) ERROR;
  432. return {
  433. cbor_value{
  434. cbor_floating_point{ieee754_hf(*(src.slice_start(3).slice_end(2).cast<gp::endian_wrapper<ieee754_hf, endian::big>>().begin().data))},
  435. alloc
  436. },
  437. src.begin()+3
  438. };
  439. }
  440. case cbor_oths::dword: {
  441. if(src.size()<5) ERROR;
  442. return {
  443. cbor_value{
  444. cbor_floating_point{float(*(src.slice_start(5).slice_end(4).cast<gp::endian_wrapper<float, endian::big>>().begin().data))},
  445. alloc
  446. },
  447. src.begin()+5
  448. };
  449. }
  450. case cbor_oths::qword: {
  451. if(src.size()<9) ERROR;
  452. return {
  453. cbor_value{
  454. cbor_floating_point{double(*(src.slice_start(9).slice_end(8).cast<gp::endian_wrapper<double, endian::big>>().begin().data))},
  455. alloc
  456. },
  457. src.begin()+9
  458. };
  459. }
  460. default: {
  461. ERROR;
  462. }
  463. }
  464. }
  465. }
  466. ERROR;
  467. #undef ERROR
  468. }
  469. static auto encode_float(buffer<std::byte> dest, cbor_floating_point& value) {
  470. switch(value.contents.type()) {
  471. case cbor_floating_point::backing::alt<ieee754_hf>():{
  472. if(dest.size() < 3) return dest.begin();
  473. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::word);
  474. (dest.slice_start(3).slice_end(2).cast<gp::endian_wrapper<ieee754_hf, gp::endian::big>>())[0] = value.contents.value<ieee754_hf>();
  475. return dest.begin()+3;
  476. }
  477. case cbor_floating_point::backing::alt<float>():{
  478. if(dest.size() < 5) return dest.begin();
  479. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::dword);
  480. (dest.slice_start(5).slice_end(4).cast<gp::endian_wrapper<float, gp::endian::big>>())[0] = value.contents.value<float>();
  481. return dest.begin()+5;
  482. }
  483. case cbor_floating_point::backing::alt<double>():{
  484. if(dest.size() < 9) return dest.begin();
  485. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::qword);
  486. (dest.slice_start(9).slice_end(8).cast<gp::endian_wrapper<double, gp::endian::big>>())[0] = value.contents.value<double>();
  487. return dest.begin()+9;
  488. }
  489. default: return dest.begin();
  490. }
  491. }
  492. static auto encode_length(buffer<std::byte> dest, cbor_type major, uint64_t value) {
  493. auto num = value;
  494. if(value <= 23) {
  495. if(dest.size() < 1) return dest.begin();
  496. dest[0] = std::byte(((uint8_t)major << 5u) + value);
  497. return dest.begin()+1;
  498. } else if(value <= 255) {
  499. if(dest.size() < 2) return dest.begin();
  500. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::byte);
  501. dest[1] = std::byte(value);
  502. return dest.begin() + 2;
  503. } else if(value <= 65535) {
  504. if(dest.size() < 3) return dest.begin();
  505. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::word);
  506. (dest.slice_start(3).slice_end(2).cast<gp::endian_wrapper<uint16_t, gp::endian::big>>())[0] = num;
  507. return dest.begin()+3;
  508. } else if(value <= 4294967295) {
  509. if(dest.size() < 5) return dest.begin();
  510. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::dword);
  511. (dest.slice_start(5).slice_end(4).cast<gp::endian_wrapper<uint32_t, gp::endian::big>>())[0] = num;
  512. return dest.begin()+5;
  513. } else {
  514. if(dest.size() < 9) return dest.begin();
  515. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::qword);
  516. (dest.slice_start(9).slice_end(8).cast<gp::endian_wrapper<uint64_t, gp::endian::big>>())[0] = num;
  517. return dest.begin()+9;
  518. }
  519. }
  520. auto encode(buffer<std::byte> dest) {
  521. switch(contents.type()) {
  522. case cbor_composite<cbor_value>::alt<undefined_t>(): {
  523. if(dest.size() < 1) return dest.begin();
  524. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_undefined);
  525. return dest.begin()+1;
  526. }
  527. case cbor_composite<cbor_value>::alt<cbor_number>(): {
  528. auto& ref = contents.value<cbor_number>();
  529. return encode_length(
  530. dest,
  531. ref.is_negative() ? cbor_type::nint : cbor_type::uint,
  532. ref.value
  533. );
  534. }
  535. case cbor_composite<cbor_value>::alt<gp::vector<std::byte>>(): {
  536. auto& ref = contents.value<gp::vector<std::byte>>();
  537. auto it = encode_length(
  538. dest,
  539. cbor_type::bstr,
  540. ref.size()
  541. );
  542. if(it == dest.begin()) return it;
  543. for(auto a : ref) {
  544. *(it++) = a;
  545. }
  546. return it;
  547. }
  548. case cbor_composite<cbor_value>::alt<bool>(): {
  549. if(dest.size() < 1) return dest.begin();
  550. if(contents.value<bool>())
  551. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_true);
  552. else
  553. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_false);
  554. return dest.begin()+1;
  555. }
  556. case cbor_composite<cbor_value>::alt<gp::vector<cbor_value>>(): {
  557. auto& ary = contents.value<gp::vector<cbor_value>>();
  558. auto it_begin = encode_length(dest, cbor_type::list, ary.size());
  559. if(it_begin == dest.begin()) return dest.begin();
  560. for(auto& elem : ary) {
  561. auto slice = dest.slice_end(dest.size() - (it_begin - dest.begin()));
  562. auto it = elem.encode(slice);
  563. if(it == it_begin)
  564. return dest.begin();
  565. it_begin = it;
  566. }
  567. return it_begin;
  568. }
  569. case cbor_composite<cbor_value>::alt<gp::vector<gp::pair<cbor_value, cbor_value>>>(): {
  570. auto& ary = contents.value<gp::vector<gp::pair<cbor_value,cbor_value>>>();
  571. auto it_begin = encode_length(dest, cbor_type::hmap, ary.size());
  572. if(it_begin == dest.begin()) return dest.begin();
  573. for(auto& elem : ary) {
  574. auto slice = dest.slice_end(dest.size() - (it_begin - dest.begin()));
  575. auto it = elem.first.encode(slice);
  576. if(it == it_begin) return dest.begin();
  577. it_begin = it;
  578. slice = dest.slice_end(dest.size() - (it_begin - dest.begin()));
  579. it = elem.second.encode(slice);
  580. if(it == it_begin) return dest.begin();
  581. it_begin = it;
  582. }
  583. return it_begin;
  584. }
  585. case cbor_composite<cbor_value>::alt<gp::nullopt_t>(): {
  586. if(dest.size() < 1) return dest.begin();
  587. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_null);
  588. return dest.begin()+1;
  589. }
  590. case cbor_composite<cbor_value>::alt<cbor_floating_point>(): {
  591. return encode_float(dest, contents.value<cbor_floating_point>());
  592. }
  593. default: return dest.begin();
  594. }
  595. }
  596. };
  597. }