General Purpose library for Freestanding C++ and POSIX systems
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

454 Zeilen
12 KiB

vor 4 Jahren
vor 4 Jahren
vor 4 Jahren
vor 4 Jahren
vor 4 Jahren
vor 4 Jahren
vor 4 Jahren
vor 4 Jahren
vor 4 Jahren
vor 4 Jahren
vor 4 Jahren
vor 4 Jahren
vor 4 Jahren
vor 4 Jahren
vor 4 Jahren
  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. switch((cbor_oths)local) {
  215. case cbor_oths::value_false: {
  216. return {
  217. cbor_value{
  218. cbor_composite<cbor_value>(false),
  219. alloc
  220. },
  221. src.begin()+1
  222. };
  223. }
  224. case cbor_oths::value_true: {
  225. return {
  226. cbor_value{
  227. cbor_composite<cbor_value>(true),
  228. alloc
  229. },
  230. src.begin()+1
  231. };
  232. }
  233. case cbor_oths::value_null: {
  234. return {
  235. cbor_value{
  236. cbor_composite<cbor_value>(nullopt),
  237. alloc
  238. },
  239. src.begin()+1
  240. };
  241. }
  242. case cbor_oths::value_undefined: {
  243. return {
  244. cbor_value{
  245. cbor_composite<cbor_value>(undefined_t{}),
  246. alloc
  247. },
  248. src.begin()+1
  249. };
  250. }
  251. case cbor_oths::word: {
  252. if(src.size()<3) ERROR;
  253. return {
  254. cbor_value{
  255. cbor_floating_point{(ieee754_hf)(*(gp::endian_wrapper<ieee754_hf, endian::big>*)(src.begin().data))},
  256. alloc
  257. },
  258. src.begin()+3
  259. };
  260. }
  261. case cbor_oths::dword: {
  262. if(src.size()<5) ERROR;
  263. return {
  264. cbor_value{
  265. cbor_floating_point{float(*(gp::endian_wrapper<float, endian::big>*)(src.begin().data))},
  266. alloc
  267. },
  268. src.begin()+5
  269. };
  270. }
  271. case cbor_oths::qword: {
  272. if(src.size()<9) ERROR;
  273. return {
  274. cbor_value{
  275. cbor_floating_point{double(*(gp::endian_wrapper<double, endian::big>*)(src.begin().data))},
  276. alloc
  277. },
  278. src.begin()+9
  279. };
  280. }
  281. default: {
  282. ERROR;
  283. }
  284. }
  285. }
  286. }
  287. ERROR;
  288. }
  289. static auto encode_float(buffer<std::byte> dest, cbor_floating_point& value) {
  290. switch(value.type()) {
  291. case cbor_floating_point::alt<ieee754_hf>():{
  292. if(dest.size() < 3) return dest.begin();
  293. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::word);
  294. (dest.slice_start(3).slice_end(2).cast<gp::endian_wrapper<ieee754_hf, gp::endian::big>>())[0] = value.value<ieee754_hf>();
  295. return dest.begin()+3;
  296. }
  297. case cbor_floating_point::alt<float>():{
  298. if(dest.size() < 5) return dest.begin();
  299. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::dword);
  300. (dest.slice_start(5).slice_end(4).cast<gp::endian_wrapper<float, gp::endian::big>>())[0] = value.value<float>();
  301. return dest.begin()+5;
  302. }
  303. case cbor_floating_point::alt<double>():{
  304. if(dest.size() < 9) return dest.begin();
  305. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::qword);
  306. (dest.slice_start(9).slice_end(8).cast<gp::endian_wrapper<double, gp::endian::big>>())[0] = value.value<double>();
  307. return dest.begin()+9;
  308. }
  309. default: return dest.begin();
  310. }
  311. }
  312. static auto encode_length(buffer<std::byte> dest, cbor_type major, uint64_t value) {
  313. auto num = value;
  314. if(value <= 23) {
  315. if(dest.size() < 1) return dest.begin();
  316. dest[0] = std::byte(((uint8_t)major << 5u) + value);
  317. return dest.begin()+1;
  318. } else if(value <= 255) {
  319. if(dest.size() < 2) return dest.begin();
  320. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::byte);
  321. dest[1] = std::byte(value);
  322. return dest.begin() + 2;
  323. } else if(value <= 65535) {
  324. if(dest.size() < 3) return dest.begin();
  325. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::word);
  326. (dest.slice_start(3).slice_end(2).cast<gp::endian_wrapper<uint16_t, gp::endian::big>>())[0] = num;
  327. return dest.begin()+3;
  328. } else if(value <= 4294967295) {
  329. if(dest.size() < 5) return dest.begin();
  330. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::dword);
  331. (dest.slice_start(5).slice_end(4).cast<gp::endian_wrapper<uint32_t, gp::endian::big>>())[0] = num;
  332. return dest.begin()+5;
  333. } else {
  334. if(dest.size() < 9) return dest.begin();
  335. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::qword);
  336. (dest.slice_start(9).slice_end(8).cast<gp::endian_wrapper<uint64_t, gp::endian::big>>())[0] = num;
  337. return dest.begin()+9;
  338. }
  339. }
  340. auto encode(buffer<std::byte> dest) {
  341. switch(contents.type()) {
  342. case cbor_composite<cbor_value>::alt<undefined_t>(): {
  343. if(dest.size() < 1) return dest.begin();
  344. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_undefined);
  345. return dest.begin()+1;
  346. }
  347. case cbor_composite<cbor_value>::alt<cbor_number>(): {
  348. auto& ref = contents.value<cbor_number>();
  349. return encode_length(
  350. dest,
  351. ref.is_negative() ? cbor_type::nint : cbor_type::uint,
  352. ref.value
  353. );
  354. }
  355. case cbor_composite<cbor_value>::alt<gp::vector<std::byte>>(): {
  356. auto& ref = contents.value<gp::vector<std::byte>>();
  357. auto it = encode_length(
  358. dest,
  359. cbor_type::bstr,
  360. ref.size()
  361. );
  362. if(it == dest.begin()) return it;
  363. for(auto a : ref) {
  364. *(it++) = a;
  365. }
  366. return it;
  367. }
  368. case cbor_composite<cbor_value>::alt<bool>(): {
  369. if(dest.size() < 1) return dest.begin();
  370. if(contents.value<bool>())
  371. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_true);
  372. else
  373. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_false);
  374. return dest.begin()+1;
  375. }
  376. case cbor_composite<cbor_value>::alt<gp::vector<cbor_value>>(): {
  377. auto& ary = contents.value<gp::vector<cbor_value>>();
  378. auto it_begin = encode_length(dest, cbor_type::list, ary.size());
  379. if(it_begin == dest.begin()) return dest.begin();
  380. for(auto& elem : ary) {
  381. auto slice = dest.slice_end(dest.size() - (it_begin - dest.begin()));
  382. auto it = elem.encode(slice);
  383. if(it == it_begin)
  384. return dest.begin();
  385. it_begin = it;
  386. }
  387. return it_begin;
  388. }
  389. case cbor_composite<cbor_value>::alt<gp::vector<gp::pair<cbor_value, cbor_value>>>(): {
  390. auto& ary = contents.value<gp::vector<gp::pair<cbor_value,cbor_value>>>();
  391. auto it_begin = encode_length(dest, cbor_type::hmap, ary.size());
  392. if(it_begin == dest.begin()) return dest.begin();
  393. for(auto& elem : ary) {
  394. auto slice = dest.slice_end(dest.size() - (it_begin - dest.begin()));
  395. auto it = elem.first.encode(slice);
  396. if(it == it_begin) return dest.begin();
  397. it_begin = it;
  398. slice = dest.slice_end(dest.size() - (it_begin - dest.begin()));
  399. it = elem.second.encode(slice);
  400. if(it == it_begin) return dest.begin();
  401. it_begin = it;
  402. }
  403. return it_begin;
  404. }
  405. case cbor_composite<cbor_value>::alt<gp::nullopt_t>(): {
  406. if(dest.size() < 1) return dest.begin();
  407. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_null);
  408. return dest.begin()+1;
  409. }
  410. case cbor_composite<cbor_value>::alt<cbor_floating_point>(): {
  411. return encode_float(dest, contents.value<cbor_floating_point>());
  412. }
  413. default: return dest.begin();
  414. }
  415. }
  416. };
  417. }