BitStream.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /*
  2. * Copyright (c) 2021, kleines Filmröllchen <filmroellchen@serenityos.org>.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/ByteBuffer.h>
  8. #include <AK/Concepts.h>
  9. #include <AK/Error.h>
  10. #include <AK/NonnullOwnPtr.h>
  11. #include <AK/NonnullRefPtr.h>
  12. #include <AK/OwnPtr.h>
  13. #include <AK/Span.h>
  14. #include <AK/StdLibExtraDetails.h>
  15. #include <AK/Types.h>
  16. #include <LibCore/Stream.h>
  17. namespace Core::Stream {
  18. /// A stream wrapper class that allows you to read arbitrary amounts of bits
  19. /// in big-endian order from another stream.
  20. class BigEndianInputBitStream : public Stream {
  21. public:
  22. static ErrorOr<NonnullOwnPtr<BigEndianInputBitStream>> construct(Handle<Stream> stream)
  23. {
  24. return adopt_nonnull_own_or_enomem<BigEndianInputBitStream>(new BigEndianInputBitStream(move(stream)));
  25. }
  26. // ^Stream
  27. virtual ErrorOr<Bytes> read(Bytes bytes) override
  28. {
  29. if (m_current_byte.has_value() && is_aligned_to_byte_boundary()) {
  30. bytes[0] = m_current_byte.release_value();
  31. return m_stream->read(bytes.slice(1));
  32. }
  33. align_to_byte_boundary();
  34. return m_stream->read(bytes);
  35. }
  36. virtual ErrorOr<size_t> write(ReadonlyBytes bytes) override { return m_stream->write(bytes); }
  37. virtual ErrorOr<void> write_entire_buffer(ReadonlyBytes bytes) override { return m_stream->write_entire_buffer(bytes); }
  38. virtual bool is_eof() const override { return m_stream->is_eof() && !m_current_byte.has_value(); }
  39. virtual bool is_open() const override { return m_stream->is_open(); }
  40. virtual void close() override
  41. {
  42. m_stream->close();
  43. align_to_byte_boundary();
  44. }
  45. ErrorOr<bool> read_bit()
  46. {
  47. return read_bits<bool>(1);
  48. }
  49. /// Depending on the number of bits to read, the return type can be chosen appropriately.
  50. /// This avoids a bunch of static_cast<>'s for the user.
  51. // TODO: Support u128, u256 etc. as well: The concepts would be quite complex.
  52. template<Unsigned T = u64>
  53. ErrorOr<T> read_bits(size_t count)
  54. {
  55. if constexpr (IsSame<bool, T>) {
  56. VERIFY(count == 1);
  57. }
  58. T result = 0;
  59. size_t nread = 0;
  60. while (nread < count) {
  61. if (m_current_byte.has_value()) {
  62. if constexpr (!IsSame<bool, T> && !IsSame<u8, T>) {
  63. // read as many bytes as possible directly
  64. if (((count - nread) >= 8) && is_aligned_to_byte_boundary()) {
  65. // shift existing data over
  66. result <<= 8;
  67. result |= m_current_byte.value();
  68. nread += 8;
  69. m_current_byte.clear();
  70. } else {
  71. auto const bit = (m_current_byte.value() >> (7 - m_bit_offset)) & 1;
  72. result <<= 1;
  73. result |= bit;
  74. ++nread;
  75. if (m_bit_offset++ == 7)
  76. m_current_byte.clear();
  77. }
  78. } else {
  79. // Always take this branch for booleans or u8: there's no purpose in reading more than a single bit
  80. auto const bit = (m_current_byte.value() >> (7 - m_bit_offset)) & 1;
  81. if constexpr (IsSame<bool, T>)
  82. result = bit;
  83. else {
  84. result <<= 1;
  85. result |= bit;
  86. }
  87. ++nread;
  88. if (m_bit_offset++ == 7)
  89. m_current_byte.clear();
  90. }
  91. } else {
  92. auto temp_buffer = TRY(ByteBuffer::create_uninitialized(1));
  93. TRY(m_stream->read(temp_buffer.bytes()));
  94. m_current_byte = temp_buffer[0];
  95. m_bit_offset = 0;
  96. }
  97. }
  98. return result;
  99. }
  100. /// Discards any sub-byte stream positioning the input stream may be keeping track of.
  101. /// Non-bitwise reads will implicitly call this.
  102. void align_to_byte_boundary()
  103. {
  104. m_current_byte.clear();
  105. m_bit_offset = 0;
  106. }
  107. /// Whether we are (accidentally or intentionally) at a byte boundary right now.
  108. ALWAYS_INLINE bool is_aligned_to_byte_boundary() const { return m_bit_offset == 0; }
  109. private:
  110. BigEndianInputBitStream(Handle<Stream> stream)
  111. : m_stream(move(stream))
  112. {
  113. }
  114. Optional<u8> m_current_byte;
  115. size_t m_bit_offset { 0 };
  116. Handle<Stream> m_stream;
  117. };
  118. /// A stream wrapper class that allows you to read arbitrary amounts of bits
  119. /// in little-endian order from another stream.
  120. class LittleEndianInputBitStream : public Stream {
  121. public:
  122. static ErrorOr<NonnullOwnPtr<LittleEndianInputBitStream>> construct(Handle<Stream> stream)
  123. {
  124. return adopt_nonnull_own_or_enomem<LittleEndianInputBitStream>(new LittleEndianInputBitStream(move(stream)));
  125. }
  126. LittleEndianInputBitStream(Handle<Stream> stream)
  127. : m_stream(move(stream))
  128. {
  129. }
  130. // ^Stream
  131. virtual ErrorOr<Bytes> read(Bytes bytes) override
  132. {
  133. if (m_current_byte.has_value() && is_aligned_to_byte_boundary()) {
  134. bytes[0] = m_current_byte.release_value();
  135. return m_stream->read(bytes.slice(1));
  136. }
  137. align_to_byte_boundary();
  138. return m_stream->read(bytes);
  139. }
  140. virtual ErrorOr<size_t> write(ReadonlyBytes bytes) override { return m_stream->write(bytes); }
  141. virtual ErrorOr<void> write_entire_buffer(ReadonlyBytes bytes) override { return m_stream->write_entire_buffer(bytes); }
  142. virtual bool is_eof() const override { return m_stream->is_eof() && !m_current_byte.has_value(); }
  143. virtual bool is_open() const override { return m_stream->is_open(); }
  144. virtual void close() override
  145. {
  146. m_stream->close();
  147. align_to_byte_boundary();
  148. }
  149. ErrorOr<bool> read_bit()
  150. {
  151. return read_bits<bool>(1);
  152. }
  153. /// Depending on the number of bits to read, the return type can be chosen appropriately.
  154. /// This avoids a bunch of static_cast<>'s for the user.
  155. // TODO: Support u128, u256 etc. as well: The concepts would be quite complex.
  156. template<Unsigned T = u64>
  157. ErrorOr<T> read_bits(size_t count)
  158. {
  159. if constexpr (IsSame<bool, T>) {
  160. VERIFY(count == 1);
  161. }
  162. T result = 0;
  163. size_t nread = 0;
  164. while (nread < count) {
  165. if (m_current_byte.has_value()) {
  166. if constexpr (!IsSame<bool, T> && !IsSame<u8, T>) {
  167. // read as many bytes as possible directly
  168. if (((count - nread) >= 8) && is_aligned_to_byte_boundary()) {
  169. // shift existing data over
  170. result |= (m_current_byte.value() << nread);
  171. nread += 8;
  172. m_current_byte.clear();
  173. } else {
  174. auto const bit = (m_current_byte.value() >> m_bit_offset) & 1;
  175. result |= (bit << nread);
  176. ++nread;
  177. if (m_bit_offset++ == 7)
  178. m_current_byte.clear();
  179. }
  180. } else {
  181. // Always take this branch for booleans or u8: there's no purpose in reading more than a single bit
  182. auto const bit = (m_current_byte.value() >> m_bit_offset) & 1;
  183. if constexpr (IsSame<bool, T>)
  184. result = bit;
  185. else
  186. result |= (bit << nread);
  187. ++nread;
  188. if (m_bit_offset++ == 7)
  189. m_current_byte.clear();
  190. }
  191. } else {
  192. auto temp_buffer = TRY(ByteBuffer::create_uninitialized(1));
  193. auto read_bytes = TRY(m_stream->read(temp_buffer.bytes()));
  194. if (read_bytes.is_empty())
  195. return Error::from_string_literal("eof");
  196. m_current_byte = temp_buffer[0];
  197. m_bit_offset = 0;
  198. }
  199. }
  200. return result;
  201. }
  202. /// Discards any sub-byte stream positioning the input stream may be keeping track of.
  203. /// Non-bitwise reads will implicitly call this.
  204. u8 align_to_byte_boundary()
  205. {
  206. u8 remaining_bits = m_current_byte.value_or(0) >> m_bit_offset;
  207. m_current_byte.clear();
  208. m_bit_offset = 0;
  209. return remaining_bits;
  210. }
  211. /// Whether we are (accidentally or intentionally) at a byte boundary right now.
  212. ALWAYS_INLINE bool is_aligned_to_byte_boundary() const { return m_bit_offset == 0; }
  213. private:
  214. Optional<u8> m_current_byte;
  215. size_t m_bit_offset { 0 };
  216. Handle<Stream> m_stream;
  217. };
  218. /// A stream wrapper class that allows you to write arbitrary amounts of bits
  219. /// in big-endian order to another stream.
  220. class BigEndianOutputBitStream : public Stream {
  221. public:
  222. static ErrorOr<NonnullOwnPtr<BigEndianOutputBitStream>> construct(Handle<Stream> stream)
  223. {
  224. return adopt_nonnull_own_or_enomem<BigEndianOutputBitStream>(new BigEndianOutputBitStream(move(stream)));
  225. }
  226. virtual ErrorOr<Bytes> read(Bytes) override
  227. {
  228. return Error::from_errno(EBADF);
  229. }
  230. virtual ErrorOr<size_t> write(ReadonlyBytes bytes) override
  231. {
  232. VERIFY(m_bit_offset == 0);
  233. return m_stream->write(bytes);
  234. }
  235. template<Unsigned T>
  236. ErrorOr<void> write_bits(T value, size_t bit_count)
  237. {
  238. VERIFY(m_bit_offset <= 7);
  239. while (bit_count > 0) {
  240. u8 next_bit = (value >> (bit_count - 1)) & 1;
  241. bit_count--;
  242. m_current_byte <<= 1;
  243. m_current_byte |= next_bit;
  244. m_bit_offset++;
  245. if (m_bit_offset > 7) {
  246. TRY(m_stream->write({ &m_current_byte, sizeof(m_current_byte) }));
  247. m_bit_offset = 0;
  248. m_current_byte = 0;
  249. }
  250. }
  251. return {};
  252. }
  253. virtual bool is_eof() const override
  254. {
  255. return true;
  256. }
  257. virtual bool is_open() const override
  258. {
  259. return m_stream->is_open();
  260. }
  261. virtual void close() override
  262. {
  263. }
  264. size_t bit_offset() const
  265. {
  266. return m_bit_offset;
  267. }
  268. ErrorOr<void> align_to_byte_boundary()
  269. {
  270. if (m_bit_offset == 0)
  271. return {};
  272. TRY(write_bits(0u, 8 - m_bit_offset));
  273. VERIFY(m_bit_offset == 0);
  274. return {};
  275. }
  276. private:
  277. BigEndianOutputBitStream(Handle<Stream> stream)
  278. : m_stream(move(stream))
  279. {
  280. }
  281. Handle<Stream> m_stream;
  282. u8 m_current_byte { 0 };
  283. size_t m_bit_offset { 0 };
  284. };
  285. /// A stream wrapper class that allows you to write arbitrary amounts of bits
  286. /// in little-endian order to another stream.
  287. class LittleEndianOutputBitStream : public Stream {
  288. public:
  289. static ErrorOr<NonnullOwnPtr<LittleEndianOutputBitStream>> construct(Handle<Stream> stream)
  290. {
  291. return adopt_nonnull_own_or_enomem<LittleEndianOutputBitStream>(new LittleEndianOutputBitStream(move(stream)));
  292. }
  293. virtual ErrorOr<Bytes> read(Bytes) override
  294. {
  295. return Error::from_errno(EBADF);
  296. }
  297. virtual ErrorOr<size_t> write(ReadonlyBytes bytes) override
  298. {
  299. VERIFY(m_bit_offset == 0);
  300. return m_stream->write(bytes);
  301. }
  302. template<Unsigned T>
  303. ErrorOr<void> write_bits(T value, size_t bit_count)
  304. {
  305. VERIFY(m_bit_offset <= 7);
  306. size_t input_offset = 0;
  307. while (input_offset < bit_count) {
  308. u8 next_bit = (value >> input_offset) & 1;
  309. input_offset++;
  310. m_current_byte |= next_bit << m_bit_offset;
  311. m_bit_offset++;
  312. if (m_bit_offset > 7) {
  313. TRY(m_stream->write({ &m_current_byte, sizeof(m_current_byte) }));
  314. m_bit_offset = 0;
  315. m_current_byte = 0;
  316. }
  317. }
  318. return {};
  319. }
  320. virtual bool is_eof() const override
  321. {
  322. return true;
  323. }
  324. virtual bool is_open() const override
  325. {
  326. return m_stream->is_open();
  327. }
  328. virtual void close() override
  329. {
  330. }
  331. size_t bit_offset() const
  332. {
  333. return m_bit_offset;
  334. }
  335. ErrorOr<void> align_to_byte_boundary()
  336. {
  337. if (m_bit_offset == 0)
  338. return {};
  339. TRY(write_bits(0u, 8 - m_bit_offset));
  340. VERIFY(m_bit_offset == 0);
  341. return {};
  342. }
  343. private:
  344. LittleEndianOutputBitStream(Handle<Stream> stream)
  345. : m_stream(move(stream))
  346. {
  347. }
  348. Handle<Stream> m_stream;
  349. u8 m_current_byte { 0 };
  350. size_t m_bit_offset { 0 };
  351. };
  352. }