Embedded Template Library 1.0
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_)
75 : pdata(reinterpret_cast<unsigned char*>(begin_))
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_)
85 : pdata(reinterpret_cast<unsigned char*>(begin_))
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 //***************************************************************************
161 bool put(int64_t value, uint_least8_t nbits = CHAR_BIT * sizeof(int64_t))
162 {
163 return put_integral(uint64_t(value), nbits);
164 }
165
166 //***************************************************************************
168 //***************************************************************************
169 bool put(uint64_t value, uint_least8_t nbits = CHAR_BIT * sizeof(uint64_t))
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;
226 uint_least8_t bits = nbits;
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 //***************************************************************************
321 const_iterator begin() const
322 {
323 return pdata;
324 }
325
326 //***************************************************************************
328 //***************************************************************************
329 const_iterator end() const
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 = ((uint32_t(1U) << mask_width) - 1U) << nbits;
354
355 // Move chunk to lowest char bits.
356 // Chunks are never larger than one char.
357 uint32_t chunk = ((value & mask) >> nbits) << (bits_available_in_char - mask_width);
358
359 put_chunk(static_cast<unsigned char>(chunk), mask_width);
360 }
361
362 success = true;
363 }
364 }
365
366 return success;
367 }
368
369#if ETL_USING_64BIT_TYPES
370 //***************************************************************************
372 //***************************************************************************
373 bool put_integral(uint64_t value, uint_least8_t nbits)
374 {
375 bool success = false;
376
377 if (pdata != ETL_NULLPTR)
378 {
379 // Do we have enough bits?
380 if (bits_available >= nbits)
381 {
382 // Send the bits to the stream.
383 while (nbits != 0)
384 {
385 unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
386 nbits -= mask_width;
387 uint64_t mask = ((uint64_t(1U) << mask_width) - 1U) << nbits;
388
389 // Move chunk to lowest char bits.
390 // Chunks are never larger than one char.
391 uint64_t chunk = ((value & mask) >> nbits) << (bits_available_in_char - mask_width);
392
393 put_chunk(static_cast<unsigned char>(chunk), mask_width);
394 }
395
396 success = true;
397 }
398 }
399
400 return success;
401 }
402#endif
403
404 //***************************************************************************
406 //***************************************************************************
407 void put_chunk(unsigned char chunk, unsigned char nbits)
408 {
409 // Clear if new byte.
410 if (bits_available_in_char == 8U)
411 {
412 pdata[char_index] = 0U;
413 }
414
415 pdata[char_index] |= chunk;
416 step(nbits);
417 }
418
419 //***************************************************************************
421 //***************************************************************************
422 unsigned char get_chunk(unsigned char nbits)
423 {
424 unsigned char value = pdata[char_index];
425
426 value >>= (bits_available_in_char - nbits);
427
428 unsigned char mask;
429
430 if (nbits == CHAR_BIT)
431 {
433 }
434 else
435 {
436 mask = (1U << nbits) - 1;
437 }
438
439 value &= mask;
440
441 step(nbits);
442
443 return value;
444 }
445
446 //***************************************************************************
448 //***************************************************************************
449 bool get_bit()
450 {
451 bool result = (pdata[char_index] & (1U << (bits_available_in_char - 1U))) != 0U;
452
453 step(1U);
454
455 return result;
456 }
457
458 //***************************************************************************
460 //***************************************************************************
461 template <typename T>
462 void from_bytes(const unsigned char* data, T& value)
463 {
465
466 // Network to host.
467 if (etl::endianness::value() == etl::endian::little)
468 {
469 etl::reverse_copy(data, data + sizeof(T), temp.raw);
470 }
471 else
472 {
473 etl::copy(data, data + sizeof(T), temp.raw);
474 }
475
476 value = *reinterpret_cast<T*>(temp.raw);
477 }
478
479 //***************************************************************************
481 //***************************************************************************
482 template <typename T>
483 void to_bytes(T value, unsigned char* data)
484 {
485 unsigned char* pf = reinterpret_cast<unsigned char*>(&value);
486
487 // Host to network.
488 if (etl::endianness::value() == etl::endian::little)
489 {
490 etl::reverse_copy(pf, pf + sizeof(T), data);
491 }
492 else
493 {
494 etl::copy(pf, pf + sizeof(T), data);
495 }
496 }
497
498 //***************************************************************************
501 //***************************************************************************
502 void step(unsigned char nbits)
503 {
504 bits_available_in_char -= nbits;
505
506 if (bits_available_in_char == 0)
507 {
508 ++char_index;
509 bits_available_in_char = 8;
510 }
511
512 bits_available -= nbits;
513 }
514
515 unsigned char *pdata;
516 size_t length_chars;
517 unsigned char bits_available_in_char;
518 size_t char_index;
519 size_t bits_available;
520 };
521
522 //***************************************************************************
524 //***************************************************************************
526 {
527 public:
528
529 typedef char value_type;
530 typedef value_type* iterator;
531 typedef const value_type* const_iterator;
534
535 //***************************************************************************
537 //***************************************************************************
539 : pdata(span_.begin())
540 , length_chars(span_.size_bytes())
541 , stream_endianness(stream_endianness_)
542 , callback(callback_)
543 {
544 restart();
545 }
546
547 //***************************************************************************
549 //***************************************************************************
551 : pdata(reinterpret_cast<char*>(span_.begin()))
552 , length_chars(span_.size_bytes())
553 , stream_endianness(stream_endianness_)
554 , callback(callback_)
555 {
556 restart();
557 }
558
559 //***************************************************************************
561 //***************************************************************************
562 bit_stream_writer(void* begin_, void* end_, etl::endian stream_endianness_, callback_type callback_ = callback_type())
563 : pdata(reinterpret_cast<char*>(begin_))
564 , length_chars(etl::distance(reinterpret_cast<unsigned char*>(begin_), reinterpret_cast<unsigned char*>(end_)))
565 , stream_endianness(stream_endianness_)
566 , callback(callback_)
567 {
568 restart();
569 }
570
571 //***************************************************************************
573 //***************************************************************************
574 bit_stream_writer(void* begin_, size_t length_chars_, etl::endian stream_endianness_, callback_type callback_ = callback_type())
575 : pdata(reinterpret_cast<char*>(begin_))
576 , length_chars(length_chars_)
577 , stream_endianness(stream_endianness_)
578 , callback(callback_)
579 {
580 restart();
581 }
582
583 //***************************************************************************
585 //***************************************************************************
586 void restart()
587 {
588 bits_available_in_char = CHAR_BIT;
589 char_index = 0U;
590 bits_available = CHAR_BIT * length_chars;
591 }
592
593 //***************************************************************************
595 //***************************************************************************
596 size_t capacity_bytes() const
597 {
598 return length_chars;
599 }
600
601 //***************************************************************************
602 size_t capacity_bits() const
603 {
604 return length_chars * CHAR_BIT;
605 }
606
607 //***************************************************************************
609 //***************************************************************************
610 bool empty() const
611 {
612 return (bits_available == length_chars);
613 }
614
615 //***************************************************************************
617 //***************************************************************************
618 bool full() const
619 {
620 return (bits_available == 0U);
621 }
622
623 //***************************************************************************
625 //***************************************************************************
626 void write_unchecked(bool value)
627 {
628 unsigned char chunk = value ? 1 : 0;
629 write_data<unsigned char>(static_cast<unsigned char>(chunk), 1);
630 }
631
632 //***************************************************************************
634 //***************************************************************************
635 bool write(bool value)
636 {
637 bool success = (available<1U>() > 0U);
638
639 if (success)
640 {
641 write_unchecked(value);
642 }
643
644 return success;
645 }
646
647 //***************************************************************************
649 //***************************************************************************
650 template <typename T>
652 write_unchecked(T value, uint_least8_t nbits = CHAR_BIT * sizeof(T))
653 {
654 typedef typename etl::unsigned_type<T>::type unsigned_t;
655
656 write_data<unsigned_t>(static_cast<unsigned_t>(value), nbits);
657 }
658
659 //***************************************************************************
661 //***************************************************************************
662 template <typename T>
664 write(T value, uint_least8_t nbits = CHAR_BIT * sizeof(T))
665 {
666 bool success = (available(nbits) > 0U);
667
668 if (success)
669 {
670 write_unchecked(value, nbits);
671 }
672
673 return success;
674 }
675
676 //***************************************************************************
680 //***************************************************************************
681 bool skip(size_t nbits)
682 {
683 bool success = (nbits <= available_bits());
684
685 if (success)
686 {
687 while (nbits > bits_available_in_char)
688 {
689 step(bits_available_in_char);
690 nbits -= bits_available_in_char;
691 }
692
693 if (nbits != 0U)
694 {
695 step(static_cast<unsigned char>(nbits));
696 }
697 }
698
699 return success;
700 }
701
702 //***************************************************************************
704 //***************************************************************************
705 size_t size_bytes() const
706 {
707 size_t s = char_index;
708
709 // Is the current byte partially used?
710 if (bits_available_in_char != CHAR_BIT)
711 {
712 ++s;
713 }
714
715 return s;
716 }
717
718 //***************************************************************************
720 //***************************************************************************
721 size_t size_bits() const
722 {
723 return capacity_bits() - available_bits();
724 }
725
726 //***************************************************************************
729 //***************************************************************************
730 template <size_t Nbits>
731 size_t available() const
732 {
733 return bits_available / Nbits;
734 }
735
736 //***************************************************************************
739 //***************************************************************************
740 template <typename T>
741 size_t available() const
742 {
743 return available<CHAR_BIT * sizeof(T)>();
744 }
745
746 //***************************************************************************
749 //***************************************************************************
750 size_t available(size_t nbits) const
751 {
752 return bits_available / nbits;
753 }
754
755 //***************************************************************************
757 //***************************************************************************
758 size_t available_bits() const
759 {
760 return bits_available;
761 }
762
763 //***************************************************************************
765 //***************************************************************************
766 iterator begin()
767 {
768 return pdata;
769 }
770
771 //***************************************************************************
773 //***************************************************************************
774 const_iterator begin() const
775 {
776 return pdata;
777 }
778
779 //***************************************************************************
781 //***************************************************************************
782 const_iterator cbegin() const
783 {
784 return pdata;
785 }
786
787 //***************************************************************************
789 //***************************************************************************
790 iterator end()
791 {
792 return pdata + size_bytes();
793 }
794
795 //***************************************************************************
797 //***************************************************************************
798 const_iterator end() const
799 {
800 return pdata + size_bytes();
801 }
802
803 //***************************************************************************
805 //***************************************************************************
806 const_iterator cend() const
807 {
808 return pdata + size_bytes();
809 }
810
811 //***************************************************************************
813 //***************************************************************************
815 {
816 return etl::span<char>(pdata, pdata + size_bytes());
817 }
818
819 //***************************************************************************
821 //***************************************************************************
823 {
824 return etl::span<const char>(pdata, pdata + size_bytes());
825 }
826
827 //***************************************************************************
829 //***************************************************************************
831 {
832 return etl::span<char>(pdata, pdata + length_chars);
833 }
834
835 //***************************************************************************
837 //***************************************************************************
839 {
840 return etl::span<const char>(pdata, pdata + length_chars);
841 }
842
843 //***************************************************************************
845 //***************************************************************************
846 void flush()
847 {
848 if (callback.is_valid())
849 {
850 if (bits_available_in_char != 0U)
851 {
852 char_index = 1U; // Indicate that the first char is actually 'full'.
853 flush_full_bytes();
854 }
855
856 restart();
857 }
858 }
859
860 //***************************************************************************
862 //***************************************************************************
864 {
865 callback = callback_;
866 }
867
868 //***************************************************************************
870 //***************************************************************************
872 {
873 return callback;
874 }
875
876 private:
877
878 //***************************************************************************
881 //***************************************************************************
882 template <typename T>
883 void write_data(T value, uint_least8_t nbits)
884 {
885 // Make sure that we are not writing more bits than should be available.
886 nbits = (nbits > (CHAR_BIT * sizeof(T))) ? (CHAR_BIT * sizeof(T)) : nbits;
887
888 if (stream_endianness == etl::endian::little)
889 {
890 value = etl::reverse_bits(value);
891 value = value >> ((CHAR_BIT * sizeof(T)) - nbits);
892 }
893
894 // Send the bits to the stream.
895 while (nbits != 0)
896 {
897 unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
898 nbits -= mask_width;
899 T mask = ((T(1U) << mask_width) - 1U) << nbits;
900
901 // Move chunk to lowest char bits.
902 // Chunks are never larger than one char.
903 T chunk = ((value & mask) >> nbits) << (bits_available_in_char - mask_width);
904
905 write_chunk(static_cast<char>(chunk), mask_width);
906 }
907
908 if (callback.is_valid())
909 {
910 flush_full_bytes();
911 }
912 }
913
914 //***************************************************************************
916 //***************************************************************************
917 void write_chunk(char chunk, unsigned char nbits)
918 {
919 // Clear if new byte.
920 if (bits_available_in_char == CHAR_BIT)
921 {
922 pdata[char_index] = 0U;
923 }
924
925 pdata[char_index] |= chunk;
926 step(nbits);
927 }
928
929 //***************************************************************************
932 //***************************************************************************
933 void flush_full_bytes()
934 {
935 // Is the first byte fully filled?
936 if (char_index > 0U)
937 {
938 callback(callback_parameter_type(pdata, pdata + char_index));
939
940 bits_available = CHAR_BIT * length_chars;
941
942 if (bits_available_in_char != 0U)
943 {
944 // Move a partially filled last byte to the start of the buffer.
945 pdata[0] = pdata[char_index];
946 bits_available -= (CHAR_BIT - bits_available_in_char);
947 }
948
949 char_index = 0U;
950 }
951 }
952
953 //***************************************************************************
956 //***************************************************************************
957 void step(unsigned char nbits)
958 {
959 bits_available_in_char -= nbits;
960
961 if (bits_available_in_char == 0)
962 {
963 ++char_index;
964 bits_available_in_char = CHAR_BIT;
965 }
966
967 bits_available -= nbits;
968 }
969
970 char* const pdata;
971 const size_t length_chars;
972 const etl::endian stream_endianness;
973 unsigned char bits_available_in_char;
974 size_t char_index;
975 size_t bits_available;
976 callback_type callback;
977 };
978
979 //***************************************************************************
982 //***************************************************************************
983 inline void write_unchecked(etl::bit_stream_writer& stream, bool value)
984 {
985 stream.write_unchecked(value);
986 }
987
988 //***************************************************************************
991 //***************************************************************************
992 inline bool write(etl::bit_stream_writer& stream, bool value)
993 {
994 return stream.write(value);
995 }
996
997 //***************************************************************************
1001 //***************************************************************************
1002 template <typename T>
1003 typename etl::enable_if<etl::is_integral<T>::value, void>::type
1004 write_unchecked(etl::bit_stream_writer& stream, const T& value, uint_least8_t nbits = CHAR_BIT * sizeof(T))
1005 {
1006 stream.write_unchecked(value, nbits);
1007 }
1008
1009 //***************************************************************************
1013 //***************************************************************************
1014 template <typename T>
1015 typename etl::enable_if<etl::is_integral<T>::value, bool>::type
1016 write(etl::bit_stream_writer& stream, const T& value, uint_least8_t nbits = CHAR_BIT * sizeof(T))
1017 {
1018 return stream.write(value, nbits);
1019 }
1020
1021 //***************************************************************************
1023 //***************************************************************************
1025 {
1026 public:
1027
1028 typedef char value_type;
1029 typedef const char* const_iterator;
1030
1031 //***************************************************************************
1033 //***************************************************************************
1035 : pdata(span_.begin())
1036 , length_chars(span_.size_bytes())
1037 , stream_endianness(stream_endianness_)
1038 {
1039 restart();
1040 }
1041
1042 //***************************************************************************
1044 //***************************************************************************
1046 : pdata(reinterpret_cast<char*>(span_.begin()))
1047 , length_chars(span_.size_bytes())
1048 , stream_endianness(stream_endianness_)
1049 {
1050 restart();
1051 }
1052
1053 //***************************************************************************
1055 //***************************************************************************
1056 bit_stream_reader(void* begin_, void* end_, etl::endian stream_endianness_)
1057 : pdata(reinterpret_cast<char*>(begin_))
1058 , length_chars(etl::distance(reinterpret_cast<char*>(begin_), reinterpret_cast<char*>(end_)))
1059 , stream_endianness(stream_endianness_)
1060 {
1061 restart();
1062 }
1063
1064 //***************************************************************************
1066 //***************************************************************************
1067 bit_stream_reader(void* begin_, size_t length_, etl::endian stream_endianness_)
1068 : pdata(reinterpret_cast<char*>(begin_))
1069 , length_chars(length_)
1070 , stream_endianness(stream_endianness_)
1071 {
1072 restart();
1073 }
1074
1075 //***************************************************************************
1077 //***************************************************************************
1078 void restart()
1079 {
1080 bits_available_in_char = CHAR_BIT;
1081 char_index = 0U;
1082 bits_available = CHAR_BIT * length_chars;
1083 }
1084
1085 //***************************************************************************
1087 //***************************************************************************
1088 template <typename T>
1091 {
1092 return get_bit();
1093 }
1094
1095 //***************************************************************************
1097 //***************************************************************************
1098 template <typename T>
1101 {
1102 etl::optional<bool> result;
1103
1104 if (bits_available > 0U)
1105 {
1106 result = read_unchecked<bool>();
1107 }
1108
1109 return result;
1110 }
1111
1112 //***************************************************************************
1114 //***************************************************************************
1115 template <typename T>
1117 read_unchecked(uint_least8_t nbits = CHAR_BIT * sizeof(T))
1118 {
1119 typedef typename etl::unsigned_type<T>::type unsigned_t;
1120
1121 T value = read_value<unsigned_t>(nbits, etl::is_signed<T>::value);
1122
1123 return static_cast<T>(value);
1124 }
1125
1126 //***************************************************************************
1128 //***************************************************************************
1129 template <typename T>
1131 read(uint_least8_t nbits = CHAR_BIT * sizeof(T))
1132 {
1133 etl::optional<T> result;
1134
1135 // Do we have enough bits?
1136 if (bits_available >= nbits)
1137 {
1138 result = read_unchecked<T>(nbits);
1139 }
1140
1141 return result;
1142 }
1143
1144 //***************************************************************************
1146 //***************************************************************************
1147 size_t size_bytes() const
1148 {
1149 return length_chars;
1150 }
1151
1152 //***************************************************************************
1154 //***************************************************************************
1155 size_t size_bits() const
1156 {
1157 return length_chars * CHAR_BIT;
1158 }
1159
1160 //***************************************************************************
1162 //***************************************************************************
1163 const_iterator begin() const
1164 {
1165 return pdata;
1166 }
1167
1168 //***************************************************************************
1170 //***************************************************************************
1171 const_iterator cbegin() const
1172 {
1173 return pdata;
1174 }
1175
1176 //***************************************************************************
1178 //***************************************************************************
1179 const_iterator end() const
1180 {
1181 return pdata + size_bytes();
1182 }
1183
1184 //***************************************************************************
1186 //***************************************************************************
1187 const_iterator cend() const
1188 {
1189 return pdata + size_bytes();
1190 }
1191
1192 //***************************************************************************
1194 //***************************************************************************
1196 {
1197 return etl::span<const char>(pdata, pdata + length_chars);
1198 }
1199
1200 //***************************************************************************
1204 //***************************************************************************
1205 bool skip(size_t nbits)
1206 {
1207 bool success = (nbits <= bits_available);
1208
1209 if (success)
1210 {
1211 while (nbits > bits_available_in_char)
1212 {
1213 nbits -= bits_available_in_char;
1214 step(bits_available_in_char);
1215 }
1216
1217 if (nbits != 0U)
1218 {
1219 step(static_cast<unsigned char>(nbits));
1220 }
1221 }
1222
1223 return success;
1224 }
1225
1226 private:
1227
1228 //***************************************************************************
1231 //***************************************************************************
1232 template <typename T>
1233 T read_value(uint_least8_t nbits, bool is_signed)
1234 {
1235 // Make sure that we are not reading more bits than should be available.
1236 nbits = (nbits > (CHAR_BIT * sizeof(T))) ? (CHAR_BIT * sizeof(T)) : nbits;
1237
1238 T value = 0;
1239 uint_least8_t bits = nbits;
1240
1241 // Get the bits from the stream.
1242 while (nbits != 0)
1243 {
1244 unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
1245
1246 T chunk = get_chunk(mask_width);
1247
1248 nbits -= mask_width;
1249 value |= static_cast<T>(chunk << nbits);
1250 }
1251
1252 if (stream_endianness == etl::endian::little)
1253 {
1254 value = value << ((CHAR_BIT * sizeof(T)) - bits);
1255 value = etl::reverse_bits(value);
1256 }
1257
1258 if (is_signed && (bits != (CHAR_BIT * sizeof(T))))
1259 {
1260 value = etl::sign_extend<T, T>(value, bits);
1261 }
1262
1263 return value;
1264 }
1265
1266 //***************************************************************************
1268 //***************************************************************************
1269 unsigned char get_chunk(unsigned char nbits)
1270 {
1271 unsigned char value = pdata[char_index];
1272 value >>= (bits_available_in_char - nbits);
1273
1274 unsigned char mask;
1275
1276 if (nbits == CHAR_BIT)
1277 {
1279 }
1280 else
1281 {
1282 mask = (1U << nbits) - 1;
1283 }
1284
1285 value &= mask;
1286
1287 step(nbits);
1288
1289 return value;
1290 }
1291
1292 //***************************************************************************
1294 //***************************************************************************
1295 bool get_bit()
1296 {
1297 bool result = (pdata[char_index] & (1U << (bits_available_in_char - 1U))) != 0U;
1298
1299 step(1U);
1300
1301 return result;
1302 }
1303
1304 //***************************************************************************
1307 //***************************************************************************
1308 void step(unsigned char nbits)
1309 {
1310 bits_available_in_char -= nbits;
1311
1312 if (bits_available_in_char == 0)
1313 {
1314 ++char_index;
1315 bits_available_in_char = 8;
1316 }
1317
1318 bits_available -= nbits;
1319 }
1320
1321 char* pdata;
1322 size_t length_chars;
1323 const etl::endian stream_endianness;
1324 unsigned char bits_available_in_char;
1325 size_t char_index;
1326 size_t bits_available;
1327 };
1328
1329 //***************************************************************************
1331 //***************************************************************************
1332 template <typename T>
1334 {
1335 return stream.read_unchecked<T>();
1336 }
1337
1338 template <typename T>
1339 T read_unchecked(etl::bit_stream_reader& stream, uint_least8_t nbits)
1340 {
1341 return stream.read_unchecked<T>(nbits);
1342 }
1343
1344 //***************************************************************************
1346 //***************************************************************************
1347 template <typename T>
1349 {
1350 return stream.read<T>();
1351 }
1352
1353 template <typename T>
1354 etl::optional<T> read(etl::bit_stream_reader& stream, uint_least8_t nbits)
1355 {
1356 return stream.read<T>(nbits);
1357 }
1358
1359 //***************************************************************************
1361 //***************************************************************************
1362 template <>
1364 {
1365 return stream.read_unchecked<bool>();
1366 }
1367
1368 //***************************************************************************
1370 //***************************************************************************
1371 template <>
1373 {
1374 return stream.read<bool>();
1375 }
1376}
1377
1378#include "private/minmax_pop.h"
1379
1380#endif
Reads bit streams.
Definition: bit_stream.h:1025
etl::enable_if< etl::is_same< bool, T >::value, etl::optional< bool > >::type read()
For bool types.
Definition: bit_stream.h:1100
const_iterator end() const
Returns end of the stream.
Definition: bit_stream.h:1179
const_iterator cend() const
Returns end of the stream.
Definition: bit_stream.h:1187
bit_stream_reader(void *begin_, void *end_, etl::endian stream_endianness_)
Construct from range.
Definition: bit_stream.h:1056
bit_stream_reader(void *begin_, size_t length_, etl::endian stream_endianness_)
Construct from begin and length.
Definition: bit_stream.h:1067
size_t size_bits() const
Returns the number of bits in the stream buffer.
Definition: bit_stream.h:1155
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:1117
bool skip(size_t nbits)
Definition: bit_stream.h:1205
bit_stream_reader(etl::span< char > span_, etl::endian stream_endianness_)
Construct from span.
Definition: bit_stream.h:1034
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:1131
void restart()
Sets the indexes back to the beginning of the stream.
Definition: bit_stream.h:1078
const_iterator cbegin() const
Returns start of the stream.
Definition: bit_stream.h:1171
etl::enable_if< etl::is_same< bool, T >::value, bool >::type read_unchecked()
For bool types.
Definition: bit_stream.h:1090
etl::span< const char > data() const
Returns a span of whole the stream.
Definition: bit_stream.h:1195
bit_stream_reader(etl::span< unsigned char > span_, etl::endian stream_endianness_)
Construct from span.
Definition: bit_stream.h:1045
const_iterator begin() const
Returns start of the stream.
Definition: bit_stream.h:1163
size_t size_bytes() const
Returns the number of bytes in the stream buffer.
Definition: bit_stream.h:1147
Writes bits streams.
Definition: bit_stream.h:526
bit_stream_writer(void *begin_, void *end_, etl::endian stream_endianness_, callback_type callback_=callback_type())
Construct from range.
Definition: bit_stream.h:562
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:664
size_t size_bytes() const
Returns the number of bytes used in the stream.
Definition: bit_stream.h:705
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:652
etl::span< const char > used_data() const
Returns a span of the used portion of the stream.
Definition: bit_stream.h:822
bool write(bool value)
Writes a boolean to the stream.
Definition: bit_stream.h:635
size_t size_bits() const
Returns the number of bits used in the stream.
Definition: bit_stream.h:721
size_t available_bits() const
The number of bits left in the stream.
Definition: bit_stream.h:758
const_iterator cend() const
Returns end of the stream.
Definition: bit_stream.h:806
callback_type get_callback() const
Gets the function to call afer every write.
Definition: bit_stream.h:871
bool empty() const
Returns true if the bitsteam indexes have been reset.
Definition: bit_stream.h:610
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:574
iterator end()
Returns end of the stream.
Definition: bit_stream.h:790
void set_callback(callback_type callback_)
Sets the function to call afer every write.
Definition: bit_stream.h:863
size_t available() const
Definition: bit_stream.h:731
etl::span< char > data()
Returns a span of whole the stream.
Definition: bit_stream.h:830
bool full() const
Returns true if the bitsteam indexes have reached the end.
Definition: bit_stream.h:618
bool skip(size_t nbits)
Definition: bit_stream.h:681
bit_stream_writer(etl::span< char > span_, etl::endian stream_endianness_, callback_type callback_=callback_type())
Construct from span.
Definition: bit_stream.h:538
etl::span< char > used_data()
Returns a span of the used portion of the stream.
Definition: bit_stream.h:814
size_t capacity_bytes() const
Returns the maximum capacity in bits.
Definition: bit_stream.h:596
etl::span< const char > data() const
Returns a span of whole the stream.
Definition: bit_stream.h:838
void restart()
Sets the indexes back to the beginning of the stream.
Definition: bit_stream.h:586
void write_unchecked(bool value)
Writes a boolean to the stream.
Definition: bit_stream.h:626
void flush()
Flush the last byte, if partially filled, to the callback, if valid.
Definition: bit_stream.h:846
const_iterator cbegin() const
Returns start of the stream.
Definition: bit_stream.h:782
size_t available(size_t nbits) const
Definition: bit_stream.h:750
const_iterator end() const
Returns end of the stream.
Definition: bit_stream.h:798
const_iterator begin() const
Returns start of the stream.
Definition: bit_stream.h:774
iterator begin()
Returns start of the stream.
Definition: bit_stream.h:766
bit_stream_writer(etl::span< unsigned char > span_, etl::endian stream_endianness_, callback_type callback_=callback_type())
Construct from span.
Definition: bit_stream.h:550
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
Definition: optional.h:108
Span - Fixed Extent.
Definition: span.h:62
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:575
Definition: endianness.h:100
Definition: integral_limits.h:468
enable_if
Definition: type_traits_generator.h:1191
is_same
Definition: type_traits_generator.h:1041
is_signed
Definition: type_traits_generator.h:1011
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:1363
etl::optional< T > read(etl::bit_stream_reader &stream)
Read a checked type from a stream.
Definition: bit_stream.h:1348
void write_unchecked(etl::bit_stream_writer &stream, bool value)
Definition: bit_stream.h:983
etl::optional< bool > read< bool >(etl::bit_stream_reader &stream)
Read a bool from a stream.
Definition: bit_stream.h:1372
T read_unchecked(etl::bit_stream_reader &stream)
Read an unchecked type from a stream.
Definition: bit_stream.h:1333
bool write(etl::bit_stream_writer &stream, bool value)
Definition: bit_stream.h:992