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