binary.hpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. // Copyright (c) 2014-2021 Thomas Fussell
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE
  20. //
  21. // @license: http://www.opensource.org/licenses/mit-license.php
  22. // @author: see AUTHORS file
  23. #pragma once
  24. #include <cstdint>
  25. #include <cstring>
  26. #include <iostream>
  27. #include <vector>
  28. #include <xlnt/utils/exceptions.hpp>
  29. namespace xlnt {
  30. namespace detail {
  31. using byte = std::uint8_t;
  32. template<typename T>
  33. class binary_reader
  34. {
  35. public:
  36. binary_reader() = delete;
  37. binary_reader(const std::vector<T> &vector)
  38. : vector_(&vector),
  39. data_(nullptr),
  40. size_(0)
  41. {
  42. }
  43. binary_reader(const T *source_data, std::size_t size)
  44. : vector_(nullptr),
  45. data_(source_data),
  46. size_(size)
  47. {
  48. }
  49. binary_reader(const binary_reader &other) = default;
  50. binary_reader &operator=(const binary_reader &other)
  51. {
  52. vector_ = other.vector_;
  53. offset_ = other.offset_;
  54. data_ = other.data_;
  55. return *this;
  56. }
  57. ~binary_reader()
  58. {
  59. }
  60. const T *data() const
  61. {
  62. return vector_ == nullptr ? data_ : vector_->data();
  63. }
  64. void offset(std::size_t offset)
  65. {
  66. offset_ = offset;
  67. }
  68. std::size_t offset() const
  69. {
  70. return offset_;
  71. }
  72. void reset()
  73. {
  74. offset_ = 0;
  75. }
  76. template<typename U>
  77. U read()
  78. {
  79. return read_reference<U>();
  80. }
  81. template<typename U>
  82. const U *read_pointer()
  83. {
  84. const auto result = reinterpret_cast<const U *>(data() + offset_);
  85. offset_ += sizeof(U) / sizeof(T);
  86. return result;
  87. }
  88. template<typename U>
  89. const U &read_reference()
  90. {
  91. return *read_pointer<U>();
  92. }
  93. template<typename U>
  94. std::vector<U> as_vector() const
  95. {
  96. auto result = std::vector<T>(bytes() / sizeof(U), U());
  97. std::memcpy(result.data(), data(), bytes());
  98. return result;
  99. }
  100. template<typename U>
  101. std::vector<U> read_vector(std::size_t count)
  102. {
  103. auto result = std::vector<U>(count, U());
  104. std::memcpy(result.data(), data() + offset_, count * sizeof(U));
  105. offset_ += count * sizeof(T) / sizeof(U);
  106. return result;
  107. }
  108. std::size_t count() const
  109. {
  110. return vector_ != nullptr ? vector_->size() : size_;
  111. }
  112. std::size_t bytes() const
  113. {
  114. return count() * sizeof(T);
  115. }
  116. private:
  117. std::size_t offset_ = 0;
  118. const std::vector<T> *vector_;
  119. const T *data_;
  120. const std::size_t size_;
  121. };
  122. template<typename T>
  123. class binary_writer
  124. {
  125. public:
  126. binary_writer(std::vector<T> &bytes)
  127. : data_(&bytes)
  128. {
  129. }
  130. binary_writer(const binary_writer &other)
  131. {
  132. *this = other;
  133. }
  134. ~binary_writer()
  135. {
  136. }
  137. binary_writer &operator=(const binary_writer &other)
  138. {
  139. data_ = other.data_;
  140. offset_ = other.offset_;
  141. return *this;
  142. }
  143. std::vector<T> &data()
  144. {
  145. return *data_;
  146. }
  147. // Make the bytes of the data pointed to by this writer equivalent to those in the given vector
  148. // sizeof(U) should be a multiple of sizeof(T)
  149. template<typename U>
  150. void assign(const std::vector<U> &ints)
  151. {
  152. resize(ints.size() * sizeof(U));
  153. std::memcpy(data_->data(), ints.data(), bytes());
  154. }
  155. // Make the bytes of the data pointed to by this writer equivalent to those in the given string
  156. // sizeof(U) should be a multiple of sizeof(T)
  157. template<typename U>
  158. void assign(const std::basic_string<U> &string)
  159. {
  160. resize(string.size() * sizeof(U));
  161. std::memcpy(data_->data(), string.data(), bytes());
  162. }
  163. void offset(std::size_t new_offset)
  164. {
  165. offset_ = new_offset;
  166. }
  167. std::size_t offset() const
  168. {
  169. return offset_;
  170. }
  171. void reset()
  172. {
  173. offset_ = 0;
  174. data_->clear();
  175. }
  176. template<typename U>
  177. void write(U value)
  178. {
  179. const auto num_bytes = sizeof(U);
  180. const auto remaining_bytes = bytes() - offset() * sizeof(T);
  181. if (remaining_bytes < num_bytes)
  182. {
  183. extend((num_bytes - remaining_bytes) / sizeof(T));
  184. }
  185. std::memcpy(data_->data() + offset(), &value, num_bytes);
  186. offset_ += num_bytes / sizeof(T);
  187. }
  188. std::size_t count() const
  189. {
  190. return data_->size();
  191. }
  192. std::size_t bytes() const
  193. {
  194. return count() * sizeof(T);
  195. }
  196. void resize(std::size_t new_size, byte fill = 0)
  197. {
  198. data_->resize(new_size, fill);
  199. }
  200. void extend(std::size_t amount, byte fill = 0)
  201. {
  202. data_->resize(count() + amount, fill);
  203. }
  204. std::vector<byte>::iterator iterator()
  205. {
  206. return data_->begin() + static_cast<std::ptrdiff_t>(offset());
  207. }
  208. template<typename U>
  209. void append(const std::vector<U> &data)
  210. {
  211. binary_reader<U> reader(data);
  212. append(reader, data.size() * sizeof(U));
  213. }
  214. template<typename U>
  215. void append(binary_reader<U> &reader, std::size_t reader_element_count)
  216. {
  217. const auto num_bytes = sizeof(U) * reader_element_count;
  218. const auto remaining_bytes = bytes() - offset() * sizeof(T);
  219. if (remaining_bytes < num_bytes)
  220. {
  221. extend((num_bytes - remaining_bytes) / sizeof(T));
  222. }
  223. if ((reader.offset() + reader_element_count) * sizeof(U) > reader.bytes())
  224. {
  225. throw xlnt::exception("reading past end");
  226. }
  227. std::memcpy(data_->data() + offset_, reader.data() + reader.offset(), reader_element_count * sizeof(U));
  228. offset_ += reader_element_count * sizeof(U) / sizeof(T);
  229. }
  230. private:
  231. std::vector<T> *data_;
  232. std::size_t offset_ = 0;
  233. };
  234. template<typename T>
  235. std::vector<byte> string_to_bytes(const std::basic_string<T> &string)
  236. {
  237. std::vector<byte> bytes;
  238. binary_writer<byte> writer(bytes);
  239. writer.assign(string);
  240. return bytes;
  241. }
  242. template<typename T>
  243. T read(std::istream &in)
  244. {
  245. T result;
  246. in.read(reinterpret_cast<char *>(&result), sizeof(T));
  247. return result;
  248. }
  249. template<typename T>
  250. std::vector<T> read_vector(std::istream &in, std::size_t count)
  251. {
  252. std::vector<T> result(count, T());
  253. in.read(reinterpret_cast<char *>(&result[0]),
  254. static_cast<std::streamsize>(sizeof(T) * count));
  255. return result;
  256. }
  257. template<typename T>
  258. std::basic_string<T> read_string(std::istream &in, std::size_t count)
  259. {
  260. std::basic_string<T> result(count, T());
  261. in.read(reinterpret_cast<char *>(&result[0]),
  262. static_cast<std::streamsize>(sizeof(T) * count));
  263. return result;
  264. }
  265. } // namespace detail
  266. } // namespace xlnt