You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by ja...@apache.org on 2018/06/18 18:35:47 UTC

[28/62] [abbrv] [partial] marmotta git commit: * Replace gtest with upstream version, including LICENSE header. * Include absl library for faster and safer string operations. * Update license headers where needed. * Removed custom code replaced by absl.

http://git-wip-us.apache.org/repos/asf/marmotta/blob/0eb556da/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_join.h
----------------------------------------------------------------------
diff --git a/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_join.h b/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_join.h
new file mode 100644
index 0000000..bd4d0e1
--- /dev/null
+++ b/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_join.h
@@ -0,0 +1,288 @@
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: str_join.h
+// -----------------------------------------------------------------------------
+//
+// This header file contains functions for joining a range of elements and
+// returning the result as a std::string. StrJoin operations are specified by passing
+// a range, a separator std::string to use between the elements joined, and an
+// optional Formatter responsible for converting each argument in the range to a
+// std::string. If omitted, a default `AlphaNumFormatter()` is called on the elements
+// to be joined, using the same formatting that `absl::StrCat()` uses. This
+// package defines a number of default formatters, and you can define your own
+// implementations.
+//
+// Ranges are specified by passing a container with `std::begin()` and
+// `std::end()` iterators, container-specific `begin()` and `end()` iterators, a
+// brace-initialized `std::initializer_list`, or a `std::tuple` of heterogeneous
+// objects. The separator std::string is specified as an `absl::string_view`.
+//
+// Because the default formatter uses the `absl::AlphaNum` class,
+// `absl::StrJoin()`, like `absl::StrCat()`, will work out-of-the-box on
+// collections of strings, ints, floats, doubles, etc.
+//
+// Example:
+//
+//   std::vector<std::string> v = {"foo", "bar", "baz"};
+//   std::string s = absl::StrJoin(v, "-");
+//   EXPECT_EQ("foo-bar-baz", s);
+//
+// See comments on the `absl::StrJoin()` function for more examples.
+
+#ifndef ABSL_STRINGS_STR_JOIN_H_
+#define ABSL_STRINGS_STR_JOIN_H_
+
+#include <cstdio>
+#include <cstring>
+#include <initializer_list>
+#include <iterator>
+#include <string>
+#include <tuple>
+#include <utility>
+
+#include "absl/base/macros.h"
+#include "absl/strings/internal/str_join_internal.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+
+// -----------------------------------------------------------------------------
+// Concept: Formatter
+// -----------------------------------------------------------------------------
+//
+// A Formatter is a function object that is responsible for formatting its
+// argument as a std::string and appending it to a given output std::string. Formatters
+// may be implemented as function objects, lambdas, or normal functions. You may
+// provide your own Formatter to enable `absl::StrJoin()` to work with arbitrary
+// types.
+//
+// The following is an example of a custom Formatter that simply uses
+// `std::to_string()` to format an integer as a std::string.
+//
+//   struct MyFormatter {
+//     void operator()(std::string* out, int i) const {
+//       out->append(std::to_string(i));
+//     }
+//   };
+//
+// You would use the above formatter by passing an instance of it as the final
+// argument to `absl::StrJoin()`:
+//
+//   std::vector<int> v = {1, 2, 3, 4};
+//   std::string s = absl::StrJoin(v, "-", MyFormatter());
+//   EXPECT_EQ("1-2-3-4", s);
+//
+// The following standard formatters are provided within this file:
+//
+// - `AlphaNumFormatter()` (the default)
+// - `StreamFormatter()`
+// - `PairFormatter()`
+// - `DereferenceFormatter()`
+
+// AlphaNumFormatter()
+//
+// Default formatter used if none is specified. Uses `absl::AlphaNum` to convert
+// numeric arguments to strings.
+inline strings_internal::AlphaNumFormatterImpl AlphaNumFormatter() {
+  return strings_internal::AlphaNumFormatterImpl();
+}
+
+// StreamFormatter()
+//
+// Formats its argument using the << operator.
+inline strings_internal::StreamFormatterImpl StreamFormatter() {
+  return strings_internal::StreamFormatterImpl();
+}
+
+// Function Template: PairFormatter(Formatter, absl::string_view, Formatter)
+//
+// Formats a `std::pair` by putting a given separator between the pair's
+// `.first` and `.second` members. This formatter allows you to specify
+// custom Formatters for both the first and second member of each pair.
+template <typename FirstFormatter, typename SecondFormatter>
+inline strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>
+PairFormatter(FirstFormatter f1, absl::string_view sep, SecondFormatter f2) {
+  return strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>(
+      std::move(f1), sep, std::move(f2));
+}
+
+// Function overload of PairFormatter() for using a default
+// `AlphaNumFormatter()` for each Formatter in the pair.
+inline strings_internal::PairFormatterImpl<
+    strings_internal::AlphaNumFormatterImpl,
+    strings_internal::AlphaNumFormatterImpl>
+PairFormatter(absl::string_view sep) {
+  return PairFormatter(AlphaNumFormatter(), sep, AlphaNumFormatter());
+}
+
+// Function Template: DereferenceFormatter(Formatter)
+//
+// Formats its argument by dereferencing it and then applying the given
+// formatter. This formatter is useful for formatting a container of
+// pointer-to-T. This pattern often shows up when joining repeated fields in
+// protocol buffers.
+template <typename Formatter>
+strings_internal::DereferenceFormatterImpl<Formatter> DereferenceFormatter(
+    Formatter&& f) {
+  return strings_internal::DereferenceFormatterImpl<Formatter>(
+      std::forward<Formatter>(f));
+}
+
+// Function overload of `DererefenceFormatter()` for using a default
+// `AlphaNumFormatter()`.
+inline strings_internal::DereferenceFormatterImpl<
+    strings_internal::AlphaNumFormatterImpl>
+DereferenceFormatter() {
+  return strings_internal::DereferenceFormatterImpl<
+      strings_internal::AlphaNumFormatterImpl>(AlphaNumFormatter());
+}
+
+// -----------------------------------------------------------------------------
+// StrJoin()
+// -----------------------------------------------------------------------------
+//
+// Joins a range of elements and returns the result as a std::string.
+// `absl::StrJoin()` takes a range, a separator std::string to use between the
+// elements joined, and an optional Formatter responsible for converting each
+// argument in the range to a std::string.
+//
+// If omitted, the default `AlphaNumFormatter()` is called on the elements to be
+// joined.
+//
+// Example 1:
+//   // Joins a collection of strings. This pattern also works with a collection
+//   // of `absl::string_view` or even `const char*`.
+//   std::vector<std::string> v = {"foo", "bar", "baz"};
+//   std::string s = absl::StrJoin(v, "-");
+//   EXPECT_EQ("foo-bar-baz", s);
+//
+// Example 2:
+//   // Joins the values in the given `std::initializer_list<>` specified using
+//   // brace initialization. This pattern also works with an initializer_list
+//   // of ints or `absl::string_view` -- any `AlphaNum`-compatible type.
+//   std::string s = absl::StrJoin({"foo", "bar", "baz"}, "-");
+//   EXPECT_EQ("foo-bar-baz", s);
+//
+// Example 3:
+//   // Joins a collection of ints. This pattern also works with floats,
+//   // doubles, int64s -- any `StrCat()`-compatible type.
+//   std::vector<int> v = {1, 2, 3, -4};
+//   std::string s = absl::StrJoin(v, "-");
+//   EXPECT_EQ("1-2-3--4", s);
+//
+// Example 4:
+//   // Joins a collection of pointer-to-int. By default, pointers are
+//   // dereferenced and the pointee is formatted using the default format for
+//   // that type; such dereferencing occurs for all levels of indirection, so
+//   // this pattern works just as well for `std::vector<int**>` as for
+//   // `std::vector<int*>`.
+//   int x = 1, y = 2, z = 3;
+//   std::vector<int*> v = {&x, &y, &z};
+//   std::string s = absl::StrJoin(v, "-");
+//   EXPECT_EQ("1-2-3", s);
+//
+// Example 5:
+//   // Dereferencing of `std::unique_ptr<>` is also supported:
+//   std::vector<std::unique_ptr<int>> v
+//   v.emplace_back(new int(1));
+//   v.emplace_back(new int(2));
+//   v.emplace_back(new int(3));
+//   std::string s = absl::StrJoin(v, "-");
+//   EXPECT_EQ("1-2-3", s);
+//
+// Example 6:
+//   // Joins a `std::map`, with each key-value pair separated by an equals
+//   // sign. This pattern would also work with, say, a
+//   // `std::vector<std::pair<>>`.
+//   std::map<std::string, int> m = {
+//       std::make_pair("a", 1),
+//       std::make_pair("b", 2),
+//       std::make_pair("c", 3)};
+//   std::string s = absl::StrJoin(m, ",", absl::PairFormatter("="));
+//   EXPECT_EQ("a=1,b=2,c=3", s);
+//
+// Example 7:
+//   // These examples show how `absl::StrJoin()` handles a few common edge
+//   // cases:
+//   std::vector<std::string> v_empty;
+//   EXPECT_EQ("", absl::StrJoin(v_empty, "-"));
+//
+//   std::vector<std::string> v_one_item = {"foo"};
+//   EXPECT_EQ("foo", absl::StrJoin(v_one_item, "-"));
+//
+//   std::vector<std::string> v_empty_string = {""};
+//   EXPECT_EQ("", absl::StrJoin(v_empty_string, "-"));
+//
+//   std::vector<std::string> v_one_item_empty_string = {"a", ""};
+//   EXPECT_EQ("a-", absl::StrJoin(v_one_item_empty_string, "-"));
+//
+//   std::vector<std::string> v_two_empty_string = {"", ""};
+//   EXPECT_EQ("-", absl::StrJoin(v_two_empty_string, "-"));
+//
+// Example 8:
+//   // Joins a `std::tuple<T...>` of heterogeneous types, converting each to
+//   // a std::string using the `absl::AlphaNum` class.
+//   std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
+//   EXPECT_EQ("123-abc-0.456", s);
+
+template <typename Iterator, typename Formatter>
+std::string StrJoin(Iterator start, Iterator end, absl::string_view sep,
+               Formatter&& fmt) {
+  return strings_internal::JoinAlgorithm(start, end, sep, fmt);
+}
+
+template <typename Range, typename Formatter>
+std::string StrJoin(const Range& range, absl::string_view separator,
+               Formatter&& fmt) {
+  return strings_internal::JoinRange(range, separator, fmt);
+}
+
+template <typename T, typename Formatter>
+std::string StrJoin(std::initializer_list<T> il, absl::string_view separator,
+               Formatter&& fmt) {
+  return strings_internal::JoinRange(il, separator, fmt);
+}
+
+template <typename... T, typename Formatter>
+std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator,
+               Formatter&& fmt) {
+  return strings_internal::JoinAlgorithm(value, separator, fmt);
+}
+
+template <typename Iterator>
+std::string StrJoin(Iterator start, Iterator end, absl::string_view separator) {
+  return strings_internal::JoinRange(start, end, separator);
+}
+
+template <typename Range>
+std::string StrJoin(const Range& range, absl::string_view separator) {
+  return strings_internal::JoinRange(range, separator);
+}
+
+template <typename T>
+std::string StrJoin(std::initializer_list<T> il, absl::string_view separator) {
+  return strings_internal::JoinRange(il, separator);
+}
+
+template <typename... T>
+std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator) {
+  return strings_internal::JoinAlgorithm(value, separator, AlphaNumFormatter());
+}
+
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_STR_JOIN_H_

