Format digits10
[folly.git] / folly / Conv.h
1 /*
2  * Copyright 2017 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 #pragma once
25
26 #include <algorithm>
27 #include <cctype>
28 #include <climits>
29 #include <cstddef>
30 #include <limits>
31 #include <stdexcept>
32 #include <string>
33 #include <tuple>
34 #include <type_traits>
35 #include <typeinfo>
36 #include <utility>
37
38 #include <double-conversion/double-conversion.h> // V8 JavaScript implementation
39
40 #include <folly/Demangle.h>
41 #include <folly/Expected.h>
42 #include <folly/FBString.h>
43 #include <folly/Likely.h>
44 #include <folly/Range.h>
45 #include <folly/Traits.h>
46 #include <folly/Unit.h>
47 #include <folly/portability/Math.h>
48
49 namespace folly {
50
51 // Keep this in sync with kErrorStrings in Conv.cpp
52 enum class ConversionCode : unsigned char {
53   SUCCESS,
54   EMPTY_INPUT_STRING,
55   NO_DIGITS,
56   BOOL_OVERFLOW,
57   BOOL_INVALID_VALUE,
58   NON_DIGIT_CHAR,
59   INVALID_LEADING_CHAR,
60   POSITIVE_OVERFLOW,
61   NEGATIVE_OVERFLOW,
62   STRING_TO_FLOAT_ERROR,
63   NON_WHITESPACE_AFTER_END,
64   ARITH_POSITIVE_OVERFLOW,
65   ARITH_NEGATIVE_OVERFLOW,
66   ARITH_LOSS_OF_PRECISION,
67   NUM_ERROR_CODES, // has to be the last entry
68 };
69
70 struct ConversionErrorBase : std::range_error {
71   using std::range_error::range_error;
72 };
73
74 class ConversionError : public ConversionErrorBase {
75  public:
76   ConversionError(const std::string& str, ConversionCode code)
77       : ConversionErrorBase(str), code_(code) {}
78
79   ConversionError(const char* str, ConversionCode code)
80       : ConversionErrorBase(str), code_(code) {}
81
82   ConversionCode errorCode() const {
83     return code_;
84   }
85
86  private:
87   ConversionCode code_;
88 };
89
90 /*******************************************************************************
91  * Custom Error Translation
92  *
93  * Your overloaded parseTo() function can return a custom error code on failure.
94  * ::folly::to() will call makeConversionError to translate that error code into
95  * an object to throw. makeConversionError is found by argument-dependent
96  * lookup. It should have this signature:
97  *
98  * namespace other_namespace {
99  * enum YourErrorCode { BAD_ERROR, WORSE_ERROR };
100  *
101  * struct YourConversionError : ConversionErrorBase {
102  *   YourConversionError(const char* what) : ConversionErrorBase(what) {}
103  * };
104  *
105  * YourConversionError
106  * makeConversionError(YourErrorCode code, ::folly::StringPiece sp) {
107  *   ...
108  *   return YourConversionError(messageString);
109  * }
110  ******************************************************************************/
111 ConversionError makeConversionError(ConversionCode code, StringPiece sp);
112
113 namespace detail {
114 /**
115  * Enforce that the suffix following a number is made up only of whitespace.
116  */
117 inline ConversionCode enforceWhitespaceErr(StringPiece sp) {
118   for (auto c : sp) {
119     if (UNLIKELY(!std::isspace(c))) {
120       return ConversionCode::NON_WHITESPACE_AFTER_END;
121     }
122   }
123   return ConversionCode::SUCCESS;
124 }
125
126 /**
127  * Keep this implementation around for prettyToDouble().
128  */
129 inline void enforceWhitespace(StringPiece sp) {
130   auto err = enforceWhitespaceErr(sp);
131   if (err != ConversionCode::SUCCESS) {
132     throw makeConversionError(err, sp);
133   }
134 }
135 } // namespace detail
136
137 /**
138  * The identity conversion function.
139  * tryTo<T>(T) returns itself for all types T.
140  */
141 template <class Tgt, class Src>
142 typename std::enable_if<
143     std::is_same<Tgt, typename std::decay<Src>::type>::value,
144     Expected<Tgt, ConversionCode>>::type
145 tryTo(Src&& value) {
146   return std::forward<Src>(value);
147 }
148
149 template <class Tgt, class Src>
150 typename std::enable_if<
151     std::is_same<Tgt, typename std::decay<Src>::type>::value,
152     Tgt>::type
153 to(Src&& value) {
154   return std::forward<Src>(value);
155 }
156
157 /*******************************************************************************
158  * Arithmetic to boolean
159  ******************************************************************************/
160
161 /**
162  * Unchecked conversion from arithmetic to boolean. This is different from the
163  * other arithmetic conversions because we use the C convention of treating any
164  * non-zero value as true, instead of range checking.
165  */
166 template <class Tgt, class Src>
167 typename std::enable_if<
168     std::is_arithmetic<Src>::value && !std::is_same<Tgt, Src>::value &&
169         std::is_same<Tgt, bool>::value,
170     Expected<Tgt, ConversionCode>>::type
171 tryTo(const Src& value) {
172   return value != Src();
173 }
174
175 template <class Tgt, class Src>
176 typename std::enable_if<
177     std::is_arithmetic<Src>::value && !std::is_same<Tgt, Src>::value &&
178         std::is_same<Tgt, bool>::value,
179     Tgt>::type
180 to(const Src& value) {
181   return value != Src();
182 }
183
184 /*******************************************************************************
185  * Anything to string
186  ******************************************************************************/
187
188 namespace detail {
189
190 #ifdef _MSC_VER
191 // MSVC can't quite figure out the LastElementImpl::call() stuff
192 // in the base implementation, so we have to use tuples instead,
193 // which result in significantly more templates being compiled,
194 // though the runtime performance is the same.
195
196 template <typename... Ts>
197 auto getLastElement(Ts&&... ts) -> decltype(
198     std::get<sizeof...(Ts)-1>(std::forward_as_tuple(std::forward<Ts>(ts)...))) {
199   return std::get<sizeof...(Ts)-1>(
200       std::forward_as_tuple(std::forward<Ts>(ts)...));
201 }
202
203 inline void getLastElement() {}
204
205 template <size_t size, typename... Ts>
206 struct LastElementType : std::tuple_element<size - 1, std::tuple<Ts...>> {};
207
208 template <>
209 struct LastElementType<0> {
210   using type = void;
211 };
212
213 template <class... Ts>
214 struct LastElement
215     : std::decay<typename LastElementType<sizeof...(Ts), Ts...>::type> {};
216 #else
217 template <typename... Ts>
218 struct LastElementImpl {
219   static void call(Ignored<Ts>...) {}
220 };
221
222 template <typename Head, typename... Ts>
223 struct LastElementImpl<Head, Ts...> {
224   template <typename Last>
225   static Last call(Ignored<Ts>..., Last&& last) {
226     return std::forward<Last>(last);
227   }
228 };
229
230 template <typename... Ts>
231 auto getLastElement(const Ts&... ts)
232     -> decltype(LastElementImpl<Ts...>::call(ts...)) {
233   return LastElementImpl<Ts...>::call(ts...);
234 }
235
236 template <class... Ts>
237 struct LastElement : std::decay<decltype(
238                          LastElementImpl<Ts...>::call(std::declval<Ts>()...))> {
239 };
240 #endif
241
242 } // namespace detail
243
244 /*******************************************************************************
245  * Conversions from integral types to string types.
246  ******************************************************************************/
247
248 #if FOLLY_HAVE_INT128_T
249 namespace detail {
250
251 template <typename IntegerType>
252 constexpr unsigned int
253 digitsEnough() {
254   return (unsigned int)(ceil(sizeof(IntegerType) * CHAR_BIT * M_LN2 / M_LN10));
255 }
256
257 inline size_t
258 unsafeTelescope128(char * buffer, size_t room, unsigned __int128 x) {
259   typedef unsigned __int128 Usrc;
260   size_t p = room - 1;
261
262   while (x >= (Usrc(1) << 64)) { // Using 128-bit division while needed
263     const auto y = x / 10;
264     const auto digit = x % 10;
265
266     buffer[p--] = '0' + digit;
267     x = y;
268   }
269
270   uint64_t xx = x; // Moving to faster 64-bit division thereafter
271
272   while (xx >= 10) {
273     const auto y = xx / 10ULL;
274     const auto digit = xx % 10ULL;
275
276     buffer[p--] = '0' + digit;
277     xx = y;
278   }
279
280   buffer[p] = '0' + xx;
281
282   return p;
283 }
284
285 } // namespace detail
286 #endif
287
288 /**
289  * Returns the number of digits in the base 10 representation of an
290  * uint64_t. Useful for preallocating buffers and such. It's also used
291  * internally, see below. Measurements suggest that defining a
292  * separate overload for 32-bit integers is not worthwhile.
293  */
294
295 inline uint32_t digits10(uint64_t v) {
296 #ifdef __x86_64__
297
298   // For this arch we can get a little help from specialized CPU instructions
299   // which can count leading zeroes; 64 minus that is appx. log (base 2).
300   // Use that to approximate base-10 digits (log_10) and then adjust if needed.
301
302   // 10^i, defined for i 0 through 19.
303   // This is 20 * 8 == 160 bytes, which fits neatly into 5 cache lines
304   // (assuming a cache line size of 64).
305   alignas(64) static const uint64_t powersOf10[20] = {
306       1,
307       10,
308       100,
309       1000,
310       10000,
311       100000,
312       1000000,
313       10000000,
314       100000000,
315       1000000000,
316       10000000000,
317       100000000000,
318       1000000000000,
319       10000000000000,
320       100000000000000,
321       1000000000000000,
322       10000000000000000,
323       100000000000000000,
324       1000000000000000000,
325       10000000000000000000UL,
326   };
327
328   // "count leading zeroes" operation not valid; for 0; special case this.
329   if (UNLIKELY(!v)) {
330     return 1;
331   }
332
333   // bits is in the ballpark of log_2(v).
334   const uint8_t leadingZeroes = __builtin_clzll(v);
335   const auto bits = 63 - leadingZeroes;
336
337   // approximate log_10(v) == log_10(2) * bits.
338   // Integer magic below: 77/256 is appx. 0.3010 (log_10(2)).
339   // The +1 is to make this the ceiling of the log_10 estimate.
340   const uint32_t minLength = 1 + ((bits * 77) >> 8);
341
342   // return that log_10 lower bound, plus adjust if input >= 10^(that bound)
343   // in case there's a small error and we misjudged length.
344   return minLength + uint32_t(v >= powersOf10[minLength]);
345
346 #else
347
348   uint32_t result = 1;
349   while (true) {
350     if (LIKELY(v < 10)) {
351       return result;
352     }
353     if (LIKELY(v < 100)) {
354       return result + 1;
355     }
356     if (LIKELY(v < 1000)) {
357       return result + 2;
358     }
359     if (LIKELY(v < 10000)) {
360       return result + 3;
361     }
362     // Skip ahead by 4 orders of magnitude
363     v /= 10000U;
364     result += 4;
365   }
366
367 #endif
368 }
369
370 /**
371  * Copies the ASCII base 10 representation of v into buffer and
372  * returns the number of bytes written. Does NOT append a \0. Assumes
373  * the buffer points to digits10(v) bytes of valid memory. Note that
374  * uint64 needs at most 20 bytes, uint32_t needs at most 10 bytes,
375  * uint16_t needs at most 5 bytes, and so on. Measurements suggest
376  * that defining a separate overload for 32-bit integers is not
377  * worthwhile.
378  *
379  * This primitive is unsafe because it makes the size assumption and
380  * because it does not add a terminating \0.
381  */
382
383 inline uint32_t uint64ToBufferUnsafe(uint64_t v, char *const buffer) {
384   auto const result = digits10(v);
385   // WARNING: using size_t or pointer arithmetic for pos slows down
386   // the loop below 20x. This is because several 32-bit ops can be
387   // done in parallel, but only fewer 64-bit ones.
388   uint32_t pos = result - 1;
389   while (v >= 10) {
390     // Keep these together so a peephole optimization "sees" them and
391     // computes them in one shot.
392     auto const q = v / 10;
393     auto const r = static_cast<char>(v % 10);
394     buffer[pos--] = '0' + r;
395     v = q;
396   }
397   // Last digit is trivial to handle
398   buffer[pos] = static_cast<char>(v) + '0';
399   return result;
400 }
401
402 /**
403  * A single char gets appended.
404  */
405 template <class Tgt>
406 void toAppend(char value, Tgt * result) {
407   *result += value;
408 }
409
410 template <class T>
411 constexpr typename std::enable_if<
412   std::is_same<T, char>::value,
413   size_t>::type
414 estimateSpaceNeeded(T) {
415   return 1;
416 }
417
418 template <size_t N>
419 constexpr size_t estimateSpaceNeeded(const char (&)[N]) {
420   return N;
421 }
422
423 /**
424  * Everything implicitly convertible to const char* gets appended.
425  */
426 template <class Tgt, class Src>
427 typename std::enable_if<
428   std::is_convertible<Src, const char*>::value
429   && IsSomeString<Tgt>::value>::type
430 toAppend(Src value, Tgt * result) {
431   // Treat null pointers like an empty string, as in:
432   // operator<<(std::ostream&, const char*).
433   const char* c = value;
434   if (c) {
435     result->append(value);
436   }
437 }
438
439 template <class Src>
440 typename std::enable_if<std::is_convertible<Src, const char*>::value, size_t>::
441     type
442     estimateSpaceNeeded(Src value) {
443   const char *c = value;
444   if (c) {
445     return folly::StringPiece(value).size();
446   };
447   return 0;
448 }
449
450 template <class Src>
451 typename std::enable_if<IsSomeString<Src>::value, size_t>::type
452 estimateSpaceNeeded(Src const& value) {
453   return value.size();
454 }
455
456 template <class Src>
457 typename std::enable_if<
458     std::is_convertible<Src, folly::StringPiece>::value &&
459         !IsSomeString<Src>::value &&
460         !std::is_convertible<Src, const char*>::value,
461     size_t>::type
462 estimateSpaceNeeded(Src value) {
463   return folly::StringPiece(value).size();
464 }
465
466 template <>
467 inline size_t estimateSpaceNeeded(std::nullptr_t /* value */) {
468   return 0;
469 }
470
471 template <class Src>
472 typename std::enable_if<
473   std::is_pointer<Src>::value &&
474   IsSomeString<std::remove_pointer<Src>>::value,
475   size_t>::type
476 estimateSpaceNeeded(Src value) {
477   return value->size();
478 }
479
480 /**
481  * Strings get appended, too.
482  */
483 template <class Tgt, class Src>
484 typename std::enable_if<
485   IsSomeString<Src>::value && IsSomeString<Tgt>::value>::type
486 toAppend(const Src& value, Tgt * result) {
487   result->append(value);
488 }
489
490 /**
491  * and StringPiece objects too
492  */
493 template <class Tgt>
494 typename std::enable_if<
495    IsSomeString<Tgt>::value>::type
496 toAppend(StringPiece value, Tgt * result) {
497   result->append(value.data(), value.size());
498 }
499
500 /**
501  * There's no implicit conversion from fbstring to other string types,
502  * so make a specialization.
503  */
504 template <class Tgt>
505 typename std::enable_if<
506    IsSomeString<Tgt>::value>::type
507 toAppend(const fbstring& value, Tgt * result) {
508   result->append(value.data(), value.size());
509 }
510
511 #if FOLLY_HAVE_INT128_T
512 /**
513  * Special handling for 128 bit integers.
514  */
515
516 template <class Tgt>
517 void
518 toAppend(__int128 value, Tgt * result) {
519   typedef unsigned __int128 Usrc;
520   char buffer[detail::digitsEnough<unsigned __int128>() + 1];
521   size_t p;
522
523   if (value < 0) {
524     p = detail::unsafeTelescope128(buffer, sizeof(buffer), -Usrc(value));
525     buffer[--p] = '-';
526   } else {
527     p = detail::unsafeTelescope128(buffer, sizeof(buffer), value);
528   }
529
530   result->append(buffer + p, buffer + sizeof(buffer));
531 }
532
533 template <class Tgt>
534 void
535 toAppend(unsigned __int128 value, Tgt * result) {
536   char buffer[detail::digitsEnough<unsigned __int128>()];
537   size_t p;
538
539   p = detail::unsafeTelescope128(buffer, sizeof(buffer), value);
540
541   result->append(buffer + p, buffer + sizeof(buffer));
542 }
543
544 template <class T>
545 constexpr typename std::enable_if<
546   std::is_same<T, __int128>::value,
547   size_t>::type
548 estimateSpaceNeeded(T) {
549   return detail::digitsEnough<__int128>();
550 }
551
552 template <class T>
553 constexpr typename std::enable_if<
554   std::is_same<T, unsigned __int128>::value,
555   size_t>::type
556 estimateSpaceNeeded(T) {
557   return detail::digitsEnough<unsigned __int128>();
558 }
559
560 #endif
561
562 /**
563  * int32_t and int64_t to string (by appending) go through here. The
564  * result is APPENDED to a preexisting string passed as the second
565  * parameter. This should be efficient with fbstring because fbstring
566  * incurs no dynamic allocation below 23 bytes and no number has more
567  * than 22 bytes in its textual representation (20 for digits, one for
568  * sign, one for the terminating 0).
569  */
570 template <class Tgt, class Src>
571 typename std::enable_if<
572   std::is_integral<Src>::value && std::is_signed<Src>::value &&
573   IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
574 toAppend(Src value, Tgt * result) {
575   char buffer[20];
576   if (value < 0) {
577     result->push_back('-');
578     result->append(
579         buffer,
580         uint64ToBufferUnsafe(~static_cast<uint64_t>(value) + 1, buffer));
581   } else {
582     result->append(buffer, uint64ToBufferUnsafe(uint64_t(value), buffer));
583   }
584 }
585
586 template <class Src>
587 typename std::enable_if<
588   std::is_integral<Src>::value && std::is_signed<Src>::value
589   && sizeof(Src) >= 4 && sizeof(Src) < 16,
590   size_t>::type
591 estimateSpaceNeeded(Src value) {
592   if (value < 0) {
593     // When "value" is the smallest negative, negating it would evoke
594     // undefined behavior, so, instead of writing "-value" below, we write
595     // "~static_cast<uint64_t>(value) + 1"
596     return 1 + digits10(~static_cast<uint64_t>(value) + 1);
597   }
598
599   return digits10(static_cast<uint64_t>(value));
600 }
601
602 /**
603  * As above, but for uint32_t and uint64_t.
604  */
605 template <class Tgt, class Src>
606 typename std::enable_if<
607   std::is_integral<Src>::value && !std::is_signed<Src>::value
608   && IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
609 toAppend(Src value, Tgt * result) {
610   char buffer[20];
611   result->append(buffer, uint64ToBufferUnsafe(value, buffer));
612 }
613
614 template <class Src>
615 typename std::enable_if<
616   std::is_integral<Src>::value && !std::is_signed<Src>::value
617   && sizeof(Src) >= 4 && sizeof(Src) < 16,
618   size_t>::type
619 estimateSpaceNeeded(Src value) {
620   return digits10(value);
621 }
622
623 /**
624  * All small signed and unsigned integers to string go through 32-bit
625  * types int32_t and uint32_t, respectively.
626  */
627 template <class Tgt, class Src>
628 typename std::enable_if<
629   std::is_integral<Src>::value
630   && IsSomeString<Tgt>::value && sizeof(Src) < 4>::type
631 toAppend(Src value, Tgt * result) {
632   typedef typename
633     std::conditional<std::is_signed<Src>::value, int64_t, uint64_t>::type
634     Intermediate;
635   toAppend<Tgt>(static_cast<Intermediate>(value), result);
636 }
637
638 template <class Src>
639 typename std::enable_if<
640   std::is_integral<Src>::value
641   && sizeof(Src) < 4
642   && !std::is_same<Src, char>::value,
643   size_t>::type
644 estimateSpaceNeeded(Src value) {
645   typedef typename
646     std::conditional<std::is_signed<Src>::value, int64_t, uint64_t>::type
647     Intermediate;
648   return estimateSpaceNeeded(static_cast<Intermediate>(value));
649 }
650
651 /**
652  * Enumerated values get appended as integers.
653  */
654 template <class Tgt, class Src>
655 typename std::enable_if<
656   std::is_enum<Src>::value && IsSomeString<Tgt>::value>::type
657 toAppend(Src value, Tgt * result) {
658   toAppend(
659       static_cast<typename std::underlying_type<Src>::type>(value), result);
660 }
661
662 template <class Src>
663 typename std::enable_if<
664   std::is_enum<Src>::value, size_t>::type
665 estimateSpaceNeeded(Src value) {
666   return estimateSpaceNeeded(
667       static_cast<typename std::underlying_type<Src>::type>(value));
668 }
669
670 /*******************************************************************************
671  * Conversions from floating-point types to string types.
672  ******************************************************************************/
673
674 namespace detail {
675 constexpr int kConvMaxDecimalInShortestLow = -6;
676 constexpr int kConvMaxDecimalInShortestHigh = 21;
677 } // namespace detail
678
679 /** Wrapper around DoubleToStringConverter **/
680 template <class Tgt, class Src>
681 typename std::enable_if<
682   std::is_floating_point<Src>::value
683   && IsSomeString<Tgt>::value>::type
684 toAppend(
685   Src value,
686   Tgt * result,
687   double_conversion::DoubleToStringConverter::DtoaMode mode,
688   unsigned int numDigits) {
689   using namespace double_conversion;
690   DoubleToStringConverter
691     conv(DoubleToStringConverter::NO_FLAGS,
692          "Infinity", "NaN", 'E',
693          detail::kConvMaxDecimalInShortestLow,
694          detail::kConvMaxDecimalInShortestHigh,
695          6,   // max leading padding zeros
696          1);  // max trailing padding zeros
697   char buffer[256];
698   StringBuilder builder(buffer, sizeof(buffer));
699   switch (mode) {
700     case DoubleToStringConverter::SHORTEST:
701       conv.ToShortest(value, &builder);
702       break;
703     case DoubleToStringConverter::FIXED:
704       conv.ToFixed(value, int(numDigits), &builder);
705       break;
706     default:
707       CHECK(mode == DoubleToStringConverter::PRECISION);
708       conv.ToPrecision(value, int(numDigits), &builder);
709       break;
710   }
711   const size_t length = size_t(builder.position());
712   builder.Finalize();
713   result->append(buffer, length);
714 }
715
716 /**
717  * As above, but for floating point
718  */
719 template <class Tgt, class Src>
720 typename std::enable_if<
721   std::is_floating_point<Src>::value
722   && IsSomeString<Tgt>::value>::type
723 toAppend(Src value, Tgt * result) {
724   toAppend(
725     value, result, double_conversion::DoubleToStringConverter::SHORTEST, 0);
726 }
727
728 /**
729  * Upper bound of the length of the output from
730  * DoubleToStringConverter::ToShortest(double, StringBuilder*),
731  * as used in toAppend(double, string*).
732  */
733 template <class Src>
734 typename std::enable_if<
735   std::is_floating_point<Src>::value, size_t>::type
736 estimateSpaceNeeded(Src value) {
737   // kBase10MaximalLength is 17. We add 1 for decimal point,
738   // e.g. 10.0/9 is 17 digits and 18 characters, including the decimal point.
739   constexpr int kMaxMantissaSpace =
740     double_conversion::DoubleToStringConverter::kBase10MaximalLength + 1;
741   // strlen("E-") + digits10(numeric_limits<double>::max_exponent10)
742   constexpr int kMaxExponentSpace = 2 + 3;
743   static const int kMaxPositiveSpace = std::max({
744       // E.g. 1.1111111111111111E-100.
745       kMaxMantissaSpace + kMaxExponentSpace,
746       // E.g. 0.000001.1111111111111111, if kConvMaxDecimalInShortestLow is -6.
747       kMaxMantissaSpace - detail::kConvMaxDecimalInShortestLow,
748       // If kConvMaxDecimalInShortestHigh is 21, then 1e21 is the smallest
749       // number > 1 which ToShortest outputs in exponential notation,
750       // so 21 is the longest non-exponential number > 1.
751       detail::kConvMaxDecimalInShortestHigh
752     });
753   return size_t(
754       kMaxPositiveSpace +
755       (value < 0 ? 1 : 0)); // +1 for minus sign, if negative
756 }
757
758 /**
759  * This can be specialized, together with adding specialization
760  * for estimateSpaceNeed for your type, so that we allocate
761  * as much as you need instead of the default
762  */
763 template <class Src>
764 struct HasLengthEstimator : std::false_type {};
765
766 template <class Src>
767 constexpr typename std::enable_if<
768   !std::is_fundamental<Src>::value
769 #if FOLLY_HAVE_INT128_T
770   // On OSX 10.10, is_fundamental<__int128> is false :-O
771   && !std::is_same<__int128, Src>::value
772   && !std::is_same<unsigned __int128, Src>::value
773 #endif
774   && !IsSomeString<Src>::value
775   && !std::is_convertible<Src, const char*>::value
776   && !std::is_convertible<Src, StringPiece>::value
777   && !std::is_enum<Src>::value
778   && !HasLengthEstimator<Src>::value,
779   size_t>::type
780 estimateSpaceNeeded(const Src&) {
781   return sizeof(Src) + 1; // dumbest best effort ever?
782 }
783
784 namespace detail {
785
786 template <class Tgt>
787 typename std::enable_if<IsSomeString<Tgt>::value, size_t>::type
788 estimateSpaceToReserve(size_t sofar, Tgt*) {
789   return sofar;
790 }
791
792 template <class T, class... Ts>
793 size_t estimateSpaceToReserve(size_t sofar, const T& v, const Ts&... vs) {
794   return estimateSpaceToReserve(sofar + estimateSpaceNeeded(v), vs...);
795 }
796
797 template <class... Ts>
798 void reserveInTarget(const Ts&...vs) {
799   getLastElement(vs...)->reserve(estimateSpaceToReserve(0, vs...));
800 }
801
802 template <class Delimiter, class... Ts>
803 void reserveInTargetDelim(const Delimiter& d, const Ts&...vs) {
804   static_assert(sizeof...(vs) >= 2, "Needs at least 2 args");
805   size_t fordelim = (sizeof...(vs) - 2) *
806       estimateSpaceToReserve(0, d, static_cast<std::string*>(nullptr));
807   getLastElement(vs...)->reserve(estimateSpaceToReserve(fordelim, vs...));
808 }
809
810 /**
811  * Variadic base case: append one element
812  */
813 template <class T, class Tgt>
814 typename std::enable_if<
815   IsSomeString<typename std::remove_pointer<Tgt>::type>
816   ::value>::type
817 toAppendStrImpl(const T& v, Tgt result) {
818   toAppend(v, result);
819 }
820
821 template <class T, class... Ts>
822 typename std::enable_if<
823     sizeof...(Ts) >= 2 &&
824     IsSomeString<typename std::remove_pointer<
825         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
826 toAppendStrImpl(const T& v, const Ts&... vs) {
827   toAppend(v, getLastElement(vs...));
828   toAppendStrImpl(vs...);
829 }
830
831 template <class Delimiter, class T, class Tgt>
832 typename std::enable_if<
833     IsSomeString<typename std::remove_pointer<Tgt>::type>::value>::type
834 toAppendDelimStrImpl(const Delimiter& /* delim */, const T& v, Tgt result) {
835   toAppend(v, result);
836 }
837
838 template <class Delimiter, class T, class... Ts>
839 typename std::enable_if<
840     sizeof...(Ts) >= 2 &&
841     IsSomeString<typename std::remove_pointer<
842         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
843 toAppendDelimStrImpl(const Delimiter& delim, const T& v, const Ts&... vs) {
844   // we are really careful here, calling toAppend with just one element does
845   // not try to estimate space needed (as we already did that). If we call
846   // toAppend(v, delim, ....) we would do unnecesary size calculation
847   toAppend(v, detail::getLastElement(vs...));
848   toAppend(delim, detail::getLastElement(vs...));
849   toAppendDelimStrImpl(delim, vs...);
850 }
851 } // namespace detail
852
853 /**
854  * Variadic conversion to string. Appends each element in turn.
855  * If we have two or more things to append, we it will not reserve
856  * the space for them and will depend on strings exponential growth.
857  * If you just append once consider using toAppendFit which reserves
858  * the space needed (but does not have exponential as a result).
859  *
860  * Custom implementations of toAppend() can be provided in the same namespace as
861  * the type to customize printing. estimateSpaceNeed() may also be provided to
862  * avoid reallocations in toAppendFit():
863  *
864  * namespace other_namespace {
865  *
866  * template <class String>
867  * void toAppend(const OtherType&, String* out);
868  *
869  * // optional
870  * size_t estimateSpaceNeeded(const OtherType&);
871  *
872  * }
873  */
874 template <class... Ts>
875 typename std::enable_if<
876     sizeof...(Ts) >= 3 &&
877     IsSomeString<typename std::remove_pointer<
878         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
879 toAppend(const Ts&... vs) {
880   ::folly::detail::toAppendStrImpl(vs...);
881 }
882
883 #ifdef _MSC_VER
884 // Special case pid_t on MSVC, because it's a void* rather than an
885 // integral type. We can't do a global special case because this is already
886 // dangerous enough (as most pointers will implicitly convert to a void*)
887 // just doing it for MSVC.
888 template <class Tgt>
889 void toAppend(const pid_t a, Tgt* res) {
890   toAppend(uint64_t(a), res);
891 }
892 #endif
893
894 /**
895  * Special version of the call that preallocates exaclty as much memory
896  * as need for arguments to be stored in target. This means we are
897  * not doing exponential growth when we append. If you are using it
898  * in a loop you are aiming at your foot with a big perf-destroying
899  * bazooka.
900  * On the other hand if you are appending to a string once, this
901  * will probably save a few calls to malloc.
902  */
903 template <class... Ts>
904 typename std::enable_if<IsSomeString<typename std::remove_pointer<
905     typename detail::LastElement<const Ts&...>::type>::type>::value>::type
906 toAppendFit(const Ts&... vs) {
907   ::folly::detail::reserveInTarget(vs...);
908   toAppend(vs...);
909 }
910
911 template <class Ts>
912 void toAppendFit(const Ts&) {}
913
914 /**
915  * Variadic base case: do nothing.
916  */
917 template <class Tgt>
918 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppend(
919     Tgt* /* result */) {}
920
921 /**
922  * Variadic base case: do nothing.
923  */
924 template <class Delimiter, class Tgt>
925 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppendDelim(
926     const Delimiter& /* delim */, Tgt* /* result */) {}
927
928 /**
929  * 1 element: same as toAppend.
930  */
931 template <class Delimiter, class T, class Tgt>
932 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppendDelim(
933     const Delimiter& /* delim */, const T& v, Tgt* tgt) {
934   toAppend(v, tgt);
935 }
936
937 /**
938  * Append to string with a delimiter in between elements. Check out
939  * comments for toAppend for details about memory allocation.
940  */
941 template <class Delimiter, class... Ts>
942 typename std::enable_if<
943     sizeof...(Ts) >= 3 &&
944     IsSomeString<typename std::remove_pointer<
945         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
946 toAppendDelim(const Delimiter& delim, const Ts&... vs) {
947   detail::toAppendDelimStrImpl(delim, vs...);
948 }
949
950 /**
951  * Detail in comment for toAppendFit
952  */
953 template <class Delimiter, class... Ts>
954 typename std::enable_if<IsSomeString<typename std::remove_pointer<
955     typename detail::LastElement<const Ts&...>::type>::type>::value>::type
956 toAppendDelimFit(const Delimiter& delim, const Ts&... vs) {
957   detail::reserveInTargetDelim(delim, vs...);
958   toAppendDelim(delim, vs...);
959 }
960
961 template <class De, class Ts>
962 void toAppendDelimFit(const De&, const Ts&) {}
963
964 /**
965  * to<SomeString>(v1, v2, ...) uses toAppend() (see below) as back-end
966  * for all types.
967  */
968 template <class Tgt, class... Ts>
969 typename std::enable_if<
970     IsSomeString<Tgt>::value &&
971         (sizeof...(Ts) != 1 ||
972          !std::is_same<Tgt, typename detail::LastElement<const Ts&...>::type>::
973              value),
974     Tgt>::type
975 to(const Ts&... vs) {
976   Tgt result;
977   toAppendFit(vs..., &result);
978   return result;
979 }
980
981 /**
982  * Special version of to<SomeString> for floating point. When calling
983  * folly::to<SomeString>(double), generic implementation above will
984  * firstly reserve 24 (or 25 when negative value) bytes. This will
985  * introduce a malloc call for most mainstream string implementations.
986  *
987  * But for most cases, a floating point doesn't need 24 (or 25) bytes to
988  * be converted as a string.
989  *
990  * This special version will not do string reserve.
991  */
992 template <class Tgt, class Src>
993 typename std::enable_if<
994     IsSomeString<Tgt>::value && std::is_floating_point<Src>::value,
995     Tgt>::type
996 to(Src value) {
997   Tgt result;
998   toAppend(value, &result);
999   return result;
1000 }
1001
1002 /**
1003  * toDelim<SomeString>(SomeString str) returns itself.
1004  */
1005 template <class Tgt, class Delim, class Src>
1006 typename std::enable_if<
1007     IsSomeString<Tgt>::value &&
1008         std::is_same<Tgt, typename std::decay<Src>::type>::value,
1009     Tgt>::type
1010 toDelim(const Delim& /* delim */, Src&& value) {
1011   return std::forward<Src>(value);
1012 }
1013
1014 /**
1015  * toDelim<SomeString>(delim, v1, v2, ...) uses toAppendDelim() as
1016  * back-end for all types.
1017  */
1018 template <class Tgt, class Delim, class... Ts>
1019 typename std::enable_if<
1020     IsSomeString<Tgt>::value &&
1021         (sizeof...(Ts) != 1 ||
1022          !std::is_same<Tgt, typename detail::LastElement<const Ts&...>::type>::
1023              value),
1024     Tgt>::type
1025 toDelim(const Delim& delim, const Ts&... vs) {
1026   Tgt result;
1027   toAppendDelimFit(delim, vs..., &result);
1028   return result;
1029 }
1030
1031 /*******************************************************************************
1032  * Conversions from string types to integral types.
1033  ******************************************************************************/
1034
1035 namespace detail {
1036
1037 Expected<bool, ConversionCode> str_to_bool(StringPiece* src) noexcept;
1038
1039 template <typename T>
1040 Expected<T, ConversionCode> str_to_floating(StringPiece* src) noexcept;
1041
1042 extern template Expected<float, ConversionCode> str_to_floating<float>(
1043     StringPiece* src) noexcept;
1044 extern template Expected<double, ConversionCode> str_to_floating<double>(
1045     StringPiece* src) noexcept;
1046
1047 template <class Tgt>
1048 Expected<Tgt, ConversionCode> digits_to(const char* b, const char* e) noexcept;
1049
1050 extern template Expected<char, ConversionCode> digits_to<char>(
1051     const char*,
1052     const char*) noexcept;
1053 extern template Expected<signed char, ConversionCode> digits_to<signed char>(
1054     const char*,
1055     const char*) noexcept;
1056 extern template Expected<unsigned char, ConversionCode>
1057 digits_to<unsigned char>(const char*, const char*) noexcept;
1058
1059 extern template Expected<short, ConversionCode> digits_to<short>(
1060     const char*,
1061     const char*) noexcept;
1062 extern template Expected<unsigned short, ConversionCode>
1063 digits_to<unsigned short>(const char*, const char*) noexcept;
1064
1065 extern template Expected<int, ConversionCode> digits_to<int>(
1066     const char*,
1067     const char*) noexcept;
1068 extern template Expected<unsigned int, ConversionCode> digits_to<unsigned int>(
1069     const char*,
1070     const char*) noexcept;
1071
1072 extern template Expected<long, ConversionCode> digits_to<long>(
1073     const char*,
1074     const char*) noexcept;
1075 extern template Expected<unsigned long, ConversionCode>
1076 digits_to<unsigned long>(const char*, const char*) noexcept;
1077
1078 extern template Expected<long long, ConversionCode> digits_to<long long>(
1079     const char*,
1080     const char*) noexcept;
1081 extern template Expected<unsigned long long, ConversionCode>
1082 digits_to<unsigned long long>(const char*, const char*) noexcept;
1083
1084 #if FOLLY_HAVE_INT128_T
1085 extern template Expected<__int128, ConversionCode> digits_to<__int128>(
1086     const char*,
1087     const char*) noexcept;
1088 extern template Expected<unsigned __int128, ConversionCode>
1089 digits_to<unsigned __int128>(const char*, const char*) noexcept;
1090 #endif
1091
1092 template <class T>
1093 Expected<T, ConversionCode> str_to_integral(StringPiece* src) noexcept;
1094
1095 extern template Expected<char, ConversionCode> str_to_integral<char>(
1096     StringPiece* src) noexcept;
1097 extern template Expected<signed char, ConversionCode>
1098 str_to_integral<signed char>(StringPiece* src) noexcept;
1099 extern template Expected<unsigned char, ConversionCode>
1100 str_to_integral<unsigned char>(StringPiece* src) noexcept;
1101
1102 extern template Expected<short, ConversionCode> str_to_integral<short>(
1103     StringPiece* src) noexcept;
1104 extern template Expected<unsigned short, ConversionCode>
1105 str_to_integral<unsigned short>(StringPiece* src) noexcept;
1106
1107 extern template Expected<int, ConversionCode> str_to_integral<int>(
1108     StringPiece* src) noexcept;
1109 extern template Expected<unsigned int, ConversionCode>
1110 str_to_integral<unsigned int>(StringPiece* src) noexcept;
1111
1112 extern template Expected<long, ConversionCode> str_to_integral<long>(
1113     StringPiece* src) noexcept;
1114 extern template Expected<unsigned long, ConversionCode>
1115 str_to_integral<unsigned long>(StringPiece* src) noexcept;
1116
1117 extern template Expected<long long, ConversionCode> str_to_integral<long long>(
1118     StringPiece* src) noexcept;
1119 extern template Expected<unsigned long long, ConversionCode>
1120 str_to_integral<unsigned long long>(StringPiece* src) noexcept;
1121
1122 #if FOLLY_HAVE_INT128_T
1123 extern template Expected<__int128, ConversionCode> str_to_integral<__int128>(
1124     StringPiece* src) noexcept;
1125 extern template Expected<unsigned __int128, ConversionCode>
1126 str_to_integral<unsigned __int128>(StringPiece* src) noexcept;
1127 #endif
1128
1129 template <typename T>
1130 typename std::
1131     enable_if<std::is_same<T, bool>::value, Expected<T, ConversionCode>>::type
1132     convertTo(StringPiece* src) noexcept {
1133   return str_to_bool(src);
1134 }
1135
1136 template <typename T>
1137 typename std::enable_if<
1138     std::is_floating_point<T>::value,
1139     Expected<T, ConversionCode>>::type
1140 convertTo(StringPiece* src) noexcept {
1141   return str_to_floating<T>(src);
1142 }
1143
1144 template <typename T>
1145 typename std::enable_if<
1146     std::is_integral<T>::value && !std::is_same<T, bool>::value,
1147     Expected<T, ConversionCode>>::type
1148 convertTo(StringPiece* src) noexcept {
1149   return str_to_integral<T>(src);
1150 }
1151
1152 } // namespace detail
1153
1154 /**
1155  * String represented as a pair of pointers to char to unsigned
1156  * integrals. Assumes NO whitespace before or after.
1157  */
1158 template <typename Tgt>
1159 typename std::enable_if<
1160     std::is_integral<Tgt>::value && !std::is_same<Tgt, bool>::value,
1161     Expected<Tgt, ConversionCode>>::type
1162 tryTo(const char* b, const char* e) {
1163   return detail::digits_to<Tgt>(b, e);
1164 }
1165
1166 template <typename Tgt>
1167 typename std::enable_if<
1168     std::is_integral<Tgt>::value && !std::is_same<Tgt, bool>::value,
1169     Tgt>::type
1170 to(const char* b, const char* e) {
1171   return tryTo<Tgt>(b, e).thenOrThrow(
1172       [](Tgt res) { return res; },
1173       [=](ConversionCode code) {
1174         return makeConversionError(code, StringPiece(b, e));
1175       });
1176 }
1177
1178 /*******************************************************************************
1179  * Conversions from string types to arithmetic types.
1180  ******************************************************************************/
1181
1182 /**
1183  * Parsing strings to numeric types.
1184  */
1185 template <typename Tgt>
1186 FOLLY_NODISCARD inline typename std::enable_if<
1187     std::is_arithmetic<Tgt>::value,
1188     Expected<StringPiece, ConversionCode>>::type
1189 parseTo(StringPiece src, Tgt& out) {
1190   return detail::convertTo<Tgt>(&src).then(
1191       [&](Tgt res) { return void(out = res), src; });
1192 }
1193
1194 /*******************************************************************************
1195  * Integral / Floating Point to integral / Floating Point
1196  ******************************************************************************/
1197
1198 namespace detail {
1199
1200 /**
1201  * Bool to integral/float doesn't need any special checks, and this
1202  * overload means we aren't trying to see if a bool is less than
1203  * an integer.
1204  */
1205 template <class Tgt>
1206 typename std::enable_if<
1207     !std::is_same<Tgt, bool>::value &&
1208         (std::is_integral<Tgt>::value || std::is_floating_point<Tgt>::value),
1209     Expected<Tgt, ConversionCode>>::type
1210 convertTo(const bool& value) noexcept {
1211   return static_cast<Tgt>(value ? 1 : 0);
1212 }
1213
1214 /**
1215  * Checked conversion from integral to integral. The checks are only
1216  * performed when meaningful, e.g. conversion from int to long goes
1217  * unchecked.
1218  */
1219 template <class Tgt, class Src>
1220 typename std::enable_if<
1221     std::is_integral<Src>::value && !std::is_same<Tgt, Src>::value &&
1222         !std::is_same<Tgt, bool>::value &&
1223         std::is_integral<Tgt>::value,
1224     Expected<Tgt, ConversionCode>>::type
1225 convertTo(const Src& value) noexcept {
1226   /* static */ if (
1227       folly::_t<std::make_unsigned<Tgt>>(std::numeric_limits<Tgt>::max()) <
1228       folly::_t<std::make_unsigned<Src>>(std::numeric_limits<Src>::max())) {
1229     if (greater_than<Tgt, std::numeric_limits<Tgt>::max()>(value)) {
1230       return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
1231     }
1232   }
1233   /* static */ if (
1234       std::is_signed<Src>::value &&
1235       (!std::is_signed<Tgt>::value || sizeof(Src) > sizeof(Tgt))) {
1236     if (less_than<Tgt, std::numeric_limits<Tgt>::min()>(value)) {
1237       return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
1238     }
1239   }
1240   return static_cast<Tgt>(value);
1241 }
1242
1243 /**
1244  * Checked conversion from floating to floating. The checks are only
1245  * performed when meaningful, e.g. conversion from float to double goes
1246  * unchecked.
1247  */
1248 template <class Tgt, class Src>
1249 typename std::enable_if<
1250     std::is_floating_point<Tgt>::value && std::is_floating_point<Src>::value &&
1251         !std::is_same<Tgt, Src>::value,
1252     Expected<Tgt, ConversionCode>>::type
1253 convertTo(const Src& value) noexcept {
1254   /* static */ if (
1255       std::numeric_limits<Tgt>::max() < std::numeric_limits<Src>::max()) {
1256     if (value > std::numeric_limits<Tgt>::max()) {
1257       return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
1258     }
1259     if (value < std::numeric_limits<Tgt>::lowest()) {
1260       return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
1261     }
1262   }
1263   return static_cast<Tgt>(value);
1264 }
1265
1266 /**
1267  * Check if a floating point value can safely be converted to an
1268  * integer value without triggering undefined behaviour.
1269  */
1270 template <typename Tgt, typename Src>
1271 inline typename std::enable_if<
1272     std::is_floating_point<Src>::value && std::is_integral<Tgt>::value &&
1273         !std::is_same<Tgt, bool>::value,
1274     bool>::type
1275 checkConversion(const Src& value) {
1276   constexpr Src tgtMaxAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::max());
1277   constexpr Src tgtMinAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::min());
1278   if (value >= tgtMaxAsSrc) {
1279     if (value > tgtMaxAsSrc) {
1280       return false;
1281     }
1282     const Src mmax = folly::nextafter(tgtMaxAsSrc, Src());
1283     if (static_cast<Tgt>(value - mmax) >
1284         std::numeric_limits<Tgt>::max() - static_cast<Tgt>(mmax)) {
1285       return false;
1286     }
1287   } else if (std::is_signed<Tgt>::value && value <= tgtMinAsSrc) {
1288     if (value < tgtMinAsSrc) {
1289       return false;
1290     }
1291     const Src mmin = folly::nextafter(tgtMinAsSrc, Src());
1292     if (static_cast<Tgt>(value - mmin) <
1293         std::numeric_limits<Tgt>::min() - static_cast<Tgt>(mmin)) {
1294       return false;
1295     }
1296   }
1297   return true;
1298 }
1299
1300 // Integers can always safely be converted to floating point values
1301 template <typename Tgt, typename Src>
1302 constexpr typename std::enable_if<
1303     std::is_integral<Src>::value && std::is_floating_point<Tgt>::value,
1304     bool>::type
1305 checkConversion(const Src&) {
1306   return true;
1307 }
1308
1309 // Also, floating point values can always be safely converted to bool
1310 // Per the standard, any floating point value that is not zero will yield true
1311 template <typename Tgt, typename Src>
1312 constexpr typename std::enable_if<
1313     std::is_floating_point<Src>::value && std::is_same<Tgt, bool>::value,
1314     bool>::type
1315 checkConversion(const Src&) {
1316   return true;
1317 }
1318
1319 /**
1320  * Checked conversion from integral to floating point and back. The
1321  * result must be convertible back to the source type without loss of
1322  * precision. This seems Draconian but sometimes is what's needed, and
1323  * complements existing routines nicely. For various rounding
1324  * routines, see <math>.
1325  */
1326 template <typename Tgt, typename Src>
1327 typename std::enable_if<
1328     (std::is_integral<Src>::value && std::is_floating_point<Tgt>::value) ||
1329         (std::is_floating_point<Src>::value && std::is_integral<Tgt>::value),
1330     Expected<Tgt, ConversionCode>>::type
1331 convertTo(const Src& value) noexcept {
1332   if (LIKELY(checkConversion<Tgt>(value))) {
1333     Tgt result = static_cast<Tgt>(value);
1334     if (LIKELY(checkConversion<Src>(result))) {
1335       Src witness = static_cast<Src>(result);
1336       if (LIKELY(value == witness)) {
1337         return result;
1338       }
1339     }
1340   }
1341   return makeUnexpected(ConversionCode::ARITH_LOSS_OF_PRECISION);
1342 }
1343
1344 template <typename Tgt, typename Src>
1345 inline std::string errorValue(const Src& value) {
1346 #ifdef FOLLY_HAS_RTTI
1347   return to<std::string>("(", demangle(typeid(Tgt)), ") ", value);
1348 #else
1349   return to<std::string>(value);
1350 #endif
1351 }
1352
1353 template <typename Tgt, typename Src>
1354 using IsArithToArith = std::integral_constant<
1355     bool,
1356     !std::is_same<Tgt, Src>::value && !std::is_same<Tgt, bool>::value &&
1357         std::is_arithmetic<Src>::value &&
1358         std::is_arithmetic<Tgt>::value>;
1359
1360 } // namespace detail
1361
1362 template <typename Tgt, typename Src>
1363 typename std::enable_if<
1364     detail::IsArithToArith<Tgt, Src>::value,
1365     Expected<Tgt, ConversionCode>>::type
1366 tryTo(const Src& value) noexcept {
1367   return detail::convertTo<Tgt>(value);
1368 }
1369
1370 template <typename Tgt, typename Src>
1371 typename std::enable_if<detail::IsArithToArith<Tgt, Src>::value, Tgt>::type to(
1372     const Src& value) {
1373   return tryTo<Tgt>(value).thenOrThrow(
1374       [](Tgt res) { return res; },
1375       [&](ConversionCode e) {
1376         return makeConversionError(e, detail::errorValue<Tgt>(value));
1377       });
1378 }
1379
1380 /*******************************************************************************
1381  * Custom Conversions
1382  *
1383  * Any type can be used with folly::to by implementing parseTo. The
1384  * implementation should be provided in the namespace of the type to facilitate
1385  * argument-dependent lookup:
1386  *
1387  * namespace other_namespace {
1388  * ::folly::Expected<::folly::StringPiece, SomeErrorCode>
1389  *   parseTo(::folly::StringPiece, OtherType&) noexcept;
1390  * }
1391  ******************************************************************************/
1392 template <class T>
1393 FOLLY_NODISCARD typename std::enable_if<
1394     std::is_enum<T>::value,
1395     Expected<StringPiece, ConversionCode>>::type
1396 parseTo(StringPiece in, T& out) noexcept {
1397   typename std::underlying_type<T>::type tmp{};
1398   auto restOrError = parseTo(in, tmp);
1399   out = static_cast<T>(tmp); // Harmless if parseTo fails
1400   return restOrError;
1401 }
1402
1403 FOLLY_NODISCARD
1404 inline Expected<StringPiece, ConversionCode> parseTo(
1405     StringPiece in,
1406     StringPiece& out) noexcept {
1407   out = in;
1408   return StringPiece{in.end(), in.end()};
1409 }
1410
1411 FOLLY_NODISCARD
1412 inline Expected<StringPiece, ConversionCode> parseTo(
1413     StringPiece in,
1414     std::string& out) {
1415   out.clear();
1416   out.append(in.data(), in.size()); // TODO try/catch?
1417   return StringPiece{in.end(), in.end()};
1418 }
1419
1420 FOLLY_NODISCARD
1421 inline Expected<StringPiece, ConversionCode> parseTo(
1422     StringPiece in,
1423     fbstring& out) {
1424   out.clear();
1425   out.append(in.data(), in.size()); // TODO try/catch?
1426   return StringPiece{in.end(), in.end()};
1427 }
1428
1429 namespace detail {
1430 template <typename Tgt>
1431 using ParseToResult = decltype(parseTo(StringPiece{}, std::declval<Tgt&>()));
1432
1433 struct CheckTrailingSpace {
1434   Expected<Unit, ConversionCode> operator()(StringPiece sp) const {
1435     auto e = enforceWhitespaceErr(sp);
1436     if (UNLIKELY(e != ConversionCode::SUCCESS)) {
1437       return makeUnexpected(e);
1438     }
1439     return unit;
1440   }
1441 };
1442
1443 template <class Error>
1444 struct ReturnUnit {
1445   template <class T>
1446   constexpr Expected<Unit, Error> operator()(T&&) const {
1447     return unit;
1448   }
1449 };
1450
1451 // Older versions of the parseTo customization point threw on error and
1452 // returned void. Handle that.
1453 template <class Tgt>
1454 inline typename std::enable_if<
1455     std::is_void<ParseToResult<Tgt>>::value,
1456     Expected<StringPiece, ConversionCode>>::type
1457 parseToWrap(StringPiece sp, Tgt& out) {
1458   parseTo(sp, out);
1459   return StringPiece(sp.end(), sp.end());
1460 }
1461
1462 template <class Tgt>
1463 inline typename std::enable_if<
1464     !std::is_void<ParseToResult<Tgt>>::value,
1465     ParseToResult<Tgt>>::type
1466 parseToWrap(StringPiece sp, Tgt& out) {
1467   return parseTo(sp, out);
1468 }
1469
1470 template <typename Tgt>
1471 using ParseToError = ExpectedErrorType<decltype(
1472     detail::parseToWrap(StringPiece{}, std::declval<Tgt&>()))>;
1473
1474 } // namespace detail
1475
1476 /**
1477  * String or StringPiece to target conversion. Accepts leading and trailing
1478  * whitespace, but no non-space trailing characters.
1479  */
1480
1481 template <class Tgt>
1482 inline typename std::enable_if<
1483     !std::is_same<StringPiece, Tgt>::value,
1484     Expected<Tgt, detail::ParseToError<Tgt>>>::type
1485 tryTo(StringPiece src) {
1486   Tgt result{};
1487   using Error = detail::ParseToError<Tgt>;
1488   using Check = typename std::conditional<
1489       std::is_arithmetic<Tgt>::value,
1490       detail::CheckTrailingSpace,
1491       detail::ReturnUnit<Error>>::type;
1492   return parseTo(src, result).then(Check(), [&](Unit) {
1493     return std::move(result);
1494   });
1495 }
1496
1497 template <class Tgt, class Src>
1498 inline typename std::enable_if<
1499     IsSomeString<Src>::value && !std::is_same<StringPiece, Tgt>::value,
1500     Tgt>::type
1501 to(Src const& src) {
1502   return to<Tgt>(StringPiece(src.data(), src.size()));
1503 }
1504
1505 template <class Tgt>
1506 inline
1507     typename std::enable_if<!std::is_same<StringPiece, Tgt>::value, Tgt>::type
1508     to(StringPiece src) {
1509   Tgt result{};
1510   using Error = detail::ParseToError<Tgt>;
1511   using Check = typename std::conditional<
1512       std::is_arithmetic<Tgt>::value,
1513       detail::CheckTrailingSpace,
1514       detail::ReturnUnit<Error>>::type;
1515   auto tmp = detail::parseToWrap(src, result);
1516   return tmp
1517       .thenOrThrow(Check(), [&](Error e) { throw makeConversionError(e, src); })
1518       .thenOrThrow(
1519           [&](Unit) { return std::move(result); },
1520           [&](Error e) { throw makeConversionError(e, tmp.value()); });
1521 }
1522
1523 /**
1524  * tryTo/to that take the strings by pointer so the caller gets information
1525  * about how much of the string was consumed by the conversion. These do not
1526  * check for trailing whitepsace.
1527  */
1528 template <class Tgt>
1529 Expected<Tgt, detail::ParseToError<Tgt>> tryTo(StringPiece* src) {
1530   Tgt result;
1531   return parseTo(*src, result).then([&, src](StringPiece sp) -> Tgt {
1532     *src = sp;
1533     return std::move(result);
1534   });
1535 }
1536
1537 template <class Tgt>
1538 Tgt to(StringPiece* src) {
1539   Tgt result{};
1540   using Error = detail::ParseToError<Tgt>;
1541   return parseTo(*src, result)
1542       .thenOrThrow(
1543           [&, src](StringPiece sp) -> Tgt {
1544             *src = sp;
1545             return std::move(result);
1546           },
1547           [=](Error e) { return makeConversionError(e, *src); });
1548 }
1549
1550 /*******************************************************************************
1551  * Enum to anything and back
1552  ******************************************************************************/
1553
1554 template <class Tgt, class Src>
1555 typename std::enable_if<
1556     std::is_enum<Src>::value && !std::is_same<Src, Tgt>::value &&
1557         !std::is_convertible<Tgt, StringPiece>::value,
1558     Expected<Tgt, ConversionCode>>::type
1559 tryTo(const Src& value) {
1560   using I = typename std::underlying_type<Src>::type;
1561   return tryTo<Tgt>(static_cast<I>(value));
1562 }
1563
1564 template <class Tgt, class Src>
1565 typename std::enable_if<
1566     !std::is_convertible<Src, StringPiece>::valuea &&
1567         std::is_enum<Tgt>::value && !std::is_same<Src, Tgt>::value,
1568     Expected<Tgt, ConversionCode>>::type
1569 tryTo(const Src& value) {
1570   using I = typename std::underlying_type<Tgt>::type;
1571   return tryTo<I>(value).then([](I i) { return static_cast<Tgt>(i); });
1572 }
1573
1574 template <class Tgt, class Src>
1575 typename std::enable_if<
1576     std::is_enum<Src>::value && !std::is_same<Src, Tgt>::value &&
1577         !std::is_convertible<Tgt, StringPiece>::value,
1578     Tgt>::type
1579 to(const Src& value) {
1580   return to<Tgt>(static_cast<typename std::underlying_type<Src>::type>(value));
1581 }
1582
1583 template <class Tgt, class Src>
1584 typename std::enable_if<
1585     !std::is_convertible<Src, StringPiece>::value && std::is_enum<Tgt>::value &&
1586         !std::is_same<Src, Tgt>::value,
1587     Tgt>::type
1588 to(const Src& value) {
1589   return static_cast<Tgt>(to<typename std::underlying_type<Tgt>::type>(value));
1590 }
1591
1592 } // namespace folly