More implicit truncation warning fixes
[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<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(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  * Bool to integral doesn't need any special checks, and this
1180  * overload means we aren't trying to see if a bool is less than
1181  * an integer.
1182  */
1183 template <class Tgt>
1184 typename std::enable_if<
1185     !std::is_same<Tgt, bool>::value && std::is_integral<Tgt>::value,
1186     Expected<Tgt, ConversionCode>>::type
1187 convertTo(const bool& value) noexcept {
1188   return static_cast<Tgt>(value ? 1 : 0);
1189 }
1190
1191 /**
1192  * Checked conversion from integral to integral. The checks are only
1193  * performed when meaningful, e.g. conversion from int to long goes
1194  * unchecked.
1195  */
1196 template <class Tgt, class Src>
1197 typename std::enable_if<
1198     std::is_integral<Src>::value && !std::is_same<Tgt, Src>::value &&
1199         !std::is_same<Tgt, bool>::value &&
1200         std::is_integral<Tgt>::value,
1201     Expected<Tgt, ConversionCode>>::type
1202 convertTo(const Src& value) noexcept {
1203   /* static */ if (
1204       std::numeric_limits<Tgt>::max() < std::numeric_limits<Src>::max()) {
1205     if (greater_than<Tgt, std::numeric_limits<Tgt>::max()>(value)) {
1206       return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
1207     }
1208   }
1209   /* static */ if (
1210       std::is_signed<Src>::value &&
1211       (!std::is_signed<Tgt>::value || sizeof(Src) > sizeof(Tgt))) {
1212     if (less_than<Tgt, std::numeric_limits<Tgt>::min()>(value)) {
1213       return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
1214     }
1215   }
1216   return static_cast<Tgt>(value);
1217 }
1218
1219 /**
1220  * Checked conversion from floating to floating. The checks are only
1221  * performed when meaningful, e.g. conversion from float to double goes
1222  * unchecked.
1223  */
1224 template <class Tgt, class Src>
1225 typename std::enable_if<
1226     std::is_floating_point<Tgt>::value && std::is_floating_point<Src>::value &&
1227         !std::is_same<Tgt, Src>::value,
1228     Expected<Tgt, ConversionCode>>::type
1229 convertTo(const Src& value) noexcept {
1230   /* static */ if (
1231       std::numeric_limits<Tgt>::max() < std::numeric_limits<Src>::max()) {
1232     if (value > std::numeric_limits<Tgt>::max()) {
1233       return makeUnexpected(ConversionCode::ARITH_POSITIVE_OVERFLOW);
1234     }
1235     if (value < std::numeric_limits<Tgt>::lowest()) {
1236       return makeUnexpected(ConversionCode::ARITH_NEGATIVE_OVERFLOW);
1237     }
1238   }
1239   return boost::implicit_cast<Tgt>(value);
1240 }
1241
1242 /**
1243  * Check if a floating point value can safely be converted to an
1244  * integer value without triggering undefined behaviour.
1245  */
1246 template <typename Tgt, typename Src>
1247 inline typename std::enable_if<
1248     std::is_floating_point<Src>::value && std::is_integral<Tgt>::value &&
1249         !std::is_same<Tgt, bool>::value,
1250     bool>::type
1251 checkConversion(const Src& value) {
1252   constexpr Src tgtMaxAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::max());
1253   constexpr Src tgtMinAsSrc = static_cast<Src>(std::numeric_limits<Tgt>::min());
1254   if (value >= tgtMaxAsSrc) {
1255     if (value > tgtMaxAsSrc) {
1256       return false;
1257     }
1258     const Src mmax = folly::nextafter(tgtMaxAsSrc, Src());
1259     if (static_cast<Tgt>(value - mmax) >
1260         std::numeric_limits<Tgt>::max() - static_cast<Tgt>(mmax)) {
1261       return false;
1262     }
1263   } else if (std::is_signed<Tgt>::value && value <= tgtMinAsSrc) {
1264     if (value < tgtMinAsSrc) {
1265       return false;
1266     }
1267     const Src mmin = folly::nextafter(tgtMinAsSrc, Src());
1268     if (static_cast<Tgt>(value - mmin) <
1269         std::numeric_limits<Tgt>::min() - static_cast<Tgt>(mmin)) {
1270       return false;
1271     }
1272   }
1273   return true;
1274 }
1275
1276 // Integers can always safely be converted to floating point values
1277 template <typename Tgt, typename Src>
1278 constexpr typename std::enable_if<
1279     std::is_integral<Src>::value && std::is_floating_point<Tgt>::value,
1280     bool>::type
1281 checkConversion(const Src&) {
1282   return true;
1283 }
1284
1285 // Also, floating point values can always be safely converted to bool
1286 // Per the standard, any floating point value that is not zero will yield true
1287 template <typename Tgt, typename Src>
1288 constexpr typename std::enable_if<
1289     std::is_floating_point<Src>::value && std::is_same<Tgt, bool>::value,
1290     bool>::type
1291 checkConversion(const Src&) {
1292   return true;
1293 }
1294
1295 /**
1296  * Checked conversion from integral to floating point and back. The
1297  * result must be convertible back to the source type without loss of
1298  * precision. This seems Draconian but sometimes is what's needed, and
1299  * complements existing routines nicely. For various rounding
1300  * routines, see <math>.
1301  */
1302 template <typename Tgt, typename Src>
1303 typename std::enable_if<
1304     (std::is_integral<Src>::value && std::is_floating_point<Tgt>::value) ||
1305         (std::is_floating_point<Src>::value && std::is_integral<Tgt>::value),
1306     Expected<Tgt, ConversionCode>>::type
1307 convertTo(const Src& value) noexcept {
1308   if (LIKELY(checkConversion<Tgt>(value))) {
1309     Tgt result = static_cast<Tgt>(value);
1310     if (LIKELY(checkConversion<Src>(result))) {
1311       Src witness = static_cast<Src>(result);
1312       if (LIKELY(value == witness)) {
1313         return result;
1314       }
1315     }
1316   }
1317   return makeUnexpected(ConversionCode::ARITH_LOSS_OF_PRECISION);
1318 }
1319
1320 template <typename Tgt, typename Src>
1321 inline std::string errorValue(const Src& value) {
1322 #ifdef FOLLY_HAS_RTTI
1323   return to<std::string>("(", demangle(typeid(Tgt)), ") ", value);
1324 #else
1325   return to<std::string>(value);
1326 #endif
1327 }
1328
1329 template <typename Tgt, typename Src>
1330 using IsArithToArith = std::integral_constant<
1331     bool,
1332     !std::is_same<Tgt, Src>::value && !std::is_same<Tgt, bool>::value &&
1333         std::is_arithmetic<Src>::value &&
1334         std::is_arithmetic<Tgt>::value>;
1335
1336 } // namespace detail
1337
1338 template <typename Tgt, typename Src>
1339 typename std::enable_if<
1340     detail::IsArithToArith<Tgt, Src>::value,
1341     Expected<Tgt, ConversionCode>>::type
1342 tryTo(const Src& value) noexcept {
1343   return detail::convertTo<Tgt>(value);
1344 }
1345
1346 template <typename Tgt, typename Src>
1347 typename std::enable_if<detail::IsArithToArith<Tgt, Src>::value, Tgt>::type to(
1348     const Src& value) {
1349   return tryTo<Tgt>(value).thenOrThrow(
1350       [](Tgt res) { return res; },
1351       [&](ConversionCode e) {
1352         return makeConversionError(e, detail::errorValue<Tgt>(value));
1353       });
1354 }
1355
1356 /*******************************************************************************
1357  * Custom Conversions
1358  *
1359  * Any type can be used with folly::to by implementing parseTo. The
1360  * implementation should be provided in the namespace of the type to facilitate
1361  * argument-dependent lookup:
1362  *
1363  * namespace other_namespace {
1364  * ::folly::Expected<::folly::StringPiece, SomeErrorCode>
1365  *   parseTo(::folly::StringPiece, OtherType&) noexcept;
1366  * }
1367  ******************************************************************************/
1368 template <class T>
1369 FOLLY_WARN_UNUSED_RESULT typename std::enable_if<
1370     std::is_enum<T>::value,
1371     Expected<StringPiece, ConversionCode>>::type
1372 parseTo(StringPiece in, T& out) noexcept {
1373   typename std::underlying_type<T>::type tmp{};
1374   auto restOrError = parseTo(in, tmp);
1375   out = static_cast<T>(tmp); // Harmless if parseTo fails
1376   return restOrError;
1377 }
1378
1379 FOLLY_WARN_UNUSED_RESULT
1380 inline Expected<StringPiece, ConversionCode> parseTo(
1381     StringPiece in,
1382     StringPiece& out) noexcept {
1383   out = in;
1384   return StringPiece{in.end(), in.end()};
1385 }
1386
1387 FOLLY_WARN_UNUSED_RESULT
1388 inline Expected<StringPiece, ConversionCode> parseTo(
1389     StringPiece in,
1390     std::string& out) {
1391   out.clear();
1392   out.append(in.data(), in.size()); // TODO try/catch?
1393   return StringPiece{in.end(), in.end()};
1394 }
1395
1396 FOLLY_WARN_UNUSED_RESULT
1397 inline Expected<StringPiece, ConversionCode> parseTo(
1398     StringPiece in,
1399     fbstring& out) {
1400   out.clear();
1401   out.append(in.data(), in.size()); // TODO try/catch?
1402   return StringPiece{in.end(), in.end()};
1403 }
1404
1405 namespace detail {
1406 template <typename Tgt>
1407 using ParseToResult = decltype(parseTo(StringPiece{}, std::declval<Tgt&>()));
1408
1409 struct CheckTrailingSpace {
1410   Expected<Unit, ConversionCode> operator()(StringPiece sp) const {
1411     auto e = enforceWhitespaceErr(sp);
1412     if (UNLIKELY(e != ConversionCode::SUCCESS))
1413       return makeUnexpected(e);
1414     return unit;
1415   }
1416 };
1417
1418 template <class Error>
1419 struct ReturnUnit {
1420   template <class T>
1421   constexpr Expected<Unit, Error> operator()(T&&) const {
1422     return unit;
1423   }
1424 };
1425
1426 // Older versions of the parseTo customization point threw on error and
1427 // returned void. Handle that.
1428 template <class Tgt>
1429 inline typename std::enable_if<
1430     std::is_void<ParseToResult<Tgt>>::value,
1431     Expected<StringPiece, ConversionCode>>::type
1432 parseToWrap(StringPiece sp, Tgt& out) {
1433   parseTo(sp, out);
1434   return StringPiece(sp.end(), sp.end());
1435 }
1436
1437 template <class Tgt>
1438 inline typename std::enable_if<
1439     !std::is_void<ParseToResult<Tgt>>::value,
1440     ParseToResult<Tgt>>::type
1441 parseToWrap(StringPiece sp, Tgt& out) {
1442   return parseTo(sp, out);
1443 }
1444
1445 template <typename Tgt>
1446 using ParseToError = ExpectedErrorType<decltype(
1447     detail::parseToWrap(StringPiece{}, std::declval<Tgt&>()))>;
1448
1449 } // namespace detail
1450
1451 /**
1452  * String or StringPiece to target conversion. Accepts leading and trailing
1453  * whitespace, but no non-space trailing characters.
1454  */
1455
1456 template <class Tgt>
1457 inline typename std::enable_if<
1458     !std::is_same<StringPiece, Tgt>::value,
1459     Expected<Tgt, detail::ParseToError<Tgt>>>::type
1460 tryTo(StringPiece src) {
1461   Tgt result{};
1462   using Error = detail::ParseToError<Tgt>;
1463   using Check = typename std::conditional<
1464       std::is_arithmetic<Tgt>::value,
1465       detail::CheckTrailingSpace,
1466       detail::ReturnUnit<Error>>::type;
1467   return parseTo(src, result).then(Check(), [&](Unit) {
1468     return std::move(result);
1469   });
1470 }
1471
1472 template <class Tgt>
1473 inline
1474     typename std::enable_if<!std::is_same<StringPiece, Tgt>::value, Tgt>::type
1475     to(StringPiece src) {
1476   Tgt result{};
1477   using Error = detail::ParseToError<Tgt>;
1478   using Check = typename std::conditional<
1479       std::is_arithmetic<Tgt>::value,
1480       detail::CheckTrailingSpace,
1481       detail::ReturnUnit<Error>>::type;
1482   auto tmp = detail::parseToWrap(src, result);
1483   return tmp
1484       .thenOrThrow(Check(), [&](Error e) { throw makeConversionError(e, src); })
1485       .thenOrThrow(
1486           [&](Unit) { return std::move(result); },
1487           [&](Error e) { throw makeConversionError(e, tmp.value()); });
1488 }
1489
1490 /**
1491  * tryTo/to that take the strings by pointer so the caller gets information
1492  * about how much of the string was consumed by the conversion. These do not
1493  * check for trailing whitepsace.
1494  */
1495 template <class Tgt>
1496 Expected<Tgt, detail::ParseToError<Tgt>> tryTo(StringPiece* src) {
1497   Tgt result;
1498   return parseTo(*src, result).then([&, src](StringPiece sp) -> Tgt {
1499     *src = sp;
1500     return std::move(result);
1501   });
1502 }
1503
1504 template <class Tgt>
1505 Tgt to(StringPiece* src) {
1506   Tgt result{};
1507   using Error = detail::ParseToError<Tgt>;
1508   return parseTo(*src, result)
1509       .thenOrThrow(
1510           [&, src](StringPiece sp) -> Tgt {
1511             *src = sp;
1512             return std::move(result);
1513           },
1514           [=](Error e) { return makeConversionError(e, *src); });
1515 }
1516
1517 /*******************************************************************************
1518  * Enum to anything and back
1519  ******************************************************************************/
1520
1521 template <class Tgt, class Src>
1522 typename std::enable_if<
1523     std::is_enum<Src>::value && !std::is_same<Src, Tgt>::value,
1524     Expected<Tgt, ConversionCode>>::type
1525 tryTo(const Src& value) {
1526   using I = typename std::underlying_type<Src>::type;
1527   return tryTo<Tgt>(static_cast<I>(value));
1528 }
1529
1530 template <class Tgt, class Src>
1531 typename std::enable_if<
1532     std::is_enum<Tgt>::value && !std::is_same<Src, Tgt>::value,
1533     Tgt>::type
1534 tryTo(const Src& value) {
1535   using I = typename std::underlying_type<Tgt>::type;
1536   return tryTo<I>(value).then([](I i) { return static_cast<Tgt>(i); });
1537 }
1538
1539 template <class Tgt, class Src>
1540 typename std::enable_if<
1541     std::is_enum<Src>::value && !std::is_same<Src, Tgt>::value,
1542     Tgt>::type
1543 to(const Src& value) {
1544   return to<Tgt>(static_cast<typename std::underlying_type<Src>::type>(value));
1545 }
1546
1547 template <class Tgt, class Src>
1548 typename std::enable_if<
1549   std::is_enum<Tgt>::value && !std::is_same<Src, Tgt>::value, Tgt>::type
1550 to(const Src & value) {
1551   return static_cast<Tgt>(to<typename std::underlying_type<Tgt>::type>(value));
1552 }
1553
1554 } // namespace folly