http://git-wip-us.apache.org/repos/asf/marmotta/blob/0eb556da/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_join_test.cc
----------------------------------------------------------------------
diff --git a/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_join_test.cc b/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_join_test.cc
new file mode 100644
index 0000000..03b60f0
--- /dev/null
+++ b/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_join_test.cc
@@ -0,0 +1,473 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Unit tests for all join.h functions
+
+#include "absl/strings/str_join.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <functional>
+#include <initializer_list>
+#include <map>
+#include <memory>
+#include <ostream>
+#include <set>
+#include <tuple>
+#include <type_traits>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/base/macros.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
+
+namespace {
+
+TEST(StrJoin, APIExamples) {
+  {
+    // Collection of strings
+    std::vector<std::string> v = {"foo", "bar", "baz"};
+    EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
+  }
+
+  {
+    // Collection of absl::string_view
+    std::vector<absl::string_view> v = {"foo", "bar", "baz"};
+    EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
+  }
+
+  {
+    // Collection of const char*
+    std::vector<const char*> v = {"foo", "bar", "baz"};
+    EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
+  }
+
+  {
+    // Collection of non-const char*
+    std::string a = "foo", b = "bar", c = "baz";
+    std::vector<char*> v = {&a[0], &b[0], &c[0]};
+    EXPECT_EQ("foo-bar-baz", absl::StrJoin(v, "-"));
+  }
+
+  {
+    // Collection of ints
+    std::vector<int> v = {1, 2, 3, -4};
+    EXPECT_EQ("1-2-3--4", absl::StrJoin(v, "-"));
+  }
+
+  {
+    // Literals passed as a std::initializer_list
+    std::string s = absl::StrJoin({"a", "b", "c"}, "-");
+    EXPECT_EQ("a-b-c", s);
+  }
+  {
+    // Join a std::tuple<T...>.
+    std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
+    EXPECT_EQ("123-abc-0.456", s);
+  }
+
+  {
+    // Collection of unique_ptrs
+    std::vector<std::unique_ptr<int>> v;
+    v.emplace_back(new int(1));
+    v.emplace_back(new int(2));
+    v.emplace_back(new int(3));
+    EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
+  }
+
+  {
+    // Array of ints
+    const int a[] = {1, 2, 3, -4};
+    EXPECT_EQ("1-2-3--4", absl::StrJoin(a, a + ABSL_ARRAYSIZE(a), "-"));
+  }
+
+  {
+    // Collection of pointers
+    int x = 1, y = 2, z = 3;
+    std::vector<int*> v = {&x, &y, &z};
+    EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
+  }
+
+  {
+    // Collection of pointers to pointers
+    int x = 1, y = 2, z = 3;
+    int *px = &x, *py = &y, *pz = &z;
+    std::vector<int**> v = {&px, &py, &pz};
+    EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
+  }
+
+  {
+    // Collection of pointers to std::string
+    std::string a("a"), b("b");
+    std::vector<std::string*> v = {&a, &b};
+    EXPECT_EQ("a-b", absl::StrJoin(v, "-"));
+  }
+
+  {
+    // A std::map, which is a collection of std::pair<>s.
+    std::map<std::string, int> m = { {"a", 1}, {"b", 2}, {"c", 3} };
+    EXPECT_EQ("a=1,b=2,c=3", absl::StrJoin(m, ",", absl::PairFormatter("=")));
+  }
+
+  {
+    // Shows absl::StrSplit and absl::StrJoin working together. This example is
+    // equivalent to s/=/-/g.
+    const std::string s = "a=b=c=d";
+    EXPECT_EQ("a-b-c-d", absl::StrJoin(absl::StrSplit(s, "="), "-"));
+  }
+
+  //
+  // A few examples of edge cases
+  //
+
+  {
+    // Empty range yields an empty std::string.
+    std::vector<std::string> v;
+    EXPECT_EQ("", absl::StrJoin(v, "-"));
+  }
+
+  {
+    // A range of 1 element gives a std::string with that element but no separator.
+    std::vector<std::string> v = {"foo"};
+    EXPECT_EQ("foo", absl::StrJoin(v, "-"));
+  }
+
+  {
+    // A range with a single empty std::string element
+    std::vector<std::string> v = {""};
+    EXPECT_EQ("", absl::StrJoin(v, "-"));
+  }
+
+  {
+    // A range with 2 elements, one of which is an empty std::string
+    std::vector<std::string> v = {"a", ""};
+    EXPECT_EQ("a-", absl::StrJoin(v, "-"));
+  }
+
+  {
+    // A range with 2 empty elements.
+    std::vector<std::string> v = {"", ""};
+    EXPECT_EQ("-", absl::StrJoin(v, "-"));
+  }
+
+  {
+    // A std::vector of bool.
+    std::vector<bool> v = {true, false, true};
+    EXPECT_EQ("1-0-1", absl::StrJoin(v, "-"));
+  }
+}
+
+TEST(StrJoin, CustomFormatter) {
+  std::vector<std::string> v{"One", "Two", "Three"};
+  {
+    std::string joined = absl::StrJoin(v, "", [](std::string* out, const std::string& in) {
+      absl::StrAppend(out, "(", in, ")");
+    });
+    EXPECT_EQ("(One)(Two)(Three)", joined);
+  }
+  {
+    class ImmovableFormatter {
+     public:
+      void operator()(std::string* out, const std::string& in) {
+        absl::StrAppend(out, "(", in, ")");
+      }
+      ImmovableFormatter() {}
+      ImmovableFormatter(const ImmovableFormatter&) = delete;
+    };
+    EXPECT_EQ("(One)(Two)(Three)", absl::StrJoin(v, "", ImmovableFormatter()));
+  }
+  {
+    class OverloadedFormatter {
+     public:
+      void operator()(std::string* out, const std::string& in) {
+        absl::StrAppend(out, "(", in, ")");
+      }
+      void operator()(std::string* out, const std::string& in) const {
+        absl::StrAppend(out, "[", in, "]");
+      }
+    };
+    EXPECT_EQ("(One)(Two)(Three)", absl::StrJoin(v, "", OverloadedFormatter()));
+    const OverloadedFormatter fmt = {};
+    EXPECT_EQ("[One][Two][Three]", absl::StrJoin(v, "", fmt));
+  }
+}
+
+//
+// Tests the Formatters
+//
+
+TEST(AlphaNumFormatter, FormatterAPI) {
+  // Not an exhaustive test. See strings/strcat_test.h for the exhaustive test
+  // of what AlphaNum can convert.
+  auto f = absl::AlphaNumFormatter();
+  std::string s;
+  f(&s, "Testing: ");
+  f(&s, static_cast<int>(1));
+  f(&s, static_cast<int16_t>(2));
+  f(&s, static_cast<int64_t>(3));
+  f(&s, static_cast<float>(4));
+  f(&s, static_cast<double>(5));
+  f(&s, static_cast<unsigned>(6));
+  f(&s, static_cast<size_t>(7));
+  f(&s, absl::string_view(" OK"));
+  EXPECT_EQ("Testing: 1234567 OK", s);
+}
+
+// Make sure people who are mistakenly using std::vector<bool> even though
+// they're not memory-constrained can use absl::AlphaNumFormatter().
+TEST(AlphaNumFormatter, VectorOfBool) {
+  auto f = absl::AlphaNumFormatter();
+  std::string s;
+  std::vector<bool> v = {true, false, true};
+  f(&s, *v.cbegin());
+  f(&s, *v.begin());
+  f(&s, v[1]);
+  EXPECT_EQ("110", s);
+}
+
+TEST(AlphaNumFormatter, AlphaNum) {
+  auto f = absl::AlphaNumFormatter();
+  std::string s;
+  f(&s, absl::AlphaNum("hello"));
+  EXPECT_EQ("hello", s);
+}
+
+struct StreamableType {
+  std::string contents;
+};
+inline std::ostream& operator<<(std::ostream& os, const StreamableType& t) {
+  os << "Streamable:" << t.contents;
+  return os;
+}
+
+TEST(StreamFormatter, FormatterAPI) {
+  auto f = absl::StreamFormatter();
+  std::string s;
+  f(&s, "Testing: ");
+  f(&s, static_cast<int>(1));
+  f(&s, static_cast<int16_t>(2));
+  f(&s, static_cast<int64_t>(3));
+  f(&s, static_cast<float>(4));
+  f(&s, static_cast<double>(5));
+  f(&s, static_cast<unsigned>(6));
+  f(&s, static_cast<size_t>(7));
+  f(&s, absl::string_view(" OK "));
+  StreamableType streamable = {"object"};
+  f(&s, streamable);
+  EXPECT_EQ("Testing: 1234567 OK Streamable:object", s);
+}
+
+// A dummy formatter that wraps each element in parens. Used in some tests
+// below.
+struct TestingParenFormatter {
+  template <typename T>
+  void operator()(std::string* s, const T& t) {
+    absl::StrAppend(s, "(", t, ")");
+  }
+};
+
+TEST(PairFormatter, FormatterAPI) {
+  {
+    // Tests default PairFormatter(sep) that uses AlphaNumFormatter for the
+    // 'first' and 'second' members.
+    const auto f = absl::PairFormatter("=");
+    std::string s;
+    f(&s, std::make_pair("a", "b"));
+    f(&s, std::make_pair(1, 2));
+    EXPECT_EQ("a=b1=2", s);
+  }
+
+  {
+    // Tests using a custom formatter for the 'first' and 'second' members.
+    auto f = absl::PairFormatter(TestingParenFormatter(), "=",
+                                 TestingParenFormatter());
+    std::string s;
+    f(&s, std::make_pair("a", "b"));
+    f(&s, std::make_pair(1, 2));
+    EXPECT_EQ("(a)=(b)(1)=(2)", s);
+  }
+}
+
+TEST(DereferenceFormatter, FormatterAPI) {
+  {
+    // Tests wrapping the default AlphaNumFormatter.
+    const absl::strings_internal::DereferenceFormatterImpl<
+        absl::strings_internal::AlphaNumFormatterImpl>
+        f;
+    int x = 1, y = 2, z = 3;
+    std::string s;
+    f(&s, &x);
+    f(&s, &y);
+    f(&s, &z);
+    EXPECT_EQ("123", s);
+  }
+
+  {
+    // Tests wrapping std::string's default formatter.
+    absl::strings_internal::DereferenceFormatterImpl<
+        absl::strings_internal::DefaultFormatter<std::string>::Type>
+        f;
+
+    std::string x = "x";
+    std::string y = "y";
+    std::string z = "z";
+    std::string s;
+    f(&s, &x);
+    f(&s, &y);
+    f(&s, &z);
+    EXPECT_EQ(s, "xyz");
+  }
+
+  {
+    // Tests wrapping a custom formatter.
+    auto f = absl::DereferenceFormatter(TestingParenFormatter());
+    int x = 1, y = 2, z = 3;
+    std::string s;
+    f(&s, &x);
+    f(&s, &y);
+    f(&s, &z);
+    EXPECT_EQ("(1)(2)(3)", s);
+  }
+
+  {
+    absl::strings_internal::DereferenceFormatterImpl<
+        absl::strings_internal::AlphaNumFormatterImpl>
+        f;
+    auto x = std::unique_ptr<int>(new int(1));
+    auto y = std::unique_ptr<int>(new int(2));
+    auto z = std::unique_ptr<int>(new int(3));
+    std::string s;
+    f(&s, x);
+    f(&s, y);
+    f(&s, z);
+    EXPECT_EQ("123", s);
+  }
+}
+
+//
+// Tests the interfaces for the 4 public Join function overloads. The semantics
+// of the algorithm is covered in the above APIExamples test.
+//
+TEST(StrJoin, PublicAPIOverloads) {
+  std::vector<std::string> v = {"a", "b", "c"};
+
+  // Iterators + formatter
+  EXPECT_EQ("a-b-c",
+            absl::StrJoin(v.begin(), v.end(), "-", absl::AlphaNumFormatter()));
+  // Range + formatter
+  EXPECT_EQ("a-b-c", absl::StrJoin(v, "-", absl::AlphaNumFormatter()));
+  // Iterators, no formatter
+  EXPECT_EQ("a-b-c", absl::StrJoin(v.begin(), v.end(), "-"));
+  // Range, no formatter
+  EXPECT_EQ("a-b-c", absl::StrJoin(v, "-"));
+}
+
+TEST(StrJoin, Array) {
+  const absl::string_view a[] = {"a", "b", "c"};
+  EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
+}
+
+TEST(StrJoin, InitializerList) {
+  { EXPECT_EQ("a-b-c", absl::StrJoin({"a", "b", "c"}, "-")); }
+
+  {
+    auto a = {"a", "b", "c"};
+    EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
+  }
+
+  {
+    std::initializer_list<const char*> a = {"a", "b", "c"};
+    EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
+  }
+
+  {
+    std::initializer_list<std::string> a = {"a", "b", "c"};
+    EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
+  }
+
+  {
+    std::initializer_list<absl::string_view> a = {"a", "b", "c"};
+    EXPECT_EQ("a-b-c", absl::StrJoin(a, "-"));
+  }
+
+  {
+    // Tests initializer_list with a non-default formatter
+    auto a = {"a", "b", "c"};
+    TestingParenFormatter f;
+    EXPECT_EQ("(a)-(b)-(c)", absl::StrJoin(a, "-", f));
+  }
+
+  {
+    // initializer_list of ints
+    EXPECT_EQ("1-2-3", absl::StrJoin({1, 2, 3}, "-"));
+  }
+
+  {
+    // Tests initializer_list of ints with a non-default formatter
+    auto a = {1, 2, 3};
+    TestingParenFormatter f;
+    EXPECT_EQ("(1)-(2)-(3)", absl::StrJoin(a, "-", f));
+  }
+}
+
+TEST(StrJoin, Tuple) {
+  EXPECT_EQ("", absl::StrJoin(std::make_tuple(), "-"));
+  EXPECT_EQ("hello", absl::StrJoin(std::make_tuple("hello"), "-"));
+
+  int x(10);
+  std::string y("hello");
+  double z(3.14);
+  EXPECT_EQ("10-hello-3.14", absl::StrJoin(std::make_tuple(x, y, z), "-"));
+
+  // Faster! Faster!!
+  EXPECT_EQ("10-hello-3.14",
+            absl::StrJoin(std::make_tuple(x, std::cref(y), z), "-"));
+
+  struct TestFormatter {
+    char buffer[128];
+    void operator()(std::string* out, int v) {
+      snprintf(buffer, sizeof(buffer), "%#.8x", v);
+      out->append(buffer);
+    }
+    void operator()(std::string* out, double v) {
+      snprintf(buffer, sizeof(buffer), "%#.0f", v);
+      out->append(buffer);
+    }
+    void operator()(std::string* out, const std::string& v) {
+      snprintf(buffer, sizeof(buffer), "%.4s", v.c_str());
+      out->append(buffer);
+    }
+  };
+  EXPECT_EQ("0x0000000a-hell-3.",
+            absl::StrJoin(std::make_tuple(x, y, z), "-", TestFormatter()));
+  EXPECT_EQ(
+      "0x0000000a-hell-3.",
+      absl::StrJoin(std::make_tuple(x, std::cref(y), z), "-", TestFormatter()));
+  EXPECT_EQ("0x0000000a-hell-3.",
+            absl::StrJoin(std::make_tuple(&x, &y, &z), "-",
+                          absl::DereferenceFormatter(TestFormatter())));
+  EXPECT_EQ("0x0000000a-hell-3.",
+            absl::StrJoin(std::make_tuple(absl::make_unique<int>(x),
+                                          absl::make_unique<std::string>(y),
+                                          absl::make_unique<double>(z)),
+                          "-", absl::DereferenceFormatter(TestFormatter())));
+  EXPECT_EQ("0x0000000a-hell-3.",
+            absl::StrJoin(std::make_tuple(absl::make_unique<int>(x), &y, &z),
+                          "-", absl::DereferenceFormatter(TestFormatter())));
+}
+
+}  // namespace

