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 "algorithm.h"
31#include "binary.h"
32#include "delegate.h"
33#include "endianness.h"
34#include "error_handler.h"
35#include "exception.h"
36#include "integral_limits.h"
37#include "iterator.h"
38#include "memory.h"
39#include "nullptr.h"
40#include "optional.h"
41#include "span.h"
42#include "type_traits.h"
43
44#include <limits.h>
45#include <stdint.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(static_cast<size_t>(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_, static_cast<size_t>(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>
151 typename etl::enable_if<etl::is_integral<T>::value, bool>::type put(T value, uint_least8_t nbits = CHAR_BIT * sizeof(T))
152 {
153 return put_integral(static_cast<uint32_t>(value), nbits);
154 }
155
156#if ETL_USING_64BIT_TYPES
157 //***************************************************************************
159 //***************************************************************************
160 bool put(int64_t value, uint_least8_t nbits = CHAR_BIT * sizeof(int64_t))
161 {
162 return put_integral(uint64_t(value), nbits);
163 }
164
165 //***************************************************************************
167 //***************************************************************************
168 bool put(uint64_t value, uint_least8_t nbits = CHAR_BIT * sizeof(uint64_t))
169 {
170 return put_integral(value, nbits);
171 }
172#endif
173
174 //***************************************************************************
176 //***************************************************************************
177 template <typename T>
178 typename etl::enable_if<etl::is_floating_point<T>::value, bool>::type put(T value)
179 {
180 bool success = true;
181
182 unsigned char data[sizeof(T)];
183 to_bytes(value, data);
184
185 for (size_t i = 0UL; i < sizeof(T); ++i)
186 {
187 if (!put_integral(uint32_t(data[i]), CHAR_BIT))
188 {
189 success = false;
190 }
191 }
192
193 return success;
194 }
195
196 //***************************************************************************
198 //***************************************************************************
199 bool get(bool& value)
200 {
201 bool success = false;
202
203 if (pdata != ETL_NULLPTR)
204 {
205 // Do we have enough bits?
206 if (bits_available > 0U)
207 {
208 value = get_bit();
209 success = true;
210 }
211 }
212
213 return success;
214 }
215
216 //***************************************************************************
218 //***************************************************************************
219 template <typename T>
220 typename etl::enable_if<etl::is_integral<T>::value, bool>::type get(T& value, uint_least8_t nbits = CHAR_BIT * sizeof(T))
221 {
222 bool success = false;
223 uint_least8_t bits = nbits;
224
225 if (pdata != ETL_NULLPTR)
226 {
227 // Do we have enough bits?
228 if (bits_available >= nbits)
229 {
230 value = 0;
231
232 // Get the bits from the stream.
233 while (nbits != 0)
234 {
235 unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
236
237 typedef typename etl::make_unsigned<T>::type chunk_t;
238 chunk_t chunk = get_chunk(mask_width);
239
240 nbits -= mask_width;
241 value |= static_cast<T>(chunk << nbits);
242 }
243
244 success = true;
245 }
246 }
247
248 // Sign extend if signed type and not already full bit width.
249 if (etl::is_signed<T>::value && (bits != (CHAR_BIT * sizeof(T))))
250 {
251 typedef typename etl::make_signed<T>::type ST;
252 value = static_cast<T>(etl::sign_extend<ST, ST>(static_cast<ST>(value), bits));
253 }
254
255 return success;
256 }
257
258 //***************************************************************************
260 //***************************************************************************
261 template <typename T>
262 typename etl::enable_if<etl::is_floating_point<T>::value, bool>::type get(T& value)
263 {
264 bool success = false;
265
266 if (pdata != ETL_NULLPTR)
267 {
268 uint_least8_t nbits = CHAR_BIT * sizeof(T);
269
270 // Do we have enough bits?
271 if (bits_available >= nbits)
272 {
273 // Temporary storage.
275
276 for (size_t i = 0UL; i < sizeof(T); ++i)
277 {
278 get(data.raw[i], CHAR_BIT);
279 }
280
281 from_bytes(reinterpret_cast<const unsigned char*>(data.raw), value);
282
283 success = true;
284 }
285 }
286
287 return success;
288 }
289
290 //***************************************************************************
292 //***************************************************************************
293 size_t size() const
294 {
295 size_t s = char_index;
296
297 // Current byte is used?
298 if (bits_available_in_char != CHAR_BIT)
299 {
300 ++s;
301 }
302
303 return s;
304 }
305
306 //***************************************************************************
308 //***************************************************************************
309 size_t bits() const
310 {
311 return (length_chars * CHAR_BIT) - bits_available;
312 }
313
314 //***************************************************************************
316 //***************************************************************************
317 const_iterator begin() const
318 {
319 return pdata;
320 }
321
322 //***************************************************************************
324 //***************************************************************************
325 const_iterator end() const
326 {
327 return pdata + size();
328 }
329
330 private:
331
332 //***************************************************************************
334 //***************************************************************************
335 bool put_integral(uint32_t value, uint_least8_t nbits)
336 {
337 bool success = false;
338
339 if (pdata != ETL_NULLPTR)
340 {
341 // Do we have enough bits?
342 if (bits_available >= nbits)
343 {
344 // Send the bits to the stream.
345 while (nbits != 0)
346 {
347 unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
348 nbits -= mask_width;
349 uint32_t mask = ((1U << mask_width) - 1U) << nbits;
350 // uint32_t mask = ((uint32_t(1U) << mask_width) - 1U) << nbits;
351
352 // Move chunk to lowest char bits.
353 // Chunks are never larger than one char.
354 uint32_t chunk = ((value & mask) >> nbits) << (bits_available_in_char - mask_width);
355
356 put_chunk(static_cast<unsigned char>(chunk), mask_width);
357 }
358
359 success = true;
360 }
361 }
362
363 return success;
364 }
365
366#if ETL_USING_64BIT_TYPES
367 //***************************************************************************
369 //***************************************************************************
370 bool put_integral(uint64_t value, uint_least8_t nbits)
371 {
372 bool success = false;
373
374 if (pdata != ETL_NULLPTR)
375 {
376 // Do we have enough bits?
377 if (bits_available >= nbits)
378 {
379 // Send the bits to the stream.
380 while (nbits != 0)
381 {
382 unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
383 nbits -= mask_width;
384 uint64_t mask = ((uint64_t(1U) << mask_width) - 1U) << nbits;
385
386 // Move chunk to lowest char bits.
387 // Chunks are never larger than one char.
388 uint64_t chunk = ((value & mask) >> nbits) << (bits_available_in_char - mask_width);
389
390 put_chunk(static_cast<unsigned char>(chunk), mask_width);
391 }
392
393 success = true;
394 }
395 }
396
397 return success;
398 }
399#endif
400
401 //***************************************************************************
403 //***************************************************************************
404 void put_chunk(unsigned char chunk, unsigned char nbits)
405 {
406 // Clear if new byte.
407 if (bits_available_in_char == 8U)
408 {
409 pdata[char_index] = 0U;
410 }
411
412 pdata[char_index] |= chunk;
413 step(nbits);
414 }
415
416 //***************************************************************************
418 //***************************************************************************
419 unsigned char get_chunk(unsigned char nbits)
420 {
421 unsigned char value = static_cast<unsigned char>(pdata[char_index]);
422
423 value >>= (bits_available_in_char - nbits);
424
425 unsigned char mask;
426
427 if (nbits == CHAR_BIT)
428 {
429 mask = etl::integral_limits<unsigned char>::max;
430 }
431 else
432 {
433 mask = static_cast<unsigned char>((1U << nbits) - 1);
434 }
435
436 value &= mask;
437
438 step(nbits);
439
440 return value;
441 }
442
443 //***************************************************************************
445 //***************************************************************************
446 bool get_bit()
447 {
448 bool result = (static_cast<unsigned char>(pdata[char_index]) & (1U << (bits_available_in_char - 1U))) != 0U;
449
450 step(1U);
451
452 return result;
453 }
454
455 //***************************************************************************
457 //***************************************************************************
458 template <typename T>
459 void from_bytes(const unsigned char* data, T& value)
460 {
461 etl::uninitialized_buffer_of<T, 1U> temp;
462
463 // Network to host.
464 if (etl::endianness::value() == etl::endian::little)
465 {
466 etl::reverse_copy(data, data + sizeof(T), reinterpret_cast<unsigned char*>(temp.raw));
467 }
468 else
469 {
470 etl::copy(data, data + sizeof(T), reinterpret_cast<unsigned char*>(temp.raw));
471 }
472
473 value = *reinterpret_cast<T*>(temp.raw);
474 }
475
476 //***************************************************************************
478 //***************************************************************************
479 template <typename T>
480 void to_bytes(T value, unsigned char* data)
481 {
482 unsigned char* pf = reinterpret_cast<unsigned char*>(&value);
483
484 // Host to network.
485 if (etl::endianness::value() == etl::endian::little)
486 {
487 etl::reverse_copy(pf, pf + sizeof(T), data);
488 }
489 else
490 {
491 etl::copy(pf, pf + sizeof(T), data);
492 }
493 }
494
495 //***************************************************************************
498 //***************************************************************************
499 void step(unsigned char nbits)
500 {
501 bits_available_in_char -= nbits;
502
503 if (bits_available_in_char == 0)
504 {
505 ++char_index;
506 bits_available_in_char = 8;
507 }
508
509 bits_available -= nbits;
510 }
511
512 unsigned char* pdata;
513 size_t length_chars;
514 unsigned char bits_available_in_char;
516 size_t char_index;
517 size_t bits_available;
519 };
520
521 //***************************************************************************
523 //***************************************************************************
525 {
526 public:
527
528 typedef char value_type;
529 typedef value_type* iterator;
530 typedef const value_type* const_iterator;
531 typedef etl::span<value_type> callback_parameter_type;
532 typedef etl::delegate<void(callback_parameter_type)> callback_type;
533
534 //***************************************************************************
536 //***************************************************************************
537 template <size_t Length>
538 bit_stream_writer(const etl::span<char, Length>& span_, etl::endian stream_endianness_, callback_type callback_ = callback_type())
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 //***************************************************************************
550 template <size_t Length>
551 bit_stream_writer(const etl::span<unsigned char, Length>& span_, etl::endian stream_endianness_, callback_type callback_ = callback_type())
552 : pdata(reinterpret_cast<char*>(span_.begin()))
553 , length_chars(span_.size_bytes())
554 , stream_endianness(stream_endianness_)
555 , callback(callback_)
556 {
557 restart();
558 }
559
560 //***************************************************************************
562 //***************************************************************************
563 bit_stream_writer(void* begin_, void* end_, etl::endian stream_endianness_, callback_type callback_ = callback_type())
564 : pdata(reinterpret_cast<char*>(begin_))
565 , length_chars(static_cast<size_t>(etl::distance(reinterpret_cast<unsigned char*>(begin_), reinterpret_cast<unsigned char*>(end_))))
566 , stream_endianness(stream_endianness_)
567 , callback(callback_)
568 {
569 restart();
570 }
571
572 //***************************************************************************
574 //***************************************************************************
575 bit_stream_writer(void* begin_, size_t length_chars_, etl::endian stream_endianness_, callback_type callback_ = callback_type())
576 : pdata(reinterpret_cast<char*>(begin_))
577 , length_chars(length_chars_)
578 , stream_endianness(stream_endianness_)
579 , callback(callback_)
580 {
581 restart();
582 }
583
584 //***************************************************************************
586 //***************************************************************************
587 void restart()
588 {
589 bits_available_in_char = CHAR_BIT;
590 char_index = 0U;
591 bits_available = capacity_bits();
592 }
593
594 //***************************************************************************
596 //***************************************************************************
597 size_t capacity_bytes() const
598 {
599 return length_chars;
600 }
601
602 //***************************************************************************
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 (available_bits() == capacity_bits());
616 }
617
618 //***************************************************************************
620 //***************************************************************************
621 bool full() const
622 {
623 return (available_bits() == 0U);
624 }
625
626 //***************************************************************************
628 //***************************************************************************
629 void write_unchecked(bool value)
630 {
631 unsigned char chunk = value ? 1 : 0;
632 write_data<unsigned char>(chunk, 1);
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>
654 typename etl::enable_if<etl::is_integral<T>::value, void>::type write_unchecked(T value, uint_least8_t nbits = CHAR_BIT * sizeof(T))
655 {
656 typedef typename etl::unsigned_type<T>::type unsigned_t;
657
658 write_data<unsigned_t>(static_cast<unsigned_t>(value), nbits);
659 }
660
661 //***************************************************************************
663 //***************************************************************************
664 template <typename T>
665 typename etl::enable_if<etl::is_integral<T>::value, bool>::type write(T value, uint_least8_t nbits = CHAR_BIT * sizeof(T))
666 {
667 bool success = (available(nbits) > 0U);
668
669 if (success)
670 {
671 write_unchecked(value, nbits);
672 }
673
674 return success;
675 }
676
677 //***************************************************************************
681 //***************************************************************************
682 bool skip(size_t nbits)
683 {
684 bool success = (nbits <= available_bits());
685
686 if (success)
687 {
688 while (nbits > bits_available_in_char)
689 {
690 step(bits_available_in_char);
691 nbits -= bits_available_in_char;
692 }
693
694 if (nbits != 0U)
695 {
696 step(static_cast<unsigned char>(nbits));
697 }
698 }
699
700 return success;
701 }
702
703 //***************************************************************************
705 //***************************************************************************
706 size_t size_bytes() const
707 {
708 size_t s = char_index;
709
710 // Is the current byte partially used?
711 if (bits_available_in_char != CHAR_BIT)
712 {
713 ++s;
714 }
715
716 return s;
717 }
718
719 //***************************************************************************
721 //***************************************************************************
722 size_t size_bits() const
723 {
724 return capacity_bits() - available_bits();
725 }
726
727 //***************************************************************************
730 //***************************************************************************
731 template <size_t Nbits>
732 size_t available() const
733 {
734 return bits_available / Nbits;
735 }
736
737 //***************************************************************************
740 //***************************************************************************
741 template <typename T>
742 size_t available() const
743 {
745 }
746
747 //***************************************************************************
750 //***************************************************************************
751 size_t available(size_t nbits) const
752 {
753 return bits_available / nbits;
754 }
755
756 //***************************************************************************
758 //***************************************************************************
759 size_t available_bits() const
760 {
761 return bits_available;
762 }
763
764 //***************************************************************************
766 //***************************************************************************
767 iterator begin()
768 {
769 return pdata;
770 }
771
772 //***************************************************************************
774 //***************************************************************************
775 const_iterator begin() const
776 {
777 return pdata;
778 }
779
780 //***************************************************************************
782 //***************************************************************************
783 const_iterator cbegin() const
784 {
785 return pdata;
786 }
787
788 //***************************************************************************
790 //***************************************************************************
791 iterator end()
792 {
793 return pdata + size_bytes();
794 }
795
796 //***************************************************************************
798 //***************************************************************************
799 const_iterator end() const
800 {
801 return pdata + size_bytes();
802 }
803
804 //***************************************************************************
806 //***************************************************************************
807 const_iterator cend() const
808 {
809 return pdata + size_bytes();
810 }
811
812 //***************************************************************************
814 //***************************************************************************
816 {
817 return etl::span<char>(pdata, pdata + size_bytes());
818 }
819
820 //***************************************************************************
822 //***************************************************************************
824 {
825 return etl::span<const char>(pdata, pdata + size_bytes());
826 }
827
828 //***************************************************************************
830 //***************************************************************************
832 {
833 return etl::span<char>(pdata, pdata + length_chars);
834 }
835
836 //***************************************************************************
838 //***************************************************************************
840 {
841 return etl::span<const char>(pdata, pdata + length_chars);
842 }
843
844 //***************************************************************************
846 //***************************************************************************
847 void flush()
848 {
849 if (callback.is_valid())
850 {
851 if (bits_available_in_char != 0U)
852 {
853 char_index = 1U; // Indicate that the first char is actually 'full'.
854 flush_full_bytes();
855 }
856
857 restart();
858 }
859 }
860
861 //***************************************************************************
863 //***************************************************************************
864 void set_callback(callback_type callback_)
865 {
866 callback = callback_;
867 }
868
869 //***************************************************************************
871 //***************************************************************************
872 callback_type get_callback() const
873 {
874 return callback;
875 }
876
877 private:
878
879 //***************************************************************************
882 //***************************************************************************
883 template <typename T>
884 void write_data(T value, uint_least8_t nbits)
885 {
886 // Make sure that we are not writing more bits than should be available.
887 nbits = (nbits > (CHAR_BIT * sizeof(T))) ? (CHAR_BIT * sizeof(T)) : nbits;
888
889 if (stream_endianness == etl::endian::little)
890 {
891 value = etl::reverse_bits(value);
892 value = value >> ((CHAR_BIT * sizeof(T)) - nbits);
893 }
894
895 // Send the bits to the stream.
896 while (nbits != 0)
897 {
898 unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
899 nbits -= mask_width;
900 T mask = ((T(1U) << mask_width) - 1U) << nbits;
901
902 // Move chunk to lowest char bits.
903 // Chunks are never larger than one char.
904 T chunk = ((value & mask) >> nbits) << (bits_available_in_char - mask_width);
905
906 write_chunk(static_cast<char>(chunk), mask_width);
907 }
908
909 if (callback.is_valid())
910 {
911 flush_full_bytes();
912 }
913 }
914
915 //***************************************************************************
917 //***************************************************************************
918 void write_chunk(char chunk, unsigned char nbits)
919 {
920 // Clear if new byte.
921 if (bits_available_in_char == CHAR_BIT)
922 {
923 pdata[char_index] = 0U;
924 }
925
926 pdata[char_index] |= chunk;
927 step(nbits);
928 }
929
930 //***************************************************************************
933 //***************************************************************************
934 void flush_full_bytes()
935 {
936 // Is the first byte fully filled?
937 if (char_index > 0U)
938 {
939 callback(callback_parameter_type(pdata, pdata + char_index));
940
941 bits_available = CHAR_BIT * length_chars;
942
943 if (bits_available_in_char != 0U)
944 {
945 // Move a partially filled last byte to the start of the buffer.
946 pdata[0] = pdata[char_index];
947 bits_available -= (CHAR_BIT - bits_available_in_char);
948 }
949
950 char_index = 0U;
951 }
952 }
953
954 //***************************************************************************
957 //***************************************************************************
958 void step(unsigned char nbits)
959 {
960 bits_available_in_char -= nbits;
961
962 if (bits_available_in_char == 0)
963 {
964 ++char_index;
965 bits_available_in_char = CHAR_BIT;
966 }
967
968 bits_available -= nbits;
969 }
970
971 char* const pdata;
972 const size_t length_chars;
973 const etl::endian stream_endianness;
974 unsigned char bits_available_in_char;
976 size_t char_index;
977 size_t bits_available;
979 callback_type callback;
980 };
981
982 //***************************************************************************
985 //***************************************************************************
986 inline void write_unchecked(etl::bit_stream_writer& stream, bool value)
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 write_unchecked(etl::bit_stream_writer& stream, const T& value,
1007 uint_least8_t nbits = CHAR_BIT * sizeof(T))
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 write(etl::bit_stream_writer& stream, const T& value,
1019 uint_least8_t nbits = CHAR_BIT * sizeof(T))
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 //***************************************************************************
1085 bit_stream_reader(const void* begin_, const void* end_, etl::endian stream_endianness_)
1086 : pdata(reinterpret_cast<const char*>(begin_))
1087 , length_chars(static_cast<size_t>(etl::distance(reinterpret_cast<const char*>(begin_), reinterpret_cast<const char*>(end_))))
1088 , stream_endianness(stream_endianness_)
1089 {
1090 restart();
1091 }
1092
1093 //***************************************************************************
1095 //***************************************************************************
1096 bit_stream_reader(const void* begin_, size_t length_, etl::endian stream_endianness_)
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>
1118 typename etl::enable_if<etl::is_same<bool, T>::value, bool>::type read_unchecked()
1119 {
1120 return get_bit();
1121 }
1122
1123 //***************************************************************************
1125 //***************************************************************************
1126 template <typename T>
1127 typename etl::enable_if<etl::is_same<bool, T>::value, etl::optional<bool> >::type read()
1128 {
1129 etl::optional<bool> result;
1130
1131 if (bits_available > 0U)
1132 {
1133 result = read_unchecked<bool>();
1134 }
1135
1136 return result;
1137 }
1138
1139 //***************************************************************************
1141 //***************************************************************************
1142 template <typename T>
1143 typename etl::enable_if< etl::is_integral<T>::value && !etl::is_same<bool, T>::value, T>::type read_unchecked(uint_least8_t nbits = CHAR_BIT
1144 * sizeof(T))
1145 {
1146 typedef typename etl::unsigned_type<T>::type unsigned_t;
1147
1148 T value = static_cast<T>(read_value<unsigned_t>(nbits, etl::is_signed<T>::value));
1149
1150 return static_cast<T>(value);
1151 }
1152
1153 //***************************************************************************
1155 //***************************************************************************
1156 template <typename T>
1157 typename etl::enable_if<etl::is_integral<T>::value && !etl::is_same<bool, T>::value, etl::optional<T> >::type
1158 read(uint_least8_t nbits = CHAR_BIT * sizeof(T))
1159 {
1160 etl::optional<T> result;
1161
1162 // Do we have enough bits?
1163 if (bits_available >= nbits)
1164 {
1165 result = read_unchecked<T>(nbits);
1166 }
1167
1168 return result;
1169 }
1170
1171 //***************************************************************************
1173 //***************************************************************************
1174 size_t size_bytes() const
1175 {
1176 return length_chars;
1177 }
1178
1179 //***************************************************************************
1181 //***************************************************************************
1182 size_t size_bits() const
1183 {
1184 return length_chars * CHAR_BIT;
1185 }
1186
1187 //***************************************************************************
1189 //***************************************************************************
1190 const_iterator begin() const
1191 {
1192 return pdata;
1193 }
1194
1195 //***************************************************************************
1197 //***************************************************************************
1198 const_iterator cbegin() const
1199 {
1200 return pdata;
1201 }
1202
1203 //***************************************************************************
1205 //***************************************************************************
1206 const_iterator end() const
1207 {
1208 return pdata + size_bytes();
1209 }
1210
1211 //***************************************************************************
1213 //***************************************************************************
1214 const_iterator cend() const
1215 {
1216 return pdata + size_bytes();
1217 }
1218
1219 //***************************************************************************
1221 //***************************************************************************
1223 {
1224 return etl::span<const char>(pdata, pdata + length_chars);
1225 }
1226
1227 //***************************************************************************
1231 //***************************************************************************
1232 bool skip(size_t nbits)
1233 {
1234 bool success = (nbits <= bits_available);
1235
1236 if (success)
1237 {
1238 while (nbits > bits_available_in_char)
1239 {
1240 nbits -= bits_available_in_char;
1241 step(bits_available_in_char);
1242 }
1243
1244 if (nbits != 0U)
1245 {
1246 step(static_cast<unsigned char>(nbits));
1247 }
1248 }
1249
1250 return success;
1251 }
1252
1253 private:
1254
1255 //***************************************************************************
1258 //***************************************************************************
1259 template <typename T>
1260 T read_value(uint_least8_t nbits, bool is_signed)
1261 {
1262 // Make sure that we are not reading more bits than should be available.
1263 nbits = (nbits > (CHAR_BIT * sizeof(T))) ? (CHAR_BIT * sizeof(T)) : nbits;
1264
1265 T value = 0;
1266 uint_least8_t bits = nbits;
1267
1268 // Get the bits from the stream.
1269 while (nbits != 0)
1270 {
1271 unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
1272
1273 T chunk = get_chunk(mask_width);
1274
1275 nbits -= mask_width;
1276 value |= static_cast<T>(chunk << nbits);
1277 }
1278
1279 if (stream_endianness == etl::endian::little)
1280 {
1281 value = value << ((CHAR_BIT * sizeof(T)) - bits);
1282 value = etl::reverse_bits(value);
1283 }
1284
1285 if (is_signed && (bits != (CHAR_BIT * sizeof(T))))
1286 {
1287 value = etl::sign_extend<T, T>(value, bits);
1288 }
1289
1290 return value;
1291 }
1292
1293 //***************************************************************************
1295 //***************************************************************************
1296 unsigned char get_chunk(unsigned char nbits)
1297 {
1298 unsigned char value = static_cast<unsigned char>(pdata[char_index]);
1299 value >>= (bits_available_in_char - nbits);
1300
1301 unsigned char mask;
1302
1303 if (nbits == CHAR_BIT)
1304 {
1305 mask = etl::integral_limits<unsigned char>::max;
1306 }
1307 else
1308 {
1309 mask = static_cast<unsigned char>((1U << nbits) - 1);
1310 }
1311
1312 value &= mask;
1313
1314 step(nbits);
1315
1316 return value;
1317 }
1318
1319 //***************************************************************************
1321 //***************************************************************************
1322 bool get_bit()
1323 {
1324 bool result = (static_cast<unsigned char>(pdata[char_index]) & (1U << (bits_available_in_char - 1U))) != 0U;
1325
1326 step(1U);
1327
1328 return result;
1329 }
1330
1331 //***************************************************************************
1334 //***************************************************************************
1335 void step(unsigned char nbits)
1336 {
1337 bits_available_in_char -= nbits;
1338
1339 if (bits_available_in_char == 0)
1340 {
1341 ++char_index;
1342 bits_available_in_char = 8;
1343 }
1344
1345 bits_available -= nbits;
1346 }
1347
1348 const char* pdata;
1349 size_t length_chars;
1350 const etl::endian stream_endianness;
1351 unsigned char bits_available_in_char;
1353 size_t char_index;
1354 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} // namespace etl
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:1127
const_iterator end() const
Returns end of the stream.
Definition bit_stream.h:1206
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:1214
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:1182
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:1143
bit_stream_reader(const void *begin_, size_t length_, etl::endian stream_endianness_)
Construct from begin and length.
Definition bit_stream.h:1096
bool skip(size_t nbits)
Definition bit_stream.h:1232
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 void *begin_, const void *end_, etl::endian stream_endianness_)
Construct from range.
Definition bit_stream.h:1085
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:1158
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:1198
etl::enable_if< etl::is_same< bool, T >::value, bool >::type read_unchecked()
For bool types.
Definition bit_stream.h:1118
etl::span< const char > data() const
Returns a span of whole the stream.
Definition bit_stream.h:1222
const_iterator begin() const
Returns start of the stream.
Definition bit_stream.h:1190
size_t size_bytes() const
Returns the number of bytes in the stream buffer.
Definition bit_stream.h:1174
Writes bits streams.
Definition bit_stream.h:525
bit_stream_writer(void *begin_, void *end_, etl::endian stream_endianness_, callback_type callback_=callback_type())
Construct from range.
Definition bit_stream.h:563
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:665
size_t size_bytes() const
Returns the number of bytes used in the stream.
Definition bit_stream.h:706
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:654
etl::span< const char > used_data() const
Returns a span of the used portion of the stream.
Definition bit_stream.h:823
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:722
size_t available_bits() const
The number of bits left in the stream.
Definition bit_stream.h:759
const_iterator cend() const
Returns end of the stream.
Definition bit_stream.h:807
callback_type get_callback() const
Gets the function to call after every write.
Definition bit_stream.h:872
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:575
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:551
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:538
iterator end()
Returns end of the stream.
Definition bit_stream.h:791
void set_callback(callback_type callback_)
Sets the function to call after every write.
Definition bit_stream.h:864
size_t available() const
Definition bit_stream.h:732
etl::span< char > data()
Returns a span of whole the stream.
Definition bit_stream.h:831
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:682
size_t capacity_bits() const
Returns the maximum capacity in bits.
Definition bit_stream.h:605
etl::span< char > used_data()
Returns a span of the used portion of the stream.
Definition bit_stream.h:815
size_t capacity_bytes() const
Returns the maximum capacity in bytes.
Definition bit_stream.h:597
etl::span< const char > data() const
Returns a span of whole the stream.
Definition bit_stream.h:839
void restart()
Sets the indexes back to the beginning of the stream.
Definition bit_stream.h:587
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:847
const_iterator cbegin() const
Returns start of the stream.
Definition bit_stream.h:783
size_t available(size_t nbits) const
Definition bit_stream.h:751
const_iterator end() const
Returns end of the stream.
Definition bit_stream.h:799
const_iterator begin() const
Returns start of the stream.
Definition bit_stream.h:775
iterator begin()
Returns start of the stream.
Definition bit_stream.h:767
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:220
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:151
bool put(int64_t value, uint_least8_t nbits=CHAR_BIT *sizeof(int64_t))
For 64bit integral types.
Definition bit_stream.h:160
etl::enable_if< etl::is_floating_point< T >::value, bool >::type put(T value)
For floating point types.
Definition bit_stream.h:178
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:293
size_t bits() const
Returns the number of bits used in the stream.
Definition bit_stream.h:309
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:168
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:262
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:199
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:325
const_iterator begin() const
Returns start of the stream.
Definition bit_stream.h:317
Declaration.
Definition delegate_cpp03.h:191
Definition optional.h:1273
Span - Fixed Extent.
Definition span.h:208
Definition memory.h:2728
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:542
ETL_CONSTEXPR14 TReturn sign_extend(TValue value)
Definition binary.h:273
Definition endianness.h:100
bitset_ext
Definition absolute.h:40
ETL_CONSTEXPR TContainer::pointer data(TContainer &container)
Definition iterator.h:1228
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
is_signed
Definition type_traits.h:458