RESTinio
from_string_details.ipp
Go to the documentation of this file.
1namespace restinio
2{
3
4namespace utils
5{
6
7namespace details
8{
9
10template< typename C >
11const C * digits_mapping()
12{
13 static constexpr C table[] = {
14 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
15 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
16 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
17
18 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
19
20 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
21 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
22 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
23 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
24 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
25 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
26 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
27 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
28 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
29 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
30 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
31 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
32 return table;
33}
34
36{
37 using type_t = std::int8_t;
38
39 static constexpr std::size_t
41 {
42 return 3;
43 }
44
45 static const char *
47 {
48 static constexpr char r[] = "128";
49 return r;
50 }
51
52 static const char *
54 {
55 static constexpr char r[] = "127";
56 return r;
57 }
58
59 static const char * type_name()
60 {
61 static constexpr char r[] = "int8_t";
62 return r;
63 }
64};
65
67{
68 using type_t = std::uint8_t;
69
70 static constexpr std::size_t
72 {
73 return 3;
74 }
75
76 static const char *
78 {
79 static constexpr char r[] = "0";
80 return r;
81 }
82
83 static const char *
85 {
86 static constexpr char r[] = "255";
87 return r;
88 }
89
90 static const char * type_name()
91 {
92 static constexpr char r[] = "uint8_t";
93 return r;
94 }
95};
96
98{
99 using type_t = std::int16_t;
100
101 static constexpr std::size_t
103 {
104 return 5;
105 }
106
107 static const char *
109 {
110 static constexpr char r[] = "32768";
111 return r;
112 }
113
114 static const char *
116 {
117 static constexpr char r[] = "32767";
118 return r;
119 }
120
121 static const char * type_name()
122 {
123 static constexpr char r[] = "int16_t";
124 return r;
125 }
126};
127
129{
130 using type_t = std::uint16_t;
131
132 static constexpr std::size_t
134 {
135 return 5;
136 }
137
138 static const char *
140 {
141 static constexpr char r[] = "0";
142 return r;
143 }
144
145 static const char *
147 {
148 static constexpr char r[] = "65535";
149 return r;
150 }
151
152 static const char * type_name()
153 {
154 static constexpr char r[] = "uint16_t";
155 return r;
156 }
157};
158
160{
161 using type_t = std::int32_t;
162
163 static constexpr std::size_t
165 {
166 return 10;
167 }
168
169 static const char *
171 {
172 static constexpr char r[] = "2147483648";
173 return r;
174 }
175
176 static const char *
178 {
179 static constexpr char r[] = "2147483647";
180 return r;
181 }
182
183 static const char * type_name()
184 {
185 static constexpr char r[] = "int32_t";
186 return r;
187 }
188};
189
191{
192 using type_t = std::uint32_t;
193
194 static constexpr std::size_t
196 {
197 return 10;
198 }
199
200 static const char *
202 {
203 static constexpr char r[] = "0";
204 return r;
205 }
206
207 static const char *
209 {
210 static constexpr char r[] = "4294967295";
211 return r;
212 }
213
214 static const char * type_name()
215 {
216 static constexpr char r[] = "uint32_t";
217 return r;
218 }
219};
220
222{
223 using type_t = std::int64_t;
224
225 static constexpr std::size_t
227 {
228 return 19;
229 }
230
231 static const char *
233 {
234 static constexpr char r[] = "9223372036854775808";
235 return r;
236 }
237
238 static const char *
240 {
241 static constexpr char r[] = "9223372036854775807";
242 return r;
243 }
244
245 static const char * type_name()
246 {
247 static constexpr char r[] = "int64_t";
248 return r;
249 }
250};
251
253{
254 using type_t = std::uint64_t;
255
256 static constexpr std::size_t
258 {
259 return 20;
260 }
261
262 static const char *
264 {
265 static constexpr char r[] = "0";
266 return r;
267 }
268
269 static const char *
271 {
272 static constexpr char r[] = "18446744073709551615";
273 return r;
274 }
275
276 static const char * type_name()
277 {
278 static constexpr char r[] = "uint64_t";
279 return r;
280 }
281};
282
283template < typename Integer >
284Integer
286 const std::uint8_t * const mapping_table,
287 const char * data_begin,
288 const char * data_end,
289 bool apply_minus_sign,
290 std::true_type /* is signed */)
291{
292 Integer result = 0;
293
294 if( apply_minus_sign )
295 while( data_begin != data_end )
296 {
297 result = result*10 - mapping_table[ static_cast< std::size_t >( *data_begin++ ) ];
298 }
299 else
300 while( data_begin != data_end )
301 {
302 result = result*10 + mapping_table[ static_cast< std::size_t >( *data_begin++ ) ];
303 }
304
305 return result;
306}
307
308template < typename Integer >
309Integer
311 const std::uint8_t * const mapping_table,
312 const char * data_begin,
313 const char * data_end,
314 bool ,
315 std::false_type /* is signed */ )
316{
317 Integer result = 0;
318
319 while( data_begin != data_end )
320 {
321 result = result * 10 + mapping_table[ static_cast< std::size_t >( *data_begin++ ) ];
322 }
323
324 return result;
325}
326
327template < typename Traits >
328typename Traits::type_t
329parse_integer( const char * data_begin, const char * data_end )
330{
331 bool apply_minus_sign = false;
332 if( '-' == *data_begin )
333 {
334 if( !std::is_signed< typename Traits::type_t >::value )
335 {
336 throw exception_t{
337 fmt::format(
338 "invalid {} value: unsigned starts with minus",
339 Traits::type_name() ) };
340 }
341
342 // else:
343 apply_minus_sign = true;
344 ++data_begin;
345 }
346 else if( '+' == *data_begin )
347 {
348 ++data_begin;
349 }
350
351 const auto representation_size = static_cast< std::size_t >( data_end - data_begin );
352
353 if( 0 == representation_size )
354 throw exception_t{ fmt::format( "invalid {} value: empty string", Traits::type_name() ) };
355
356 if( Traits::digits_representation_max_size() < representation_size )
357 throw exception_t{
358 fmt::format(
359 "invalid {} value: max digits for type is {}",
360 Traits::type_name(),
361 Traits::digits_representation_max_size() ) };
362
363 const std::uint8_t * const mapping_table = digits_mapping< std::uint8_t >();
364
365 if( std::any_of(
366 data_begin,
367 data_end,
368 [&]( auto d ){ return 0xFF == mapping_table[ static_cast< std::size_t >( d ) ]; } ) )
369 {
370 throw exception_t{
371 fmt::format( "invalid {} value: invalid digit", Traits::type_name() ) };
372 }
373
374 if( Traits::digits_representation_max_size() == representation_size )
375 {
376 const char * const posssible_max = apply_minus_sign ?
377 Traits::min_representation() : Traits::max_representation();
378
379 if( 0 < std::memcmp( data_begin, posssible_max, representation_size ) )
380 throw std::out_of_range{
381 fmt::format( "invalid {} value: out of range", Traits::type_name() ) };
382 }
383
384 using is_signed_t = typename std::is_signed< typename Traits::type_t >::type;
385
386 return
387 parse_integer_no_checks< typename Traits::type_t >(
388 mapping_table,
389 data_begin,
390 data_end,
391 apply_minus_sign,
392 is_signed_t{} );
393}
394
395} /* namespace details */
396
397} /* namespace utils */
398
399} /* namespace restinio */
Exception class for all exceptions thrown by RESTinio.
Definition: exception.hpp:26
bool_constant< false > false_type
Definition: optional.hpp:460
bool_constant< true > true_type
Definition: optional.hpp:459
Integer parse_integer_no_checks(const std::uint8_t *const mapping_table, const char *data_begin, const char *data_end, bool apply_minus_sign, std::true_type)
Traits::type_t parse_integer(const char *data_begin, const char *data_end)
RESTINIO_NODISCARD bool any_of(Tuple &&tuple, Predicate &&predicate)
static constexpr std::size_t digits_representation_max_size()
static constexpr std::size_t digits_representation_max_size()
static constexpr std::size_t digits_representation_max_size()
static constexpr std::size_t digits_representation_max_size()
static constexpr std::size_t digits_representation_max_size()
static constexpr std::size_t digits_representation_max_size()
static constexpr std::size_t digits_representation_max_size()
static constexpr std::size_t digits_representation_max_size()