http://git-wip-us.apache.org/repos/asf/marmotta/blob/0eb556da/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_replace.cc
----------------------------------------------------------------------
diff --git a/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_replace.cc b/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_replace.cc
new file mode 100644
index 0000000..69efa35
--- /dev/null
+++ b/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_replace.cc
@@ -0,0 +1,79 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/str_replace.h"
+
+#include "absl/strings/str_cat.h"
+
+namespace absl {
+namespace strings_internal {
+
+using FixedMapping =
+    std::initializer_list<std::pair<absl::string_view, absl::string_view>>;
+
+// Applies the ViableSubstitutions in subs_ptr to the absl::string_view s, and
+// stores the result in *result_ptr. Returns the number of substitutions that
+// occurred.
+int ApplySubstitutions(
+    absl::string_view s,
+    std::vector<strings_internal::ViableSubstitution>* subs_ptr,
+    std::string* result_ptr) {
+  auto& subs = *subs_ptr;
+  int substitutions = 0;
+  size_t pos = 0;
+  while (!subs.empty()) {
+    auto& sub = subs.back();
+    if (sub.offset >= pos) {
+      if (pos <= s.size()) {
+        StrAppend(result_ptr, s.substr(pos, sub.offset - pos), sub.replacement);
+      }
+      pos = sub.offset + sub.old.size();
+      substitutions += 1;
+    }
+    sub.offset = s.find(sub.old, pos);
+    if (sub.offset == s.npos) {
+      subs.pop_back();
+    } else {
+      // Insertion sort to ensure the last ViableSubstitution continues to be
+      // before all the others.
+      size_t index = subs.size();
+      while (--index && subs[index - 1].OccursBefore(subs[index])) {
+        std::swap(subs[index], subs[index - 1]);
+      }
+    }
+  }
+  result_ptr->append(s.data() + pos, s.size() - pos);
+  return substitutions;
+}
+
+}  // namespace strings_internal
+
+// We can implement this in terms of the generic StrReplaceAll, but
+// we must specify the template overload because C++ cannot deduce the type
+// of an initializer_list parameter to a function, and also if we don't specify
+// the type, we just call ourselves.
+//
+// Note that we implement them here, rather than in the header, so that they
+// aren't inlined.
+
+std::string StrReplaceAll(absl::string_view s,
+                     strings_internal::FixedMapping replacements) {
+  return StrReplaceAll<strings_internal::FixedMapping>(s, replacements);
+}
+
+int StrReplaceAll(strings_internal::FixedMapping replacements, std::string* target) {
+  return StrReplaceAll<strings_internal::FixedMapping>(replacements, target);
+}
+
+}  // namespace absl

