Make fbstring libgcc-safe
[folly.git] / folly / String-inl.h
index a2179209e4e240e6d83bf81f6da3550b6a3d342f..52b665c75e6e662d464fa65ba42dfb18999f9078 100644 (file)
@@ -347,25 +347,36 @@ template<class String> StringPiece prepareDelim(const String& s) {
 }
 inline char prepareDelim(char c) { return c; }
 
+template <class Dst>
+struct convertTo {
+  template <class Src>
+  static Dst from(const Src& src) { return folly::to<Dst>(src); }
+  static Dst from(const Dst& src) { return src; }
+};
+
 template<bool exact,
-         class Delim>
-bool splitFixed(const Delim& delimiter,
-                StringPiece input,
-                StringPiece& out) {
+         class Delim,
+         class OutputType>
+typename std::enable_if<IsSplitTargetType<OutputType>::value, bool>::type
+splitFixed(const Delim& delimiter,
+           StringPiece input,
+           OutputType& out) {
   if (exact && UNLIKELY(std::string::npos != input.find(delimiter))) {
     return false;
   }
-  out = input;
+  out = convertTo<OutputType>::from(input);
   return true;
 }
 
 template<bool exact,
          class Delim,
-         class... StringPieces>
-bool splitFixed(const Delim& delimiter,
-                StringPiece input,
-                StringPiece& outHead,
-                StringPieces&... outTail) {
+         class OutputType,
+         class... OutputTypes>
+typename std::enable_if<IsSplitTargetType<OutputType>::value, bool>::type
+splitFixed(const Delim& delimiter,
+           StringPiece input,
+           OutputType& outHead,
+           OutputTypes&... outTail) {
   size_t cut = input.find(delimiter);
   if (UNLIKELY(cut == std::string::npos)) {
     return false;
@@ -374,7 +385,7 @@ bool splitFixed(const Delim& delimiter,
   StringPiece tail(input.begin() + cut + detail::delimSize(delimiter),
                    input.end());
   if (LIKELY(splitFixed<exact>(delimiter, tail, outTail...))) {
-    outHead = head;
+    outHead = convertTo<OutputType>::from(head);
     return true;
   }
   return false;
@@ -423,11 +434,13 @@ void splitTo(const Delim& delimiter,
 
 template<bool exact,
          class Delim,
-         class... StringPieces>
-bool split(const Delim& delimiter,
-           StringPiece input,
-           StringPiece& outHead,
-           StringPieces&... outTail) {
+         class OutputType,
+         class... OutputTypes>
+typename std::enable_if<IsSplitTargetType<OutputType>::value, bool>::type
+split(const Delim& delimiter,
+      StringPiece input,
+      OutputType& outHead,
+      OutputTypes&... outTail) {
   return detail::splitFixed<exact>(
     detail::prepareDelim(delimiter),
     input,
@@ -437,9 +450,20 @@ bool split(const Delim& delimiter,
 
 namespace detail {
 
+/*
+ * If a type can have its string size determined cheaply, we can more
+ * efficiently append it in a loop (see internalJoinAppend). Note that the
+ * struct need not conform to the std::string api completely (ex. does not need
+ * to implement append()).
+ */
+template <class T> struct IsSizableString {
+  enum { value = IsSomeString<T>::value
+         || std::is_same<T, StringPiece>::value };
+};
+
 template <class Iterator>
-struct IsStringContainerIterator :
-  IsSomeString<typename std::iterator_traits<Iterator>::value_type> {
+struct IsSizableStringContainerIterator :
+  IsSizableString<typename std::iterator_traits<Iterator>::value_type> {
 };
 
 template <class Delim, class Iterator, class String>
@@ -460,7 +484,7 @@ void internalJoinAppend(Delim delimiter,
 }
 
 template <class Delim, class Iterator, class String>
-typename std::enable_if<IsStringContainerIterator<Iterator>::value>::type
+typename std::enable_if<IsSizableStringContainerIterator<Iterator>::value>::type
 internalJoin(Delim delimiter,
              Iterator begin,
              Iterator end,
@@ -480,7 +504,8 @@ internalJoin(Delim delimiter,
 }
 
 template <class Delim, class Iterator, class String>
-typename std::enable_if<!IsStringContainerIterator<Iterator>::value>::type
+typename
+std::enable_if<!IsSizableStringContainerIterator<Iterator>::value>::type
 internalJoin(Delim delimiter,
              Iterator begin,
              Iterator end,