This source file includes following definitions.
- num_digits_in_base10
- uint64ToBufferUnsafe
- folly_ascii_to_int
- ascii_to_int_baseline
- tostring
- tostring
- tostring
- tostring_zero_pad_right_justify
- tostring
- noexcept
- noexcept
- noexcept
- tostring
- tostring
- tostring
- tostring
- fromstring
- noexcept
- noexcept
- noexcept
- delete_ptr
- toupper
- tolower
- toupper
- tolower
1 #ifndef libjmmcg_core_ttypes_hpp
2 #define libjmmcg_core_ttypes_hpp
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include "debug_defines.hpp"
25
26 #include <cassert>
27 #include <cinttypes>
28 #include <cmath>
29
30 #ifdef _MSC_VER
31
32 # include <tchar.h>
33
34 #endif
35
36 #include <algorithm>
37 #include <functional>
38 #include <istream>
39 #include <iterator>
40 #include <ostream>
41 #include <sstream>
42 #include <string>
43
44 #ifndef _TCHAR_DEFINED
45 # define TCHAR jmmcg::tchar;
46 # define _TCHAR_DEFINED
47 # ifdef UNICODE
48 # define _JMMCG_WIDE_CHARS
49 # endif
50 #endif
51
52 #undef _T
53
54 namespace jmmcg {
55
56
57 #ifdef _JMMCG_WIDE_CHARS
58 typedef std::wchar_t tchar;
59 # define _T(str) L##str
60 # define tsscanf swscanf
61 # define tstrlen wstrlen
62 #else
63 typedef char tchar;
64 # define _T(str) str
65 # define tsscanf sscanf
66 # define tstrlen strlen
67 #endif
68
69 typedef std::basic_string<tchar> tstring;
70 typedef std::basic_stringstream<tchar> tstringstream;
71 typedef std::basic_istringstream<tchar> tistringstream;
72 typedef std::basic_ostringstream<tchar> tostringstream;
73 typedef std::basic_istream<tchar> tistream;
74 typedef std::basic_ostream<tchar> tostream;
75
76 #if defined(_MSC_VER) && (_MSC_VER < 1300)
77
78
79
80
81 inline tostream & __fastcall
82 operator<<(tostream &o,const __int64 &i) {
83 tchar buff[34];
84 int radix=10;
85 if ((o.flags() & std::ios::basefield) == std::ios::oct) {
86 radix=8;
87 } else if ((o.flags() & std::ios::basefield) == std::ios::hex) {
88 radix=16;
89 }
90 ::_i64tot_s(i, buff, sizeof(buff), radix);
91 o << buff;
92 return o;
93 }
94
95
96
97
98 inline tistream & __fastcall
99 operator>>(tistream &o,__int64 &i) {
100 tstring buff;
101 o>>buff;
102 i=::_ttoi64(buff.c_str());
103 return o;
104 }
105
106
107
108
109 inline tostream & __fastcall
110 operator<<(tostream &o,const unsigned __int64 &i) {
111 tchar buff[34];
112 int radix=10;
113 if ((o.flags() & std::ios::basefield) == std::ios::oct) {
114 radix=8;
115 } else if ((o.flags() & std::ios::basefield) == std::ios::hex) {
116 radix=16;
117 }
118 ::_ui64tot_s(i, buff, sizeof(buff), radix);
119 o << buff;
120 return o;
121 }
122
123
124
125
126 inline tistream & __fastcall
127 operator>>(tistream &o,unsigned __int64 &i) {
128 tstring buff;
129 o>>buff;
130 i=::_ttoi64(buff.c_str());
131 return o;
132 }
133
134 #endif
135
136
137
138
139
140
141
142 constexpr inline std::uint32_t
143 num_digits_in_base10(std::uint64_t v) noexcept(true) __attribute__((pure));
144 constexpr inline std::uint32_t
145 num_digits_in_base10(std::uint64_t v) noexcept(true) {
146 #ifdef __x86_64__
147
148
149
150 ALIGN_TO_L1_CACHE constexpr const std::uint64_t powersOf10[]={
151 1ULL,
152 10ULL,
153 100ULL,
154 1000ULL,
155 10000ULL,
156 100000ULL,
157 1000000ULL,
158 10000000ULL,
159 100000000ULL,
160 1000000000ULL,
161 10000000000ULL,
162 100000000000ULL,
163 1000000000000ULL,
164 10000000000000ULL,
165 100000000000000ULL,
166 1000000000000000ULL,
167 10000000000000000ULL,
168 100000000000000000ULL,
169 1000000000000000000ULL,
170 10000000000000000000ULL,
171 };
172
173
174 if (UNLIKELY(!v)) {
175 return 1;
176 }
177
178 const std::uint8_t leadingZeroes=__builtin_clzll(v);
179 const auto bits=sizeof(std::uint64_t)*8-1-leadingZeroes;
180
181
182
183
184 const std::uint32_t minLength=1+((bits*77)>>8);
185
186
187
188 return minLength+static_cast<std::uint32_t>(UNLIKELY(v>=powersOf10[minLength]));
189 #else
190 std::uint32_t result=1;
191 for (;;) {
192 if (LIKELY(v<10)) return result;
193 if (LIKELY(v<100)) return result + 1;
194 if (LIKELY(v<1000)) return result + 2;
195 if (LIKELY(v<10000)) return result + 3;
196
197 v/=10000U;
198 result+=4;
199 }
200 #endif
201 }
202
203
204
205
206
207
208
209
210
211 inline std::uint32_t
212 uint64ToBufferUnsafe(std::uint64_t v, char * const buffer, __attribute__((unused)) std::uint32_t sz) noexcept(true) __attribute__((pure));
213 inline std::uint32_t
214 uint64ToBufferUnsafe(std::uint64_t v, char * const buffer, __attribute__((unused)) std::uint32_t sz) noexcept(true) {
215 assert(sz>0);
216 auto const digits_to_write=num_digits_in_base10(v);
217 assert(digits_to_write<=sz);
218
219 std::uint32_t pos=digits_to_write-1;
220 while (v>=10) {
221
222 const auto q=v/10;
223 const auto r=static_cast<std::uint32_t>(v%10);
224 buffer[pos--]='0'+r;
225 v=q;
226 }
227 assert(pos==0);
228
229 buffer[pos]='0'+static_cast<char>(v);
230 return digits_to_write;
231 }
232
233
234
235
236
237
238
239
240 inline std::uint32_t
241 folly_ascii_to_int(char const *buffer, std::uint32_t sz) noexcept(true) __attribute__((pure));
242 inline std::uint32_t
243 folly_ascii_to_int(char const *buffer, std::uint32_t sz) noexcept(true) {
244 assert(buffer);
245 assert(sz>0);
246 ALIGN_TO_L1_CACHE static constexpr const std::uint64_t pow10[]={
247 10000000000000000000ULL,
248 1000000000000000000ULL,
249 100000000000000000ULL,
250 10000000000000000ULL,
251 1000000000000000ULL,
252 100000000000000ULL,
253 10000000000000ULL,
254 1000000000000ULL,
255 100000000000ULL,
256 10000000000ULL,
257 1000000000ULL,
258 100000000ULL,
259 10000000ULL,
260 1000000ULL,
261 100000ULL,
262 10000ULL,
263 1000ULL,
264 100ULL,
265 10ULL,
266 1ULL
267 };
268 char const * const e=buffer+sz;
269 std::uint32_t result=0;
270 auto i=sizeof(pow10)/sizeof(pow10[0])-sz;
271 for(; buffer!=e; ++buffer) {
272 assert(std::isdigit(*buffer));
273 const std::uint32_t digit=std::uint32_t(*buffer)-'0';
274 assert(digit<10U);
275 result+=digit*pow10[i++];
276 }
277 assert(std::strtol(e-sz, nullptr, 10)==result);
278 return result;
279 }
280
281
282
283
284
285
286 template<unsigned Base> inline std::uint32_t
287 ascii_to_int_baseline(char const * const buffer, std::size_t sz) noexcept(true) __attribute__((pure));
288 template<unsigned Base> inline std::uint32_t
289 ascii_to_int_baseline(char const * const buffer, std::size_t sz) noexcept(true) {
290 assert(buffer);
291 assert(sz>0);
292 char const *digit=buffer+sz;
293 std::uint32_t result=0;
294 std::uint32_t units=1;
295 while (--digit!=buffer) {
296 assert(std::isdigit(*digit));
297 const std::uint32_t d=std::uint32_t(*digit)-'0';
298 assert(d<10U);
299 result+=d*units;
300 units*=Base;
301 }
302 assert(std::isdigit(*digit));
303 result+=((*digit)-'0')*units;
304 assert(std::strtol(buffer, nullptr, Base)==result);
305 return result;
306 }
307
308
309 template<typename T> inline tstring __fastcall
310 tostring(const T &val) {
311 tostringstream ss;
312 ss<<val;
313 return ss.str();
314 }
315 template<> inline tstring __fastcall
316 tostring<tstring>(const tstring &val) {
317 return val;
318 }
319
320 template<typename A,typename Fmt> inline tstring __fastcall
321 tostring(const A &a,const Fmt &format) {
322 tostringstream ss;
323 ss<<format<<a;
324 return ss.str();
325 }
326
327
328
329
330
331
332
333 template<std::size_t Sz> constexpr inline std::size_t FORCE_INLINE
334 tostring(std::uint64_t v, char (&buff)[Sz]) noexcept(true) __attribute__((pure));
335 template<std::size_t Sz> constexpr inline std::size_t FORCE_INLINE
336 tostring(std::uint64_t v, char (&buff)[Sz]) noexcept(true) {
337 return uint64ToBufferUnsafe(v, buff, Sz);
338 }
339
340
341
342
343
344
345 template<std::uint8_t Base, std::size_t Sz> constexpr inline std::size_t FORCE_INLINE
346 tostring_zero_pad_right_justify(std::uint32_t v, char (&buff)[Sz]) noexcept(true) __attribute__((pure));
347 template<std::uint8_t Base, std::size_t Sz> constexpr inline std::size_t FORCE_INLINE
348 tostring_zero_pad_right_justify(std::uint32_t v, char (&buff)[Sz]) noexcept(true) {
349 for (std::size_t i=Sz; i; --i) {
350 auto const q=v/Base;
351 auto const r=static_cast<char>(v%Base);
352 buff[i-1]=static_cast<char>(static_cast<std::uint8_t>('0')+r);
353 v=q;
354 }
355 return Sz;
356 }
357
358
359
360
361
362
363 template<std::size_t Sz> constexpr inline std::size_t FORCE_INLINE
364 tostring(std::int64_t v, char (&buff)[Sz]) noexcept(true) __attribute__((pure));
365 template<std::size_t Sz> constexpr inline std::size_t FORCE_INLINE
366 tostring(std::int64_t v, char (&buff)[Sz]) noexcept(true) {
367 if (v<0) {
368 buff[0]='-';
369 return uint64ToBufferUnsafe(-v, buff+1, Sz-1);
370 } else {
371 return uint64ToBufferUnsafe(v, buff, Sz);
372 }
373 }
374 template<class V> inline std::size_t
375 tostring(V v, char * const buff, std::size_t sz) noexcept(true)=delete;
376
377
378
379
380
381
382 template<> inline std::size_t
383 tostring<int>(int v, char * const buff, std::size_t sz) noexcept(true) __attribute__((pure));
384 template<> inline std::size_t
385 tostring<int>(int v, char * const buff, std::size_t sz) noexcept(true) {
386 if (v<0) {
387 buff[0]='-';
388 return uint64ToBufferUnsafe(-v, buff+1, sz-1);
389 } else {
390 return uint64ToBufferUnsafe(v, buff, sz);
391 }
392 }
393
394
395
396
397
398
399 template<> inline std::size_t
400 tostring<long>(long v, char * const buff, std::size_t sz) noexcept(true) __attribute__((pure));
401 template<> inline std::size_t
402 tostring<long>(long v, char * const buff, std::size_t sz) noexcept(true) {
403 if (v<0) {
404 buff[0]='-';
405 return uint64ToBufferUnsafe(-v, buff+1, sz-1);
406 } else {
407 return uint64ToBufferUnsafe(v, buff, sz);
408 }
409 }
410
411
412
413
414
415
416 template<> inline std::size_t
417 tostring<std::size_t>(std::size_t v, char * const buff, std::size_t sz) noexcept(true) __attribute__((pure));
418 template<> inline std::size_t
419 tostring<std::size_t>(std::size_t v, char * const buff, std::size_t sz) noexcept(true) {
420 return uint64ToBufferUnsafe(v, buff, sz);
421 }
422
423
424
425
426
427
428 inline std::size_t
429 tostring(std::uint32_t v, char * const buff, std::size_t sz) noexcept(true) __attribute__((pure));
430 inline std::size_t
431 tostring(std::uint32_t v, char * const buff, std::size_t sz) noexcept(true) {
432 return uint64ToBufferUnsafe(v, buff, sz);
433 }
434
435
436
437
438
439
440 inline std::size_t
441 tostring(std::int64_t v, char * const buff, std::size_t sz) noexcept(true) __attribute__((pure));
442 inline std::size_t
443 tostring(std::int64_t v, char * const buff, std::size_t sz) noexcept(true) {
444 if (v<0) {
445 buff[0]='-';
446 return uint64ToBufferUnsafe(-v, buff+1, sz-1);
447 } else {
448 return uint64ToBufferUnsafe(v, buff, sz);
449 }
450 }
451
452
453
454
455
456
457 inline std::size_t
458 tostring(std::uint64_t v, char * const buff, std::size_t sz) noexcept(true) __attribute__((pure));
459 inline std::size_t
460 tostring(std::uint64_t v, char * const buff, std::size_t sz) noexcept(true) {
461 return uint64ToBufferUnsafe(v, buff, sz);
462 }
463
464
465
466
467
468
469
470
471 inline std::size_t
472 tostring(double v, char * const buff, std::size_t sz) noexcept(true) {
473 return std::snprintf(buff, sz, "%f", v);
474 }
475
476
477 template<typename T> inline void __fastcall
478 fromstring(const tstring &str, T &val) {
479 tstringstream ss;
480 ss<<str;
481 ss>>val;
482 }
483 template<> inline void __fastcall
484 fromstring<tstring>(const tstring &str, tstring &val) {
485 val=str;
486 }
487 template<class V> typename std::enable_if<std::is_integral<V>::value || std::is_floating_point<V>::value, V>::type
488 fromstring(char const * const, std::uint32_t) noexcept(true) __attribute__((pure)) =delete;
489
490
491
492
493
494 template<> inline long
495 fromstring<long>(char const * const begin, std::uint32_t sz) noexcept(true) __attribute__((pure));
496 template<> inline long
497 fromstring<long>(char const * const begin, std::uint32_t sz) noexcept(true) {
498 return ascii_to_int_baseline<10u>(begin, sz);
499 }
500
501
502
503
504
505 template<> inline unsigned long
506 fromstring<unsigned long>(char const * const begin, std::uint32_t sz) noexcept(true) __attribute__((pure));
507 template<> inline unsigned long
508 fromstring<unsigned long>(char const * const begin, std::uint32_t sz) noexcept(true) {
509 return ascii_to_int_baseline<10u>(begin, sz);
510 }
511
512
513
514
515
516 template<> inline double
517 fromstring<double>(char const * const begin, std::uint32_t) noexcept(true) __attribute__((pure));
518 template<> inline double
519 fromstring<double>(char const * const begin, std::uint32_t) noexcept(true) {
520 constexpr unsigned Base=10;
521 char const *decimal_point=begin;
522 while (*decimal_point!='.') {
523 ++decimal_point;
524 }
525 char const *whole=decimal_point;
526 double result=0;
527 unsigned units=0;
528 char const *fraction=decimal_point+1;
529 while (std::isdigit(*fraction)) {
530 ++fraction;
531 ++units;
532 }
533 while (--fraction!=decimal_point) {
534 assert(std::isdigit(*fraction));
535 result+=((*fraction)-'0')/__builtin_powif(Base, units);
536 --units;
537 }
538 units=1;
539 while (--whole!=begin) {
540 assert(std::isdigit(*whole));
541 result+=((*whole)-'0')*units;
542 units*=Base;
543 }
544 assert(std::isdigit(*whole));
545 result+=((*whole)-'0')*units;
546 assert(std::abs(std::strtod(begin, nullptr)-result)<0.000001d);
547 return result;
548 }
549
550 template<typename T> inline void __fastcall
551 delete_ptr(T *ptr) {
552
553 delete ptr;
554 }
555
556
557 template<typename T>
558 class upperletter : public std::unary_function<T, T> {
559 public:
560 upperletter()
561 : ct(std::use_facet<std::ctype<T> >(std::locale())) {
562 }
563 T operator()(const T c) const {
564 return ct.toupper(c);
565 }
566
567 private:
568 std::ctype<T> const &ct;
569 };
570
571
572 template<typename T>
573 class lowerletter : public std::unary_function<T, T> {
574 public:
575 lowerletter()
576 : ct(std::use_facet<std::ctype<T> >(std::locale())) {
577 }
578
579 T operator()(const T c) const {
580 return ct.tolower(c);
581 }
582
583 private:
584 std::ctype<T> const &ct;
585 };
586
587
588 inline tstring
589 toupper(const tstring &l) {
590 tstring u;
591 std::transform(l.begin(),l.end(),std::back_inserter(u),upperletter<tstring::value_type>());
592 return u;
593 }
594
595
596 inline tstring
597 tolower(const tstring &u) {
598 tstring l;
599 std::transform(u.begin(),u.end(),std::back_inserter<tstring>(l),lowerletter<tstring::value_type>());
600 return l;
601 }
602
603
604 template<class Iter> inline Iter
605 toupper(const Iter b,const Iter e,Iter o) {
606 std::transform(b,e,o,upperletter<typename std::iterator_traits<Iter>::value_type>());
607 return o;
608 }
609
610
611 template<class Iter> inline Iter
612 tolower(const Iter b,const Iter e,Iter o) {
613 std::transform(b,e,o,lowerletter<typename std::iterator_traits<Iter>::value_type>());
614 return o;
615 }
616
617 }
618
619 namespace std {
620
621 inline std::ostream & __fastcall
622 operator<<(std::ostream &o, std::exception_ptr ex) noexcept(false) {
623 try {
624 if (ex) {
625 std::rethrow_exception(ex);
626 }
627 } catch (std::exception const &e) {
628 o<<e.what();
629 }
630 return o;
631 }
632
633 }
634
635 #endif