http://git-wip-us.apache.org/repos/asf/marmotta/blob/0eb556da/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_replace.h
----------------------------------------------------------------------
diff --git a/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_replace.h b/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_replace.h
new file mode 100644
index 0000000..f4d9bb9
--- /dev/null
+++ b/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_replace.h
@@ -0,0 +1,213 @@
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: str_replace.h
+// -----------------------------------------------------------------------------
+//
+// This file defines `absl::StrReplaceAll()`, a general-purpose std::string
+// replacement function designed for large, arbitrary text substitutions,
+// especially on strings which you are receiving from some other system for
+// further processing (e.g. processing regular expressions, escaping HTML
+// entities, etc. `StrReplaceAll` is designed to be efficient even when only
+// one substitution is being performed, or when substitution is rare.
+//
+// If the std::string being modified is known at compile-time, and the substitutions
+// vary, `absl::Substitute()` may be a better choice.
+//
+// Example:
+//
+// std::string html_escaped = absl::StrReplaceAll(user_input, {
+//                                           {"&", "&amp;"},
+//                                           {"<", "&lt;"},
+//                                           {">", "&gt;"},
+//                                           {"\"", "&quot;"},
+//                                           {"'", "&#39;"}});
+#ifndef ABSL_STRINGS_STR_REPLACE_H_
+#define ABSL_STRINGS_STR_REPLACE_H_
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/base/attributes.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+
+// StrReplaceAll()
+//
+// Replaces character sequences within a given std::string with replacements provided
+// within an initializer list of key/value pairs. Candidate replacements are
+// considered in order as they occur within the std::string, with earlier matches
+// taking precedence, and longer matches taking precedence for candidates
+// starting at the same position in the std::string. Once a substitution is made, the
+// replaced text is not considered for any further substitutions.
+//
+// Example:
+//
+//   std::string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
+//                                  {{"$count", absl::StrCat(5)},
+//                                   {"$who", "Bob"},
+//                                   {"#Noun", "Apples"}});
+//   EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
+ABSL_MUST_USE_RESULT std::string StrReplaceAll(
+    absl::string_view s,
+    std::initializer_list<std::pair<absl::string_view, absl::string_view>>
+        replacements);
+
+// Overload of `StrReplaceAll()` to accept a container of key/value replacement
+// pairs (typically either an associative map or a `std::vector` of `std::pair`
+// elements). A vector of pairs is generally more efficient.
+//
+// Examples:
+//
+//   std::map<const absl::string_view, const absl::string_view> replacements;
+//   replacements["$who"] = "Bob";
+//   replacements["$count"] = "5";
+//   replacements["#Noun"] = "Apples";
+//   std::string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
+//                                  replacements);
+//   EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
+//
+//   // A std::vector of std::pair elements can be more efficient.
+//   std::vector<std::pair<const absl::string_view, std::string>> replacements;
+//   replacements.push_back({"&", "&amp;"});
+//   replacements.push_back({"<", "&lt;"});
+//   replacements.push_back({">", "&gt;"});
+//   std::string s = absl::StrReplaceAll("if (ptr < &foo)",
+//                                  replacements);
+//   EXPECT_EQ("if (ptr &lt; &amp;foo)", s);
+template <typename StrToStrMapping>
+std::string StrReplaceAll(absl::string_view s, const StrToStrMapping& replacements);
+
+// Overload of `StrReplaceAll()` to replace character sequences within a given
+// output std::string *in place* with replacements provided within an initializer
+// list of key/value pairs, returning the number of substitutions that occurred.
+//
+// Example:
+//
+//   std::string s = std::string("$who bought $count #Noun. Thanks $who!");
+//   int count;
+//   count = absl::StrReplaceAll({{"$count", absl::StrCat(5)},
+//                               {"$who", "Bob"},
+//                               {"#Noun", "Apples"}}, &s);
+//  EXPECT_EQ(count, 4);
+//  EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
+int StrReplaceAll(
+    std::initializer_list<std::pair<absl::string_view, absl::string_view>>
+        replacements,
+    std::string* target);
+
+// Overload of `StrReplaceAll()` to replace patterns within a given output
+// std::string *in place* with replacements provided within a container of key/value
+// pairs.
+//
+// Example:
+//
+//   std::string s = std::string("if (ptr < &foo)");
+//   int count = absl::StrReplaceAll({{"&", "&amp;"},
+//                                    {"<", "&lt;"},
+//                                    {">", "&gt;"}}, &s);
+//  EXPECT_EQ(count, 2);
+//  EXPECT_EQ("if (ptr &lt; &amp;foo)", s);
+template <typename StrToStrMapping>
+int StrReplaceAll(const StrToStrMapping& replacements, std::string* target);
+
+// Implementation details only, past this point.
+namespace strings_internal {
+
+struct ViableSubstitution {
+  absl::string_view old;
+  absl::string_view replacement;
+  size_t offset;
+
+  ViableSubstitution(absl::string_view old_str,
+                     absl::string_view replacement_str, size_t offset_val)
+      : old(old_str), replacement(replacement_str), offset(offset_val) {}
+
+  // One substitution occurs "before" another (takes priority) if either
+  // it has the lowest offset, or it has the same offset but a larger size.
+  bool OccursBefore(const ViableSubstitution& y) const {
+    if (offset != y.offset) return offset < y.offset;
+    return old.size() > y.old.size();
+  }
+};
+
+// Build a vector of ViableSubstitutions based on the given list of
+// replacements. subs can be implemented as a priority_queue. However, it turns
+// out that most callers have small enough a list of substitutions that the
+// overhead of such a queue isn't worth it.
+template <typename StrToStrMapping>
+std::vector<ViableSubstitution> FindSubstitutions(
+    absl::string_view s, const StrToStrMapping& replacements) {
+  std::vector<ViableSubstitution> subs;
+  subs.reserve(replacements.size());
+
+  for (const auto& rep : replacements) {
+    using std::get;
+    absl::string_view old(get<0>(rep));
+
+    size_t pos = s.find(old);
+    if (pos == s.npos) continue;
+
+    // Ignore attempts to replace "". This condition is almost never true,
+    // but above condition is frequently true. That's why we test for this
+    // now and not before.
+    if (old.empty()) continue;
+
+    subs.emplace_back(old, get<1>(rep), pos);
+
+    // Insertion sort to ensure the last ViableSubstitution comes before
+    // all the others.
+    size_t index = subs.size();
+    while (--index && subs[index - 1].OccursBefore(subs[index])) {
+      std::swap(subs[index], subs[index - 1]);
+    }
+  }
+  return subs;
+}
+
+int ApplySubstitutions(absl::string_view s,
+                       std::vector<ViableSubstitution>* subs_ptr,
+                       std::string* result_ptr);
+
+}  // namespace strings_internal
+
+template <typename StrToStrMapping>
+std::string StrReplaceAll(absl::string_view s, const StrToStrMapping& replacements) {
+  auto subs = strings_internal::FindSubstitutions(s, replacements);
+  std::string result;
+  result.reserve(s.size());
+  strings_internal::ApplySubstitutions(s, &subs, &result);
+  return result;
+}
+
+template <typename StrToStrMapping>
+int StrReplaceAll(const StrToStrMapping& replacements, std::string* target) {
+  auto subs = strings_internal::FindSubstitutions(*target, replacements);
+  if (subs.empty()) return 0;
+
+  std::string result;
+  result.reserve(target->size());
+  int substitutions =
+      strings_internal::ApplySubstitutions(*target, &subs, &result);
+  target->swap(result);
+  return substitutions;
+}
+
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_STR_REPLACE_H_

