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