11#pragma once
22#include " ../utility/assert.h"
3- #include " ../utility/bits.h"
43
54#include " ../stream/serialize_traits.h"
65#include " ../stream/bit_reader.h"
76#include " ../stream/bit_writer.h"
87
8+ #include " ../traits/bool_trait.h"
9+ #include " ../traits/integral_traits.h"
10+
911#include < cstdint>
1012
1113namespace bitstream
@@ -16,49 +18,113 @@ namespace bitstream
1618 template <typename T, typename Trait>
1719 struct serialize_traits <array_subset<T, Trait>>
1820 {
21+ private:
22+ template <uint32_t Min, uint32_t Max, typename Stream>
23+ static bool serialize_difference (Stream& stream, int & previous, int & current, uint32_t & difference)
24+ {
25+ bool use_bits;
26+ if (Stream::writing)
27+ use_bits = difference <= Max;
28+ BS_ASSERT (stream.template serialize <bool >(use_bits));
29+ if (use_bits)
30+ {
31+ using bounded_trait = bounded_int<uint32_t , Min, Max>;
32+
33+ BS_ASSERT (stream.template serialize <bounded_trait>(difference));
34+ if (Stream::reading)
35+ current = previous + difference;
36+ previous = current;
37+ return true ;
38+ }
39+
40+ return false ;
41+ }
42+
43+ template <typename Stream>
44+ static bool serialize_index (Stream& stream, int & previous, int & current, int max_size)
45+ {
46+ uint32_t difference;
47+ if (Stream::writing)
48+ {
49+ BS_ASSERT (previous < current);
50+ difference = current - previous;
51+ BS_ASSERT (difference > 0 );
52+ }
53+
54+ // +1 (1 bit)
55+ bool plus_one;
56+ if (Stream::writing)
57+ plus_one = difference == 1 ;
58+ BS_ASSERT (stream.template serialize <bool >(plus_one));
59+ if (plus_one)
60+ {
61+ if (Stream::reading)
62+ current = previous + 1 ;
63+ previous = current;
64+ return true ;
65+ }
66+
67+ // [+2,5] -> [0,3] (2 bits)
68+ if (serialize_difference<2 , 5 >(stream, previous, current, difference))
69+ return true ;
70+
71+ // [6,13] -> [0,7] (3 bits)
72+ if (serialize_difference<6 , 13 >(stream, previous, current, difference))
73+ return true ;
74+
75+ // [14,29] -> [0,15] (4 bits)
76+ if (serialize_difference<14 , 29 >(stream, previous, current, difference))
77+ return true ;
78+
79+ // [30,61] -> [0,31] (5 bits)
80+ if (serialize_difference<30 , 61 >(stream, previous, current, difference))
81+ return true ;
82+
83+ // [62,125] -> [0,63] (6 bits)
84+ if (serialize_difference<62 , 125 >(stream, previous, current, difference))
85+ return true ;
86+
87+ // [126,MaxObjects+1]
88+ BS_ASSERT (stream.template serialize <uint32_t >(difference, 126 , max_size));
89+ if (Stream::reading)
90+ current = previous + difference;
91+ previous = current;
92+ return true ;
93+ }
94+
95+ public:
1996 template <typename Compare, typename ... Args>
20- static bool serialize (bit_writer& writer, T* values, uint32_t max_size, Compare compare, Args&&... args) noexcept
97+ static bool serialize (bit_writer& writer, T* values, int max_size, Compare compare, Args&&... args) noexcept
2198 {
22- uint32_t prev_index = 0 ;
23- for (uint32_t i = 0 ; i < max_size; i ++)
99+ int prev_index = - 1 ;
100+ for (int index = 0 ; index < max_size; index ++)
24101 {
25- if (!compare (values[i ]))
102+ if (!compare (values[index ]))
26103 continue ;
27104
28- uint32_t num_bits = utility::bits_in_range (prev_index, max_size);
29-
30- uint32_t index = i - prev_index;
31- BS_ASSERT (writer.serialize_bits (index, num_bits));
32-
33- BS_ASSERT (writer.serialize <Trait>(values[i], std::forward<Args>(args)...));
105+ BS_ASSERT (serialize_index (writer, prev_index, index, max_size));
34106
35- prev_index = i ;
107+ BS_ASSERT (writer. serialize <Trait>(values[index], std::forward<Args>(args)...)) ;
36108 }
37109
38- uint32_t num_bits = utility::bits_in_range (prev_index, max_size);
39-
40- BS_ASSERT (writer.serialize_bits (max_size - prev_index, num_bits));
110+ BS_ASSERT (serialize_index (writer, prev_index, max_size, max_size));
41111
42112 return true ;
43113 }
44114
45115 template <typename Compare, typename ... Args>
46- static bool serialize (bit_reader& reader, T* values, uint32_t max_size, Compare compare, Args&&... args) noexcept
116+ static bool serialize (bit_reader& reader, T* values, int max_size, Compare compare, Args&&... args) noexcept
47117 {
48- uint32_t prev_index = 0 ;
49- for (uint32_t i = 0 ; i <= max_size; i++)
118+ int prev_index = -1 ;
119+ int index = 0 ;
120+ while (true )
50121 {
51- uint32_t num_bits = utility::bits_in_range (prev_index, max_size);
52-
53- uint32_t index;
54- BS_ASSERT (reader.serialize_bits (index, num_bits));
122+ BS_ASSERT (serialize_index (reader, prev_index, index, max_size));
55123
56- if (index + prev_index == max_size)
124+ if (index == max_size)
57125 break ;
58126
59- BS_ASSERT (reader.serialize <Trait>(values[index + prev_index], std::forward<Args>(args)...));
60-
61- prev_index += index;
127+ BS_ASSERT (reader.serialize <Trait>(values[index], std::forward<Args>(args)...));
62128 }
63129
64130 return true ;
0 commit comments