tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

str_join.h (11853B)


      1 //
      2 // Copyright 2017 The Abseil Authors.
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      https://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 // -----------------------------------------------------------------------------
     17 // File: str_join.h
     18 // -----------------------------------------------------------------------------
     19 //
     20 // This header file contains functions for joining a range of elements and
     21 // returning the result as a std::string. StrJoin operations are specified by
     22 // passing a range, a separator string to use between the elements joined, and
     23 // an optional Formatter responsible for converting each argument in the range
     24 // to a string. If omitted, a default `AlphaNumFormatter()` is called on the
     25 // elements to be joined, using the same formatting that `absl::StrCat()` uses.
     26 // This package defines a number of default formatters, and you can define your
     27 // own implementations.
     28 //
     29 // Ranges are specified by passing a container with `std::begin()` and
     30 // `std::end()` iterators, container-specific `begin()` and `end()` iterators, a
     31 // brace-initialized `std::initializer_list`, or a `std::tuple` of heterogeneous
     32 // objects. The separator string is specified as an `absl::string_view`.
     33 //
     34 // Because the default formatter uses the `absl::AlphaNum` class,
     35 // `absl::StrJoin()`, like `absl::StrCat()`, will work out-of-the-box on
     36 // collections of strings, ints, floats, doubles, etc.
     37 //
     38 // Example:
     39 //
     40 //   std::vector<std::string> v = {"foo", "bar", "baz"};
     41 //   std::string s = absl::StrJoin(v, "-");
     42 //   EXPECT_EQ("foo-bar-baz", s);
     43 //
     44 // See comments on the `absl::StrJoin()` function for more examples.
     45 
     46 #ifndef ABSL_STRINGS_STR_JOIN_H_
     47 #define ABSL_STRINGS_STR_JOIN_H_
     48 
     49 #include <cstdio>
     50 #include <cstring>
     51 #include <initializer_list>
     52 #include <iterator>
     53 #include <string>
     54 #include <tuple>
     55 #include <type_traits>
     56 #include <utility>
     57 
     58 #include "absl/base/macros.h"
     59 #include "absl/strings/internal/str_join_internal.h"
     60 #include "absl/strings/string_view.h"
     61 
     62 namespace absl {
     63 ABSL_NAMESPACE_BEGIN
     64 
     65 // -----------------------------------------------------------------------------
     66 // Concept: Formatter
     67 // -----------------------------------------------------------------------------
     68 //
     69 // A Formatter is a function object that is responsible for formatting its
     70 // argument as a string and appending it to a given output std::string.
     71 // Formatters may be implemented as function objects, lambdas, or normal
     72 // functions. You may provide your own Formatter to enable `absl::StrJoin()` to
     73 // work with arbitrary types.
     74 //
     75 // The following is an example of a custom Formatter that uses
     76 // `absl::FormatDuration` to join a list of `absl::Duration`s.
     77 //
     78 //   std::vector<absl::Duration> v = {absl::Seconds(1), absl::Milliseconds(10)};
     79 //   std::string s =
     80 //       absl::StrJoin(v, ", ", [](std::string* out, absl::Duration dur) {
     81 //         absl::StrAppend(out, absl::FormatDuration(dur));
     82 //       });
     83 //   EXPECT_EQ(s, "1s, 10ms");
     84 //
     85 // The following standard formatters are provided within this file:
     86 //
     87 // - `AlphaNumFormatter()` (the default)
     88 // - `StreamFormatter()`
     89 // - `PairFormatter()`
     90 // - `DereferenceFormatter()`
     91 
     92 // AlphaNumFormatter()
     93 //
     94 // Default formatter used if none is specified. Uses `absl::AlphaNum` to convert
     95 // numeric arguments to strings.
     96 inline strings_internal::AlphaNumFormatterImpl AlphaNumFormatter() {
     97  return strings_internal::AlphaNumFormatterImpl();
     98 }
     99 
    100 // StreamFormatter()
    101 //
    102 // Formats its argument using the << operator.
    103 inline strings_internal::StreamFormatterImpl StreamFormatter() {
    104  return strings_internal::StreamFormatterImpl();
    105 }
    106 
    107 // Function Template: PairFormatter(Formatter, absl::string_view, Formatter)
    108 //
    109 // Formats a `std::pair` by putting a given separator between the pair's
    110 // `.first` and `.second` members. This formatter allows you to specify
    111 // custom Formatters for both the first and second member of each pair.
    112 template <typename FirstFormatter, typename SecondFormatter>
    113 inline strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>
    114 PairFormatter(FirstFormatter f1, absl::string_view sep, SecondFormatter f2) {
    115  return strings_internal::PairFormatterImpl<FirstFormatter, SecondFormatter>(
    116      std::move(f1), sep, std::move(f2));
    117 }
    118 
    119 // Function overload of PairFormatter() for using a default
    120 // `AlphaNumFormatter()` for each Formatter in the pair.
    121 inline strings_internal::PairFormatterImpl<
    122    strings_internal::AlphaNumFormatterImpl,
    123    strings_internal::AlphaNumFormatterImpl>
    124 PairFormatter(absl::string_view sep) {
    125  return PairFormatter(AlphaNumFormatter(), sep, AlphaNumFormatter());
    126 }
    127 
    128 // Function Template: DereferenceFormatter(Formatter)
    129 //
    130 // Formats its argument by dereferencing it and then applying the given
    131 // formatter. This formatter is useful for formatting a container of
    132 // pointer-to-T. This pattern often shows up when joining repeated fields in
    133 // protocol buffers.
    134 template <typename Formatter>
    135 strings_internal::DereferenceFormatterImpl<Formatter> DereferenceFormatter(
    136    Formatter&& f) {
    137  return strings_internal::DereferenceFormatterImpl<Formatter>(
    138      std::forward<Formatter>(f));
    139 }
    140 
    141 // Function overload of `DereferenceFormatter()` for using a default
    142 // `AlphaNumFormatter()`.
    143 inline strings_internal::DereferenceFormatterImpl<
    144    strings_internal::AlphaNumFormatterImpl>
    145 DereferenceFormatter() {
    146  return strings_internal::DereferenceFormatterImpl<
    147      strings_internal::AlphaNumFormatterImpl>(AlphaNumFormatter());
    148 }
    149 
    150 // -----------------------------------------------------------------------------
    151 // StrJoin()
    152 // -----------------------------------------------------------------------------
    153 //
    154 // Joins a range of elements and returns the result as a std::string.
    155 // `absl::StrJoin()` takes a range, a separator string to use between the
    156 // elements joined, and an optional Formatter responsible for converting each
    157 // argument in the range to a string.
    158 //
    159 // If omitted, the default `AlphaNumFormatter()` is called on the elements to be
    160 // joined.
    161 //
    162 // Example 1:
    163 //   // Joins a collection of strings. This pattern also works with a collection
    164 //   // of `absl::string_view` or even `const char*`.
    165 //   std::vector<std::string> v = {"foo", "bar", "baz"};
    166 //   std::string s = absl::StrJoin(v, "-");
    167 //   EXPECT_EQ(s, "foo-bar-baz");
    168 //
    169 // Example 2:
    170 //   // Joins the values in the given `std::initializer_list<>` specified using
    171 //   // brace initialization. This pattern also works with an initializer_list
    172 //   // of ints or `absl::string_view` -- any `AlphaNum`-compatible type.
    173 //   std::string s = absl::StrJoin({"foo", "bar", "baz"}, "-");
    174 //   EXPECT_EQs, "foo-bar-baz");
    175 //
    176 // Example 3:
    177 //   // Joins a collection of ints. This pattern also works with floats,
    178 //   // doubles, int64s -- any `StrCat()`-compatible type.
    179 //   std::vector<int> v = {1, 2, 3, -4};
    180 //   std::string s = absl::StrJoin(v, "-");
    181 //   EXPECT_EQ(s, "1-2-3--4");
    182 //
    183 // Example 4:
    184 //   // Joins a collection of pointer-to-int. By default, pointers are
    185 //   // dereferenced and the pointee is formatted using the default format for
    186 //   // that type; such dereferencing occurs for all levels of indirection, so
    187 //   // this pattern works just as well for `std::vector<int**>` as for
    188 //   // `std::vector<int*>`.
    189 //   int x = 1, y = 2, z = 3;
    190 //   std::vector<int*> v = {&x, &y, &z};
    191 //   std::string s = absl::StrJoin(v, "-");
    192 //   EXPECT_EQ(s, "1-2-3");
    193 //
    194 // Example 5:
    195 //   // Dereferencing of `std::unique_ptr<>` is also supported:
    196 //   std::vector<std::unique_ptr<int>> v
    197 //   v.emplace_back(new int(1));
    198 //   v.emplace_back(new int(2));
    199 //   v.emplace_back(new int(3));
    200 //   std::string s = absl::StrJoin(v, "-");
    201 //   EXPECT_EQ(s, "1-2-3");
    202 //
    203 // Example 6:
    204 //   // Joins a `std::map`, with each key-value pair separated by an equals
    205 //   // sign. This pattern would also work with, say, a
    206 //   // `std::vector<std::pair<>>`.
    207 //   std::map<std::string, int> m = {
    208 //       {"a", 1},
    209 //       {"b", 2},
    210 //       {"c", 3}};
    211 //   std::string s = absl::StrJoin(m, ",", absl::PairFormatter("="));
    212 //   EXPECT_EQ(s, "a=1,b=2,c=3");
    213 //
    214 // Example 7:
    215 //   // These examples show how `absl::StrJoin()` handles a few common edge
    216 //   // cases:
    217 //   std::vector<std::string> v_empty;
    218 //   EXPECT_EQ(absl::StrJoin(v_empty, "-"), "");
    219 //
    220 //   std::vector<std::string> v_one_item = {"foo"};
    221 //   EXPECT_EQ(absl::StrJoin(v_one_item, "-"), "foo");
    222 //
    223 //   std::vector<std::string> v_empty_string = {""};
    224 //   EXPECT_EQ(absl::StrJoin(v_empty_string, "-"), "");
    225 //
    226 //   std::vector<std::string> v_one_item_empty_string = {"a", ""};
    227 //   EXPECT_EQ(absl::StrJoin(v_one_item_empty_string, "-"), "a-");
    228 //
    229 //   std::vector<std::string> v_two_empty_string = {"", ""};
    230 //   EXPECT_EQ(absl::StrJoin(v_two_empty_string, "-"), "-");
    231 //
    232 // Example 8:
    233 //   // Joins a `std::tuple<T...>` of heterogeneous types, converting each to
    234 //   // a std::string using the `absl::AlphaNum` class.
    235 //   std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
    236 //   EXPECT_EQ(s, "123-abc-0.456");
    237 
    238 template <typename Iterator, typename Formatter>
    239 std::string StrJoin(Iterator start, Iterator end, absl::string_view sep,
    240                    Formatter&& fmt) {
    241  return strings_internal::JoinAlgorithm(start, end, sep, fmt);
    242 }
    243 
    244 template <typename Range, typename Formatter>
    245 std::string StrJoin(const Range& range, absl::string_view separator,
    246                    Formatter&& fmt) {
    247  return strings_internal::JoinRange(range, separator, fmt);
    248 }
    249 
    250 template <typename T, typename Formatter,
    251          typename = typename std::enable_if<
    252              !std::is_convertible<T, absl::string_view>::value>::type>
    253 std::string StrJoin(std::initializer_list<T> il, absl::string_view separator,
    254                    Formatter&& fmt) {
    255  return strings_internal::JoinRange(il, separator, fmt);
    256 }
    257 
    258 template <typename Formatter>
    259 inline std::string StrJoin(std::initializer_list<absl::string_view> il,
    260                           absl::string_view separator, Formatter&& fmt) {
    261  return strings_internal::JoinRange(il, separator, fmt);
    262 }
    263 
    264 template <typename... T, typename Formatter>
    265 std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator,
    266                    Formatter&& fmt) {
    267  return strings_internal::JoinAlgorithm(value, separator, fmt);
    268 }
    269 
    270 template <typename Iterator>
    271 std::string StrJoin(Iterator start, Iterator end, absl::string_view separator) {
    272  return strings_internal::JoinRange(start, end, separator);
    273 }
    274 
    275 template <typename Range>
    276 std::string StrJoin(const Range& range, absl::string_view separator) {
    277  return strings_internal::JoinRange(range, separator);
    278 }
    279 
    280 template <typename T, typename = typename std::enable_if<!std::is_convertible<
    281                          T, absl::string_view>::value>::type>
    282 std::string StrJoin(std::initializer_list<T> il, absl::string_view separator) {
    283  return strings_internal::JoinRange(il, separator);
    284 }
    285 
    286 inline std::string StrJoin(std::initializer_list<absl::string_view> il,
    287                           absl::string_view separator) {
    288  return strings_internal::JoinRange(il, separator);
    289 }
    290 
    291 template <typename... T>
    292 std::string StrJoin(const std::tuple<T...>& value,
    293                    absl::string_view separator) {
    294  return strings_internal::JoinTuple(value, separator,
    295                                     std::index_sequence_for<T...>{});
    296 }
    297 
    298 ABSL_NAMESPACE_END
    299 }  // namespace absl
    300 
    301 #endif  // ABSL_STRINGS_STR_JOIN_H_