http://git-wip-us.apache.org/repos/asf/marmotta/blob/0eb556da/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_replace_test.cc
----------------------------------------------------------------------
diff --git a/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_replace_test.cc b/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_replace_test.cc
new file mode 100644
index 0000000..5d003a2
--- /dev/null
+++ b/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_replace_test.cc
@@ -0,0 +1,341 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/str_replace.h"
+
+#include <list>
+#include <map>
+#include <tuple>
+
+#include "gtest/gtest.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
+
+TEST(StrReplaceAll, OneReplacement) {
+  std::string s;
+
+  // Empty std::string.
+  s = absl::StrReplaceAll(s, {{"", ""}});
+  EXPECT_EQ(s, "");
+  s = absl::StrReplaceAll(s, {{"x", ""}});
+  EXPECT_EQ(s, "");
+  s = absl::StrReplaceAll(s, {{"", "y"}});
+  EXPECT_EQ(s, "");
+  s = absl::StrReplaceAll(s, {{"x", "y"}});
+  EXPECT_EQ(s, "");
+
+  // Empty substring.
+  s = absl::StrReplaceAll("abc", {{"", ""}});
+  EXPECT_EQ(s, "abc");
+  s = absl::StrReplaceAll("abc", {{"", "y"}});
+  EXPECT_EQ(s, "abc");
+  s = absl::StrReplaceAll("abc", {{"x", ""}});
+  EXPECT_EQ(s, "abc");
+
+  // Substring not found.
+  s = absl::StrReplaceAll("abc", {{"xyz", "123"}});
+  EXPECT_EQ(s, "abc");
+
+  // Replace entire std::string.
+  s = absl::StrReplaceAll("abc", {{"abc", "xyz"}});
+  EXPECT_EQ(s, "xyz");
+
+  // Replace once at the start.
+  s = absl::StrReplaceAll("abc", {{"a", "x"}});
+  EXPECT_EQ(s, "xbc");
+
+  // Replace once in the middle.
+  s = absl::StrReplaceAll("abc", {{"b", "x"}});
+  EXPECT_EQ(s, "axc");
+
+  // Replace once at the end.
+  s = absl::StrReplaceAll("abc", {{"c", "x"}});
+  EXPECT_EQ(s, "abx");
+
+  // Replace multiple times with varying lengths of original/replacement.
+  s = absl::StrReplaceAll("ababa", {{"a", "xxx"}});
+  EXPECT_EQ(s, "xxxbxxxbxxx");
+
+  s = absl::StrReplaceAll("ababa", {{"b", "xxx"}});
+  EXPECT_EQ(s, "axxxaxxxa");
+
+  s = absl::StrReplaceAll("aaabaaabaaa", {{"aaa", "x"}});
+  EXPECT_EQ(s, "xbxbx");
+
+  s = absl::StrReplaceAll("abbbabbba", {{"bbb", "x"}});
+  EXPECT_EQ(s, "axaxa");
+
+  // Overlapping matches are replaced greedily.
+  s = absl::StrReplaceAll("aaa", {{"aa", "x"}});
+  EXPECT_EQ(s, "xa");
+
+  // The replacements are not recursive.
+  s = absl::StrReplaceAll("aaa", {{"aa", "a"}});
+  EXPECT_EQ(s, "aa");
+}
+
+TEST(StrReplaceAll, ManyReplacements) {
+  std::string s;
+
+  // Empty std::string.
+  s = absl::StrReplaceAll("", {{"", ""}, {"x", ""}, {"", "y"}, {"x", "y"}});
+  EXPECT_EQ(s, "");
+
+  // Empty substring.
+  s = absl::StrReplaceAll("abc", {{"", ""}, {"", "y"}, {"x", ""}});
+  EXPECT_EQ(s, "abc");
+
+  // Replace entire std::string, one char at a time
+  s = absl::StrReplaceAll("abc", {{"a", "x"}, {"b", "y"}, {"c", "z"}});
+  EXPECT_EQ(s, "xyz");
+  s = absl::StrReplaceAll("zxy", {{"z", "x"}, {"x", "y"}, {"y", "z"}});
+  EXPECT_EQ(s, "xyz");
+
+  // Replace once at the start (longer matches take precedence)
+  s = absl::StrReplaceAll("abc", {{"a", "x"}, {"ab", "xy"}, {"abc", "xyz"}});
+  EXPECT_EQ(s, "xyz");
+
+  // Replace once in the middle.
+  s = absl::StrReplaceAll(
+      "Abc!", {{"a", "x"}, {"ab", "xy"}, {"b", "y"}, {"bc", "yz"}, {"c", "z"}});
+  EXPECT_EQ(s, "Ayz!");
+
+  // Replace once at the end.
+  s = absl::StrReplaceAll(
+      "Abc!",
+      {{"a", "x"}, {"ab", "xy"}, {"b", "y"}, {"bc!", "yz?"}, {"c!", "z;"}});
+  EXPECT_EQ(s, "Ayz?");
+
+  // Replace multiple times with varying lengths of original/replacement.
+  s = absl::StrReplaceAll("ababa", {{"a", "xxx"}, {"b", "XXXX"}});
+  EXPECT_EQ(s, "xxxXXXXxxxXXXXxxx");
+
+  // Overlapping matches are replaced greedily.
+  s = absl::StrReplaceAll("aaa", {{"aa", "x"}, {"a", "X"}});
+  EXPECT_EQ(s, "xX");
+  s = absl::StrReplaceAll("aaa", {{"a", "X"}, {"aa", "x"}});
+  EXPECT_EQ(s, "xX");
+
+  // Two well-known sentences
+  s = absl::StrReplaceAll("the quick brown fox jumped over the lazy dogs",
+                          {
+                              {"brown", "box"},
+                              {"dogs", "jugs"},
+                              {"fox", "with"},
+                              {"jumped", "five"},
+                              {"over", "dozen"},
+                              {"quick", "my"},
+                              {"the", "pack"},
+                              {"the lazy", "liquor"},
+                          });
+  EXPECT_EQ(s, "pack my box with five dozen liquor jugs");
+}
+
+TEST(StrReplaceAll, ManyReplacementsInMap) {
+  std::map<const char *, const char *> replacements;
+  replacements["$who"] = "Bob";
+  replacements["$count"] = "5";
+  replacements["#Noun"] = "Apples";
+  std::string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
+                                 replacements);
+  EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
+}
+
+TEST(StrReplaceAll, ReplacementsInPlace) {
+  std::string s = std::string("$who bought $count #Noun. Thanks $who!");
+  int count;
+  count = absl::StrReplaceAll({{"$count", absl::StrCat(5)},
+                              {"$who", "Bob"},
+                              {"#Noun", "Apples"}}, &s);
+  EXPECT_EQ(count, 4);
+  EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
+}
+
+TEST(StrReplaceAll, ReplacementsInPlaceInMap) {
+  std::string s = std::string("$who bought $count #Noun. Thanks $who!");
+  std::map<absl::string_view, absl::string_view> replacements;
+  replacements["$who"] = "Bob";
+  replacements["$count"] = "5";
+  replacements["#Noun"] = "Apples";
+  int count;
+  count = absl::StrReplaceAll(replacements, &s);
+  EXPECT_EQ(count, 4);
+  EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
+}
+
+struct Cont {
+  Cont() {}
+  explicit Cont(absl::string_view src) : data(src) {}
+
+  absl::string_view data;
+};
+
+template <int index>
+absl::string_view get(const Cont& c) {
+  auto splitter = absl::StrSplit(c.data, ':');
+  auto it = splitter.begin();
+  for (int i = 0; i < index; ++i) ++it;
+
+  return *it;
+}
+
+TEST(StrReplaceAll, VariableNumber) {
+  std::string s;
+  {
+    std::vector<std::pair<std::string, std::string>> replacements;
+
+    s = "abc";
+    EXPECT_EQ(0, absl::StrReplaceAll(replacements, &s));
+    EXPECT_EQ("abc", s);
+
+    s = "abc";
+    replacements.push_back({"a", "A"});
+    EXPECT_EQ(1, absl::StrReplaceAll(replacements, &s));
+    EXPECT_EQ("Abc", s);
+
+    s = "abc";
+    replacements.push_back({"b", "B"});
+    EXPECT_EQ(2, absl::StrReplaceAll(replacements, &s));
+    EXPECT_EQ("ABc", s);
+
+    s = "abc";
+    replacements.push_back({"d", "D"});
+    EXPECT_EQ(2, absl::StrReplaceAll(replacements, &s));
+    EXPECT_EQ("ABc", s);
+
+    EXPECT_EQ("ABcABc", absl::StrReplaceAll("abcabc", replacements));
+  }
+
+  {
+    std::map<const char*, const char*> replacements;
+    replacements["aa"] = "x";
+    replacements["a"] = "X";
+    s = "aaa";
+    EXPECT_EQ(2, absl::StrReplaceAll(replacements, &s));
+    EXPECT_EQ("xX", s);
+
+    EXPECT_EQ("xxX", absl::StrReplaceAll("aaaaa", replacements));
+  }
+
+  {
+    std::list<std::pair<absl::string_view, absl::string_view>> replacements = {
+        {"a", "x"}, {"b", "y"}, {"c", "z"}};
+
+    std::string s = absl::StrReplaceAll("abc", replacements);
+    EXPECT_EQ(s, "xyz");
+  }
+
+  {
+    using X = std::tuple<absl::string_view, std::string, int>;
+    std::vector<X> replacements(3);
+    replacements[0] = X{"a", "x", 1};
+    replacements[1] = X{"b", "y", 0};
+    replacements[2] = X{"c", "z", -1};
+
+    std::string s = absl::StrReplaceAll("abc", replacements);
+    EXPECT_EQ(s, "xyz");
+  }
+
+  {
+    std::vector<Cont> replacements(3);
+    replacements[0] = Cont{"a:x"};
+    replacements[1] = Cont{"b:y"};
+    replacements[2] = Cont{"c:z"};
+
+    std::string s = absl::StrReplaceAll("abc", replacements);
+    EXPECT_EQ(s, "xyz");
+  }
+}
+
+// Same as above, but using the in-place variant of absl::StrReplaceAll,
+// that returns the # of replacements performed.
+TEST(StrReplaceAll, Inplace) {
+  std::string s;
+  int reps;
+
+  // Empty std::string.
+  s = "";
+  reps = absl::StrReplaceAll({{"", ""}, {"x", ""}, {"", "y"}, {"x", "y"}}, &s);
+  EXPECT_EQ(reps, 0);
+  EXPECT_EQ(s, "");
+
+  // Empty substring.
+  s = "abc";
+  reps = absl::StrReplaceAll({{"", ""}, {"", "y"}, {"x", ""}}, &s);
+  EXPECT_EQ(reps, 0);
+  EXPECT_EQ(s, "abc");
+
+  // Replace entire std::string, one char at a time
+  s = "abc";
+  reps = absl::StrReplaceAll({{"a", "x"}, {"b", "y"}, {"c", "z"}}, &s);
+  EXPECT_EQ(reps, 3);
+  EXPECT_EQ(s, "xyz");
+  s = "zxy";
+  reps = absl::StrReplaceAll({{"z", "x"}, {"x", "y"}, {"y", "z"}}, &s);
+  EXPECT_EQ(reps, 3);
+  EXPECT_EQ(s, "xyz");
+
+  // Replace once at the start (longer matches take precedence)
+  s = "abc";
+  reps = absl::StrReplaceAll({{"a", "x"}, {"ab", "xy"}, {"abc", "xyz"}}, &s);
+  EXPECT_EQ(reps, 1);
+  EXPECT_EQ(s, "xyz");
+
+  // Replace once in the middle.
+  s = "Abc!";
+  reps = absl::StrReplaceAll(
+      {{"a", "x"}, {"ab", "xy"}, {"b", "y"}, {"bc", "yz"}, {"c", "z"}}, &s);
+  EXPECT_EQ(reps, 1);
+  EXPECT_EQ(s, "Ayz!");
+
+  // Replace once at the end.
+  s = "Abc!";
+  reps = absl::StrReplaceAll(
+      {{"a", "x"}, {"ab", "xy"}, {"b", "y"}, {"bc!", "yz?"}, {"c!", "z;"}}, &s);
+  EXPECT_EQ(reps, 1);
+  EXPECT_EQ(s, "Ayz?");
+
+  // Replace multiple times with varying lengths of original/replacement.
+  s = "ababa";
+  reps = absl::StrReplaceAll({{"a", "xxx"}, {"b", "XXXX"}}, &s);
+  EXPECT_EQ(reps, 5);
+  EXPECT_EQ(s, "xxxXXXXxxxXXXXxxx");
+
+  // Overlapping matches are replaced greedily.
+  s = "aaa";
+  reps = absl::StrReplaceAll({{"aa", "x"}, {"a", "X"}}, &s);
+  EXPECT_EQ(reps, 2);
+  EXPECT_EQ(s, "xX");
+  s = "aaa";
+  reps = absl::StrReplaceAll({{"a", "X"}, {"aa", "x"}}, &s);
+  EXPECT_EQ(reps, 2);
+  EXPECT_EQ(s, "xX");
+
+  // Two well-known sentences
+  s = "the quick brown fox jumped over the lazy dogs";
+  reps = absl::StrReplaceAll(
+      {
+          {"brown", "box"},
+          {"dogs", "jugs"},
+          {"fox", "with"},
+          {"jumped", "five"},
+          {"over", "dozen"},
+          {"quick", "my"},
+          {"the", "pack"},
+          {"the lazy", "liquor"},
+      },
+      &s);
+  EXPECT_EQ(reps, 8);
+  EXPECT_EQ(s, "pack my box with five dozen liquor jugs");
+}

