General Purpose library for Freestanding C++ and POSIX systems
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

237 рядки
5.6 KiB

4 роки тому
4 роки тому
4 роки тому
4 роки тому
4 роки тому
4 роки тому
4 роки тому
4 роки тому
4 роки тому
4 роки тому
4 роки тому
4 роки тому
4 роки тому
  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. };
  64. using cbor_floating_point = gp::fixed_variant<
  65. float,
  66. double
  67. >;
  68. struct undefined_t final {};
  69. template<typename T>
  70. using cbor_composite = gp::fixed_variant<
  71. undefined_t,
  72. cbor_number,
  73. gp::buffer<std::byte>,
  74. bool,
  75. gp::vector<T>,
  76. gp::vector<gp::pair<T, T>>,
  77. gp::nullopt_t,
  78. cbor_floating_point
  79. >;
  80. class cbor_value {
  81. cbor_composite<cbor_value> contents;
  82. gp::reference_wrapper<allocator> alloc;
  83. public:
  84. cbor_value(allocator& alloc_v)
  85. : contents(cbor_composite<cbor_value>(undefined_t{}))
  86. , alloc(alloc_v)
  87. {}
  88. cbor_value(cbor_number number, allocator& alloc_v)
  89. : contents(number)
  90. , alloc(alloc_v)
  91. {}
  92. cbor_value(const cbor_value& oth)
  93. : contents(oth.contents)
  94. , alloc(oth.alloc)
  95. {}
  96. cbor_value(cbor_value&& oth)
  97. : contents(gp::move(oth.contents))
  98. , alloc(gp::move(oth.alloc))
  99. {}
  100. cbor_value& operator=(cbor_value& value) {
  101. contents = value.contents;
  102. alloc = value.alloc;
  103. return *this;
  104. }
  105. cbor_value& operator=(cbor_value&& value) {
  106. gp::swap(contents, value.contents);
  107. gp::swap(alloc, value.alloc);
  108. return *this;
  109. }
  110. cbor_value& operator=(cbor_composite<cbor_value>& value) {
  111. contents = value;
  112. return *this;
  113. }
  114. template<typename T>
  115. cbor_value& operator=(T& value) {
  116. contents = value;
  117. return *this;
  118. }
  119. template<typename T>
  120. cbor_value& operator=(T&& value) {
  121. contents = gp::move(value);
  122. return *this;
  123. }
  124. auto new_array() {
  125. return gp::vector<cbor_value>{alloc};
  126. }
  127. auto new_object() {
  128. return gp::vector<gp::pair<cbor_value, cbor_value>>{alloc};
  129. }
  130. static auto encode_length(buffer<std::byte> dest, cbor_type major, uint64_t value) {
  131. auto num = value;
  132. if(value <= 23) {
  133. if(dest.size() < 1) return dest.begin();
  134. dest[0] = std::byte(((uint8_t)major << 5u) + value);
  135. return dest.begin()+1;
  136. } else if(value <= 255) {
  137. if(dest.size() < 2) return dest.begin();
  138. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::byte);
  139. dest[1] = std::byte(value);
  140. return dest.begin() + 2;
  141. } else if(value <= 65535) {
  142. if(dest.size() < 3) return dest.begin();
  143. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::word);
  144. (dest.slice_start(3).slice_end(2).cast<gp::endian_wrapper<uint16_t, gp::endian::big>>())[0] = num.value;
  145. return dest.begin()+3;
  146. } else if(value <= 4294967295) {
  147. if(dest.size() < 5) return dest.begin();
  148. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::dword);
  149. (dest.slice_start(5).slice_end(4).cast<gp::endian_wrapper<uint32_t, gp::endian::big>>())[0] = num.value;
  150. return dest.begin()+5;
  151. } else {
  152. if(dest.size() < 9) return dest.begin();
  153. dest[0] = std::byte(((uint8_t)major << 5u) + (uint8_t)cbor_oths::qword);
  154. (dest.slice_start(9).slice_end(8).cast<gp::endian_wrapper<uint64_t, gp::endian::big>>())[0] = num.value;
  155. return dest.begin()+9;
  156. }
  157. }
  158. auto encode(buffer<std::byte> dest) {
  159. switch(contents.type()) {
  160. case cbor_composite<cbor_value>::alt<undefined_t>(): {
  161. if(dest.size() < 1) return dest.begin();
  162. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_undefined);
  163. return dest.begin()+1;
  164. }
  165. case cbor_composite<cbor_value>::alt<cbor_number>(): {
  166. auto& ref = contents.value<cbor_number>();
  167. return encode_length(
  168. dest,
  169. ref.is_negative() ? cbor_type::nint : cbor_type::uint,
  170. ref.value
  171. );
  172. }
  173. case cbor_composite<cbor_value>::alt<gp::buffer<std::byte>>(): {
  174. auto& ref = contents.value<gp::buffer<std::byte>>();
  175. auto it = encode_length(
  176. dest,
  177. cbor_type::bstr,
  178. ref.size()
  179. );
  180. if(it == dest.begin()) return it;
  181. for(auto a : ref) {
  182. *(it++) = a;
  183. }
  184. return it;
  185. }
  186. case cbor_composite<cbor_value>::alt<bool>(): {
  187. if(dest.size() < 1) return dest.begin();
  188. if(contents.value<bool>())
  189. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_true);
  190. else
  191. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_false);
  192. return dest.begin()+1;
  193. }
  194. case cbor_composite<cbor_value>::alt<gp::vector<cbor_value>>(): {
  195. }
  196. case cbor_composite<cbor_value>::alt<gp::vector<gp::pair<cbor_value, cbor_value>>>(): {
  197. }
  198. case cbor_composite<cbor_value>::alt<gp::nullopt_t>(): {
  199. if(dest.size() < 1) return dest.begin();
  200. dest[0] = std::byte(((uint8_t)cbor_type::oths << 5u) + (uint8_t)cbor_oths::value_null);
  201. return dest.begin()+1;
  202. }
  203. case cbor_composite<cbor_value>::alt<cbor_floating_point>(): {
  204. }
  205. }
  206. }
  207. };
  208. }