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, {
+// {"&", "&"},
+// {"<", "<"},
+// {">", ">"},
+// {"\"", """},
+// {"'", "'"}});
+#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({"&", "&"});
+// replacements.push_back({"<", "<"});
+// replacements.push_back({">", ">"});
+// std::string s = absl::StrReplaceAll("if (ptr < &foo)",
+// replacements);
+// EXPECT_EQ("if (ptr < &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({{"&", "&"},
+// {"<", "<"},
+// {">", ">"}}, &s);
+// EXPECT_EQ(count, 2);
+// EXPECT_EQ("if (ptr < &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_