logging: make XLOG_GET_CATEGORY() safe for all callers
[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 <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<char>(v % 10);
387     buffer[pos--] = '0' + r;
388     v = q;
389   }
390   // Last digit is trivial to handle
391   buffer[pos] = static_cast<char>(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(
561         buffer,
562         uint64ToBufferUnsafe(~static_cast<uint64_t>(value) + 1, buffer));
563   } else {
564     result->append(buffer, uint64ToBufferUnsafe(uint64_t(value), buffer));
565   }
566 }
567
568 template <class Src>
569 typename std::enable_if<
570   std::is_integral<Src>::value && std::is_signed<Src>::value
571   && sizeof(Src) >= 4 && sizeof(Src) < 16,
572   size_t>::type
573 estimateSpaceNeeded(Src value) {
574   if (value < 0) {
575     // When "value" is the smallest negative, negating it would evoke
576     // undefined behavior, so, instead of writing "-value" below, we write
577     // "~static_cast<uint64_t>(value) + 1"
578     return 1 + digits10(~static_cast<uint64_t>(value) + 1);
579   }
580
581   return digits10(static_cast<uint64_t>(value));
582 }
583
584 /**
585  * As above, but for uint32_t and uint64_t.
586  */
587 template <class Tgt, class Src>
588 typename std::enable_if<
589   std::is_integral<Src>::value && !std::is_signed<Src>::value
590   && IsSomeString<Tgt>::value && sizeof(Src) >= 4>::type
591 toAppend(Src value, Tgt * result) {
592   char buffer[20];
593   result->append(buffer, uint64ToBufferUnsafe(value, buffer));
594 }
595
596 template <class Src>
597 typename std::enable_if<
598   std::is_integral<Src>::value && !std::is_signed<Src>::value
599   && sizeof(Src) >= 4 && sizeof(Src) < 16,
600   size_t>::type
601 estimateSpaceNeeded(Src value) {
602   return digits10(value);
603 }
604
605 /**
606  * All small signed and unsigned integers to string go through 32-bit
607  * types int32_t and uint32_t, respectively.
608  */
609 template <class Tgt, class Src>
610 typename std::enable_if<
611   std::is_integral<Src>::value
612   && IsSomeString<Tgt>::value && sizeof(Src) < 4>::type
613 toAppend(Src value, Tgt * result) {
614   typedef typename
615     std::conditional<std::is_signed<Src>::value, int64_t, uint64_t>::type
616     Intermediate;
617   toAppend<Tgt>(static_cast<Intermediate>(value), result);
618 }
619
620 template <class Src>
621 typename std::enable_if<
622   std::is_integral<Src>::value
623   && sizeof(Src) < 4
624   && !std::is_same<Src, char>::value,
625   size_t>::type
626 estimateSpaceNeeded(Src value) {
627   typedef typename
628     std::conditional<std::is_signed<Src>::value, int64_t, uint64_t>::type
629     Intermediate;
630   return estimateSpaceNeeded(static_cast<Intermediate>(value));
631 }
632
633 /**
634  * Enumerated values get appended as integers.
635  */
636 template <class Tgt, class Src>
637 typename std::enable_if<
638   std::is_enum<Src>::value && IsSomeString<Tgt>::value>::type
639 toAppend(Src value, Tgt * result) {
640   toAppend(
641       static_cast<typename std::underlying_type<Src>::type>(value), result);
642 }
643
644 template <class Src>
645 typename std::enable_if<
646   std::is_enum<Src>::value, size_t>::type
647 estimateSpaceNeeded(Src value) {
648   return estimateSpaceNeeded(
649       static_cast<typename std::underlying_type<Src>::type>(value));
650 }
651
652 /*******************************************************************************
653  * Conversions from floating-point types to string types.
654  ******************************************************************************/
655
656 namespace detail {
657 constexpr int kConvMaxDecimalInShortestLow = -6;
658 constexpr int kConvMaxDecimalInShortestHigh = 21;
659 } // folly::detail
660
661 /** Wrapper around DoubleToStringConverter **/
662 template <class Tgt, class Src>
663 typename std::enable_if<
664   std::is_floating_point<Src>::value
665   && IsSomeString<Tgt>::value>::type
666 toAppend(
667   Src value,
668   Tgt * result,
669   double_conversion::DoubleToStringConverter::DtoaMode mode,
670   unsigned int numDigits) {
671   using namespace double_conversion;
672   DoubleToStringConverter
673     conv(DoubleToStringConverter::NO_FLAGS,
674          "Infinity", "NaN", 'E',
675          detail::kConvMaxDecimalInShortestLow,
676          detail::kConvMaxDecimalInShortestHigh,
677          6,   // max leading padding zeros
678          1);  // max trailing padding zeros
679   char buffer[256];
680   StringBuilder builder(buffer, sizeof(buffer));
681   switch (mode) {
682     case DoubleToStringConverter::SHORTEST:
683       conv.ToShortest(value, &builder);
684       break;
685     case DoubleToStringConverter::FIXED:
686       conv.ToFixed(value, int(numDigits), &builder);
687       break;
688     default:
689       CHECK(mode == DoubleToStringConverter::PRECISION);
690       conv.ToPrecision(value, int(numDigits), &builder);
691       break;
692   }
693   const size_t length = size_t(builder.position());
694   builder.Finalize();
695   result->append(buffer, length);
696 }
697
698 /**
699  * As above, but for floating point
700  */
701 template <class Tgt, class Src>
702 typename std::enable_if<
703   std::is_floating_point<Src>::value
704   && IsSomeString<Tgt>::value>::type
705 toAppend(Src value, Tgt * result) {
706   toAppend(
707     value, result, double_conversion::DoubleToStringConverter::SHORTEST, 0);
708 }
709
710 /**
711  * Upper bound of the length of the output from
712  * DoubleToStringConverter::ToShortest(double, StringBuilder*),
713  * as used in toAppend(double, string*).
714  */
715 template <class Src>
716 typename std::enable_if<
717   std::is_floating_point<Src>::value, size_t>::type
718 estimateSpaceNeeded(Src value) {
719   // kBase10MaximalLength is 17. We add 1 for decimal point,
720   // e.g. 10.0/9 is 17 digits and 18 characters, including the decimal point.
721   constexpr int kMaxMantissaSpace =
722     double_conversion::DoubleToStringConverter::kBase10MaximalLength + 1;
723   // strlen("E-") + digits10(numeric_limits<double>::max_exponent10)
724   constexpr int kMaxExponentSpace = 2 + 3;
725   static const int kMaxPositiveSpace = std::max({
726       // E.g. 1.1111111111111111E-100.
727       kMaxMantissaSpace + kMaxExponentSpace,
728       // E.g. 0.000001.1111111111111111, if kConvMaxDecimalInShortestLow is -6.
729       kMaxMantissaSpace - detail::kConvMaxDecimalInShortestLow,
730       // If kConvMaxDecimalInShortestHigh is 21, then 1e21 is the smallest
731       // number > 1 which ToShortest outputs in exponential notation,
732       // so 21 is the longest non-exponential number > 1.
733       detail::kConvMaxDecimalInShortestHigh
734     });
735   return size_t(
736       kMaxPositiveSpace +
737       (value < 0 ? 1 : 0)); // +1 for minus sign, if negative
738 }
739
740 /**
741  * This can be specialized, together with adding specialization
742  * for estimateSpaceNeed for your type, so that we allocate
743  * as much as you need instead of the default
744  */
745 template<class Src>
746 struct HasLengthEstimator : std::false_type {};
747
748 template <class Src>
749 constexpr typename std::enable_if<
750   !std::is_fundamental<Src>::value
751 #if FOLLY_HAVE_INT128_T
752   // On OSX 10.10, is_fundamental<__int128> is false :-O
753   && !std::is_same<__int128, Src>::value
754   && !std::is_same<unsigned __int128, Src>::value
755 #endif
756   && !IsSomeString<Src>::value
757   && !std::is_convertible<Src, const char*>::value
758   && !std::is_convertible<Src, StringPiece>::value
759   && !std::is_enum<Src>::value
760   && !HasLengthEstimator<Src>::value,
761   size_t>::type
762 estimateSpaceNeeded(const Src&) {
763   return sizeof(Src) + 1; // dumbest best effort ever?
764 }
765
766 namespace detail {
767
768 template <class Tgt>
769 typename std::enable_if<IsSomeString<Tgt>::value, size_t>::type
770 estimateSpaceToReserve(size_t sofar, Tgt*) {
771   return sofar;
772 }
773
774 template <class T, class... Ts>
775 size_t estimateSpaceToReserve(size_t sofar, const T& v, const Ts&... vs) {
776   return estimateSpaceToReserve(sofar + estimateSpaceNeeded(v), vs...);
777 }
778
779 template<class...Ts>
780 void reserveInTarget(const Ts&...vs) {
781   getLastElement(vs...)->reserve(estimateSpaceToReserve(0, vs...));
782 }
783
784 template<class Delimiter, class...Ts>
785 void reserveInTargetDelim(const Delimiter& d, const Ts&...vs) {
786   static_assert(sizeof...(vs) >= 2, "Needs at least 2 args");
787   size_t fordelim = (sizeof...(vs) - 2) *
788       estimateSpaceToReserve(0, d, static_cast<std::string*>(nullptr));
789   getLastElement(vs...)->reserve(estimateSpaceToReserve(fordelim, vs...));
790 }
791
792 /**
793  * Variadic base case: append one element
794  */
795 template <class T, class Tgt>
796 typename std::enable_if<
797   IsSomeString<typename std::remove_pointer<Tgt>::type>
798   ::value>::type
799 toAppendStrImpl(const T& v, Tgt result) {
800   toAppend(v, result);
801 }
802
803 template <class T, class... Ts>
804 typename std::enable_if<
805     sizeof...(Ts) >= 2 &&
806     IsSomeString<typename std::remove_pointer<
807         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
808 toAppendStrImpl(const T& v, const Ts&... vs) {
809   toAppend(v, getLastElement(vs...));
810   toAppendStrImpl(vs...);
811 }
812
813 template <class Delimiter, class T, class Tgt>
814 typename std::enable_if<
815     IsSomeString<typename std::remove_pointer<Tgt>::type>::value>::type
816 toAppendDelimStrImpl(const Delimiter& /* delim */, const T& v, Tgt result) {
817   toAppend(v, result);
818 }
819
820 template <class Delimiter, class T, class... Ts>
821 typename std::enable_if<
822     sizeof...(Ts) >= 2 &&
823     IsSomeString<typename std::remove_pointer<
824         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
825 toAppendDelimStrImpl(const Delimiter& delim, const T& v, const Ts&... vs) {
826   // we are really careful here, calling toAppend with just one element does
827   // not try to estimate space needed (as we already did that). If we call
828   // toAppend(v, delim, ....) we would do unnecesary size calculation
829   toAppend(v, detail::getLastElement(vs...));
830   toAppend(delim, detail::getLastElement(vs...));
831   toAppendDelimStrImpl(delim, vs...);
832 }
833 } // folly::detail
834
835
836 /**
837  * Variadic conversion to string. Appends each element in turn.
838  * If we have two or more things to append, we it will not reserve
839  * the space for them and will depend on strings exponential growth.
840  * If you just append once consider using toAppendFit which reserves
841  * the space needed (but does not have exponential as a result).
842  *
843  * Custom implementations of toAppend() can be provided in the same namespace as
844  * the type to customize printing. estimateSpaceNeed() may also be provided to
845  * avoid reallocations in toAppendFit():
846  *
847  * namespace other_namespace {
848  *
849  * template <class String>
850  * void toAppend(const OtherType&, String* out);
851  *
852  * // optional
853  * size_t estimateSpaceNeeded(const OtherType&);
854  *
855  * }
856  */
857 template <class... Ts>
858 typename std::enable_if<
859     sizeof...(Ts) >= 3 &&
860     IsSomeString<typename std::remove_pointer<
861         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
862 toAppend(const Ts&... vs) {
863   ::folly::detail::toAppendStrImpl(vs...);
864 }
865
866 #ifdef _MSC_VER
867 // Special case pid_t on MSVC, because it's a void* rather than an
868 // integral type. We can't do a global special case because this is already
869 // dangerous enough (as most pointers will implicitly convert to a void*)
870 // just doing it for MSVC.
871 template <class Tgt>
872 void toAppend(const pid_t a, Tgt* res) {
873   toAppend(uint64_t(a), res);
874 }
875 #endif
876
877 /**
878  * Special version of the call that preallocates exaclty as much memory
879  * as need for arguments to be stored in target. This means we are
880  * not doing exponential growth when we append. If you are using it
881  * in a loop you are aiming at your foot with a big perf-destroying
882  * bazooka.
883  * On the other hand if you are appending to a string once, this
884  * will probably save a few calls to malloc.
885  */
886 template <class... Ts>
887 typename std::enable_if<IsSomeString<typename std::remove_pointer<
888     typename detail::LastElement<const Ts&...>::type>::type>::value>::type
889 toAppendFit(const Ts&... vs) {
890   ::folly::detail::reserveInTarget(vs...);
891   toAppend(vs...);
892 }
893
894 template <class Ts>
895 void toAppendFit(const Ts&) {}
896
897 /**
898  * Variadic base case: do nothing.
899  */
900 template <class Tgt>
901 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppend(
902     Tgt* /* result */) {}
903
904 /**
905  * Variadic base case: do nothing.
906  */
907 template <class Delimiter, class Tgt>
908 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppendDelim(
909     const Delimiter& /* delim */, Tgt* /* result */) {}
910
911 /**
912  * 1 element: same as toAppend.
913  */
914 template <class Delimiter, class T, class Tgt>
915 typename std::enable_if<IsSomeString<Tgt>::value>::type toAppendDelim(
916     const Delimiter& /* delim */, const T& v, Tgt* tgt) {
917   toAppend(v, tgt);
918 }
919
920 /**
921  * Append to string with a delimiter in between elements. Check out
922  * comments for toAppend for details about memory allocation.
923  */
924 template <class Delimiter, class... Ts>
925 typename std::enable_if<
926     sizeof...(Ts) >= 3 &&
927     IsSomeString<typename std::remove_pointer<
928         typename detail::LastElement<const Ts&...>::type>::type>::value>::type
929 toAppendDelim(const Delimiter& delim, const Ts&... vs) {
930   detail::toAppendDelimStrImpl(delim, vs...);
931 }
932
933 /**
934  * Detail in comment for toAppendFit
935  */
936 template <class Delimiter, class... Ts>
937 typename std::enable_if<IsSomeString<typename std::remove_pointer<
938     typename detail::LastElement<const Ts&...>::type>::type>::value>::type
939 toAppendDelimFit(const Delimiter& delim, const Ts&... vs) {
940   detail::reserveInTargetDelim(delim, vs...);
941   toAppendDelim(delim, vs...);
942 }
943
944 template <class De, class Ts>
945 void toAppendDelimFit(const De&, const Ts&) {}
946
947 /**
948  * to<SomeString>(v1, v2, ...) uses toAppend() (see below) as back-end
949  * for all types.
950  */
951 template <class Tgt, class... Ts>
952 typename std::enable_if<
953     IsSomeString<Tgt>::value &&
954         (sizeof...(Ts) != 1 ||
955          !std::is_same<Tgt, typename detail::LastElement<const Ts&...>::type>::
956              value),
957     Tgt>::type
958 to(const Ts&... vs) {
959   Tgt result;
960   toAppendFit(vs..., &result);
961   return result;
962 }
963
964 /**
965  * Special version of to<SomeString> for floating point. When calling
966  * folly::to<SomeString>(double), generic implementation above will
967  * firstly reserve 24 (or 25 when negative value) bytes. This will
968  * introduce a malloc call for most mainstream string implementations.
969  *
970  * But for most cases, a floating point doesn't need 24 (or 25) bytes to
971  * be converted as a string.
972  *
973  * This special version will not do string reserve.
974  */
975 template <class Tgt, class Src>
976 typename std::enable_if<
977     IsSomeString<Tgt>::value && std::is_floating_point<Src>::value,
978     Tgt>::type
979 to(Src value) {
980   Tgt result;
981   toAppend(value, &result);
982   return result;
983 }
984
985 /**
986  * toDelim<SomeString>(SomeString str) returns itself.
987  */
988 template <class Tgt, class Delim, class Src>
989 typename std::enable_if<IsSomeString<Tgt>::value &&
990                             std::is_same<Tgt, Src>::value,
991                         Tgt>::type
992 toDelim(const Delim& /* delim */, const Src& value) {
993   return value;
994 }
995
996 /**
997  * toDelim<SomeString>(delim, v1, v2, ...) uses toAppendDelim() as
998  * back-end for all types.
999  */
1000 template <class Tgt, class Delim, class... Ts>
1001 typename std::enable_if<
1002     IsSomeString<Tgt>::value &&
1003         (sizeof...(Ts) != 1 ||
1004          !std::is_same<Tgt, typename detail::LastElement<const Ts&...>::type>::
1005              value),
1006     Tgt>::type
1007 toDelim(const Delim& delim, const Ts&... vs) {
1008   Tgt result;
1009   toAppendDelimFit(delim, vs..., &result);
1010   return result;
1011 }
1012
1013 /*******************************************************************************
1014  * Conversions from string types to integral types.
1015  ******************************************************************************/
1016
1017 namespace detail {
1018
1019 Expected<bool, ConversionCode> str_to_bool(StringPiece* src) noexcept;
1020
1021 template <typename T>
1022 Expected<T, ConversionCode> str_to_floating(StringPiece* src) noexcept;
1023
1024 extern template Expected<float, ConversionCode> str_to_floating<float>(
1025     StringPiece* src) noexcept;
1026 extern template Expected<double, ConversionCode> str_to_floating<double>(
1027     StringPiece* src) noexcept;
1028
1029 template <class Tgt>
1030 Expected<Tgt, ConversionCode> digits_to(const char* b, const char* e) noexcept;
1031
1032 extern template Expected<char, ConversionCode> digits_to<char>(
1033     const char*,
1034     const char*) noexcept;
1035 extern template Expected<signed char, ConversionCode> digits_to<signed char>(
1036     const char*,
1037     const char*) noexcept;
1038 extern template Expected<unsigned char, ConversionCode>
1039 digits_to<unsigned char>(const char*, const char*) noexcept;
1040
1041 extern template Expected<short, ConversionCode> digits_to<short>(
1042     const char*,
1043     const char*) noexcept;
1044 extern template Expected<unsigned short, ConversionCode>
1045 digits_to<unsigned short>(const char*, const char*) noexcept;
1046
1047 extern template Expected<int, ConversionCode> digits_to<int>(
1048     const char*,
1049     const char*) noexcept;
1050 extern template Expected<unsigned int, ConversionCode> digits_to<unsigned int>(
1051     const char*,
1052     const char*) noexcept;
1053
1054 extern template Expected<long, ConversionCode> digits_to<long>(
1055     const char*,
1056     const char*) noexcept;
1057 extern template Expected<unsigned long, ConversionCode>
1058 digits_to<unsigned long>(const char*, const char*) noexcept;
1059
1060 extern template Expected<long long, ConversionCode> digits_to<long long>(
1061     const char*,
1062     const char*) noexcept;
1063 extern template Expected<unsigned long long, ConversionCode>
1064 digits_to<unsigned long long>(const char*, const char*) noexcept;
1065
1066 #if FOLLY_HAVE_INT128_T
1067 extern template Expected<__int128, ConversionCode> digits_to<__int128>(
1068     const char*,
1069     const char*) noexcept;
1070 extern template Expected<unsigned __int128, ConversionCode>
1071 digits_to<unsigned __int128>(const char*, const char*) noexcept;
1072 #endif
1073
1074 template <class T>
1075 Expected<T, ConversionCode> str_to_integral(StringPiece* src) noexcept;
1076
1077 extern template Expected<char, ConversionCode> str_to_integral<char>(
1078     StringPiece* src) noexcept;
1079 extern template Expected<signed char, ConversionCode>
1080 str_to_integral<signed char>(StringPiece* src) noexcept;
1081 extern template Expected<unsigned char, ConversionCode>
1082 str_to_integral<unsigned char>(StringPiece* src) noexcept;
1083
1084 extern template Expected<short, ConversionCode> str_to_integral<short>(
1085     StringPiece* src) noexcept;
1086 extern template Expected<unsigned short, ConversionCode>
1087 str_to_integral<unsigned short>(StringPiece* src) noexcept;
1088
1089 extern template Expected<int, ConversionCode> str_to_integral<int>(
1090     StringPiece* src) noexcept;
1091 extern template Expected<unsigned int, ConversionCode>
1092 str_to_integral<unsigned int>(StringPiece* src) noexcept;
1093
1094 extern template Expected<long, ConversionCode> str_to_integral<long>(
1095     StringPiece* src) noexcept;
1096 extern template Expected<unsigned long, ConversionCode>
1097 str_to_integral<unsigned long>(StringPiece* src) noexcept;
1098
1099 extern template Expected<long long, ConversionCode> str_to_integral<long long>(
1100     StringPiece* src) noexcept;
1101 extern template Expected<unsigned long long, ConversionCode>
1102 str_to_integral<unsigned long long>(StringPiece* src) noexcept;
1103
1104 #if FOLLY_HAVE_INT128_T
1105 extern template Expected<__int128, ConversionCode> str_to_integral<__int128>(
1106     StringPiece* src) noexcept;
1107 extern template Expected<unsigned __int128, ConversionCode>
1108 str_to_integral<unsigned __int128>(StringPiece* src) noexcept;
1109 #endif
1110
1111 template <typename T>
1112 typename std::
1113     enable_if<std::is_same<T, bool>::value, Expected<T, ConversionCode>>::type
1114     convertTo(StringPiece* src) noexcept {
1115   return str_to_bool(src);
1116 }
1117
1118 template <typename T>
1119 typename std::enable_if<
1120     std::is_floating_point<T>::value,
1121     Expected<T, ConversionCode>>::type
1122 convertTo(StringPiece* src) noexcept {
1123   return str_to_floating<T>(src);
1124 }
1125
1126 template <typename T>
1127 typename std::enable_if<
1128     std::is_integral<T>::value && !std::is_same<T, bool>::value,
1129     Expected<T, ConversionCode>>::type
1130 convertTo(StringPiece* src) noexcept {
1131   return str_to_integral<T>(src);
1132 }
1133
1134 } // namespace detail
1135
1136 /**
1137  * String represented as a pair of pointers to char to unsigned
1138  * integrals. Assumes NO whitespace before or after.
1139  */
1140 template <typename Tgt>
1141 typename std::enable_if<
1142     std::is_integral<Tgt>::value && !std::is_same<Tgt, bool>::value,
1143     Expected<Tgt, ConversionCode>>::type
1144 tryTo(const char* b, const char* e) {
1145   return detail::digits_to<Tgt>(b, e);
1146 }
1147
1148 template <typename Tgt>
1149 typename std::enable_if<
1150     std::is_integral<Tgt>::value && !std::is_same<Tgt, bool>::value,
1151     Tgt>::type
1152 to(const char* b, const char* e) {
1153   return tryTo<Tgt>(b, e).thenOrThrow(
1154       [](Tgt res) { return res; },
1155       [=](ConversionCode code) {
1156         return makeConversionError(code, StringPiece(b, e));
1157       });
1158 }
1159
1160 /*******************************************************************************
1161  * Conversions from string types to arithmetic types.
1162  ******************************************************************************/
1163
1164 /**
1165  * Parsing strings to numeric types.
1166  */
1167 template <typename Tgt>
1168 FOLLY_NODISCARD inline typename std::enable_if<
1169     std::is_arithmetic<Tgt>::value,
1170     Expected<StringPiece, ConversionCode>>::type
1171 parseTo(StringPiece src, Tgt& out) {
1172   return detail::convertTo<Tgt>(&src).then(
1173       [&](Tgt res) { return void(out = res), src; });
1174 }
1175
1176 /*******************************************************************************
1177  * Integral / Floating Point to integral / Floating Point
1178  ******************************************************************************/
1179
1180 namespace detail {
1181
1182 /**
1183  * Bool to integral/float doesn't need any special checks, and this
1184  * overload means we aren't trying to see if a bool is less than
1185  * an integer.
1186  */
1187 template <class Tgt>
1188 typename std::enable_if<
1189     !std::is_same<Tgt, bool>::value &&
1190         (std::is_integral<Tgt>::value || std::is_floating_point<Tgt>::value),
1191     Expected<Tgt, ConversionCode>>::type
1192 convertTo(const bool& value) noexcept {
1193   return static_cast<Tgt>(value ? 1 : 0);
1194 }
1195
1196 /**
1197  * Checked conversion from integral to integral. The checks are only
1198  * performed when meaningful, e.g. conversion from int to long goes
1199  * unchecked.
1200  */
1201 template <class Tgt, class Src>
1202 typename std::enable_if<
1203     std::is_integral<Src>::value && !std::is_same<Tgt, Src>::value &&
1204         !std::is_same<Tgt, bool>::value &&
1205         std::is_integral<Tgt>::value,
1206     Expected<Tgt, ConversionCode>>::type
1207 convertTo(const Src& value) noexcept {
1208   /* static */ if (
1209       folly::_t<std::make_unsigned<Tgt>>(std::numeric_limits<Tgt>::max()) <
1210       folly::_t<std::make_unsigned<Src>>(std::numeric_limits<Src>::max())) {
1211     if (greater_than<Tgt, std::numeric_limits<Tgt>::max()>(value)) {
1212       return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
1213     }
1214   }
1215   /* static */ if (
1216       std::is_signed<Src>::value &&
1217       (!std::is_signed<Tgt>::value || sizeof(Src) > sizeof(Tgt))) {
1218     if (less_than<Tgt, std::numeric_limits<Tgt>::min()>(value)) {
1219       return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
1220     }
1221   }
1222   return static_cast<Tgt>(value);
1223 }
1224
1225 /**
1226  * Checked conversion from floating to floating. The checks are only
1227  * performed when meaningful, e.g. conversion from float to double goes
1228  * unchecked.
1229  */
1230 template <class Tgt, class Src>
1231 typename std::enable_if<
1232     std::is_floating_point<Tgt>::value && std::is_floating_point<Src>::value &&
1233         !std::is_same<Tgt, Src>::value,
1234     Expected<Tgt, ConversionCode>>::type
1235 convertTo(const Src& value) noexcept {
1236   /* static */ if (
1237       std::numeric_limits<Tgt>::max() < std::numeric_limits<Src>::max()) {
1238     if (value > std::numeric_limits<Tgt>::max()) {
1239       return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
1240     }
1241     if (value < std::numeric_limits<Tgt>::lowest()) {
1242       return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
1243     }
1244   }
1245   return static_cast<Tgt>(value);
1246 }
1247
1248 /**
1249  * Check if a floating point value can safely be converted to an
1250  * integer value without triggering undefined behaviour.
1251  */
1252 template <typename Tgt, typename Src>
1253 inline typename std::enable_if<
1254     std::is_floating_point<Src>::value && std::is_integral<Tgt>::value &&
1255         !std::is_same<Tgt, bool>::value,
1256     bool>::type
1257 checkConversion(const Src& value) {
1258   constexpr Src tgtMaxAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::max());
1259   constexpr Src tgtMinAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::min());
1260   if (value >= tgtMaxAsSrc) {
1261     if (value > tgtMaxAsSrc) {
1262       return false;
1263     }
1264     const Src mmax = folly::nextafter(tgtMaxAsSrc, Src());
1265     if (static_cast<Tgt>(value - mmax) >
1266         std::numeric_limits<Tgt>::max() - static_cast<Tgt>(mmax)) {
1267       return false;
1268     }
1269   } else if (std::is_signed<Tgt>::value && value <= tgtMinAsSrc) {
1270     if (value < tgtMinAsSrc) {
1271       return false;
1272     }
1273     const Src mmin = folly::nextafter(tgtMinAsSrc, Src());
1274     if (static_cast<Tgt>(value - mmin) <
1275         std::numeric_limits<Tgt>::min() - static_cast<Tgt>(mmin)) {
1276       return false;
1277     }
1278   }
1279   return true;
1280 }
1281
1282 // Integers can always safely be converted to floating point values
1283 template <typename Tgt, typename Src>
1284 constexpr typename std::enable_if<
1285     std::is_integral<Src>::value && std::is_floating_point<Tgt>::value,
1286     bool>::type
1287 checkConversion(const Src&) {
1288   return true;
1289 }
1290
1291 // Also, floating point values can always be safely converted to bool
1292 // Per the standard, any floating point value that is not zero will yield true
1293 template <typename Tgt, typename Src>
1294 constexpr typename std::enable_if<
1295     std::is_floating_point<Src>::value && std::is_same<Tgt, bool>::value,
1296     bool>::type
1297 checkConversion(const Src&) {
1298   return true;
1299 }
1300
1301 /**
1302  * Checked conversion from integral to floating point and back. The
1303  * result must be convertible back to the source type without loss of
1304  * precision. This seems Draconian but sometimes is what's needed, and
1305  * complements existing routines nicely. For various rounding
1306  * routines, see <math>.
1307  */
1308 template <typename Tgt, typename Src>
1309 typename std::enable_if<
1310     (std::is_integral<Src>::value && std::is_floating_point<Tgt>::value) ||
1311         (std::is_floating_point<Src>::value && std::is_integral<Tgt>::value),
1312     Expected<Tgt, ConversionCode>>::type
1313 convertTo(const Src& value) noexcept {
1314   if (LIKELY(checkConversion<Tgt>(value))) {
1315     Tgt result = static_cast<Tgt>(value);
1316     if (LIKELY(checkConversion<Src>(result))) {
1317       Src witness = static_cast<Src>(result);
1318       if (LIKELY(value == witness)) {
1319         return result;
1320       }
1321     }
1322   }
1323   return makeUnexpected(ConversionCode::ARITH_LOSS_OF_PRECISION);
1324 }
1325
1326 template <typename Tgt, typename Src>
1327 inline std::string errorValue(const Src& value) {
1328 #ifdef FOLLY_HAS_RTTI
1329   return to<std::string>("(", demangle(typeid(Tgt)), ") ", value);
1330 #else
1331   return to<std::string>(value);
1332 #endif
1333 }
1334
1335 template <typename Tgt, typename Src>
1336 using IsArithToArith = std::integral_constant<
1337     bool,
1338     !std::is_same<Tgt, Src>::value && !std::is_same<Tgt, bool>::value &&
1339         std::is_arithmetic<Src>::value &&
1340         std::is_arithmetic<Tgt>::value>;
1341
1342 } // namespace detail
1343
1344 template <typename Tgt, typename Src>
1345 typename std::enable_if<
1346     detail::IsArithToArith<Tgt, Src>::value,
1347     Expected<Tgt, ConversionCode>>::type
1348 tryTo(const Src& value) noexcept {
1349   return detail::convertTo<Tgt>(value);
1350 }
1351
1352 template <typename Tgt, typename Src>
1353 typename std::enable_if<detail::IsArithToArith<Tgt, Src>::value, Tgt>::type to(
1354     const Src& value) {
1355   return tryTo<Tgt>(value).thenOrThrow(
1356       [](Tgt res) { return res; },
1357       [&](ConversionCode e) {
1358         return makeConversionError(e, detail::errorValue<Tgt>(value));
1359       });
1360 }
1361
1362 /*******************************************************************************
1363  * Custom Conversions
1364  *
1365  * Any type can be used with folly::to by implementing parseTo. The
1366  * implementation should be provided in the namespace of the type to facilitate
1367  * argument-dependent lookup:
1368  *
1369  * namespace other_namespace {
1370  * ::folly::Expected<::folly::StringPiece, SomeErrorCode>
1371  *   parseTo(::folly::StringPiece, OtherType&) noexcept;
1372  * }
1373  ******************************************************************************/
1374 template <class T>
1375 FOLLY_NODISCARD typename std::enable_if<
1376     std::is_enum<T>::value,
1377     Expected<StringPiece, ConversionCode>>::type
1378 parseTo(StringPiece in, T& out) noexcept {
1379   typename std::underlying_type<T>::type tmp{};
1380   auto restOrError = parseTo(in, tmp);
1381   out = static_cast<T>(tmp); // Harmless if parseTo fails
1382   return restOrError;
1383 }
1384
1385 FOLLY_NODISCARD
1386 inline Expected<StringPiece, ConversionCode> parseTo(
1387     StringPiece in,
1388     StringPiece& out) noexcept {
1389   out = in;
1390   return StringPiece{in.end(), in.end()};
1391 }
1392
1393 FOLLY_NODISCARD
1394 inline Expected<StringPiece, ConversionCode> parseTo(
1395     StringPiece in,
1396     std::string& out) {
1397   out.clear();
1398   out.append(in.data(), in.size()); // TODO try/catch?
1399   return StringPiece{in.end(), in.end()};
1400 }
1401
1402 FOLLY_NODISCARD
1403 inline Expected<StringPiece, ConversionCode> parseTo(
1404     StringPiece in,
1405     fbstring& out) {
1406   out.clear();
1407   out.append(in.data(), in.size()); // TODO try/catch?
1408   return StringPiece{in.end(), in.end()};
1409 }
1410
1411 namespace detail {
1412 template <typename Tgt>
1413 using ParseToResult = decltype(parseTo(StringPiece{}, std::declval<Tgt&>()));
1414
1415 struct CheckTrailingSpace {
1416   Expected<Unit, ConversionCode> operator()(StringPiece sp) const {
1417     auto e = enforceWhitespaceErr(sp);
1418     if (UNLIKELY(e != ConversionCode::SUCCESS))
1419       return makeUnexpected(e);
1420     return unit;
1421   }
1422 };
1423
1424 template <class Error>
1425 struct ReturnUnit {
1426   template <class T>
1427   constexpr Expected<Unit, Error> operator()(T&&) const {
1428     return unit;
1429   }
1430 };
1431
1432 // Older versions of the parseTo customization point threw on error and
1433 // returned void. Handle that.
1434 template <class Tgt>
1435 inline typename std::enable_if<
1436     std::is_void<ParseToResult<Tgt>>::value,
1437     Expected<StringPiece, ConversionCode>>::type
1438 parseToWrap(StringPiece sp, Tgt& out) {
1439   parseTo(sp, out);
1440   return StringPiece(sp.end(), sp.end());
1441 }
1442
1443 template <class Tgt>
1444 inline typename std::enable_if<
1445     !std::is_void<ParseToResult<Tgt>>::value,
1446     ParseToResult<Tgt>>::type
1447 parseToWrap(StringPiece sp, Tgt& out) {
1448   return parseTo(sp, out);
1449 }
1450
1451 template <typename Tgt>
1452 using ParseToError = ExpectedErrorType<decltype(
1453     detail::parseToWrap(StringPiece{}, std::declval<Tgt&>()))>;
1454
1455 } // namespace detail
1456
1457 /**
1458  * String or StringPiece to target conversion. Accepts leading and trailing
1459  * whitespace, but no non-space trailing characters.
1460  */
1461
1462 template <class Tgt>
1463 inline typename std::enable_if<
1464     !std::is_same<StringPiece, Tgt>::value,
1465     Expected<Tgt, detail::ParseToError<Tgt>>>::type
1466 tryTo(StringPiece src) {
1467   Tgt result{};
1468   using Error = detail::ParseToError<Tgt>;
1469   using Check = typename std::conditional<
1470       std::is_arithmetic<Tgt>::value,
1471       detail::CheckTrailingSpace,
1472       detail::ReturnUnit<Error>>::type;
1473   return parseTo(src, result).then(Check(), [&](Unit) {
1474     return std::move(result);
1475   });
1476 }
1477
1478 template <class Tgt>
1479 inline
1480     typename std::enable_if<!std::is_same<StringPiece, Tgt>::value, Tgt>::type
1481     to(StringPiece src) {
1482   Tgt result{};
1483   using Error = detail::ParseToError<Tgt>;
1484   using Check = typename std::conditional<
1485       std::is_arithmetic<Tgt>::value,
1486       detail::CheckTrailingSpace,
1487       detail::ReturnUnit<Error>>::type;
1488   auto tmp = detail::parseToWrap(src, result);
1489   return tmp
1490       .thenOrThrow(Check(), [&](Error e) { throw makeConversionError(e, src); })
1491       .thenOrThrow(
1492           [&](Unit) { return std::move(result); },
1493           [&](Error e) { throw makeConversionError(e, tmp.value()); });
1494 }
1495
1496 /**
1497  * tryTo/to that take the strings by pointer so the caller gets information
1498  * about how much of the string was consumed by the conversion. These do not
1499  * check for trailing whitepsace.
1500  */
1501 template <class Tgt>
1502 Expected<Tgt, detail::ParseToError<Tgt>> tryTo(StringPiece* src) {
1503   Tgt result;
1504   return parseTo(*src, result).then([&, src](StringPiece sp) -> Tgt {
1505     *src = sp;
1506     return std::move(result);
1507   });
1508 }
1509
1510 template <class Tgt>
1511 Tgt to(StringPiece* src) {
1512   Tgt result{};
1513   using Error = detail::ParseToError<Tgt>;
1514   return parseTo(*src, result)
1515       .thenOrThrow(
1516           [&, src](StringPiece sp) -> Tgt {
1517             *src = sp;
1518             return std::move(result);
1519           },
1520           [=](Error e) { return makeConversionError(e, *src); });
1521 }
1522
1523 /*******************************************************************************
1524  * Enum to anything and back
1525  ******************************************************************************/
1526
1527 template <class Tgt, class Src>
1528 typename std::enable_if<
1529     std::is_enum<Src>::value && !std::is_same<Src, Tgt>::value,
1530     Expected<Tgt, ConversionCode>>::type
1531 tryTo(const Src& value) {
1532   using I = typename std::underlying_type<Src>::type;
1533   return tryTo<Tgt>(static_cast<I>(value));
1534 }
1535
1536 template <class Tgt, class Src>
1537 typename std::enable_if<
1538     std::is_enum<Tgt>::value && !std::is_same<Src, Tgt>::value,
1539     Expected<Tgt, ConversionCode>>::type
1540 tryTo(const Src& value) {
1541   using I = typename std::underlying_type<Tgt>::type;
1542   return tryTo<I>(value).then([](I i) { return static_cast<Tgt>(i); });
1543 }
1544
1545 template <class Tgt, class Src>
1546 typename std::enable_if<
1547     std::is_enum<Src>::value && !std::is_same<Src, Tgt>::value,
1548     Tgt>::type
1549 to(const Src& value) {
1550   return to<Tgt>(static_cast<typename std::underlying_type<Src>::type>(value));
1551 }
1552
1553 template <class Tgt, class Src>
1554 typename std::enable_if<
1555   std::is_enum<Tgt>::value && !std::is_same<Src, Tgt>::value, Tgt>::type
1556 to(const Src & value) {
1557   return static_cast<Tgt>(to<typename std::underlying_type<Tgt>::type>(value));
1558 }
1559
1560 } // namespace folly