http://git-wip-us.apache.org/repos/asf/marmotta/blob/0eb556da/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_split.cc
----------------------------------------------------------------------
diff --git a/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_split.cc b/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_split.cc
new file mode 100644
index 0000000..0207213
--- /dev/null
+++ b/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_split.cc
@@ -0,0 +1,136 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/str_split.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iterator>
+#include <limits>
+#include <memory>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/strings/ascii.h"
+
+namespace absl {
+
+namespace {
+
+// This GenericFind() template function encapsulates the finding algorithm
+// shared between the ByString and ByAnyChar delimiters. The FindPolicy
+// template parameter allows each delimiter to customize the actual find
+// function to use and the length of the found delimiter. For example, the
+// Literal delimiter will ultimately use absl::string_view::find(), and the
+// AnyOf delimiter will use absl::string_view::find_first_of().
+template <typename FindPolicy>
+absl::string_view GenericFind(absl::string_view text,
+                              absl::string_view delimiter, size_t pos,
+                              FindPolicy find_policy) {
+  if (delimiter.empty() && text.length() > 0) {
+    // Special case for empty std::string delimiters: always return a zero-length
+    // absl::string_view referring to the item at position 1 past pos.
+    return absl::string_view(text.begin() + pos + 1, 0);
+  }
+  size_t found_pos = absl::string_view::npos;
+  absl::string_view found(text.end(), 0);  // By default, not found
+  found_pos = find_policy.Find(text, delimiter, pos);
+  if (found_pos != absl::string_view::npos) {
+    found = absl::string_view(text.data() + found_pos,
+                              find_policy.Length(delimiter));
+  }
+  return found;
+}
+
+// Finds using absl::string_view::find(), therefore the length of the found
+// delimiter is delimiter.length().
+struct LiteralPolicy {
+  size_t Find(absl::string_view text, absl::string_view delimiter, size_t pos) {
+    return text.find(delimiter, pos);
+  }
+  size_t Length(absl::string_view delimiter) { return delimiter.length(); }
+};
+
+// Finds using absl::string_view::find_first_of(), therefore the length of the
+// found delimiter is 1.
+struct AnyOfPolicy {
+  size_t Find(absl::string_view text, absl::string_view delimiter, size_t pos) {
+    return text.find_first_of(delimiter, pos);
+  }
+  size_t Length(absl::string_view /* delimiter */) { return 1; }
+};
+
+}  // namespace
+
+//
+// ByString
+//
+
+ByString::ByString(absl::string_view sp) : delimiter_(sp) {}
+
+absl::string_view ByString::Find(absl::string_view text, size_t pos) const {
+  if (delimiter_.length() == 1) {
+    // Much faster to call find on a single character than on an
+    // absl::string_view.
+    size_t found_pos = text.find(delimiter_[0], pos);
+    if (found_pos == absl::string_view::npos)
+      return absl::string_view(text.end(), 0);
+    return text.substr(found_pos, 1);
+  }
+  return GenericFind(text, delimiter_, pos, LiteralPolicy());
+}
+
+//
+// ByChar
+//
+
+absl::string_view ByChar::Find(absl::string_view text, size_t pos) const {
+  size_t found_pos = text.find(c_, pos);
+  if (found_pos == absl::string_view::npos)
+    return absl::string_view(text.end(), 0);
+  return text.substr(found_pos, 1);
+}
+
+//
+// ByAnyChar
+//
+
+ByAnyChar::ByAnyChar(absl::string_view sp) : delimiters_(sp) {}
+
+absl::string_view ByAnyChar::Find(absl::string_view text, size_t pos) const {
+  return GenericFind(text, delimiters_, pos, AnyOfPolicy());
+}
+
+//
+// ByLength
+//
+ByLength::ByLength(ptrdiff_t length) : length_(length) {
+  ABSL_RAW_CHECK(length > 0, "");
+}
+
+absl::string_view ByLength::Find(absl::string_view text,
+                                      size_t pos) const {
+  pos = std::min(pos, text.size());  // truncate `pos`
+  absl::string_view substr = text.substr(pos);
+  // If the std::string is shorter than the chunk size we say we
+  // "can't find the delimiter" so this will be the last chunk.
+  if (substr.length() <= static_cast<size_t>(length_))
+    return absl::string_view(text.end(), 0);
+
+  return absl::string_view(substr.begin() + length_, 0);
+}
+
+}  // namespace absl

