| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 | //// 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////      https://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 string to use between the elements joined, and// an optional Formatter responsible for converting each argument in the range// to a 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 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 <type_traits>#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 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 string to use between the// elements joined, and an optional Formatter responsible for converting each// argument in the range to a 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_
 |