1
1
#pragma once
2
2
3
- #include < iostream>
4
3
#include < base/types.h>
5
4
#include < IO/ReadBuffer.h>
6
5
#include < IO/WriteBuffer.h>
7
6
8
7
9
8
namespace DB
10
9
{
11
- namespace ErrorCodes
12
- {
13
- extern const int ATTEMPT_TO_READ_AFTER_EOF;
14
- }
15
-
16
10
17
- /* * Write UInt64 in variable length format (base128) NOTE Only up to 2^63 - 1 are supported. */
18
- void writeVarUInt (UInt64 x, std::ostream & ostr);
19
- void writeVarUInt (UInt64 x, WriteBuffer & ostr);
20
- char * writeVarUInt (UInt64 x, char * ostr);
11
+ // / Variable-Length Quantity (VLQ) Base-128 compression, also known as Variable Byte (VB) or Varint encoding.
21
12
13
+ [[noreturn]] void throwReadAfterEOF ();
22
14
23
- /* * Read UInt64, written in variable length format (base128) */
24
- void readVarUInt (UInt64 & x, std::istream & istr);
25
- void readVarUInt (UInt64 & x, ReadBuffer & istr);
26
- const char * readVarUInt (UInt64 & x, const char * istr, size_t size);
27
15
16
+ inline void writeVarUInt (UInt64 x, WriteBuffer & ostr)
17
+ {
18
+ while (x > 0x7F )
19
+ {
20
+ uint8_t byte = 0x80 | (x & 0x7F );
28
21
29
- /* * Get the length of UInt64 in VarUInt format */
30
- size_t getLengthOfVarUInt (UInt64 x);
22
+ ostr.nextIfAtEnd ();
23
+ *ostr.position () = byte;
24
+ ++ostr.position ();
31
25
32
- /* * Get the Int64 length in VarInt format */
33
- size_t getLengthOfVarInt (Int64 x);
26
+ x >>= 7 ;
27
+ }
34
28
29
+ uint8_t final_byte = static_cast <uint8_t >(x);
35
30
36
- /* * Write Int64 in variable length format (base128) */
37
- template <typename OUT>
38
- inline void writeVarInt (Int64 x, OUT & ostr)
39
- {
40
- writeVarUInt (static_cast <UInt64>((x << 1 ) ^ (x >> 63 )), ostr);
31
+ ostr.nextIfAtEnd ();
32
+ *ostr.position () = final_byte;
33
+ ++ostr.position ();
41
34
}
42
35
43
- inline char * writeVarInt (Int64 x, char * ostr)
36
+ inline void writeVarUInt (UInt64 x, std::ostream & ostr)
44
37
{
45
- return writeVarUInt (static_cast <UInt64>((x << 1 ) ^ (x >> 63 )), ostr);
46
- }
38
+ while (x > 0x7F )
39
+ {
40
+ uint8_t byte = 0x80 | (x & 0x7F );
41
+ ostr.put (byte);
47
42
43
+ x >>= 7 ;
44
+ }
48
45
49
- /* * Read Int64, written in variable length format (base128) */
50
- template <typename IN>
51
- inline void readVarInt (Int64 & x, IN & istr)
52
- {
53
- readVarUInt (*reinterpret_cast <UInt64*>(&x), istr);
54
- x = (static_cast <UInt64>(x) >> 1 ) ^ -(x & 1 );
46
+ uint8_t final_byte = static_cast <uint8_t >(x);
47
+ ostr.put (final_byte);
55
48
}
56
49
57
- inline const char * readVarInt (Int64 & x, const char * istr, size_t size )
50
+ inline char * writeVarUInt (UInt64 x, char * ostr )
58
51
{
59
- const char * res = readVarUInt (*reinterpret_cast <UInt64*>(&x), istr, size);
60
- x = (static_cast <UInt64>(x) >> 1 ) ^ -(x & 1 );
61
- return res;
62
- }
63
-
64
-
65
- inline void writeVarT (UInt64 x, std::ostream & ostr) { writeVarUInt (x, ostr); }
66
- inline void writeVarT (Int64 x, std::ostream & ostr) { writeVarInt (x, ostr); }
67
- inline void writeVarT (UInt64 x, WriteBuffer & ostr) { writeVarUInt (x, ostr); }
68
- inline void writeVarT (Int64 x, WriteBuffer & ostr) { writeVarInt (x, ostr); }
69
- inline char * writeVarT (UInt64 x, char * & ostr) { return writeVarUInt (x, ostr); }
70
- inline char * writeVarT (Int64 x, char * & ostr) { return writeVarInt (x, ostr); }
52
+ while (x > 0x7F )
53
+ {
54
+ uint8_t byte = 0x80 | (x & 0x7F );
71
55
72
- inline void readVarT (UInt64 & x, std::istream & istr) { readVarUInt (x, istr); }
73
- inline void readVarT (Int64 & x, std::istream & istr) { readVarInt (x, istr); }
74
- inline void readVarT (UInt64 & x, ReadBuffer & istr) { readVarUInt (x, istr); }
75
- inline void readVarT (Int64 & x, ReadBuffer & istr) { readVarInt (x, istr); }
76
- inline const char * readVarT (UInt64 & x, const char * istr, size_t size) { return readVarUInt (x, istr, size); }
77
- inline const char * readVarT (Int64 & x, const char * istr, size_t size) { return readVarInt (x, istr, size); }
56
+ *ostr = byte;
57
+ ++ostr;
78
58
59
+ x >>= 7 ;
60
+ }
79
61
80
- // / For [U]Int32, [U]Int16, size_t.
62
+ uint8_t final_byte = static_cast < uint8_t >(x);
81
63
82
- inline void readVarUInt (UInt32 & x, ReadBuffer & istr)
83
- {
84
- UInt64 tmp;
85
- readVarUInt (tmp, istr);
86
- x = static_cast <UInt32>(tmp);
87
- }
64
+ *ostr = final_byte;
65
+ ++ostr;
88
66
89
- inline void readVarInt (Int32 & x, ReadBuffer & istr)
90
- {
91
- Int64 tmp;
92
- readVarInt (tmp, istr);
93
- x = static_cast <Int32>(tmp);
67
+ return ostr;
94
68
}
95
69
96
- inline void readVarUInt (UInt16 & x, ReadBuffer & istr)
70
+ template <typename Out>
71
+ inline void writeVarInt (Int64 x, Out & ostr)
97
72
{
98
- UInt64 tmp;
99
- readVarUInt (tmp, istr);
100
- x = tmp;
73
+ writeVarUInt (static_cast <UInt64>((x << 1 ) ^ (x >> 63 )), ostr);
101
74
}
102
75
103
- inline void readVarInt (Int16 & x, ReadBuffer & istr )
76
+ inline char * writeVarInt (Int64 x, char * ostr )
104
77
{
105
- Int64 tmp;
106
- readVarInt (tmp, istr);
107
- x = tmp;
78
+ return writeVarUInt (static_cast <UInt64>((x << 1 ) ^ (x >> 63 )), ostr);
108
79
}
109
80
110
- template <typename T>
111
- requires (!std::is_same_v<T, UInt64>)
112
- inline void readVarUInt (T & x, ReadBuffer & istr)
81
+ namespace impl
113
82
{
114
- UInt64 tmp;
115
- readVarUInt (tmp, istr);
116
- x = tmp;
117
- }
118
-
119
83
120
- [[noreturn]] inline void throwReadAfterEOF ()
121
- {
122
- throw Exception (" Attempt to read after eof" , ErrorCodes::ATTEMPT_TO_READ_AFTER_EOF);
123
- }
124
-
125
- template <bool fast>
126
- inline void readVarUIntImpl (UInt64 & x, ReadBuffer & istr)
84
+ template <bool check_eof>
85
+ inline void readVarUInt (UInt64 & x, ReadBuffer & istr)
127
86
{
128
87
x = 0 ;
129
- for (size_t i = 0 ; i < 9 ; ++i)
88
+ for (size_t i = 0 ; i < 10 ; ++i)
130
89
{
131
- if constexpr (!fast )
132
- if (istr.eof ())
90
+ if constexpr (check_eof )
91
+ if (istr.eof ()) [[unlikely]]
133
92
throwReadAfterEOF ();
134
93
135
- UInt64 byte = *istr.position (); // / NOLINT
94
+ UInt64 byte = *istr.position ();
136
95
++istr.position ();
137
96
x |= (byte & 0x7F ) << (7 * i);
138
97
@@ -141,18 +100,19 @@ inline void readVarUIntImpl(UInt64 & x, ReadBuffer & istr)
141
100
}
142
101
}
143
102
103
+ }
104
+
144
105
inline void readVarUInt (UInt64 & x, ReadBuffer & istr)
145
106
{
146
- if (istr.buffer ().end () - istr.position () >= 9 )
147
- return readVarUIntImpl< true >(x, istr);
148
- return readVarUIntImpl< false >(x, istr);
107
+ if (istr.buffer ().end () - istr.position () >= 10 )
108
+ return impl::readVarUInt< false >(x, istr);
109
+ return impl::readVarUInt< true >(x, istr);
149
110
}
150
111
151
-
152
112
inline void readVarUInt (UInt64 & x, std::istream & istr)
153
113
{
154
114
x = 0 ;
155
- for (size_t i = 0 ; i < 9 ; ++i)
115
+ for (size_t i = 0 ; i < 10 ; ++i)
156
116
{
157
117
UInt64 byte = istr.get ();
158
118
x |= (byte & 0x7F ) << (7 * i);
@@ -167,12 +127,12 @@ inline const char * readVarUInt(UInt64 & x, const char * istr, size_t size)
167
127
const char * end = istr + size;
168
128
169
129
x = 0 ;
170
- for (size_t i = 0 ; i < 9 ; ++i)
130
+ for (size_t i = 0 ; i < 10 ; ++i)
171
131
{
172
- if (istr == end)
132
+ if (istr == end) [[unlikely]]
173
133
throwReadAfterEOF ();
174
134
175
- UInt64 byte = *istr; // / NOLINT
135
+ UInt64 byte = *istr;
176
136
++istr;
177
137
x |= (byte & 0x7F ) << (7 * i);
178
138
@@ -183,62 +143,56 @@ inline const char * readVarUInt(UInt64 & x, const char * istr, size_t size)
183
143
return istr;
184
144
}
185
145
186
-
187
- inline void writeVarUInt (UInt64 x, WriteBuffer & ostr )
146
+ template < typename In>
147
+ inline void readVarInt (Int64 & x, In & istr )
188
148
{
189
- for (size_t i = 0 ; i < 9 ; ++i)
190
- {
191
- uint8_t byte = x & 0x7F ;
192
- if (x > 0x7F )
193
- byte |= 0x80 ;
194
-
195
- ostr.nextIfAtEnd ();
196
- *ostr.position () = byte;
197
- ++ostr.position ();
198
-
199
- x >>= 7 ;
200
- if (!x)
201
- return ;
202
- }
149
+ readVarUInt (*reinterpret_cast <UInt64*>(&x), istr);
150
+ x = (static_cast <UInt64>(x) >> 1 ) ^ -(x & 1 );
203
151
}
204
152
205
-
206
- inline void writeVarUInt (UInt64 x, std::ostream & ostr)
153
+ inline const char * readVarInt (Int64 & x, const char * istr, size_t size)
207
154
{
208
- for (size_t i = 0 ; i < 9 ; ++i)
209
- {
210
- uint8_t byte = x & 0x7F ;
211
- if (x > 0x7F )
212
- byte |= 0x80 ;
213
-
214
- ostr.put (byte);
215
-
216
- x >>= 7 ;
217
- if (!x)
218
- return ;
219
- }
155
+ const char * res = readVarUInt (*reinterpret_cast <UInt64*>(&x), istr, size);
156
+ x = (static_cast <UInt64>(x) >> 1 ) ^ -(x & 1 );
157
+ return res;
220
158
}
221
159
222
-
223
- inline char * writeVarUInt (UInt64 x, char * ostr)
160
+ inline void readVarUInt (UInt32 & x, ReadBuffer & istr)
224
161
{
225
- for (size_t i = 0 ; i < 9 ; ++i)
226
- {
227
- uint8_t byte = x & 0x7F ;
228
- if (x > 0x7F )
229
- byte |= 0x80 ;
162
+ UInt64 tmp;
163
+ readVarUInt (tmp, istr);
164
+ x = static_cast <UInt32>(tmp);
165
+ }
230
166
231
- *ostr = byte;
232
- ++ostr;
167
+ inline void readVarInt (Int32 & x, ReadBuffer & istr)
168
+ {
169
+ Int64 tmp;
170
+ readVarInt (tmp, istr);
171
+ x = static_cast <Int32>(tmp);
172
+ }
233
173
234
- x >>= 7 ;
235
- if (!x)
236
- return ostr;
237
- }
174
+ inline void readVarUInt (UInt16 & x, ReadBuffer & istr)
175
+ {
176
+ UInt64 tmp;
177
+ readVarUInt (tmp, istr);
178
+ x = tmp;
179
+ }
238
180
239
- return ostr;
181
+ inline void readVarInt (Int16 & x, ReadBuffer & istr)
182
+ {
183
+ Int64 tmp;
184
+ readVarInt (tmp, istr);
185
+ x = tmp;
240
186
}
241
187
188
+ template <typename T>
189
+ requires (!std::is_same_v<T, UInt64>)
190
+ inline void readVarUInt (T & x, ReadBuffer & istr)
191
+ {
192
+ UInt64 tmp;
193
+ readVarUInt (tmp, istr);
194
+ x = tmp;
195
+ }
242
196
243
197
inline size_t getLengthOfVarUInt (UInt64 x)
244
198
{
@@ -250,7 +204,8 @@ inline size_t getLengthOfVarUInt(UInt64 x)
250
204
: (x < (1ULL << 42 ) ? 6
251
205
: (x < (1ULL << 49 ) ? 7
252
206
: (x < (1ULL << 56 ) ? 8
253
- : 9 )))))));
207
+ : (x < (1ULL << 63 ) ? 9
208
+ : 10 ))))))));
254
209
}
255
210
256
211
0 commit comments