2 * Copyright 2014 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * Converts anything to anything, with an emphasis on performance and
21 * @author Andrei Alexandrescu (andrei.alexandrescu@fb.com)
24 #ifndef FOLLY_BASE_CONV_H_
25 #define FOLLY_BASE_CONV_H_
27 #include "folly/FBString.h"
28 #include "folly/Likely.h"
29 #include "folly/Preprocessor.h"
30 #include "folly/Range.h"
32 #include <boost/implicit_cast.hpp>
33 #include <type_traits>
42 #include "double-conversion.h" // V8 JavaScript implementation
44 #define FOLLY_RANGE_CHECK(condition, message) \
45 ((condition) ? (void)0 : throw std::range_error( \
46 (__FILE__ "(" + std::to_string((long long int) __LINE__) + "): " \
47 + (message)).c_str()))
51 /*******************************************************************************
52 * Integral to integral
53 ******************************************************************************/
56 * Checked conversion from integral to integral. The checks are only
57 * performed when meaningful, e.g. conversion from int to long goes
60 template <class Tgt, class Src>
61 typename std::enable_if<
62 std::is_integral<Src>::value && std::is_integral<Tgt>::value,
64 to(const Src & value) {
65 /* static */ if (std::numeric_limits<Tgt>::max()
66 < std::numeric_limits<Src>::max()) {
68 (!greater_than<Tgt, std::numeric_limits<Tgt>::max()>(value)),
72 /* static */ if (std::is_signed<Src>::value &&
73 (!std::is_signed<Tgt>::value || sizeof(Src) > sizeof(Tgt))) {
75 (!less_than<Tgt, std::numeric_limits<Tgt>::min()>(value)),
79 return static_cast<Tgt>(value);
82 /*******************************************************************************
83 * Floating point to floating point
84 ******************************************************************************/
86 template <class Tgt, class Src>
87 typename std::enable_if<
88 std::is_floating_point<Tgt>::value && std::is_floating_point<Src>::value,
90 to(const Src & value) {
91 /* static */ if (std::numeric_limits<Tgt>::max() <
92 std::numeric_limits<Src>::max()) {
93 FOLLY_RANGE_CHECK(value <= std::numeric_limits<Tgt>::max(),
95 FOLLY_RANGE_CHECK(value >= -std::numeric_limits<Tgt>::max(),
98 return boost::implicit_cast<Tgt>(value);
101 /*******************************************************************************
103 ******************************************************************************/
108 const T& getLastElement(const T & v) {
112 template <class T, class... Ts>
113 typename std::tuple_element<
115 std::tuple<T, Ts...> >::type const&
116 getLastElement(const T& v, const Ts&... vs) {
117 return getLastElement(vs...);
120 // This class exists to specialize away std::tuple_element in the case where we
121 // have 0 template arguments. Without this, Clang/libc++ will blow a
122 // static_assert even if tuple_element is protected by an enable_if.
123 template <class... Ts>
124 struct last_element {
125 typedef typename std::enable_if<
127 typename std::tuple_element<
128 sizeof...(Ts) - 1, std::tuple<Ts...>
133 struct last_element<> {
137 } // namespace detail
139 /*******************************************************************************
140 * Conversions from integral types to string types.
141 ******************************************************************************/
143 #if FOLLY_HAVE_INT128_T
146 template <typename IntegerType>
147 constexpr unsigned int
149 return ceil((double(sizeof(IntegerType) * CHAR_BIT) * M_LN2) / M_LN10);
153 unsafeTelescope128(char * buffer, unsigned int room, unsigned __int128 x) {
154 typedef unsigned __int128 Usrc;
155 unsigned int p = room - 1;
157 while (x >= (Usrc(1) << 64)) { // Using 128-bit division while needed
158 const auto y = x / 10;
159 const auto digit = x % 10;
161 buffer[p--] = '0' + digit;
165 uint64_t xx = x; // Moving to faster 64-bit division thereafter
168 const auto y = xx / 10ULL;
169 const auto digit = xx % 10ULL;
171 buffer[p--] = '0' + digit;
175 buffer[p] = '0' + xx;
184 * Returns the number of digits in the base 10 representation of an
185 * uint64_t. Useful for preallocating buffers and such. It's also used
186 * internally, see below. Measurements suggest that defining a
187 * separate overload for 32-bit integers is not worthwhile.
190 inline uint32_t digits10(uint64_t v) {
193 if (LIKELY(v < 10)) return result;
194 if (LIKELY(v < 100)) return result + 1;
195 if (LIKELY(v < 1000)) return result + 2;
196 if (LIKELY(v < 10000)) return result + 3;
197 // Skip ahead by 4 orders of magnitude
204 * Copies the ASCII base 10 representation of v into buffer and
205 * returns the number of bytes written. Does NOT append a \0. Assumes
206 * the buffer points to digits10(v) bytes of valid memory. Note that
207 * uint64 needs at most 20 bytes, uint32_t needs at most 10 bytes,
208 * uint16_t needs at most 5 bytes, and so on. Measurements suggest
209 * that defining a separate overload for 32-bit integers is not
212 * This primitive is unsafe because it makes the size assumption and
213 * because it does not add a terminating \0.
216 inline uint32_t uint64ToBufferUnsafe(uint64_t v, char *const buffer) {
217 auto const result = digits10(v);
218 // WARNING: using size_t or pointer arithmetic for pos slows down
219 // the loop below 20x. This is because several 32-bit ops can be
220 // done in parallel, but only fewer 64-bit ones.
221 uint32_t pos = result - 1;
223 // Keep these together so a peephole optimization "sees" them and
224 // computes them in one shot.
225 auto const q = v / 10;
226 auto const r = static_cast<uint32_t>(v % 10);
227 buffer[pos--] = '0' + r;
230 // Last digit is trivial to handle
231 buffer[pos] = static_cast<uint32_t>(v) + '0';
236 * A single char gets appended.
239 void toAppend(char value, Tgt * result) {
244 * Ubiquitous helper template for writing string appenders
246 template <class T> struct IsSomeString {
247 enum { value = std::is_same<T, std::string>::value
248 || std::is_same<T, fbstring>::value };
252 * Everything implicitly convertible to const char* gets appended.
254 template <class Tgt, class Src>
255 typename std::enable_if<
256 std::is_convertible<Src, const char*>::value
257 && IsSomeString<Tgt>::value>::type
258 toAppend(Src value, Tgt * result) {
259 // Treat null pointers like an empty string, as in:
260 // operator<<(std::ostream&, const char*).
261 const char* c = value;
263 result->append(value);
268 * Strings get appended, too.
270 template <class Tgt, class Src>
271 typename std::enable_if<
272 IsSomeString<Src>::value && IsSomeString<Tgt>::value>::type
273 toAppend(const Src& value, Tgt * result) {
274 result->append(value);
278 * and StringPiece objects too
281 typename std::enable_if<
282 IsSomeString<Tgt>::value>::type
283 toAppend(StringPiece value, Tgt * result) {
284 result->append(value.data(), value.size());
288 * There's no implicit conversion from fbstring to other string types,
289 * so make a specialization.
292 typename std::enable_if<
293 IsSomeString<Tgt>::value>::type
294 toAppend(const fbstring& value, Tgt * result) {
295 result->append(value.data(), value.size());
298 #if FOLLY_HAVE_INT128_T
300 * Special handling for 128 bit integers.
305 toAppend(__int128 value, Tgt * result) {
306 typedef unsigned __int128 Usrc;
307 char buffer[detail::digitsEnough<unsigned __int128>() + 1];
311 p = detail::unsafeTelescope128(buffer, sizeof(buffer), Usrc(-value));
314 p = detail::unsafeTelescope128(buffer, sizeof(buffer), value);
317 result->append(buffer + p, buffer + sizeof(buffer));
322 toAppend(unsigned __int128 value, Tgt * result) {
323 char buffer[detail::digitsEnough<unsigned __int128>()];
326 p = detail::unsafeTelescope128(buffer, sizeof(buffer), value);
328 result->append(buffer + p, buffer + sizeof(buffer));
334 * int32_t and int64_t to string (by appending) go through here. The
335 * result is APPENDED to a preexisting string passed as the second
336 * parameter. This should be efficient with fbstring because fbstring
337 * incurs no dynamic allocation below 23 bytes and no number has more
338 * than 22 bytes in its textual representation (20 for digits, one for
339 * sign, one for the terminating 0).
341 template <class Tgt, class Src>
342 typename std::enable_if<
343 std::is_integral<Src>::value && std::is_signed<Src>::value &&
344 IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
345 toAppend(Src value, Tgt * result) {
348 result->push_back('-');
349 result->append(buffer, uint64ToBufferUnsafe(-uint64_t(value), buffer));
351 result->append(buffer, uint64ToBufferUnsafe(value, buffer));
356 * As above, but for uint32_t and uint64_t.
358 template <class Tgt, class Src>
359 typename std::enable_if<
360 std::is_integral<Src>::value && !std::is_signed<Src>::value
361 && IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
362 toAppend(Src value, Tgt * result) {
364 result->append(buffer, buffer + uint64ToBufferUnsafe(value, buffer));
368 * All small signed and unsigned integers to string go through 32-bit
369 * types int32_t and uint32_t, respectively.
371 template <class Tgt, class Src>
372 typename std::enable_if<
373 std::is_integral<Src>::value
374 && IsSomeString<Tgt>::value && sizeof(Src) < 4>::type
375 toAppend(Src value, Tgt * result) {
377 std::conditional<std::is_signed<Src>::value, int64_t, uint64_t>::type
379 toAppend<Tgt>(static_cast<Intermediate>(value), result);
382 #if defined(__GNUC__) && __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
383 // std::underlying_type became available by gcc 4.7.0
386 * Enumerated values get appended as integers.
388 template <class Tgt, class Src>
389 typename std::enable_if<
390 std::is_enum<Src>::value && IsSomeString<Tgt>::value>::type
391 toAppend(Src value, Tgt * result) {
393 static_cast<typename std::underlying_type<Src>::type>(value), result);
399 * Enumerated values get appended as integers.
401 template <class Tgt, class Src>
402 typename std::enable_if<
403 std::is_enum<Src>::value && IsSomeString<Tgt>::value>::type
404 toAppend(Src value, Tgt * result) {
405 /* static */ if (Src(-1) < 0) {
406 /* static */ if (sizeof(Src) <= sizeof(int)) {
407 toAppend(static_cast<int>(value), result);
409 toAppend(static_cast<long>(value), result);
412 /* static */ if (sizeof(Src) <= sizeof(int)) {
413 toAppend(static_cast<unsigned int>(value), result);
415 toAppend(static_cast<unsigned long>(value), result);
420 #endif // gcc 4.7 onwards
422 /*******************************************************************************
423 * Conversions from floating-point types to string types.
424 ******************************************************************************/
426 /** Wrapper around DoubleToStringConverter **/
427 template <class Tgt, class Src>
428 typename std::enable_if<
429 std::is_floating_point<Src>::value
430 && IsSomeString<Tgt>::value>::type
434 double_conversion::DoubleToStringConverter::DtoaMode mode,
435 unsigned int numDigits) {
436 using namespace double_conversion;
437 DoubleToStringConverter
438 conv(DoubleToStringConverter::NO_FLAGS,
439 "infinity", "NaN", 'E',
440 -6, // decimal in shortest low
441 21, // decimal in shortest high
442 6, // max leading padding zeros
443 1); // max trailing padding zeros
445 StringBuilder builder(buffer, sizeof(buffer));
447 case DoubleToStringConverter::SHORTEST:
448 conv.ToShortest(value, &builder);
450 case DoubleToStringConverter::FIXED:
451 conv.ToFixed(value, numDigits, &builder);
454 CHECK(mode == DoubleToStringConverter::PRECISION);
455 conv.ToPrecision(value, numDigits, &builder);
458 const size_t length = builder.position();
460 result->append(buffer, length);
464 * As above, but for floating point
466 template <class Tgt, class Src>
467 typename std::enable_if<
468 std::is_floating_point<Src>::value
469 && IsSomeString<Tgt>::value>::type
470 toAppend(Src value, Tgt * result) {
472 value, result, double_conversion::DoubleToStringConverter::SHORTEST, 0);
476 * Variadic conversion to string. Appends each element in turn.
478 template <class T, class... Ts>
479 typename std::enable_if<sizeof...(Ts) >= 2
481 typename std::remove_pointer<
482 typename detail::last_element<Ts...>::type
483 >::type>::value>::type
484 toAppend(const T& v, const Ts&... vs) {
485 toAppend(v, detail::getLastElement(vs...));
490 * Variadic base case: do nothing.
493 typename std::enable_if<IsSomeString<Tgt>::value>::type
494 toAppend(Tgt* result) {
498 * Variadic base case: do nothing.
500 template <class Delimiter, class Tgt>
501 typename std::enable_if<IsSomeString<Tgt>::value>::type
502 toAppendDelim(const Delimiter& delim, Tgt* result) {
506 * 1 element: same as toAppend.
508 template <class Delimiter, class T, class Tgt>
509 typename std::enable_if<IsSomeString<Tgt>::value>::type
510 toAppendDelim(const Delimiter& delim, const T& v, Tgt* tgt) {
515 * Append to string with a delimiter in between elements.
517 template <class Delimiter, class T, class... Ts>
518 typename std::enable_if<sizeof...(Ts) >= 2
520 typename std::remove_pointer<
521 typename detail::last_element<Ts...>::type
522 >::type>::value>::type
523 toAppendDelim(const Delimiter& delim, const T& v, const Ts&... vs) {
524 toAppend(v, delim, detail::getLastElement(vs...));
525 toAppendDelim(delim, vs...);
529 * to<SomeString>(v1, v2, ...) uses toAppend() (see below) as back-end
532 template <class Tgt, class... Ts>
533 typename std::enable_if<IsSomeString<Tgt>::value, Tgt>::type
534 to(const Ts&... vs) {
536 toAppend(vs..., &result);
541 * toDelim<SomeString>(delim, v1, v2, ...) uses toAppendDelim() as
542 * back-end for all types.
544 template <class Tgt, class Delim, class... Ts>
545 typename std::enable_if<IsSomeString<Tgt>::value, Tgt>::type
546 toDelim(const Delim& delim, const Ts&... vs) {
548 toAppendDelim(delim, vs..., &result);
552 /*******************************************************************************
553 * Conversions from string types to integral types.
554 ******************************************************************************/
559 * Finds the first non-digit in a string. The number of digits
560 * searched depends on the precision of the Tgt integral. Assumes the
561 * string starts with NO whitespace and NO sign.
563 * The semantics of the routine is:
565 * if (b >= e || !isdigit(*b)) return b;
568 * Complete unrolling marks bottom-line (i.e. entire conversion)
569 * improvements of 20%.
572 const char* findFirstNonDigit(const char* b, const char* e) {
574 auto const c = static_cast<unsigned>(*b) - '0';
580 // Maximum value of number when represented as a string
581 template <class T> struct MaxString {
582 static const char*const value;
587 * Lookup tables that converts from a decimal character value to an integral
588 * binary value, shifted by a decimal "shift" multiplier.
589 * For all character values in the range '0'..'9', the table at those
590 * index locations returns the actual decimal value shifted by the multiplier.
591 * For all other values, the lookup table returns an invalid OOR value.
593 // Out-of-range flag value, larger than the largest value that can fit in
594 // four decimal bytes (9999), but four of these added up together should
595 // still not overflow uint16_t.
596 constexpr int32_t OOR = 10000;
598 __attribute__((aligned(16))) constexpr uint16_t shift1[] = {
599 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 0-9
600 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 10
601 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 20
602 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 30
603 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 0, // 40
604 1, 2, 3, 4, 5, 6, 7, 8, 9, OOR, OOR,
605 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 60
606 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 70
607 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 80
608 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 90
609 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 100
610 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 110
611 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 120
612 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 130
613 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 140
614 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 150
615 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 160
616 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 170
617 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 180
618 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 190
619 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 200
620 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 210
621 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 220
622 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 230
623 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 240
624 OOR, OOR, OOR, OOR, OOR, OOR // 250
627 __attribute__((aligned(16))) constexpr uint16_t shift10[] = {
628 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 0-9
629 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 10
630 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 20
631 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 30
632 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 0, // 40
633 10, 20, 30, 40, 50, 60, 70, 80, 90, OOR, OOR,
634 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 60
635 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 70
636 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 80
637 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 90
638 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 100
639 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 110
640 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 120
641 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 130
642 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 140
643 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 150
644 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 160
645 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 170
646 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 180
647 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 190
648 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 200
649 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 210
650 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 220
651 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 230
652 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 240
653 OOR, OOR, OOR, OOR, OOR, OOR // 250
656 __attribute__((aligned(16))) constexpr uint16_t shift100[] = {
657 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 0-9
658 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 10
659 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 20
660 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 30
661 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 0, // 40
662 100, 200, 300, 400, 500, 600, 700, 800, 900, OOR, OOR,
663 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 60
664 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 70
665 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 80
666 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 90
667 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 100
668 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 110
669 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 120
670 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 130
671 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 140
672 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 150
673 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 160
674 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 170
675 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 180
676 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 190
677 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 200
678 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 210
679 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 220
680 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 230
681 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 240
682 OOR, OOR, OOR, OOR, OOR, OOR // 250
685 __attribute__((aligned(16))) constexpr uint16_t shift1000[] = {
686 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 0-9
687 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 10
688 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 20
689 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 30
690 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 0, // 40
691 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, OOR, OOR,
692 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 60
693 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 70
694 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 80
695 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 90
696 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 100
697 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 110
698 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 120
699 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 130
700 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 140
701 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 150
702 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 160
703 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 170
704 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 180
705 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 190
706 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 200
707 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 210
708 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 220
709 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 230
710 OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 240
711 OOR, OOR, OOR, OOR, OOR, OOR // 250
715 * String represented as a pair of pointers to char to unsigned
716 * integrals. Assumes NO whitespace before or after, and also that the
717 * string is composed entirely of digits. Tgt must be unsigned, and no
718 * sign is allowed in the string (even it's '+'). String may be empty,
719 * in which case digits_to throws.
722 Tgt digits_to(const char * b, const char * e) {
724 static_assert(!std::is_signed<Tgt>::value, "Unsigned type expected");
727 const size_t size = e - b;
729 /* Although the string is entirely made of digits, we still need to
730 * check for overflow.
732 if (size >= std::numeric_limits<Tgt>::digits10 + 1) {
733 // Leading zeros? If so, recurse to keep things simple
734 if (b < e && *b == '0') {
736 if (b == e) return 0; // just zeros, e.g. "0000"
737 if (*b != '0') return digits_to<Tgt>(b, e);
740 FOLLY_RANGE_CHECK(size == std::numeric_limits<Tgt>::digits10 + 1 &&
741 strncmp(b, detail::MaxString<Tgt>::value, size) <= 0,
742 "Numeric overflow upon conversion");
745 // Here we know that the number won't overflow when
746 // converted. Proceed without checks.
750 for (; e - b >= 4; b += 4) {
752 const int32_t r0 = shift1000[static_cast<size_t>(b[0])];
753 const int32_t r1 = shift100[static_cast<size_t>(b[1])];
754 const int32_t r2 = shift10[static_cast<size_t>(b[2])];
755 const int32_t r3 = shift1[static_cast<size_t>(b[3])];
756 const auto sum = r0 + r1 + r2 + r3;
757 assert(sum < OOR && "Assumption: string only has digits");
763 const int32_t r0 = shift100[static_cast<size_t>(b[0])];
764 const int32_t r1 = shift10[static_cast<size_t>(b[1])];
765 const int32_t r2 = shift1[static_cast<size_t>(b[2])];
766 const auto sum = r0 + r1 + r2;
767 assert(sum < OOR && "Assumption: string only has digits");
768 return result * 1000 + sum;
771 const int32_t r0 = shift10[static_cast<size_t>(b[0])];
772 const int32_t r1 = shift1[static_cast<size_t>(b[1])];
773 const auto sum = r0 + r1;
774 assert(sum < OOR && "Assumption: string only has digits");
775 return result * 100 + sum;
778 const int32_t sum = shift1[static_cast<size_t>(b[0])];
779 assert(sum < OOR && "Assumption: string only has digits");
780 return result * 10 + sum;
785 FOLLY_RANGE_CHECK(size > 0, "Found no digits to convert in input");
790 bool str_to_bool(StringPiece * src);
792 } // namespace detail
795 * String represented as a pair of pointers to char to unsigned
796 * integrals. Assumes NO whitespace before or after.
799 typename std::enable_if<
800 std::is_integral<Tgt>::value && !std::is_signed<Tgt>::value
801 && !std::is_same<typename std::remove_cv<Tgt>::type, bool>::value,
803 to(const char * b, const char * e) {
804 return detail::digits_to<Tgt>(b, e);
808 * String represented as a pair of pointers to char to signed
809 * integrals. Assumes NO whitespace before or after. Allows an
810 * optional leading sign.
813 typename std::enable_if<
814 std::is_integral<Tgt>::value && std::is_signed<Tgt>::value,
816 to(const char * b, const char * e) {
817 FOLLY_RANGE_CHECK(b < e, "Empty input string in conversion to integral");
820 Tgt result = -to<typename std::make_unsigned<Tgt>::type>(b + 1, e);
821 FOLLY_RANGE_CHECK(result <= 0, "Negative overflow.");
824 FOLLY_RANGE_CHECK(*b == '+', "Invalid lead character");
827 Tgt result = to<typename std::make_unsigned<Tgt>::type>(b, e);
828 FOLLY_RANGE_CHECK(result >= 0, "Overflow.");
833 * Parsing strings to integrals. These routines differ from
834 * to<integral>(string) in that they take a POINTER TO a StringPiece
835 * and alter that StringPiece to reflect progress information.
839 * StringPiece to integrals, with progress information. Alters the
840 * StringPiece parameter to munch the already-parsed characters.
843 typename std::enable_if<
844 std::is_integral<Tgt>::value
845 && !std::is_same<typename std::remove_cv<Tgt>::type, bool>::value,
847 to(StringPiece * src) {
849 auto b = src->data(), past = src->data() + src->size();
851 FOLLY_RANGE_CHECK(b < past, "No digits found in input string");
852 if (!isspace(*b)) break;
857 // First digit is customized because we test for sign
858 bool negative = false;
859 /* static */ if (std::is_signed<Tgt>::value) {
864 FOLLY_RANGE_CHECK(*m == '+', "Invalid leading character in conversion"
871 FOLLY_RANGE_CHECK(m < past, "No digits found in input string");
872 FOLLY_RANGE_CHECK(isdigit(*m), "Non-digit character found");
873 m = detail::findFirstNonDigit<Tgt>(m + 1, past);
876 /* static */ if (!std::is_signed<Tgt>::value) {
877 result = detail::digits_to<typename std::make_unsigned<Tgt>::type>(b, m);
879 auto t = detail::digits_to<typename std::make_unsigned<Tgt>::type>(b, m);
882 FOLLY_RANGE_CHECK(is_non_positive(result), "Negative overflow");
885 FOLLY_RANGE_CHECK(is_non_negative(result), "Overflow");
888 src->advance(m - src->data());
893 * StringPiece to bool, with progress information. Alters the
894 * StringPiece parameter to munch the already-parsed characters.
897 typename std::enable_if<
898 std::is_same<typename std::remove_cv<Tgt>::type, bool>::value,
900 to(StringPiece * src) {
901 return detail::str_to_bool(src);
907 * Enforce that the suffix following a number is made up only of whitespace.
909 inline void enforceWhitespace(const char* b, const char* e) {
910 for (; b != e; ++b) {
911 FOLLY_RANGE_CHECK(isspace(*b), to<std::string>("Non-whitespace: ", *b));
915 } // namespace detail
918 * String or StringPiece to integrals. Accepts leading and trailing
919 * whitespace, but no non-space trailing characters.
922 typename std::enable_if<
923 std::is_integral<Tgt>::value,
925 to(StringPiece src) {
926 Tgt result = to<Tgt>(&src);
927 detail::enforceWhitespace(src.data(), src.data() + src.size());
931 /*******************************************************************************
932 * Conversions from string types to floating-point types.
933 ******************************************************************************/
936 * StringPiece to double, with progress information. Alters the
937 * StringPiece parameter to munch the already-parsed characters.
940 inline typename std::enable_if<
941 std::is_floating_point<Tgt>::value,
943 to(StringPiece *const src) {
944 using namespace double_conversion;
945 static StringToDoubleConverter
946 conv(StringToDoubleConverter::ALLOW_TRAILING_JUNK
947 | StringToDoubleConverter::ALLOW_LEADING_SPACES,
949 // return this for junk input string
950 std::numeric_limits<double>::quiet_NaN(),
953 FOLLY_RANGE_CHECK(!src->empty(), "No digits found in input string");
956 auto result = conv.StringToDouble(src->data(), src->size(),
957 &length); // processed char count
959 if (!std::isnan(result)) {
960 src->advance(length);
964 for (;; src->advance(1)) {
966 throw std::range_error("Unable to convert an empty string"
967 " to a floating point value.");
969 if (!isspace(src->front())) {
974 // Was that "inf[inity]"?
975 if (src->size() >= 3 && toupper((*src)[0]) == 'I'
976 && toupper((*src)[1]) == 'N' && toupper((*src)[2]) == 'F') {
977 if (src->size() >= 8 &&
978 toupper((*src)[3]) == 'I' &&
979 toupper((*src)[4]) == 'N' &&
980 toupper((*src)[5]) == 'I' &&
981 toupper((*src)[6]) == 'T' &&
982 toupper((*src)[7]) == 'Y') {
987 return std::numeric_limits<Tgt>::infinity();
990 // Was that "-inf[inity]"?
991 if (src->size() >= 4 && toupper((*src)[0]) == '-'
992 && toupper((*src)[1]) == 'I' && toupper((*src)[2]) == 'N'
993 && toupper((*src)[3]) == 'F') {
994 if (src->size() >= 9 &&
995 toupper((*src)[4]) == 'I' &&
996 toupper((*src)[5]) == 'N' &&
997 toupper((*src)[6]) == 'I' &&
998 toupper((*src)[7]) == 'T' &&
999 toupper((*src)[8]) == 'Y') {
1004 return -std::numeric_limits<Tgt>::infinity();
1008 if (src->size() >= 3 && toupper((*src)[0]) == 'N'
1009 && toupper((*src)[1]) == 'A' && toupper((*src)[2]) == 'N') {
1011 return std::numeric_limits<Tgt>::quiet_NaN();
1015 if (src->size() >= 4 &&
1016 toupper((*src)[0]) == '-' &&
1017 toupper((*src)[1]) == 'N' &&
1018 toupper((*src)[2]) == 'A' &&
1019 toupper((*src)[3]) == 'N') {
1021 return -std::numeric_limits<Tgt>::quiet_NaN();
1025 throw std::range_error("Unable to convert \"" + src->toString()
1026 + "\" to a floating point value.");
1030 * Any string, const char*, or StringPiece to double.
1032 template <class Tgt>
1033 typename std::enable_if<
1034 std::is_floating_point<Tgt>::value,
1036 to(StringPiece src) {
1037 Tgt result = to<double>(&src);
1038 detail::enforceWhitespace(src.data(), src.data() + src.size());
1042 /*******************************************************************************
1043 * Integral to floating point and back
1044 ******************************************************************************/
1047 * Checked conversion from integral to flating point and back. The
1048 * result must be convertible back to the source type without loss of
1049 * precision. This seems Draconian but sometimes is what's needed, and
1050 * complements existing routines nicely. For various rounding
1051 * routines, see <math>.
1053 template <class Tgt, class Src>
1054 typename std::enable_if<
1055 (std::is_integral<Src>::value && std::is_floating_point<Tgt>::value)
1057 (std::is_floating_point<Src>::value && std::is_integral<Tgt>::value),
1059 to(const Src & value) {
1061 auto witness = static_cast<Src>(result);
1062 if (value != witness) {
1063 throw std::range_error(
1064 to<std::string>("to<>: loss of precision when converting ", value,
1065 " to type ", typeid(Tgt).name()).c_str());
1070 /*******************************************************************************
1071 * Enum to anything and back
1072 ******************************************************************************/
1074 #if defined(__GNUC__) && __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
1075 // std::underlying_type became available by gcc 4.7.0
1077 template <class Tgt, class Src>
1078 typename std::enable_if<std::is_enum<Src>::value, Tgt>::type
1079 to(const Src & value) {
1080 return to<Tgt>(static_cast<typename std::underlying_type<Src>::type>(value));
1083 template <class Tgt, class Src>
1084 typename std::enable_if<std::is_enum<Tgt>::value, Tgt>::type
1085 to(const Src & value) {
1086 return static_cast<Tgt>(to<typename std::underlying_type<Tgt>::type>(value));
1091 template <class Tgt, class Src>
1092 typename std::enable_if<std::is_enum<Src>::value, Tgt>::type
1093 to(const Src & value) {
1094 /* static */ if (Src(-1) < 0) {
1095 /* static */ if (sizeof(Src) <= sizeof(int)) {
1096 return to<Tgt>(static_cast<int>(value));
1098 return to<Tgt>(static_cast<long>(value));
1101 /* static */ if (sizeof(Src) <= sizeof(int)) {
1102 return to<Tgt>(static_cast<unsigned int>(value));
1104 return to<Tgt>(static_cast<unsigned long>(value));
1109 template <class Tgt, class Src>
1110 typename std::enable_if<std::is_enum<Tgt>::value, Tgt>::type
1111 to(const Src & value) {
1112 /* static */ if (Tgt(-1) < 0) {
1113 /* static */ if (sizeof(Tgt) <= sizeof(int)) {
1114 return static_cast<Tgt>(to<int>(value));
1116 return static_cast<Tgt>(to<long>(value));
1119 /* static */ if (sizeof(Tgt) <= sizeof(int)) {
1120 return static_cast<Tgt>(to<unsigned int>(value));
1122 return static_cast<Tgt>(to<unsigned long>(value));
1127 #endif // gcc 4.7 onwards
1129 } // namespace folly
1131 // FOLLY_CONV_INTERNAL is defined by Conv.cpp. Keep the FOLLY_RANGE_CHECK
1132 // macro for use in Conv.cpp, but #undefine it everywhere else we are included,
1133 // to avoid defining this global macro name in other files that include Conv.h.
1134 #ifndef FOLLY_CONV_INTERNAL
1135 #undef FOLLY_RANGE_CHECK
1138 #endif /* FOLLY_BASE_CONV_H_ */