Embedded Template Library 1.0
Loading...
Searching...
No Matches
bit_stream.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5Embedded Template Library.
6https://github.com/ETLCPP/etl
7https://www.etlcpp.com
8Copyright(c) 2018 John Wellbelove
9Permission is hereby granted, free of charge, to any person obtaining a copy
10of this software and associated documentation files(the "Software"), to deal
11in the Software without restriction, including without limitation the rights
12to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
13copies of the Software, and to permit persons to whom the Software is
14furnished to do so, subject to the following conditions :
15The above copyright notice and this permission notice shall be included in all
16copies or substantial portions of the Software.
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24******************************************************************************/
25
26#ifndef ETL_BIT_STREAM_INCLUDED
27#define ETL_BIT_STREAM_INCLUDED
28
29#include "platform.h"
30#include "type_traits.h"
31#include "nullptr.h"
32#include "endianness.h"
33#include "integral_limits.h"
34#include "binary.h"
35#include "algorithm.h"
36#include "iterator.h"
37#include "memory.h"
38#include "delegate.h"
39#include "span.h"
40#include "optional.h"
41#include "exception.h"
42#include "error_handler.h"
43
44#include <stdint.h>
45#include <limits.h>
46
47#include "private/minmax_push.h"
48
49namespace etl
50{
51 //***************************************************************************
54 //***************************************************************************
56 {
57 public:
58
59 typedef const unsigned char* const_iterator;
60
61 //***************************************************************************
63 //***************************************************************************
65 : pdata(ETL_NULLPTR)
66 , length_chars(0U)
67 {
68 restart();
69 }
70
71 //***************************************************************************
73 //***************************************************************************
74 bit_stream(void* begin_, void* end_)
76 , length_chars(etl::distance(reinterpret_cast<unsigned char*>(begin_), reinterpret_cast<unsigned char*>(end_)))
77 {
78 restart();
79 }
80
81 //***************************************************************************
83 //***************************************************************************
84 bit_stream(void* begin_, size_t length_)
86 , length_chars(length_)
87 {
88 restart();
89 }
90
91 //***************************************************************************
93 //***************************************************************************
94 void set_stream(void* begin_, size_t length_)
95 {
96 pdata = reinterpret_cast<unsigned char*>(begin_);
97 length_chars = length_;
98 restart();
99 }
100
101 //***************************************************************************
103 //***************************************************************************
104 void set_stream(void* begin_, void* end_)
105 {
106 set_stream(begin_, etl::distance(reinterpret_cast<unsigned char*>(begin_), reinterpret_cast<unsigned char*>(end_)));
107 }
108
109 //***************************************************************************
111 //***************************************************************************
112 void restart()
113 {
114 bits_available_in_char = CHAR_BIT;
115 char_index = 0U;
116 bits_available = CHAR_BIT * length_chars;
117 }
118
119 //***************************************************************************
121 //***************************************************************************
122 bool at_end() const
123 {
124 return (bits_available == 0U);
125 }
126
127 //***************************************************************************
129 //***************************************************************************
130 bool put(bool value)
131 {
132 bool success = false;
133
134 if (pdata != ETL_NULLPTR)
135 {
136 if (bits_available > 0)
137 {
138 unsigned char chunk = value ? 1 : 0;
139 put_integral(uint32_t(chunk), 1);
140 success = true;
141 }
142 }
143
144 return success;
145 }
146
147 //***************************************************************************
149 //***************************************************************************
150 template <typename T>
152 put(T value, uint_least8_t nbits = CHAR_BIT * sizeof(T))
153 {
154 return put_integral(static_cast<uint32_t>(value), nbits);
155 }
156
157#if ETL_USING_64BIT_TYPES
158 //***************************************************************************
160 //***************************************************************************
162 {
163 return put_integral(uint64_t(value), nbits);
164 }
165
166 //***************************************************************************
168 //***************************************************************************
170 {
171 return put_integral(value, nbits);
172 }
173#endif
174
175 //***************************************************************************
177 //***************************************************************************
178 template <typename T>
180 put(T value)
181 {
182 bool success = true;
183
184 unsigned char data[sizeof(T)];
185 to_bytes(value, data);
186
187 for (size_t i = 0UL; i < sizeof(T); ++i)
188 {
189 if (!put_integral(uint32_t(data[i]), CHAR_BIT))
190 {
191 success = false;
192 }
193 }
194
195 return success;
196 }
197
198 //***************************************************************************
200 //***************************************************************************
201 bool get(bool& value)
202 {
203 bool success = false;
204
205 if (pdata != ETL_NULLPTR)
206 {
207 // Do we have enough bits?
208 if (bits_available > 0U)
209 {
210 value = get_bit();
211 success = true;
212 }
213 }
214
215 return success;
216 }
217
218 //***************************************************************************
220 //***************************************************************************
221 template <typename T>
223 get(T& value, uint_least8_t nbits = CHAR_BIT * sizeof(T))
224 {
225 bool success = false;
227
228 if (pdata != ETL_NULLPTR)
229 {
230 // Do we have enough bits?
231 if (bits_available >= nbits)
232 {
233 value = 0;
234
235 // Get the bits from the stream.
236 while (nbits != 0)
237 {
238 unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
239
240 typedef typename etl::make_unsigned<T>::type chunk_t;
241 chunk_t chunk = get_chunk(mask_width);
242
243 nbits -= mask_width;
244 value |= static_cast<T>(chunk << nbits);
245 }
246
247 success = true;
248 }
249 }
250
251 // Sign extend if signed type and not already full bit width.
252 if (etl::is_signed<T>::value && (bits != (CHAR_BIT * sizeof(T))))
253 {
254 typedef typename etl::make_signed<T>::type ST;
255 value = etl::sign_extend<ST, ST>(value, bits);
256 }
257
258 return success;
259 }
260
261 //***************************************************************************
263 //***************************************************************************
264 template <typename T>
266 get(T& value)
267 {
268 bool success = false;
269
270 if (pdata != ETL_NULLPTR)
271 {
272 uint_least8_t nbits = CHAR_BIT * sizeof(T);
273
274 // Do we have enough bits?
275 if (bits_available >= nbits)
276 {
277 // Temporary storage.
279
280 for (size_t i = 0UL; i < sizeof(T); ++i)
281 {
282 get(data.raw[i], CHAR_BIT);
283 }
284
285 from_bytes(reinterpret_cast<const unsigned char*>(data.raw), value);
286
287 success = true;
288 }
289 }
290
291 return success;
292 }
293
294 //***************************************************************************
296 //***************************************************************************
297 size_t size() const
298 {
299 size_t s = char_index;
300
301 // Current byte is used?
302 if (bits_available_in_char != CHAR_BIT)
303 {
304 ++s;
305 }
306
307 return s;
308 }
309
310 //***************************************************************************
312 //***************************************************************************
313 size_t bits() const
314 {
315 return (length_chars * CHAR_BIT) - bits_available;
316 }
317
318 //***************************************************************************
320 //***************************************************************************
322 {
323 return pdata;
324 }
325
326 //***************************************************************************
328 //***************************************************************************
330 {
331 return pdata + size();
332 }
333
334 private:
335
336 //***************************************************************************
338 //***************************************************************************
339 bool put_integral(uint32_t value, uint_least8_t nbits)
340 {
341 bool success = false;
342
343 if (pdata != ETL_NULLPTR)
344 {
345 // Do we have enough bits?
346 if (bits_available >= nbits)
347 {
348 // Send the bits to the stream.
349 while (nbits != 0)
350 {
351 unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
352 nbits -= mask_width;
353 uint32_t mask = ((1U << mask_width) - 1U) << nbits;
354 //uint32_t mask = ((uint32_t(1U) << mask_width) - 1U) << nbits;
355
356 // Move chunk to lowest char bits.
357 // Chunks are never larger than one char.
358 uint32_t chunk = ((value & mask) >> nbits) << (bits_available_in_char - mask_width);
359
360 put_chunk(static_cast<unsigned char>(chunk), mask_width);
361 }
362
363 success = true;
364 }
365 }
366
367 return success;
368 }
369
370#if ETL_USING_64BIT_TYPES
371 //***************************************************************************
373 //***************************************************************************
374 bool put_integral(uint64_t value, uint_least8_t nbits)
375 {
376 bool success = false;
377
378 if (pdata != ETL_NULLPTR)
379 {
380 // Do we have enough bits?
381 if (bits_available >= nbits)
382 {
383 // Send the bits to the stream.
384 while (nbits != 0)
385 {
386 unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
387 nbits -= mask_width;
388 uint64_t mask = ((uint64_t(1U) << mask_width) - 1U) << nbits;
389
390 // Move chunk to lowest char bits.
391 // Chunks are never larger than one char.
392 uint64_t chunk = ((value & mask) >> nbits) << (bits_available_in_char - mask_width);
393
394 put_chunk(static_cast<unsigned char>(chunk), mask_width);
395 }
396
397 success = true;
398 }
399 }
400
401 return success;
402 }
403#endif
404
405 //***************************************************************************
407 //***************************************************************************
408 void put_chunk(unsigned char chunk, unsigned char nbits)
409 {
410 // Clear if new byte.
411 if (bits_available_in_char == 8U)
412 {
413 pdata[char_index] = 0U;
414 }
415
416 pdata[char_index] |= chunk;
417 step(nbits);
418 }
419
420 //***************************************************************************
422 //***************************************************************************
423 unsigned char get_chunk(unsigned char nbits)
424 {
425 unsigned char value = pdata[char_index];
426
427 value >>= (bits_available_in_char - nbits);
428
429 unsigned char mask;
430
431 if (nbits == CHAR_BIT)
432 {
434 }
435 else
436 {
437 mask = (1U << nbits) - 1;
438 }
439
440 value &= mask;
441
442 step(nbits);
443
444 return value;
445 }
446
447 //***************************************************************************
449 //***************************************************************************
450 bool get_bit()
451 {
452 bool result = (pdata[char_index] & (1U << (bits_available_in_char - 1U))) != 0U;
453
454 step(1U);
455
456 return result;
457 }
458
459 //***************************************************************************
461 //***************************************************************************
462 template <typename T>
463 void from_bytes(const unsigned char* data, T& value)
464 {
466
467 // Network to host.
468 if (etl::endianness::value() == etl::endian::little)
469 {
470 etl::reverse_copy(data, data + sizeof(T), temp.raw);
471 }
472 else
473 {
474 etl::copy(data, data + sizeof(T), temp.raw);
475 }
476
477 value = *reinterpret_cast<T*>(temp.raw);
478 }
479
480 //***************************************************************************
482 //***************************************************************************
483 template <typename T>
484 void to_bytes(T value, unsigned char* data)
485 {
486 unsigned char* pf = reinterpret_cast<unsigned char*>(&value);
487
488 // Host to network.
489 if (etl::endianness::value() == etl::endian::little)
490 {
491 etl::reverse_copy(pf, pf + sizeof(T), data);
492 }
493 else
494 {
495 etl::copy(pf, pf + sizeof(T), data);
496 }
497 }
498
499 //***************************************************************************
502 //***************************************************************************
503 void step(unsigned char nbits)
504 {
505 bits_available_in_char -= nbits;
506
507 if (bits_available_in_char == 0)
508 {
509 ++char_index;
510 bits_available_in_char = 8;
511 }
512
513 bits_available -= nbits;
514 }
515
516 unsigned char *pdata;
517 size_t length_chars;
518 unsigned char bits_available_in_char;
519 size_t char_index;
520 size_t bits_available;
521 };
522
523 //***************************************************************************
525 //***************************************************************************
527 {
528 public:
529
530 typedef char value_type;
531 typedef value_type* iterator;
532 typedef const value_type* const_iterator;
535
536 //***************************************************************************
538 //***************************************************************************
539 template <size_t Length>
548
549 //***************************************************************************
551 //***************************************************************************
552 template <size_t Length>
561
562 //***************************************************************************
564 //***************************************************************************
573
574 //***************************************************************************
576 //***************************************************************************
578 : pdata(reinterpret_cast<char*>(begin_))
579 , length_chars(length_chars_)
580 , stream_endianness(stream_endianness_)
582 {
583 restart();
584 }
585
586 //***************************************************************************
588 //***************************************************************************
589 void restart()
590 {
591 bits_available_in_char = CHAR_BIT;
592 char_index = 0U;
593 bits_available = CHAR_BIT * length_chars;
594 }
595
596 //***************************************************************************
598 //***************************************************************************
599 size_t capacity_bytes() const
600 {
601 return length_chars;
602 }
603
604 //***************************************************************************
605 size_t capacity_bits() const
606 {
607 return length_chars * CHAR_BIT;
608 }
609
610 //***************************************************************************
612 //***************************************************************************
613 bool empty() const
614 {
615 return (bits_available == length_chars);
616 }
617
618 //***************************************************************************
620 //***************************************************************************
621 bool full() const
622 {
623 return (bits_available == 0U);
624 }
625
626 //***************************************************************************
628 //***************************************************************************
629 void write_unchecked(bool value)
630 {
631 unsigned char chunk = value ? 1 : 0;
633 }
634
635 //***************************************************************************
637 //***************************************************************************
638 bool write(bool value)
639 {
640 bool success = (available<1U>() > 0U);
641
642 if (success)
643 {
644 write_unchecked(value);
645 }
646
647 return success;
648 }
649
650 //***************************************************************************
652 //***************************************************************************
653 template <typename T>
656 {
658
659 write_data<unsigned_t>(static_cast<unsigned_t>(value), nbits);
660 }
661
662 //***************************************************************************
664 //***************************************************************************
665 template <typename T>
667 write(T value, uint_least8_t nbits = CHAR_BIT * sizeof(T))
668 {
669 bool success = (available(nbits) > 0U);
670
671 if (success)
672 {
673 write_unchecked(value, nbits);
674 }
675
676 return success;
677 }
678
679 //***************************************************************************
683 //***************************************************************************
684 bool skip(size_t nbits)
685 {
686 bool success = (nbits <= available_bits());
687
688 if (success)
689 {
690 while (nbits > bits_available_in_char)
691 {
692 step(bits_available_in_char);
693 nbits -= bits_available_in_char;
694 }
695
696 if (nbits != 0U)
697 {
698 step(static_cast<unsigned char>(nbits));
699 }
700 }
701
702 return success;
703 }
704
705 //***************************************************************************
707 //***************************************************************************
708 size_t size_bytes() const
709 {
710 size_t s = char_index;
711
712 // Is the current byte partially used?
713 if (bits_available_in_char != CHAR_BIT)
714 {
715 ++s;
716 }
717
718 return s;
719 }
720
721 //***************************************************************************
723 //***************************************************************************
724 size_t size_bits() const
725 {
726 return capacity_bits() - available_bits();
727 }
728
729 //***************************************************************************
732 //***************************************************************************
733 template <size_t Nbits>
734 size_t available() const
735 {
736 return bits_available / Nbits;
737 }
738
739 //***************************************************************************
742 //***************************************************************************
743 template <typename T>
744 size_t available() const
745 {
747 }
748
749 //***************************************************************************
752 //***************************************************************************
753 size_t available(size_t nbits) const
754 {
755 return bits_available / nbits;
756 }
757
758 //***************************************************************************
760 //***************************************************************************
761 size_t available_bits() const
762 {
763 return bits_available;
764 }
765
766 //***************************************************************************
768 //***************************************************************************
770 {
771 return pdata;
772 }
773
774 //***************************************************************************
776 //***************************************************************************
778 {
779 return pdata;
780 }
781
782 //***************************************************************************
784 //***************************************************************************
786 {
787 return pdata;
788 }
789
790 //***************************************************************************
792 //***************************************************************************
794 {
795 return pdata + size_bytes();
796 }
797
798 //***************************************************************************
800 //***************************************************************************
802 {
803 return pdata + size_bytes();
804 }
805
806 //***************************************************************************
808 //***************************************************************************
810 {
811 return pdata + size_bytes();
812 }
813
814 //***************************************************************************
816 //***************************************************************************
818 {
819 return etl::span<char>(pdata, pdata + size_bytes());
820 }
821
822 //***************************************************************************
824 //***************************************************************************
826 {
827 return etl::span<const char>(pdata, pdata + size_bytes());
828 }
829
830 //***************************************************************************
832 //***************************************************************************
834 {
835 return etl::span<char>(pdata, pdata + length_chars);
836 }
837
838 //***************************************************************************
840 //***************************************************************************
842 {
843 return etl::span<const char>(pdata, pdata + length_chars);
844 }
845
846 //***************************************************************************
848 //***************************************************************************
849 void flush()
850 {
851 if (callback.is_valid())
852 {
853 if (bits_available_in_char != 0U)
854 {
855 char_index = 1U; // Indicate that the first char is actually 'full'.
856 flush_full_bytes();
857 }
858
859 restart();
860 }
861 }
862
863 //***************************************************************************
865 //***************************************************************************
870
871 //***************************************************************************
873 //***************************************************************************
875 {
876 return callback;
877 }
878
879 private:
880
881 //***************************************************************************
884 //***************************************************************************
885 template <typename T>
886 void write_data(T value, uint_least8_t nbits)
887 {
888 // Make sure that we are not writing more bits than should be available.
889 nbits = (nbits > (CHAR_BIT * sizeof(T))) ? (CHAR_BIT * sizeof(T)) : nbits;
890
891 if (stream_endianness == etl::endian::little)
892 {
893 value = etl::reverse_bits(value);
894 value = value >> ((CHAR_BIT * sizeof(T)) - nbits);
895 }
896
897 // Send the bits to the stream.
898 while (nbits != 0)
899 {
900 unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
901 nbits -= mask_width;
902 T mask = ((T(1U) << mask_width) - 1U) << nbits;
903
904 // Move chunk to lowest char bits.
905 // Chunks are never larger than one char.
906 T chunk = ((value & mask) >> nbits) << (bits_available_in_char - mask_width);
907
908 write_chunk(static_cast<char>(chunk), mask_width);
909 }
910
911 if (callback.is_valid())
912 {
913 flush_full_bytes();
914 }
915 }
916
917 //***************************************************************************
919 //***************************************************************************
920 void write_chunk(char chunk, unsigned char nbits)
921 {
922 // Clear if new byte.
923 if (bits_available_in_char == CHAR_BIT)
924 {
925 pdata[char_index] = 0U;
926 }
927
928 pdata[char_index] |= chunk;
929 step(nbits);
930 }
931
932 //***************************************************************************
935 //***************************************************************************
936 void flush_full_bytes()
937 {
938 // Is the first byte fully filled?
939 if (char_index > 0U)
940 {
941 callback(callback_parameter_type(pdata, pdata + char_index));
942
943 bits_available = CHAR_BIT * length_chars;
944
945 if (bits_available_in_char != 0U)
946 {
947 // Move a partially filled last byte to the start of the buffer.
948 pdata[0] = pdata[char_index];
949 bits_available -= (CHAR_BIT - bits_available_in_char);
950 }
951
952 char_index = 0U;
953 }
954 }
955
956 //***************************************************************************
959 //***************************************************************************
960 void step(unsigned char nbits)
961 {
962 bits_available_in_char -= nbits;
963
964 if (bits_available_in_char == 0)
965 {
966 ++char_index;
967 bits_available_in_char = CHAR_BIT;
968 }
969
970 bits_available -= nbits;
971 }
972
973 char* const pdata;
974 const size_t length_chars;
975 const etl::endian stream_endianness;
976 unsigned char bits_available_in_char;
977 size_t char_index;
978 size_t bits_available;
979 callback_type callback;
980 };
981
982 //***************************************************************************
985 //***************************************************************************
987 {
988 stream.write_unchecked(value);
989 }
990
991 //***************************************************************************
994 //***************************************************************************
995 inline bool write(etl::bit_stream_writer& stream, bool value)
996 {
997 return stream.write(value);
998 }
999
1000 //***************************************************************************
1004 //***************************************************************************
1005 template <typename T>
1006 typename etl::enable_if<etl::is_integral<T>::value, void>::type
1008 {
1009 stream.write_unchecked(value, nbits);
1010 }
1011
1012 //***************************************************************************
1016 //***************************************************************************
1017 template <typename T>
1018 typename etl::enable_if<etl::is_integral<T>::value, bool>::type
1020 {
1021 return stream.write(value, nbits);
1022 }
1023
1024 //***************************************************************************
1026 //***************************************************************************
1028 {
1029 public:
1030
1031 typedef char value_type;
1032 typedef const char* const_iterator;
1033
1034 //***************************************************************************
1036 //***************************************************************************
1037 template <size_t Length>
1039 : pdata(span_.begin())
1040 , length_chars(span_.size_bytes())
1041 , stream_endianness(stream_endianness_)
1042 {
1043 restart();
1044 }
1045
1046 //***************************************************************************
1048 //***************************************************************************
1049 template <size_t Length>
1051 : pdata(reinterpret_cast<const char*>(span_.begin()))
1052 , length_chars(span_.size_bytes())
1053 , stream_endianness(stream_endianness_)
1054 {
1055 restart();
1056 }
1057
1058 //***************************************************************************
1060 //***************************************************************************
1061 template <size_t Length>
1063 : pdata(span_.begin())
1064 , length_chars(span_.size_bytes())
1065 , stream_endianness(stream_endianness_)
1066 {
1067 restart();
1068 }
1069
1070 //***************************************************************************
1072 //***************************************************************************
1073 template <size_t Length>
1075 : pdata(reinterpret_cast<const char*>(span_.begin()))
1076 , length_chars(span_.size_bytes())
1077 , stream_endianness(stream_endianness_)
1078 {
1079 restart();
1080 }
1081
1082 //***************************************************************************
1084 //***************************************************************************
1086 : pdata(reinterpret_cast<const char*>(begin_))
1087 , length_chars(etl::distance(reinterpret_cast<const char*>(begin_), reinterpret_cast<const char*>(end_)))
1088 , stream_endianness(stream_endianness_)
1089 {
1090 restart();
1091 }
1092
1093 //***************************************************************************
1095 //***************************************************************************
1097 : pdata(reinterpret_cast<const char*>(begin_))
1098 , length_chars(length_)
1099 , stream_endianness(stream_endianness_)
1100 {
1101 restart();
1102 }
1103
1104 //***************************************************************************
1106 //***************************************************************************
1107 void restart()
1108 {
1109 bits_available_in_char = CHAR_BIT;
1110 char_index = 0U;
1111 bits_available = CHAR_BIT * length_chars;
1112 }
1113
1114 //***************************************************************************
1116 //***************************************************************************
1117 template <typename T>
1120 {
1121 return get_bit();
1122 }
1123
1124 //***************************************************************************
1126 //***************************************************************************
1127 template <typename T>
1130 {
1131 etl::optional<bool> result;
1132
1133 if (bits_available > 0U)
1134 {
1135 result = read_unchecked<bool>();
1136 }
1137
1138 return result;
1139 }
1140
1141 //***************************************************************************
1143 //***************************************************************************
1144 template <typename T>
1147 {
1148 typedef typename etl::unsigned_type<T>::type unsigned_t;
1149
1151
1152 return static_cast<T>(value);
1153 }
1154
1155 //***************************************************************************
1157 //***************************************************************************
1158 template <typename T>
1161 {
1162 etl::optional<T> result;
1163
1164 // Do we have enough bits?
1165 if (bits_available >= nbits)
1166 {
1167 result = read_unchecked<T>(nbits);
1168 }
1169
1170 return result;
1171 }
1172
1173 //***************************************************************************
1175 //***************************************************************************
1176 size_t size_bytes() const
1177 {
1178 return length_chars;
1179 }
1180
1181 //***************************************************************************
1183 //***************************************************************************
1184 size_t size_bits() const
1185 {
1186 return length_chars * CHAR_BIT;
1187 }
1188
1189 //***************************************************************************
1191 //***************************************************************************
1193 {
1194 return pdata;
1195 }
1196
1197 //***************************************************************************
1199 //***************************************************************************
1201 {
1202 return pdata;
1203 }
1204
1205 //***************************************************************************
1207 //***************************************************************************
1209 {
1210 return pdata + size_bytes();
1211 }
1212
1213 //***************************************************************************
1215 //***************************************************************************
1217 {
1218 return pdata + size_bytes();
1219 }
1220
1221 //***************************************************************************
1223 //***************************************************************************
1225 {
1226 return etl::span<const char>(pdata, pdata + length_chars);
1227 }
1228
1229 //***************************************************************************
1233 //***************************************************************************
1234 bool skip(size_t nbits)
1235 {
1236 bool success = (nbits <= bits_available);
1237
1238 if (success)
1239 {
1240 while (nbits > bits_available_in_char)
1241 {
1242 nbits -= bits_available_in_char;
1243 step(bits_available_in_char);
1244 }
1245
1246 if (nbits != 0U)
1247 {
1248 step(static_cast<unsigned char>(nbits));
1249 }
1250 }
1251
1252 return success;
1253 }
1254
1255 private:
1256
1257 //***************************************************************************
1260 //***************************************************************************
1261 template <typename T>
1262 T read_value(uint_least8_t nbits, bool is_signed)
1263 {
1264 // Make sure that we are not reading more bits than should be available.
1265 nbits = (nbits > (CHAR_BIT * sizeof(T))) ? (CHAR_BIT * sizeof(T)) : nbits;
1266
1267 T value = 0;
1268 uint_least8_t bits = nbits;
1269
1270 // Get the bits from the stream.
1271 while (nbits != 0)
1272 {
1273 unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
1274
1275 T chunk = get_chunk(mask_width);
1276
1277 nbits -= mask_width;
1278 value |= static_cast<T>(chunk << nbits);
1279 }
1280
1281 if (stream_endianness == etl::endian::little)
1282 {
1283 value = value << ((CHAR_BIT * sizeof(T)) - bits);
1284 value = etl::reverse_bits(value);
1285 }
1286
1287 if (is_signed && (bits != (CHAR_BIT * sizeof(T))))
1288 {
1289 value = etl::sign_extend<T, T>(value, bits);
1290 }
1291
1292 return value;
1293 }
1294
1295 //***************************************************************************
1297 //***************************************************************************
1298 unsigned char get_chunk(unsigned char nbits)
1299 {
1300 unsigned char value = pdata[char_index];
1301 value >>= (bits_available_in_char - nbits);
1302
1303 unsigned char mask;
1304
1305 if (nbits == CHAR_BIT)
1306 {
1308 }
1309 else
1310 {
1311 mask = (1U << nbits) - 1;
1312 }
1313
1314 value &= mask;
1315
1316 step(nbits);
1317
1318 return value;
1319 }
1320
1321 //***************************************************************************
1323 //***************************************************************************
1324 bool get_bit()
1325 {
1326 bool result = (pdata[char_index] & (1U << (bits_available_in_char - 1U))) != 0U;
1327
1328 step(1U);
1329
1330 return result;
1331 }
1332
1333 //***************************************************************************
1336 //***************************************************************************
1337 void step(unsigned char nbits)
1338 {
1339 bits_available_in_char -= nbits;
1340
1341 if (bits_available_in_char == 0)
1342 {
1343 ++char_index;
1344 bits_available_in_char = 8;
1345 }
1346
1347 bits_available -= nbits;
1348 }
1349
1350 const char* pdata;
1351 size_t length_chars;
1352 const etl::endian stream_endianness;
1353 unsigned char bits_available_in_char;
1354 size_t char_index;
1355 size_t bits_available;
1356 };
1357
1358 //***************************************************************************
1360 //***************************************************************************
1361 template <typename T>
1363 {
1364 return stream.read_unchecked<T>();
1365 }
1366
1367 template <typename T>
1368 T read_unchecked(etl::bit_stream_reader& stream, uint_least8_t nbits)
1369 {
1370 return stream.read_unchecked<T>(nbits);
1371 }
1372
1373 //***************************************************************************
1375 //***************************************************************************
1376 template <typename T>
1378 {
1379 return stream.read<T>();
1380 }
1381
1382 template <typename T>
1383 etl::optional<T> read(etl::bit_stream_reader& stream, uint_least8_t nbits)
1384 {
1385 return stream.read<T>(nbits);
1386 }
1387
1388 //***************************************************************************
1390 //***************************************************************************
1391 template <>
1393 {
1394 return stream.read_unchecked<bool>();
1395 }
1396
1397 //***************************************************************************
1399 //***************************************************************************
1400 template <>
1402 {
1403 return stream.read<bool>();
1404 }
1405}
1406
1407#include "private/minmax_pop.h"
1408
1409#endif
Reads bit streams.
Definition bit_stream.h:1028
etl::enable_if< etl::is_same< bool, T >::value, etl::optional< bool > >::type read()
For bool types.
Definition bit_stream.h:1129
const_iterator end() const
Returns end of the stream.
Definition bit_stream.h:1208
bit_stream_reader(const etl::span< const unsigned char, Length > &span_, etl::endian stream_endianness_)
Construct from span.
Definition bit_stream.h:1074
const_iterator cend() const
Returns end of the stream.
Definition bit_stream.h:1216
bit_stream_reader(void *begin_, void *end_, etl::endian stream_endianness_)
Construct from range.
Definition bit_stream.h:1085
bit_stream_reader(void *begin_, size_t length_, etl::endian stream_endianness_)
Construct from begin and length.
Definition bit_stream.h:1096
bit_stream_reader(const etl::span< char, Length > &span_, etl::endian stream_endianness_)
Construct from span.
Definition bit_stream.h:1038
size_t size_bits() const
Returns the number of bits in the stream buffer.
Definition bit_stream.h:1184
etl::enable_if< etl::is_integral< T >::value &&!etl::is_same< bool, T >::value, T >::type read_unchecked(uint_least8_t nbits=CHAR_BIT *sizeof(T))
For integral types.
Definition bit_stream.h:1146
bool skip(size_t nbits)
Definition bit_stream.h:1234
bit_stream_reader(const etl::span< const char, Length > &span_, etl::endian stream_endianness_)
Construct from span.
Definition bit_stream.h:1062
bit_stream_reader(const etl::span< unsigned char, Length > &span_, etl::endian stream_endianness_)
Construct from span.
Definition bit_stream.h:1050
etl::enable_if< etl::is_integral< T >::value &&!etl::is_same< bool, T >::value, etl::optional< T > >::type read(uint_least8_t nbits=CHAR_BIT *sizeof(T))
For integral types.
Definition bit_stream.h:1160
void restart()
Sets the indexes back to the beginning of the stream.
Definition bit_stream.h:1107
const_iterator cbegin() const
Returns start of the stream.
Definition bit_stream.h:1200
etl::enable_if< etl::is_same< bool, T >::value, bool >::type read_unchecked()
For bool types.
Definition bit_stream.h:1119
etl::span< const char > data() const
Returns a span of whole the stream.
Definition bit_stream.h:1224
const_iterator begin() const
Returns start of the stream.
Definition bit_stream.h:1192
size_t size_bytes() const
Returns the number of bytes in the stream buffer.
Definition bit_stream.h:1176
Writes bits streams.
Definition bit_stream.h:527
bit_stream_writer(void *begin_, void *end_, etl::endian stream_endianness_, callback_type callback_=callback_type())
Construct from range.
Definition bit_stream.h:565
etl::enable_if< etl::is_integral< T >::value, bool >::type write(T value, uint_least8_t nbits=CHAR_BIT *sizeof(T))
For integral types.
Definition bit_stream.h:667
size_t size_bytes() const
Returns the number of bytes used in the stream.
Definition bit_stream.h:708
etl::enable_if< etl::is_integral< T >::value, void >::type write_unchecked(T value, uint_least8_t nbits=CHAR_BIT *sizeof(T))
For integral types.
Definition bit_stream.h:655
etl::span< const char > used_data() const
Returns a span of the used portion of the stream.
Definition bit_stream.h:825
bool write(bool value)
Writes a boolean to the stream.
Definition bit_stream.h:638
size_t size_bits() const
Returns the number of bits used in the stream.
Definition bit_stream.h:724
size_t available_bits() const
The number of bits left in the stream.
Definition bit_stream.h:761
const_iterator cend() const
Returns end of the stream.
Definition bit_stream.h:809
callback_type get_callback() const
Gets the function to call after every write.
Definition bit_stream.h:874
bool empty() const
Returns true if the bitsteam indexes have been reset.
Definition bit_stream.h:613
bit_stream_writer(void *begin_, size_t length_chars_, etl::endian stream_endianness_, callback_type callback_=callback_type())
Construct from begin and length.
Definition bit_stream.h:577
bit_stream_writer(const etl::span< unsigned char, Length > &span_, etl::endian stream_endianness_, callback_type callback_=callback_type())
Construct from span.
Definition bit_stream.h:553
bit_stream_writer(const etl::span< char, Length > &span_, etl::endian stream_endianness_, callback_type callback_=callback_type())
Construct from span.
Definition bit_stream.h:540
iterator end()
Returns end of the stream.
Definition bit_stream.h:793
void set_callback(callback_type callback_)
Sets the function to call after every write.
Definition bit_stream.h:866
size_t available() const
Definition bit_stream.h:734
etl::span< char > data()
Returns a span of whole the stream.
Definition bit_stream.h:833
bool full() const
Returns true if the bitsteam indexes have reached the end.
Definition bit_stream.h:621
bool skip(size_t nbits)
Definition bit_stream.h:684
etl::span< char > used_data()
Returns a span of the used portion of the stream.
Definition bit_stream.h:817
size_t capacity_bytes() const
Returns the maximum capacity in bits.
Definition bit_stream.h:599
etl::span< const char > data() const
Returns a span of whole the stream.
Definition bit_stream.h:841
void restart()
Sets the indexes back to the beginning of the stream.
Definition bit_stream.h:589
void write_unchecked(bool value)
Writes a boolean to the stream.
Definition bit_stream.h:629
void flush()
Flush the last byte, if partially filled, to the callback, if valid.
Definition bit_stream.h:849
const_iterator cbegin() const
Returns start of the stream.
Definition bit_stream.h:785
size_t available(size_t nbits) const
Definition bit_stream.h:753
const_iterator end() const
Returns end of the stream.
Definition bit_stream.h:801
const_iterator begin() const
Returns start of the stream.
Definition bit_stream.h:777
iterator begin()
Returns start of the stream.
Definition bit_stream.h:769
Definition bit_stream.h:56
etl::enable_if< etl::is_integral< T >::value, bool >::type get(T &value, uint_least8_t nbits=CHAR_BIT *sizeof(T))
For integral types.
Definition bit_stream.h:223
etl::enable_if< etl::is_integral< T >::value, bool >::type put(T value, uint_least8_t nbits=CHAR_BIT *sizeof(T))
For integral types.
Definition bit_stream.h:152
bool put(int64_t value, uint_least8_t nbits=CHAR_BIT *sizeof(int64_t))
For 64bit integral types.
Definition bit_stream.h:161
etl::enable_if< etl::is_floating_point< T >::value, bool >::type put(T value)
For floating point types.
Definition bit_stream.h:180
void restart()
Sets the indexes back to the beginning of the stream.
Definition bit_stream.h:112
size_t size() const
Returns the number of bytes used in the stream.
Definition bit_stream.h:297
size_t bits() const
Returns the number of bits used in the stream.
Definition bit_stream.h:313
bit_stream(void *begin_, void *end_)
Construct from range.
Definition bit_stream.h:74
bool put(uint64_t value, uint_least8_t nbits=CHAR_BIT *sizeof(uint64_t))
For 64bit integral types.
Definition bit_stream.h:169
bit_stream(void *begin_, size_t length_)
Construct from begin and length.
Definition bit_stream.h:84
etl::enable_if< etl::is_floating_point< T >::value, bool >::type get(T &value)
For floating point types.
Definition bit_stream.h:266
bool at_end() const
Returns true if the bitsteam indexes have reached the end.
Definition bit_stream.h:122
bool put(bool value)
Writes a boolean to the stream.
Definition bit_stream.h:130
bit_stream()
Default constructor.
Definition bit_stream.h:64
bool get(bool &value)
For bool types.
Definition bit_stream.h:201
void set_stream(void *begin_, size_t length_)
Construct from begin and length.
Definition bit_stream.h:94
void set_stream(void *begin_, void *end_)
Construct from range.
Definition bit_stream.h:104
const_iterator end() const
Returns end of the stream.
Definition bit_stream.h:329
const_iterator begin() const
Returns start of the stream.
Definition bit_stream.h:321
Definition callback.h:45
Declaration.
Definition delegate_cpp03.h:175
ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&etl::is_unsigned< T >::value &&(etl::integral_limits< T >::bits==16U), T >::type reverse_bits(T value)
Definition binary.h:541
Definition endianness.h:100
Definition integral_limits.h:516
is_same
Definition type_traits_generator.h:1041
is_signed
Definition type_traits_generator.h:1011
make_signed
Definition type_traits_generator.h:1171
make_unsigned
Definition type_traits_generator.h:1181
bitset_ext
Definition absolute.h:38
bool read_unchecked< bool >(etl::bit_stream_reader &stream)
Read an unchecked bool from a stream.
Definition bit_stream.h:1392
etl::optional< T > read(etl::bit_stream_reader &stream)
Read a checked type from a stream.
Definition bit_stream.h:1377
void write_unchecked(etl::bit_stream_writer &stream, bool value)
Definition bit_stream.h:986
etl::optional< bool > read< bool >(etl::bit_stream_reader &stream)
Read a bool from a stream.
Definition bit_stream.h:1401
T read_unchecked(etl::bit_stream_reader &stream)
Read an unchecked type from a stream.
Definition bit_stream.h:1362
bool write(etl::bit_stream_writer &stream, bool value)
Definition bit_stream.h:995
pair holds two objects of arbitrary type
Definition utility.h:164