798c27323c2e2b87f2528ff677e570149eda3989
[folly.git] / folly / Conv.h
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 /**
18  * Converts anything to anything, with an emphasis on performance and
19  * safety.
20  *
21  * @author Andrei Alexandrescu (andrei.alexandrescu@fb.com)
22  */
23
24 #ifndef FOLLY_BASE_CONV_H_
25 #define FOLLY_BASE_CONV_H_
26
27 #include <folly/FBString.h>
28 #include <folly/Likely.h>
29 #include <folly/Preprocessor.h>
30 #include <folly/Range.h>
31
32 #include <boost/implicit_cast.hpp>
33 #include <type_traits>
34 #include <limits>
35 #include <string>
36 #include <tuple>
37 #include <stdexcept>
38 #include <typeinfo>
39
40 #include <limits.h>
41
42 // V8 JavaScript implementation
43 #include <double-conversion/double-conversion.h>
44
45 #define FOLLY_RANGE_CHECK_STRINGIZE(x) #x
46 #define FOLLY_RANGE_CHECK_STRINGIZE2(x) FOLLY_RANGE_CHECK_STRINGIZE(x)
47
48 #define FOLLY_RANGE_CHECK(condition, message)                               \
49   ((condition) ? (void)0 : throw std::range_error(                          \
50     (std::string(__FILE__ "(" FOLLY_RANGE_CHECK_STRINGIZE2(__LINE__) "): ") \
51      + (message)).c_str()))
52
53 namespace folly {
54
55 /*******************************************************************************
56  * Integral to integral
57  ******************************************************************************/
58
59 /**
60  * Checked conversion from integral to integral. The checks are only
61  * performed when meaningful, e.g. conversion from int to long goes
62  * unchecked.
63  */
64 template <class Tgt, class Src>
65 typename std::enable_if<
66   std::is_integral<Src>::value && std::is_integral<Tgt>::value,
67   Tgt>::type
68 to(const Src & value) {
69   /* static */ if (std::numeric_limits<Tgt>::max()
70                    < std::numeric_limits<Src>::max()) {
71     FOLLY_RANGE_CHECK(
72       (!greater_than<Tgt, std::numeric_limits<Tgt>::max()>(value)),
73       "Overflow"
74     );
75   }
76   /* static */ if (std::is_signed<Src>::value &&
77                    (!std::is_signed<Tgt>::value || sizeof(Src) > sizeof(Tgt))) {
78     FOLLY_RANGE_CHECK(
79       (!less_than<Tgt, std::numeric_limits<Tgt>::min()>(value)),
80       "Negative overflow"
81     );
82   }
83   return static_cast<Tgt>(value);
84 }
85
86 /*******************************************************************************
87  * Floating point to floating point
88  ******************************************************************************/
89
90 template <class Tgt, class Src>
91 typename std::enable_if<
92   std::is_floating_point<Tgt>::value && std::is_floating_point<Src>::value,
93   Tgt>::type
94 to(const Src & value) {
95   /* static */ if (std::numeric_limits<Tgt>::max() <
96                    std::numeric_limits<Src>::max()) {
97     FOLLY_RANGE_CHECK(value <= std::numeric_limits<Tgt>::max(),
98                       "Overflow");
99     FOLLY_RANGE_CHECK(value >= -std::numeric_limits<Tgt>::max(),
100                       "Negative overflow");
101   }
102   return boost::implicit_cast<Tgt>(value);
103 }
104
105 /*******************************************************************************
106  * Anything to string
107  ******************************************************************************/
108
109 namespace detail {
110
111 template <class T>
112 const T& getLastElement(const T & v) {
113   return v;
114 }
115
116 template <class T, class... Ts>
117 typename std::tuple_element<
118   sizeof...(Ts),
119   std::tuple<T, Ts...> >::type const&
120   getLastElement(const T& v, const Ts&... vs) {
121   return getLastElement(vs...);
122 }
123
124 // This class exists to specialize away std::tuple_element in the case where we
125 // have 0 template arguments. Without this, Clang/libc++ will blow a
126 // static_assert even if tuple_element is protected by an enable_if.
127 template <class... Ts>
128 struct last_element {
129   typedef typename std::enable_if<
130     sizeof...(Ts) >= 1,
131     typename std::tuple_element<
132       sizeof...(Ts) - 1, std::tuple<Ts...>
133     >::type>::type type;
134 };
135
136 template <>
137 struct last_element<> {
138   typedef void type;
139 };
140
141 } // namespace detail
142
143 /*******************************************************************************
144  * Conversions from integral types to string types.
145  ******************************************************************************/
146
147 #if FOLLY_HAVE_INT128_T
148 namespace detail {
149
150 template <typename IntegerType>
151 constexpr unsigned int
152 digitsEnough() {
153   return ceil((double(sizeof(IntegerType) * CHAR_BIT) * M_LN2) / M_LN10);
154 }
155
156 inline unsigned int
157 unsafeTelescope128(char * buffer, unsigned int room, unsigned __int128 x) {
158   typedef unsigned __int128 Usrc;
159   unsigned int p = room - 1;
160
161   while (x >= (Usrc(1) << 64)) { // Using 128-bit division while needed
162     const auto y = x / 10;
163     const auto digit = x % 10;
164
165     buffer[p--] = '0' + digit;
166     x = y;
167   }
168
169   uint64_t xx = x; // Moving to faster 64-bit division thereafter
170
171   while (xx >= 10) {
172     const auto y = xx / 10ULL;
173     const auto digit = xx % 10ULL;
174
175     buffer[p--] = '0' + digit;
176     xx = y;
177   }
178
179   buffer[p] = '0' + xx;
180
181   return p;
182 }
183
184 }
185 #endif
186
187 /**
188  * Returns the number of digits in the base 10 representation of an
189  * uint64_t. Useful for preallocating buffers and such. It's also used
190  * internally, see below. Measurements suggest that defining a
191  * separate overload for 32-bit integers is not worthwhile.
192  */
193
194 inline uint32_t digits10(uint64_t v) {
195   uint32_t result = 1;
196   for (;;) {
197     if (LIKELY(v < 10)) return result;
198     if (LIKELY(v < 100)) return result + 1;
199     if (LIKELY(v < 1000)) return result + 2;
200     if (LIKELY(v < 10000)) return result + 3;
201     // Skip ahead by 4 orders of magnitude
202     v /= 10000U;
203     result += 4;
204   }
205 }
206
207 /**
208  * Copies the ASCII base 10 representation of v into buffer and
209  * returns the number of bytes written. Does NOT append a \0. Assumes
210  * the buffer points to digits10(v) bytes of valid memory. Note that
211  * uint64 needs at most 20 bytes, uint32_t needs at most 10 bytes,
212  * uint16_t needs at most 5 bytes, and so on. Measurements suggest
213  * that defining a separate overload for 32-bit integers is not
214  * worthwhile.
215  *
216  * This primitive is unsafe because it makes the size assumption and
217  * because it does not add a terminating \0.
218  */
219
220 inline uint32_t uint64ToBufferUnsafe(uint64_t v, char *const buffer) {
221   auto const result = digits10(v);
222   // WARNING: using size_t or pointer arithmetic for pos slows down
223   // the loop below 20x. This is because several 32-bit ops can be
224   // done in parallel, but only fewer 64-bit ones.
225   uint32_t pos = result - 1;
226   while (v >= 10) {
227     // Keep these together so a peephole optimization "sees" them and
228     // computes them in one shot.
229     auto const q = v / 10;
230     auto const r = static_cast<uint32_t>(v % 10);
231     buffer[pos--] = '0' + r;
232     v = q;
233   }
234   // Last digit is trivial to handle
235   buffer[pos] = static_cast<uint32_t>(v) + '0';
236   return result;
237 }
238
239 /**
240  * A single char gets appended.
241  */
242 template <class Tgt>
243 void toAppend(char value, Tgt * result) {
244   *result += value;
245 }
246
247 template<class T>
248 constexpr typename std::enable_if<
249   std::is_same<T, char>::value,
250   size_t>::type
251 estimateSpaceNeeded(T) {
252   return 1;
253 }
254
255 /**
256  * Ubiquitous helper template for writing string appenders
257  */
258 template <class T> struct IsSomeString {
259   enum { value = std::is_same<T, std::string>::value
260          || std::is_same<T, fbstring>::value };
261 };
262
263 /**
264  * Everything implicitly convertible to const char* gets appended.
265  */
266 template <class Tgt, class Src>
267 typename std::enable_if<
268   std::is_convertible<Src, const char*>::value
269   && IsSomeString<Tgt>::value>::type
270 toAppend(Src value, Tgt * result) {
271   // Treat null pointers like an empty string, as in:
272   // operator<<(std::ostream&, const char*).
273   const char* c = value;
274   if (c) {
275     result->append(value);
276   }
277 }
278
279 template<class Src>
280 typename std::enable_if<
281   std::is_convertible<Src, const char*>::value,
282   size_t>::type
283 estimateSpaceNeeded(Src value) {
284   const char *c = value;
285   if (c) {
286     return folly::StringPiece(value).size();
287   };
288   return 0;
289 }
290
291 template<class Src>
292 typename std::enable_if<
293   (std::is_convertible<Src, folly::StringPiece>::value ||
294   IsSomeString<Src>::value) &&
295   !std::is_convertible<Src, const char*>::value,
296   size_t>::type
297 estimateSpaceNeeded(Src value) {
298   return folly::StringPiece(value).size();
299 }
300
301 template<class Src>
302 typename std::enable_if<
303   std::is_pointer<Src>::value &&
304   IsSomeString<std::remove_pointer<Src>>::value,
305   size_t>::type
306 estimateSpaceNeeded(Src value) {
307   return value->size();
308 }
309
310 /**
311  * Strings get appended, too.
312  */
313 template <class Tgt, class Src>
314 typename std::enable_if<
315   IsSomeString<Src>::value && IsSomeString<Tgt>::value>::type
316 toAppend(const Src& value, Tgt * result) {
317   result->append(value);
318 }
319
320 /**
321  * and StringPiece objects too
322  */
323 template <class Tgt>
324 typename std::enable_if<
325    IsSomeString<Tgt>::value>::type
326 toAppend(StringPiece value, Tgt * result) {
327   result->append(value.data(), value.size());
328 }
329
330 /**
331  * There's no implicit conversion from fbstring to other string types,
332  * so make a specialization.
333  */
334 template <class Tgt>
335 typename std::enable_if<
336    IsSomeString<Tgt>::value>::type
337 toAppend(const fbstring& value, Tgt * result) {
338   result->append(value.data(), value.size());
339 }
340
341 #if FOLLY_HAVE_INT128_T
342 /**
343  * Special handling for 128 bit integers.
344  */
345
346 template <class Tgt>
347 void
348 toAppend(__int128 value, Tgt * result) {
349   typedef unsigned __int128 Usrc;
350   char buffer[detail::digitsEnough<unsigned __int128>() + 1];
351   unsigned int p;
352
353   if (value < 0) {
354     p = detail::unsafeTelescope128(buffer, sizeof(buffer), Usrc(-value));
355     buffer[--p] = '-';
356   } else {
357     p = detail::unsafeTelescope128(buffer, sizeof(buffer), value);
358   }
359
360   result->append(buffer + p, buffer + sizeof(buffer));
361 }
362
363 template <class Tgt>
364 void
365 toAppend(unsigned __int128 value, Tgt * result) {
366   char buffer[detail::digitsEnough<unsigned __int128>()];
367   unsigned int p;
368
369   p = detail::unsafeTelescope128(buffer, sizeof(buffer), value);
370
371   result->append(buffer + p, buffer + sizeof(buffer));
372 }
373
374 template<class T>
375 constexpr typename std::enable_if<
376   std::is_same<T, __int128>::value,
377   size_t>::type
378 estimateSpaceNeeded(T) {
379   return detail::digitsEnough<__int128>();
380 }
381
382 template<class T>
383 constexpr typename std::enable_if<
384   std::is_same<T, unsigned __int128>::value,
385   size_t>::type
386 estimateSpaceNeeded(T) {
387   return detail::digitsEnough<unsigned __int128>();
388 }
389
390 #endif
391
392 /**
393  * int32_t and int64_t to string (by appending) go through here. The
394  * result is APPENDED to a preexisting string passed as the second
395  * parameter. This should be efficient with fbstring because fbstring
396  * incurs no dynamic allocation below 23 bytes and no number has more
397  * than 22 bytes in its textual representation (20 for digits, one for
398  * sign, one for the terminating 0).
399  */
400 template <class Tgt, class Src>
401 typename std::enable_if<
402   std::is_integral<Src>::value && std::is_signed<Src>::value &&
403   IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
404 toAppend(Src value, Tgt * result) {
405   char buffer[20];
406   if (value < 0) {
407     result->push_back('-');
408     result->append(buffer, uint64ToBufferUnsafe(-uint64_t(value), buffer));
409   } else {
410     result->append(buffer, uint64ToBufferUnsafe(value, buffer));
411   }
412 }
413
414 template <class Src>
415 typename std::enable_if<
416   std::is_integral<Src>::value && std::is_signed<Src>::value
417   && sizeof(Src) >= 4 && sizeof(Src) < 16,
418   size_t>::type
419 estimateSpaceNeeded(Src value) {
420   if (value < 0) {
421     return 1 + digits10(static_cast<uint64_t>(-value));
422   }
423
424   return digits10(static_cast<uint64_t>(value));
425 }
426
427 /**
428  * As above, but for uint32_t and uint64_t.
429  */
430 template <class Tgt, class Src>
431 typename std::enable_if<
432   std::is_integral<Src>::value && !std::is_signed<Src>::value
433   && IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
434 toAppend(Src value, Tgt * result) {
435   char buffer[20];
436   result->append(buffer, buffer + uint64ToBufferUnsafe(value, buffer));
437 }
438
439 template <class Src>
440 typename std::enable_if<
441   std::is_integral<Src>::value && !std::is_signed<Src>::value
442   && sizeof(Src) >= 4 && sizeof(Src) < 16,
443   size_t>::type
444 estimateSpaceNeeded(Src value) {
445   return digits10(value);
446 }
447
448 /**
449  * All small signed and unsigned integers to string go through 32-bit
450  * types int32_t and uint32_t, respectively.
451  */
452 template <class Tgt, class Src>
453 typename std::enable_if<
454   std::is_integral<Src>::value
455   && IsSomeString<Tgt>::value && sizeof(Src) < 4>::type
456 toAppend(Src value, Tgt * result) {
457   typedef typename
458     std::conditional<std::is_signed<Src>::value, int64_t, uint64_t>::type
459     Intermediate;
460   toAppend<Tgt>(static_cast<Intermediate>(value), result);
461 }
462
463 template <class Src>
464 typename std::enable_if<
465   std::is_integral<Src>::value
466   && sizeof(Src) < 4
467   && !std::is_same<Src, char>::value,
468   size_t>::type
469 estimateSpaceNeeded(Src value) {
470   typedef typename
471     std::conditional<std::is_signed<Src>::value, int64_t, uint64_t>::type
472     Intermediate;
473   return estimateSpaceNeeded(static_cast<Intermediate>(value));
474 }
475
476 #if defined(__clang__) || __GNUC_PREREQ(4, 7)
477 // std::underlying_type became available by gcc 4.7.0
478
479 /**
480  * Enumerated values get appended as integers.
481  */
482 template <class Tgt, class Src>
483 typename std::enable_if<
484   std::is_enum<Src>::value && IsSomeString<Tgt>::value>::type
485 toAppend(Src value, Tgt * result) {
486   toAppend(
487       static_cast<typename std::underlying_type<Src>::type>(value), result);
488 }
489
490 template <class Src>
491 typename std::enable_if<
492   std::is_enum<Src>::value, size_t>::type
493 estimateSpaceNeeded(Src value) {
494   return estimateSpaceNeeded(
495       static_cast<typename std::underlying_type<Src>::type>(value));
496 }
497
498 #else
499
500 /**
501  * Enumerated values get appended as integers.
502  */
503 template <class Tgt, class Src>
504 typename std::enable_if<
505   std::is_enum<Src>::value && IsSomeString<Tgt>::value>::type
506 toAppend(Src value, Tgt * result) {
507   /* static */ if (Src(-1) < 0) {
508     /* static */ if (sizeof(Src) <= sizeof(int)) {
509       toAppend(static_cast<int>(value), result);
510     } else {
511       toAppend(static_cast<long>(value), result);
512     }
513   } else {
514     /* static */ if (sizeof(Src) <= sizeof(int)) {
515       toAppend(static_cast<unsigned int>(value), result);
516     } else {
517       toAppend(static_cast<unsigned long>(value), result);
518     }
519   }
520 }
521
522 template <class Src>
523 typename std::enable_if<
524   std::is_enum<Src>::value, size_t>::type
525 estimateSpaceNeeded(Src value) {
526   /* static */ if (Src(-1) < 0) {
527     /* static */ if (sizeof(Src) <= sizeof(int)) {
528       return estimateSpaceNeeded(static_cast<int>(value));
529     } else {
530       return estimateSpaceNeeded(static_cast<long>(value));
531     }
532   } else {
533     /* static */ if (sizeof(Src) <= sizeof(int)) {
534       return estimateSpaceNeeded(static_cast<unsigned int>(value));
535     } else {
536       return estimateSpaceNeeded(static_cast<unsigned long>(value));
537     }
538   }
539 }
540
541 #endif // gcc 4.7 onwards
542
543 /*******************************************************************************
544  * Conversions from floating-point types to string types.
545  ******************************************************************************/
546
547 /** Wrapper around DoubleToStringConverter **/
548 template <class Tgt, class Src>
549 typename std::enable_if<
550   std::is_floating_point<Src>::value
551   && IsSomeString<Tgt>::value>::type
552 toAppend(
553   Src value,
554   Tgt * result,
555   double_conversion::DoubleToStringConverter::DtoaMode mode,
556   unsigned int numDigits) {
557   using namespace double_conversion;
558   DoubleToStringConverter
559     conv(DoubleToStringConverter::NO_FLAGS,
560          "infinity", "NaN", 'E',
561          -6,  // decimal in shortest low
562          21,  // decimal in shortest high
563          6,   // max leading padding zeros
564          1);  // max trailing padding zeros
565   char buffer[256];
566   StringBuilder builder(buffer, sizeof(buffer));
567   switch (mode) {
568     case DoubleToStringConverter::SHORTEST:
569       conv.ToShortest(value, &builder);
570       break;
571     case DoubleToStringConverter::FIXED:
572       conv.ToFixed(value, numDigits, &builder);
573       break;
574     default:
575       CHECK(mode == DoubleToStringConverter::PRECISION);
576       conv.ToPrecision(value, numDigits, &builder);
577       break;
578   }
579   const size_t length = builder.position();
580   builder.Finalize();
581   result->append(buffer, length);
582 }
583
584 /**
585  * As above, but for floating point
586  */
587 template <class Tgt, class Src>
588 typename std::enable_if<
589   std::is_floating_point<Src>::value
590   && IsSomeString<Tgt>::value>::type
591 toAppend(Src value, Tgt * result) {
592   toAppend(
593     value, result, double_conversion::DoubleToStringConverter::SHORTEST, 0);
594 }
595
596 /**
597  * Very primitive, lets say its our best effort
598  */
599 template <class Src>
600 typename std::enable_if<
601   std::is_floating_point<Src>::value, size_t>::type
602 estimateSpaceNeeded(Src value) {
603   size_t sofar = 0;
604   if (value < 0) {
605     ++sofar;
606     value = -value;
607   }
608
609   if (value < 1) {
610     return sofar + 10; // lets assume 0 + '.' + 8 precision digits
611   }
612
613   if (value < static_cast<double>(std::numeric_limits<uint64_t>::max())) {
614     sofar += digits10(static_cast<uint64_t>(value));
615   } else {
616     return 64; // give up, it will be more than 23 anyway
617   }
618
619   return sofar + 10; // integral part + '.' + 8 precision digits
620 }
621
622 /**
623  * This can be specialized, together with adding specialization
624  * for estimateSpaceNeed for your type, so that we allocate
625  * as much as you need instead of the default
626  */
627 template<class Src>
628 struct HasLengthEstimator : std::false_type {};
629
630 template <class Src>
631 constexpr typename std::enable_if<
632   !std::is_fundamental<Src>::value
633   && !IsSomeString<Src>::value
634   && !std::is_convertible<Src, const char*>::value
635   && !std::is_convertible<Src, StringPiece>::value
636   && !std::is_enum<Src>::value
637   && !HasLengthEstimator<Src>::value,
638   size_t>::type
639 estimateSpaceNeeded(const Src&) {
640   return sizeof(Src) + 1; // dumbest best effort ever?
641 }
642
643 namespace detail {
644
645 inline size_t estimateSpaceToReserve(size_t sofar) {
646   return sofar;
647 }
648
649 template <class T, class... Ts>
650 size_t estimateSpaceToReserve(size_t sofar, const T& v, const Ts&... vs) {
651   return estimateSpaceToReserve(sofar + estimateSpaceNeeded(v), vs...);
652 }
653
654 template<class T>
655 size_t estimateSpaceToReserve(size_t sofar, const T& v) {
656   return sofar + estimateSpaceNeeded(v);
657 }
658
659 template<class...Ts>
660 void reserveInTarget(const Ts&...vs) {
661   getLastElement(vs...)->reserve(estimateSpaceToReserve(0, vs...));
662 }
663
664 template<class Delimiter, class...Ts>
665 void reserveInTargetDelim(const Delimiter& d, const Ts&...vs) {
666   static_assert(sizeof...(vs) >= 2, "Needs at least 2 args");
667   size_t fordelim = (sizeof...(vs) - 2) * estimateSpaceToReserve(0, d);
668   getLastElement(vs...)->reserve(estimateSpaceToReserve(fordelim, vs...));
669 }
670
671 /**
672  * Variadic base case: append one element
673  */
674 template <class T, class Tgt>
675 typename std::enable_if<
676   IsSomeString<typename std::remove_pointer<Tgt>::type>
677   ::value>::type
678 toAppendStrImpl(const T& v, Tgt result) {
679   toAppend(v, result);
680 }
681
682 template <class T, class... Ts>
683 typename std::enable_if<sizeof...(Ts) >= 2
684   && IsSomeString<
685   typename std::remove_pointer<
686     typename detail::last_element<Ts...>::type
687   >::type>::value>::type
688 toAppendStrImpl(const T& v, const Ts&... vs) {
689   toAppend(v, getLastElement(vs...));
690   toAppendStrImpl(vs...);
691 }
692
693 template <class Delimiter, class T, class Tgt>
694 typename std::enable_if<
695   IsSomeString<typename std::remove_pointer<Tgt>::type>
696   ::value>::type
697 toAppendDelimStrImpl(const Delimiter& delim, const T& v, Tgt result) {
698   toAppend(v, result);
699 }
700
701 template <class Delimiter, class T, class... Ts>
702 typename std::enable_if<sizeof...(Ts) >= 2
703   && IsSomeString<
704   typename std::remove_pointer<
705     typename detail::last_element<Ts...>::type
706   >::type>::value>::type
707 toAppendDelimStrImpl(const Delimiter& delim, const T& v, const Ts&... vs) {
708   // we are really careful here, calling toAppend with just one element does
709   // not try to estimate space needed (as we already did that). If we call
710   // toAppend(v, delim, ....) we would do unnecesary size calculation
711   toAppend(v, detail::getLastElement(vs...));
712   toAppend(delim, detail::getLastElement(vs...));
713   toAppendDelimStrImpl(delim, vs...);
714 }
715 } // folly::detail
716
717
718 /**
719  * Variadic conversion to string. Appends each element in turn.
720  * If we have two or more things to append, we will reserve
721  * the space for them (at least we will try).
722  */
723 template <class... Ts>
724 typename std::enable_if<sizeof...(Ts) >= 3
725   && IsSomeString<
726   typename std::remove_pointer<
727     typename detail::last_element<Ts...>::type
728   >::type>::value>::type
729 toAppend(const Ts&... vs) {
730   detail::reserveInTarget(vs...);
731   detail::toAppendStrImpl(vs...);
732 }
733
734 /**
735  * Variadic base case: do nothing.
736  */
737 template <class Tgt>
738 typename std::enable_if<IsSomeString<Tgt>::value>::type
739 toAppend(Tgt* result) {
740 }
741
742 /**
743  * Variadic base case: do nothing.
744  */
745 template <class Delimiter, class Tgt>
746 typename std::enable_if<IsSomeString<Tgt>::value>::type
747 toAppendDelim(const Delimiter& delim, Tgt* result) {
748 }
749
750 /**
751  * 1 element: same as toAppend.
752  */
753 template <class Delimiter, class T, class Tgt>
754 typename std::enable_if<IsSomeString<Tgt>::value>::type
755 toAppendDelim(const Delimiter& delim, const T& v, Tgt* tgt) {
756   toAppend(v, tgt);
757 }
758
759 /**
760  * Append to string with a delimiter in between elements.
761  */
762 template <class Delimiter, class... Ts>
763 typename std::enable_if<sizeof...(Ts) >= 3
764   && IsSomeString<
765   typename std::remove_pointer<
766     typename detail::last_element<Ts...>::type
767   >::type>::value>::type
768 toAppendDelim(const Delimiter& delim, const Ts&... vs) {
769   detail::reserveInTargetDelim(delim, vs...);
770   detail::toAppendDelimStrImpl(delim, vs...);
771 }
772
773 /**
774  * to<SomeString>(SomeString str) returns itself. As both std::string and
775  * folly::fbstring use Copy-on-Write, it's much more efficient by
776  * avoiding copying the underlying char array.
777  */
778 template <class Tgt, class Src>
779 typename std::enable_if<
780   IsSomeString<Tgt>::value && std::is_same<Tgt, Src>::value,
781   Tgt>::type
782 to(const Src & value) {
783   return value;
784 }
785
786 /**
787  * to<SomeString>(v1, v2, ...) uses toAppend() (see below) as back-end
788  * for all types.
789  */
790 template <class Tgt, class... Ts>
791 typename std::enable_if<
792   IsSomeString<Tgt>::value && (
793     sizeof...(Ts) != 1 ||
794     !std::is_same<Tgt, typename detail::last_element<Ts...>::type>::value),
795   Tgt>::type
796 to(const Ts&... vs) {
797   Tgt result;
798   toAppend(vs..., &result);
799   return result;
800 }
801
802 /**
803  * toDelim<SomeString>(SomeString str) returns itself.
804  */
805 template <class Tgt, class Delim, class Src>
806 typename std::enable_if<
807   IsSomeString<Tgt>::value && std::is_same<Tgt, Src>::value,
808   Tgt>::type
809 toDelim(const Delim& delim, const Src & value) {
810   return value;
811 }
812
813 /**
814  * toDelim<SomeString>(delim, v1, v2, ...) uses toAppendDelim() as
815  * back-end for all types.
816  */
817 template <class Tgt, class Delim, class... Ts>
818 typename std::enable_if<
819   IsSomeString<Tgt>::value && (
820     sizeof...(Ts) != 1 ||
821     !std::is_same<Tgt, typename detail::last_element<Ts...>::type>::value),
822   Tgt>::type
823 toDelim(const Delim& delim, const Ts&... vs) {
824   Tgt result;
825   toAppendDelim(delim, vs..., &result);
826   return result;
827 }
828
829 /*******************************************************************************
830  * Conversions from string types to integral types.
831  ******************************************************************************/
832
833 namespace detail {
834
835 /**
836  * Finds the first non-digit in a string. The number of digits
837  * searched depends on the precision of the Tgt integral. Assumes the
838  * string starts with NO whitespace and NO sign.
839  *
840  * The semantics of the routine is:
841  *   for (;; ++b) {
842  *     if (b >= e || !isdigit(*b)) return b;
843  *   }
844  *
845  *  Complete unrolling marks bottom-line (i.e. entire conversion)
846  *  improvements of 20%.
847  */
848   template <class Tgt>
849   const char* findFirstNonDigit(const char* b, const char* e) {
850     for (; b < e; ++b) {
851       auto const c = static_cast<unsigned>(*b) - '0';
852       if (c >= 10) break;
853     }
854     return b;
855   }
856
857   // Maximum value of number when represented as a string
858   template <class T> struct MaxString {
859     static const char*const value;
860   };
861
862
863 /*
864  * Lookup tables that converts from a decimal character value to an integral
865  * binary value, shifted by a decimal "shift" multiplier.
866  * For all character values in the range '0'..'9', the table at those
867  * index locations returns the actual decimal value shifted by the multiplier.
868  * For all other values, the lookup table returns an invalid OOR value.
869  */
870 // Out-of-range flag value, larger than the largest value that can fit in
871 // four decimal bytes (9999), but four of these added up together should
872 // still not overflow uint16_t.
873 constexpr int32_t OOR = 10000;
874
875 __attribute__((__aligned__(16))) constexpr uint16_t shift1[] = {
876   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 0-9
877   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  10
878   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  20
879   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  30
880   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 0,         //  40
881   1, 2, 3, 4, 5, 6, 7, 8, 9, OOR, OOR,
882   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  60
883   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  70
884   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  80
885   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  90
886   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 100
887   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 110
888   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 120
889   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 130
890   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 140
891   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 150
892   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 160
893   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 170
894   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 180
895   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 190
896   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 200
897   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 210
898   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 220
899   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 230
900   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 240
901   OOR, OOR, OOR, OOR, OOR, OOR                       // 250
902 };
903
904 __attribute__((__aligned__(16))) constexpr uint16_t shift10[] = {
905   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 0-9
906   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  10
907   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  20
908   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  30
909   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 0,         //  40
910   10, 20, 30, 40, 50, 60, 70, 80, 90, OOR, OOR,
911   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  60
912   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  70
913   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  80
914   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  90
915   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 100
916   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 110
917   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 120
918   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 130
919   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 140
920   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 150
921   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 160
922   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 170
923   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 180
924   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 190
925   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 200
926   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 210
927   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 220
928   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 230
929   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 240
930   OOR, OOR, OOR, OOR, OOR, OOR                       // 250
931 };
932
933 __attribute__((__aligned__(16))) constexpr uint16_t shift100[] = {
934   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 0-9
935   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  10
936   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  20
937   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  30
938   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 0,         //  40
939   100, 200, 300, 400, 500, 600, 700, 800, 900, OOR, OOR,
940   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  60
941   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  70
942   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  80
943   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  90
944   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 100
945   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 110
946   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 120
947   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 130
948   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 140
949   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 150
950   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 160
951   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 170
952   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 180
953   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 190
954   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 200
955   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 210
956   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 220
957   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 230
958   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 240
959   OOR, OOR, OOR, OOR, OOR, OOR                       // 250
960 };
961
962 __attribute__((__aligned__(16))) constexpr uint16_t shift1000[] = {
963   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 0-9
964   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  10
965   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  20
966   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  30
967   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, 0,         //  40
968   1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, OOR, OOR,
969   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  60
970   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  70
971   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  80
972   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  //  90
973   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 100
974   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 110
975   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 120
976   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 130
977   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 140
978   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 150
979   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 160
980   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 170
981   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 180
982   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 190
983   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 200
984   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 210
985   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 220
986   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 230
987   OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR,  // 240
988   OOR, OOR, OOR, OOR, OOR, OOR                       // 250
989 };
990
991 /**
992  * String represented as a pair of pointers to char to unsigned
993  * integrals. Assumes NO whitespace before or after, and also that the
994  * string is composed entirely of digits. Tgt must be unsigned, and no
995  * sign is allowed in the string (even it's '+'). String may be empty,
996  * in which case digits_to throws.
997  */
998   template <class Tgt>
999   Tgt digits_to(const char * b, const char * e) {
1000
1001     static_assert(!std::is_signed<Tgt>::value, "Unsigned type expected");
1002     assert(b <= e);
1003
1004     const size_t size = e - b;
1005
1006     /* Although the string is entirely made of digits, we still need to
1007      * check for overflow.
1008      */
1009     if (size >= std::numeric_limits<Tgt>::digits10 + 1) {
1010       // Leading zeros? If so, recurse to keep things simple
1011       if (b < e && *b == '0') {
1012         for (++b;; ++b) {
1013           if (b == e) return 0; // just zeros, e.g. "0000"
1014           if (*b != '0') return digits_to<Tgt>(b, e);
1015         }
1016       }
1017       FOLLY_RANGE_CHECK(size == std::numeric_limits<Tgt>::digits10 + 1 &&
1018                         strncmp(b, detail::MaxString<Tgt>::value, size) <= 0,
1019                         "Numeric overflow upon conversion");
1020     }
1021
1022     // Here we know that the number won't overflow when
1023     // converted. Proceed without checks.
1024
1025     Tgt result = 0;
1026
1027     for (; e - b >= 4; b += 4) {
1028       result *= 10000;
1029       const int32_t r0 = shift1000[static_cast<size_t>(b[0])];
1030       const int32_t r1 = shift100[static_cast<size_t>(b[1])];
1031       const int32_t r2 = shift10[static_cast<size_t>(b[2])];
1032       const int32_t r3 = shift1[static_cast<size_t>(b[3])];
1033       const auto sum = r0 + r1 + r2 + r3;
1034       assert(sum < OOR && "Assumption: string only has digits");
1035       result += sum;
1036     }
1037
1038     switch (e - b) {
1039       case 3: {
1040         const int32_t r0 = shift100[static_cast<size_t>(b[0])];
1041         const int32_t r1 = shift10[static_cast<size_t>(b[1])];
1042         const int32_t r2 = shift1[static_cast<size_t>(b[2])];
1043         const auto sum = r0 + r1 + r2;
1044         assert(sum < OOR && "Assumption: string only has digits");
1045         return result * 1000 + sum;
1046       }
1047       case 2: {
1048         const int32_t r0 = shift10[static_cast<size_t>(b[0])];
1049         const int32_t r1 = shift1[static_cast<size_t>(b[1])];
1050         const auto sum = r0 + r1;
1051         assert(sum < OOR && "Assumption: string only has digits");
1052         return result * 100 + sum;
1053       }
1054       case 1: {
1055         const int32_t sum = shift1[static_cast<size_t>(b[0])];
1056         assert(sum < OOR && "Assumption: string only has digits");
1057         return result * 10 + sum;
1058       }
1059     }
1060
1061     assert(b == e);
1062     FOLLY_RANGE_CHECK(size > 0, "Found no digits to convert in input");
1063     return result;
1064   }
1065
1066
1067   bool str_to_bool(StringPiece * src);
1068
1069 }                                 // namespace detail
1070
1071 /**
1072  * String represented as a pair of pointers to char to unsigned
1073  * integrals. Assumes NO whitespace before or after.
1074  */
1075 template <class Tgt>
1076 typename std::enable_if<
1077   std::is_integral<Tgt>::value && !std::is_signed<Tgt>::value
1078   && !std::is_same<typename std::remove_cv<Tgt>::type, bool>::value,
1079   Tgt>::type
1080 to(const char * b, const char * e) {
1081   return detail::digits_to<Tgt>(b, e);
1082 }
1083
1084 /**
1085  * String represented as a pair of pointers to char to signed
1086  * integrals. Assumes NO whitespace before or after. Allows an
1087  * optional leading sign.
1088  */
1089 template <class Tgt>
1090 typename std::enable_if<
1091   std::is_integral<Tgt>::value && std::is_signed<Tgt>::value,
1092   Tgt>::type
1093 to(const char * b, const char * e) {
1094   FOLLY_RANGE_CHECK(b < e, "Empty input string in conversion to integral");
1095   if (!isdigit(*b)) {
1096     if (*b == '-') {
1097       Tgt result = -to<typename std::make_unsigned<Tgt>::type>(b + 1, e);
1098       FOLLY_RANGE_CHECK(result <= 0, "Negative overflow.");
1099       return result;
1100     }
1101     FOLLY_RANGE_CHECK(*b == '+', "Invalid lead character");
1102     ++b;
1103   }
1104   Tgt result = to<typename std::make_unsigned<Tgt>::type>(b, e);
1105   FOLLY_RANGE_CHECK(result >= 0, "Overflow.");
1106   return result;
1107 }
1108
1109 /**
1110  * Parsing strings to integrals. These routines differ from
1111  * to<integral>(string) in that they take a POINTER TO a StringPiece
1112  * and alter that StringPiece to reflect progress information.
1113  */
1114
1115 /**
1116  * StringPiece to integrals, with progress information. Alters the
1117  * StringPiece parameter to munch the already-parsed characters.
1118  */
1119 template <class Tgt>
1120 typename std::enable_if<
1121   std::is_integral<Tgt>::value
1122   && !std::is_same<typename std::remove_cv<Tgt>::type, bool>::value,
1123   Tgt>::type
1124 to(StringPiece * src) {
1125
1126   auto b = src->data(), past = src->data() + src->size();
1127   for (;; ++b) {
1128     FOLLY_RANGE_CHECK(b < past, "No digits found in input string");
1129     if (!isspace(*b)) break;
1130   }
1131
1132   auto m = b;
1133
1134   // First digit is customized because we test for sign
1135   bool negative = false;
1136   /* static */ if (std::is_signed<Tgt>::value) {
1137     if (!isdigit(*m)) {
1138       if (*m == '-') {
1139         negative = true;
1140       } else {
1141         FOLLY_RANGE_CHECK(*m == '+', "Invalid leading character in conversion"
1142                           " to integral");
1143       }
1144       ++b;
1145       ++m;
1146     }
1147   }
1148   FOLLY_RANGE_CHECK(m < past, "No digits found in input string");
1149   FOLLY_RANGE_CHECK(isdigit(*m), "Non-digit character found");
1150   m = detail::findFirstNonDigit<Tgt>(m + 1, past);
1151
1152   Tgt result;
1153   /* static */ if (!std::is_signed<Tgt>::value) {
1154     result = detail::digits_to<typename std::make_unsigned<Tgt>::type>(b, m);
1155   } else {
1156     auto t = detail::digits_to<typename std::make_unsigned<Tgt>::type>(b, m);
1157     if (negative) {
1158       result = -t;
1159       FOLLY_RANGE_CHECK(is_non_positive(result), "Negative overflow");
1160     } else {
1161       result = t;
1162       FOLLY_RANGE_CHECK(is_non_negative(result), "Overflow");
1163     }
1164   }
1165   src->advance(m - src->data());
1166   return result;
1167 }
1168
1169 /**
1170  * StringPiece to bool, with progress information. Alters the
1171  * StringPiece parameter to munch the already-parsed characters.
1172  */
1173 template <class Tgt>
1174 typename std::enable_if<
1175   std::is_same<typename std::remove_cv<Tgt>::type, bool>::value,
1176   Tgt>::type
1177 to(StringPiece * src) {
1178   return detail::str_to_bool(src);
1179 }
1180
1181 namespace detail {
1182
1183 /**
1184  * Enforce that the suffix following a number is made up only of whitespace.
1185  */
1186 inline void enforceWhitespace(const char* b, const char* e) {
1187   for (; b != e; ++b) {
1188     FOLLY_RANGE_CHECK(isspace(*b), to<std::string>("Non-whitespace: ", *b));
1189   }
1190 }
1191
1192 }  // namespace detail
1193
1194 /**
1195  * String or StringPiece to integrals. Accepts leading and trailing
1196  * whitespace, but no non-space trailing characters.
1197  */
1198 template <class Tgt>
1199 typename std::enable_if<
1200   std::is_integral<Tgt>::value,
1201   Tgt>::type
1202 to(StringPiece src) {
1203   Tgt result = to<Tgt>(&src);
1204   detail::enforceWhitespace(src.data(), src.data() + src.size());
1205   return result;
1206 }
1207
1208 /*******************************************************************************
1209  * Conversions from string types to floating-point types.
1210  ******************************************************************************/
1211
1212 /**
1213  * StringPiece to double, with progress information. Alters the
1214  * StringPiece parameter to munch the already-parsed characters.
1215  */
1216 template <class Tgt>
1217 inline typename std::enable_if<
1218   std::is_floating_point<Tgt>::value,
1219   Tgt>::type
1220 to(StringPiece *const src) {
1221   using namespace double_conversion;
1222   static StringToDoubleConverter
1223     conv(StringToDoubleConverter::ALLOW_TRAILING_JUNK
1224          | StringToDoubleConverter::ALLOW_LEADING_SPACES,
1225          0.0,
1226          // return this for junk input string
1227          std::numeric_limits<double>::quiet_NaN(),
1228          nullptr, nullptr);
1229
1230   FOLLY_RANGE_CHECK(!src->empty(), "No digits found in input string");
1231
1232   int length;
1233   auto result = conv.StringToDouble(src->data(), src->size(),
1234                                        &length); // processed char count
1235
1236   if (!std::isnan(result)) {
1237     src->advance(length);
1238     return result;
1239   }
1240
1241   for (;; src->advance(1)) {
1242     if (src->empty()) {
1243       throw std::range_error("Unable to convert an empty string"
1244                              " to a floating point value.");
1245     }
1246     if (!isspace(src->front())) {
1247       break;
1248     }
1249   }
1250
1251   // Was that "inf[inity]"?
1252   if (src->size() >= 3 && toupper((*src)[0]) == 'I'
1253         && toupper((*src)[1]) == 'N' && toupper((*src)[2]) == 'F') {
1254     if (src->size() >= 8 &&
1255         toupper((*src)[3]) == 'I' &&
1256         toupper((*src)[4]) == 'N' &&
1257         toupper((*src)[5]) == 'I' &&
1258         toupper((*src)[6]) == 'T' &&
1259         toupper((*src)[7]) == 'Y') {
1260       src->advance(8);
1261     } else {
1262       src->advance(3);
1263     }
1264     return std::numeric_limits<Tgt>::infinity();
1265   }
1266
1267   // Was that "-inf[inity]"?
1268   if (src->size() >= 4 && toupper((*src)[0]) == '-'
1269       && toupper((*src)[1]) == 'I' && toupper((*src)[2]) == 'N'
1270       && toupper((*src)[3]) == 'F') {
1271     if (src->size() >= 9 &&
1272         toupper((*src)[4]) == 'I' &&
1273         toupper((*src)[5]) == 'N' &&
1274         toupper((*src)[6]) == 'I' &&
1275         toupper((*src)[7]) == 'T' &&
1276         toupper((*src)[8]) == 'Y') {
1277       src->advance(9);
1278     } else {
1279       src->advance(4);
1280     }
1281     return -std::numeric_limits<Tgt>::infinity();
1282   }
1283
1284   // "nan"?
1285   if (src->size() >= 3 && toupper((*src)[0]) == 'N'
1286         && toupper((*src)[1]) == 'A' && toupper((*src)[2]) == 'N') {
1287     src->advance(3);
1288     return std::numeric_limits<Tgt>::quiet_NaN();
1289   }
1290
1291   // "-nan"?
1292   if (src->size() >= 4 &&
1293       toupper((*src)[0]) == '-' &&
1294       toupper((*src)[1]) == 'N' &&
1295       toupper((*src)[2]) == 'A' &&
1296       toupper((*src)[3]) == 'N') {
1297     src->advance(4);
1298     return -std::numeric_limits<Tgt>::quiet_NaN();
1299   }
1300
1301   // All bets are off
1302   throw std::range_error("Unable to convert \"" + src->toString()
1303                          + "\" to a floating point value.");
1304 }
1305
1306 /**
1307  * Any string, const char*, or StringPiece to double.
1308  */
1309 template <class Tgt>
1310 typename std::enable_if<
1311   std::is_floating_point<Tgt>::value,
1312   Tgt>::type
1313 to(StringPiece src) {
1314   Tgt result = to<double>(&src);
1315   detail::enforceWhitespace(src.data(), src.data() + src.size());
1316   return result;
1317 }
1318
1319 /*******************************************************************************
1320  * Integral to floating point and back
1321  ******************************************************************************/
1322
1323 /**
1324  * Checked conversion from integral to flating point and back. The
1325  * result must be convertible back to the source type without loss of
1326  * precision. This seems Draconian but sometimes is what's needed, and
1327  * complements existing routines nicely. For various rounding
1328  * routines, see <math>.
1329  */
1330 template <class Tgt, class Src>
1331 typename std::enable_if<
1332   (std::is_integral<Src>::value && std::is_floating_point<Tgt>::value)
1333   ||
1334   (std::is_floating_point<Src>::value && std::is_integral<Tgt>::value),
1335   Tgt>::type
1336 to(const Src & value) {
1337   Tgt result = value;
1338   auto witness = static_cast<Src>(result);
1339   if (value != witness) {
1340     throw std::range_error(
1341       to<std::string>("to<>: loss of precision when converting ", value,
1342                       " to type ", typeid(Tgt).name()).c_str());
1343   }
1344   return result;
1345 }
1346
1347 /*******************************************************************************
1348  * Enum to anything and back
1349  ******************************************************************************/
1350
1351 #if defined(__clang__) || __GNUC_PREREQ(4, 7)
1352 // std::underlying_type became available by gcc 4.7.0
1353
1354 template <class Tgt, class Src>
1355 typename std::enable_if<std::is_enum<Src>::value, Tgt>::type
1356 to(const Src & value) {
1357   return to<Tgt>(static_cast<typename std::underlying_type<Src>::type>(value));
1358 }
1359
1360 template <class Tgt, class Src>
1361 typename std::enable_if<std::is_enum<Tgt>::value, Tgt>::type
1362 to(const Src & value) {
1363   return static_cast<Tgt>(to<typename std::underlying_type<Tgt>::type>(value));
1364 }
1365
1366 #else
1367
1368 template <class Tgt, class Src>
1369 typename std::enable_if<std::is_enum<Src>::value, Tgt>::type
1370 to(const Src & value) {
1371   /* static */ if (Src(-1) < 0) {
1372     /* static */ if (sizeof(Src) <= sizeof(int)) {
1373       return to<Tgt>(static_cast<int>(value));
1374     } else {
1375       return to<Tgt>(static_cast<long>(value));
1376     }
1377   } else {
1378     /* static */ if (sizeof(Src) <= sizeof(int)) {
1379       return to<Tgt>(static_cast<unsigned int>(value));
1380     } else {
1381       return to<Tgt>(static_cast<unsigned long>(value));
1382     }
1383   }
1384 }
1385
1386 template <class Tgt, class Src>
1387 typename std::enable_if<std::is_enum<Tgt>::value, Tgt>::type
1388 to(const Src & value) {
1389   /* static */ if (Tgt(-1) < 0) {
1390     /* static */ if (sizeof(Tgt) <= sizeof(int)) {
1391       return static_cast<Tgt>(to<int>(value));
1392     } else {
1393       return static_cast<Tgt>(to<long>(value));
1394     }
1395   } else {
1396     /* static */ if (sizeof(Tgt) <= sizeof(int)) {
1397       return static_cast<Tgt>(to<unsigned int>(value));
1398     } else {
1399       return static_cast<Tgt>(to<unsigned long>(value));
1400     }
1401   }
1402 }
1403
1404 #endif // gcc 4.7 onwards
1405
1406 } // namespace folly
1407
1408 // FOLLY_CONV_INTERNAL is defined by Conv.cpp.  Keep the FOLLY_RANGE_CHECK
1409 // macro for use in Conv.cpp, but #undefine it everywhere else we are included,
1410 // to avoid defining this global macro name in other files that include Conv.h.
1411 #ifndef FOLLY_CONV_INTERNAL
1412 #undef FOLLY_RANGE_CHECK
1413 #undef FOLLY_RANGE_CHECK_STRINGIZE2
1414 #undef FOLLY_RANGE_CHECK_STRINGIZE
1415 #endif
1416
1417 #endif /* FOLLY_BASE_CONV_H_ */