http://git-wip-us.apache.org/repos/asf/marmotta/blob/0eb556da/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_split.h
----------------------------------------------------------------------
diff --git a/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_split.h b/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_split.h
new file mode 100644
index 0000000..1f089b9
--- /dev/null
+++ b/libraries/ostrich/backend/3rdparty/abseil/absl/strings/str_split.h
@@ -0,0 +1,511 @@
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: str_split.h
+// -----------------------------------------------------------------------------
+//
+// This file contains functions for splitting strings. It defines the main
+// `StrSplit()` function, several delimiters for determining the boundaries on
+// which to split the std::string, and predicates for filtering delimited results.
+// `StrSplit()` adapts the returned collection to the type specified by the
+// caller.
+//
+// Example:
+//
+//   // Splits the given std::string on commas. Returns the results in a
+//   // vector of strings.
+//   std::vector<std::string> v = absl::StrSplit("a,b,c", ',');
+//   // Can also use ","
+//   // v[0] == "a", v[1] == "b", v[2] == "c"
+//
+// See StrSplit() below for more information.
+#ifndef ABSL_STRINGS_STR_SPLIT_H_
+#define ABSL_STRINGS_STR_SPLIT_H_
+
+#include <algorithm>
+#include <cstddef>
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/strings/internal/str_split_internal.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+
+namespace absl {
+
+//------------------------------------------------------------------------------
+// Delimiters
+//------------------------------------------------------------------------------
+//
+// `StrSplit()` uses delimiters to define the boundaries between elements in the
+// provided input. Several `Delimiter` types are defined below. If a std::string
+// (`const char*`, `std::string`, or `absl::string_view`) is passed in place of
+// an explicit `Delimiter` object, `StrSplit()` treats it the same way as if it
+// were passed a `ByString` delimiter.
+//
+// A `Delimiter` is an object with a `Find()` function that knows how to find
+// the first occurrence of itself in a given `absl::string_view`.
+//
+// The following `Delimiter` types are available for use within `StrSplit()`:
+//
+//   - `ByString` (default for std::string arguments)
+//   - `ByChar` (default for a char argument)
+//   - `ByAnyChar`
+//   - `ByLength`
+//   - `MaxSplits`
+//
+//
+// A Delimiter's Find() member function will be passed the input text that is to
+// be split and the position to begin searching for the next delimiter in the
+// input text. The returned absl::string_view should refer to the next
+// occurrence (after pos) of the represented delimiter; this returned
+// absl::string_view represents the next location where the input std::string should
+// be broken. The returned absl::string_view may be zero-length if the Delimiter
+// does not represent a part of the std::string (e.g., a fixed-length delimiter). If
+// no delimiter is found in the given text, a zero-length absl::string_view
+// referring to text.end() should be returned (e.g.,
+// absl::string_view(text.end(), 0)). It is important that the returned
+// absl::string_view always be within the bounds of input text given as an
+// argument--it must not refer to a std::string that is physically located outside of
+// the given std::string.
+//
+// The following example is a simple Delimiter object that is created with a
+// single char and will look for that char in the text passed to the Find()
+// function:
+//
+//   struct SimpleDelimiter {
+//     const char c_;
+//     explicit SimpleDelimiter(char c) : c_(c) {}
+//     absl::string_view Find(absl::string_view text, size_t pos) {
+//       auto found = text.find(c_, pos);
+//       if (found == absl::string_view::npos)
+//         return absl::string_view(text.end(), 0);
+//
+//       return absl::string_view(text, found, 1);
+//     }
+//   };
+
+// ByString
+//
+// A sub-std::string delimiter. If `StrSplit()` is passed a std::string in place of a
+// `Delimiter` object, the std::string will be implicitly converted into a
+// `ByString` delimiter.
+//
+// Example:
+//
+//   // Because a std::string literal is converted to an `absl::ByString`,
+//   // the following two splits are equivalent.
+//
+//   std::vector<std::string> v1 = absl::StrSplit("a, b, c", ", ");
+//
+//   using absl::ByString;
+//   std::vector<std::string> v2 = absl::StrSplit("a, b, c",
+//                                                ByString(", "));
+//   // v[0] == "a", v[1] == "b", v[2] == "c"
+class ByString {
+ public:
+  explicit ByString(absl::string_view sp);
+  absl::string_view Find(absl::string_view text, size_t pos) const;
+
+ private:
+  const std::string delimiter_;
+};
+
+// ByChar
+//
+// A single character delimiter. `ByChar` is functionally equivalent to a
+// 1-char std::string within a `ByString` delimiter, but slightly more
+// efficient.
+//
+// Example:
+//
+//   // Because a char literal is converted to a absl::ByChar,
+//   // the following two splits are equivalent.
+//   std::vector<std::string> v1 = absl::StrSplit("a,b,c", ',');
+//   using absl::ByChar;
+//   std::vector<std::string> v2 = absl::StrSplit("a,b,c", ByChar(','));
+//   // v[0] == "a", v[1] == "b", v[2] == "c"
+//
+// `ByChar` is also the default delimiter if a single character is given
+// as the delimiter to `StrSplit()`. For example, the following calls are
+// equivalent:
+//
+//   std::vector<std::string> v = absl::StrSplit("a-b", '-');
+//
+//   using absl::ByChar;
+//   std::vector<std::string> v = absl::StrSplit("a-b", ByChar('-'));
+//
+class ByChar {
+ public:
+  explicit ByChar(char c) : c_(c) {}
+  absl::string_view Find(absl::string_view text, size_t pos) const;
+
+ private:
+  char c_;
+};
+
+// ByAnyChar
+//
+// A delimiter that will match any of the given byte-sized characters within
+// its provided std::string.
+//
+// Note: this delimiter works with single-byte std::string data, but does not work
+// with variable-width encodings, such as UTF-8.
+//
+// Example:
+//
+//   using absl::ByAnyChar;
+//   std::vector<std::string> v = absl::StrSplit("a,b=c", ByAnyChar(",="));
+//   // v[0] == "a", v[1] == "b", v[2] == "c"
+//
+// If `ByAnyChar` is given the empty std::string, it behaves exactly like
+// `ByString` and matches each individual character in the input std::string.
+//
+class ByAnyChar {
+ public:
+  explicit ByAnyChar(absl::string_view sp);
+  absl::string_view Find(absl::string_view text, size_t pos) const;
+
+ private:
+  const std::string delimiters_;
+};
+
+// ByLength
+//
+// A delimiter for splitting into equal-length strings. The length argument to
+// the constructor must be greater than 0.
+//
+// Note: this delimiter works with single-byte std::string data, but does not work
+// with variable-width encodings, such as UTF-8.
+//
+// Example:
+//
+//   using absl::ByLength;
+//   std::vector<std::string> v = absl::StrSplit("123456789", ByLength(3));
+
+//   // v[0] == "123", v[1] == "456", v[2] == "789"
+//
+// Note that the std::string does not have to be a multiple of the fixed split
+// length. In such a case, the last substring will be shorter.
+//
+//   using absl::ByLength;
+//   std::vector<std::string> v = absl::StrSplit("12345", ByLength(2));
+//
+//   // v[0] == "12", v[1] == "34", v[2] == "5"
+class ByLength {
+ public:
+  explicit ByLength(ptrdiff_t length);
+  absl::string_view Find(absl::string_view text, size_t pos) const;
+
+ private:
+  const ptrdiff_t length_;
+};
+
+namespace strings_internal {
+
+// A traits-like metafunction for selecting the default Delimiter object type
+// for a particular Delimiter type. The base case simply exposes type Delimiter
+// itself as the delimiter's Type. However, there are specializations for
+// std::string-like objects that map them to the ByString delimiter object.
+// This allows functions like absl::StrSplit() and absl::MaxSplits() to accept
+// std::string-like objects (e.g., ',') as delimiter arguments but they will be
+// treated as if a ByString delimiter was given.
+template <typename Delimiter>
+struct SelectDelimiter {
+  using type = Delimiter;
+};
+
+template <>
+struct SelectDelimiter<char> {
+  using type = ByChar;
+};
+template <>
+struct SelectDelimiter<char*> {
+  using type = ByString;
+};
+template <>
+struct SelectDelimiter<const char*> {
+  using type = ByString;
+};
+template <>
+struct SelectDelimiter<absl::string_view> {
+  using type = ByString;
+};
+template <>
+struct SelectDelimiter<std::string> {
+  using type = ByString;
+};
+
+// Wraps another delimiter and sets a max number of matches for that delimiter.
+template <typename Delimiter>
+class MaxSplitsImpl {
+ public:
+  MaxSplitsImpl(Delimiter delimiter, int limit)
+      : delimiter_(delimiter), limit_(limit), count_(0) {}
+  absl::string_view Find(absl::string_view text, size_t pos) {
+    if (count_++ == limit_) {
+      return absl::string_view(text.end(), 0);  // No more matches.
+    }
+    return delimiter_.Find(text, pos);
+  }
+
+ private:
+  Delimiter delimiter_;
+  const int limit_;
+  int count_;
+};
+
+}  // namespace strings_internal
+
+// MaxSplits()
+//
+// A delimiter that limits the number of matches which can occur to the passed
+// `limit`. The last element in the returned collection will contain all
+// remaining unsplit pieces, which may contain instances of the delimiter.
+// The collection will contain at most `limit` + 1 elements.
+// Example:
+//
+//   using absl::MaxSplits;
+//   std::vector<std::string> v = absl::StrSplit("a,b,c", MaxSplits(',', 1));
+//
+//   // v[0] == "a", v[1] == "b,c"
+template <typename Delimiter>
+inline strings_internal::MaxSplitsImpl<
+    typename strings_internal::SelectDelimiter<Delimiter>::type>
+MaxSplits(Delimiter delimiter, int limit) {
+  typedef
+      typename strings_internal::SelectDelimiter<Delimiter>::type DelimiterType;
+  return strings_internal::MaxSplitsImpl<DelimiterType>(
+      DelimiterType(delimiter), limit);
+}
+
+//------------------------------------------------------------------------------
+// Predicates
+//------------------------------------------------------------------------------
+//
+// Predicates filter the results of a `StrSplit()` by determining whether or not
+// a resultant element is included in the result set. A predicate may be passed
+// as an optional third argument to the `StrSplit()` function.
+//
+// Predicates are unary functions (or functors) that take a single
+// `absl::string_view` argument and return a bool indicating whether the
+// argument should be included (`true`) or excluded (`false`).
+//
+// Predicates are useful when filtering out empty substrings. By default, empty
+// substrings may be returned by `StrSplit()`, which is similar to the way split
+// functions work in other programming languages.
+
+// AllowEmpty()
+//
+// Always returns `true`, indicating that all strings--including empty
+// strings--should be included in the split output. This predicate is not
+// strictly needed because this is the default behavior of `StrSplit()`;
+// however, it might be useful at some call sites to make the intent explicit.
+//
+// Example:
+//
+//  std::vector<std::string> v = absl::StrSplit(" a , ,,b,", ',', AllowEmpty());
+//
+//  // v[0] == " a ", v[1] == " ", v[2] == "", v[3] = "b", v[4] == ""
+struct AllowEmpty {
+  bool operator()(absl::string_view) const { return true; }
+};
+
+// SkipEmpty()
+//
+// Returns `false` if the given `absl::string_view` is empty, indicating that
+// `StrSplit()` should omit the empty std::string.
+//
+// Example:
+//
+//   std::vector<std::string> v = absl::StrSplit(",a,,b,", ',', SkipEmpty());
+//
+//   // v[0] == "a", v[1] == "b"
+//
+// Note: `SkipEmpty()` does not consider a std::string containing only whitespace
+// to be empty. To skip such whitespace as well, use the `SkipWhitespace()`
+// predicate.
+struct SkipEmpty {
+  bool operator()(absl::string_view sp) const { return !sp.empty(); }
+};
+
+// SkipWhitespace()
+//
+// Returns `false` if the given `absl::string_view` is empty *or* contains only
+// whitespace, indicating that `StrSplit()` should omit the std::string.
+//
+// Example:
+//
+//   std::vector<std::string> v = absl::StrSplit(" a , ,,b,",
+//                                               ',', SkipWhitespace());
+//   // v[0] == " a ", v[1] == "b"
+//
+//   // SkipEmpty() would return whitespace elements
+//   std::vector<std::string> v = absl::StrSplit(" a , ,,b,", ',', SkipEmpty());
+//   // v[0] == " a ", v[1] == " ", v[2] == "b"
+struct SkipWhitespace {
+  bool operator()(absl::string_view sp) const {
+    sp = absl::StripAsciiWhitespace(sp);
+    return !sp.empty();
+  }
+};
+
+//------------------------------------------------------------------------------
+//                                  StrSplit()
+//------------------------------------------------------------------------------
+
+// StrSplit()
+//
+// Splits a given `std::string` based on the provided `Delimiter` object,
+// returning the elements within the type specified by the caller. Optionally,
+// you may also pass a `Predicate` to `StrSplit()` indicating whether to include
+// or exclude the resulting element within the final result set. (See the
+// overviews for Delimiters and Predicates above.)
+//
+// Example:
+//
+//   std::vector<std::string> v = absl::StrSplit("a,b,c,d", ',');
+//   // v[0] == "a", v[1] == "b", v[2] == "c", v[3] == "d"
+//
+// You can also provide an explicit `Delimiter` object:
+//
+// Example:
+//
+//   using absl::ByAnyChar;
+//   std::vector<std::string> v = absl::StrSplit("a,b=c", ByAnyChar(",="));
+//   // v[0] == "a", v[1] == "b", v[2] == "c"
+//
+// See above for more information on delimiters.
+//
+// By default, empty strings are included in the result set. You can optionally
+// include a third `Predicate` argument to apply a test for whether the
+// resultant element should be included in the result set:
+//
+// Example:
+//
+//   std::vector<std::string> v = absl::StrSplit(" a , ,,b,",
+//                                               ',', SkipWhitespace());
+//   // v[0] == " a ", v[1] == "b"
+//
+// See above for more information on predicates.
+//
+//------------------------------------------------------------------------------
+// StrSplit() Return Types
+//------------------------------------------------------------------------------
+//
+// The `StrSplit()` function adapts the returned collection to the collection
+// specified by the caller (e.g. `std::vector` above). The returned collections
+// may contain `string`, `absl::string_view` (in which case the original std::string
+// being split must ensure that it outlives the collection), or any object that
+// can be explicitly created from an `absl::string_view`. This behavior works
+// for:
+//
+// 1) All standard STL containers including `std::vector`, `std::list`,
+//    `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap`
+// 2) `std::pair` (which is not actually a container). See below.
+//
+// Example:
+//
+//   // The results are returned as `absl::string_view` objects. Note that we
+//   // have to ensure that the input std::string outlives any results.
+//   std::vector<absl::string_view> v = absl::StrSplit("a,b,c", ',');
+//
+//   // Stores results in a std::set<std::string>, which also performs
+//   // de-duplication and orders the elements in ascending order.
+//   std::set<std::string> a = absl::StrSplit("b,a,c,a,b", ',');
+//   // v[0] == "a", v[1] == "b", v[2] = "c"
+//
+//   // `StrSplit()` can be used within a range-based for loop, in which case
+//   // each element will be of type `absl::string_view`.
+//   std::vector<std::string> v;
+//   for (const auto sv : absl::StrSplit("a,b,c", ',')) {
+//     if (sv != "b") v.emplace_back(sv);
+//   }
+//   // v[0] == "a", v[1] == "c"
+//
+//   // Stores results in a map. The map implementation assumes that the input
+//   // is provided as a series of key/value pairs. For example, the 0th element
+//   // resulting from the split will be stored as a key to the 1st element. If
+//   // an odd number of elements are resolved, the last element is paired with
+//   // a default-constructed value (e.g., empty std::string).
+//   std::map<std::string, std::string> m = absl::StrSplit("a,b,c", ',');
+//   // m["a"] == "b", m["c"] == ""     // last component value equals ""
+//
+// Splitting to `std::pair` is an interesting case because it can hold only two
+// elements and is not a collection type. When splitting to a `std::pair` the
+// first two split strings become the `std::pair` `.first` and `.second`
+// members, respectively. The remaining split substrings are discarded. If there
+// are less than two split substrings, the empty std::string is used for the
+// corresponding
+// `std::pair` member.
+//
+// Example:
+//
+//   // Stores first two split strings as the members in a std::pair.
+//   std::pair<std::string, std::string> p = absl::StrSplit("a,b,c", ',');
+//   // p.first == "a", p.second == "b"       // "c" is omitted.
+//
+// The `StrSplit()` function can be used multiple times to perform more
+// complicated splitting logic, such as intelligently parsing key-value pairs.
+//
+// Example:
+//
+//   // The input std::string "a=b=c,d=e,f=,g" becomes
+//   // { "a" => "b=c", "d" => "e", "f" => "", "g" => "" }
+//   std::map<std::string, std::string> m;
+//   for (absl::string_view sp : absl::StrSplit("a=b=c,d=e,f=,g", ',')) {
+//     m.insert(absl::StrSplit(sp, absl::MaxSplits('=', 1)));
+//   }
+//   EXPECT_EQ("b=c", m.find("a")->second);
+//   EXPECT_EQ("e", m.find("d")->second);
+//   EXPECT_EQ("", m.find("f")->second);
+//   EXPECT_EQ("", m.find("g")->second);
+//
+// WARNING: Due to a legacy bug that is maintained for backward compatibility,
+// splitting the following empty string_views produces different results:
+//
+//   absl::StrSplit(absl::string_view(""), '-');  // {""}
+//   absl::StrSplit(absl::string_view(), '-');    // {}, but should be {""}
+//
+// Try not to depend on this distinction because the bug may one day be fixed.
+template <typename Delimiter>
+strings_internal::Splitter<
+    typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty>
+StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d) {
+  using DelimiterType =
+      typename strings_internal::SelectDelimiter<Delimiter>::type;
+  return strings_internal::Splitter<DelimiterType, AllowEmpty>(
+      std::move(text), DelimiterType(d), AllowEmpty());
+}
+
+template <typename Delimiter, typename Predicate>
+strings_internal::Splitter<
+    typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate>
+StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d,
+         Predicate p) {
+  using DelimiterType =
+      typename strings_internal::SelectDelimiter<Delimiter>::type;
+  return strings_internal::Splitter<DelimiterType, Predicate>(
+      std::move(text), DelimiterType(d), std::move(p));
+}
+
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_STR_SPLIT_H_