strings join
[folly.git] / folly / String-inl.h
index 3829f1f872fe951cbc6d36bd7508e553be8c9502..02d376d82f06e02fd4b64b30f6758705091cc0ca 100644 (file)
@@ -18,6 +18,7 @@
 #define FOLLY_STRING_INL_H_
 
 #include <stdexcept>
+#include <iterator>
 
 #ifndef FOLLY_BASE_STRING_H_
 #error This file may only be included from String.h
@@ -298,6 +299,72 @@ void splitTo(const Delim& delimiter,
     ignoreEmpty);
 }
 
+namespace detail {
+
+template <class Iterator>
+struct IsStringContainerIterator :
+  IsSomeString<typename std::iterator_traits<Iterator>::value_type> {
+};
+
+template <class Delim, class Iterator, class String>
+void internalJoinAppend(Delim delimiter,
+                        Iterator begin,
+                        Iterator end,
+                        String& output) {
+  assert(begin != end);
+  toAppend(*begin, &output);
+  while (++begin != end) {
+    toAppend(delimiter, *begin, &output);
+  }
+}
+
+template <class Delim, class Iterator, class String>
+typename std::enable_if<IsStringContainerIterator<Iterator>::value>::type
+internalJoin(Delim delimiter,
+             Iterator begin,
+             Iterator end,
+             String& output) {
+  output.clear();
+  if (begin == end) {
+    return;
+  }
+  const size_t dsize = delimSize(delimiter);
+  Iterator it = begin;
+  size_t size = it->size();
+  while (++it != end) {
+    size += dsize + it->size();
+  }
+  output.reserve(size);
+  internalJoinAppend(delimiter, begin, end, output);
+}
+
+template <class Delim, class Iterator, class String>
+typename std::enable_if<!IsStringContainerIterator<Iterator>::value>::type
+internalJoin(Delim delimiter,
+             Iterator begin,
+             Iterator end,
+             String& output) {
+  output.clear();
+  if (begin == end) {
+    return;
+  }
+  internalJoinAppend(delimiter, begin, end, output);
+}
+
+}  // namespace detail
+
+template <class Delim, class Iterator, class String>
+void join(const Delim& delimiter,
+          Iterator begin,
+          Iterator end,
+          String& output) {
+  detail::internalJoin(
+    detail::prepareDelim(delimiter),
+    begin,
+    end,
+    output);
+}
+
 template <class String1, class String2>
 void backslashify(const String1& input, String2& output, bool hex_style) {
   static const char hexValues[] = "0123456789abcdef";