// // 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. // // This file declares INTERNAL parts of the Join API that are inlined/templated // or otherwise need to be available at compile time. The main abstractions // defined in this file are: // // - A handful of default Formatters // - JoinAlgorithm() overloads // - JoinRange() overloads // - JoinTuple() // // DO NOT INCLUDE THIS FILE DIRECTLY. Use this file by including // absl/strings/str_join.h // // IWYU pragma: private, include "absl/strings/str_join.h" #ifndef ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_ #define ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_ #include <cstdint> #include <cstring> #include <initializer_list> #include <iterator> #include <limits> #include <memory> #include <string> #include <tuple> #include <type_traits> #include <utility> #include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" #include "absl/strings/internal/ostringstream.h" #include "absl/strings/internal/resize_uninitialized.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace strings_internal { // // Formatter objects // // The following are implementation classes for standard Formatter objects. The // factory functions that users will call to create and use these formatters are // defined and documented in strings/join.h. // // The default formatter. Converts alpha-numeric types to strings. struct AlphaNumFormatterImpl { … }; // A type that's used to overload the JoinAlgorithm() function (defined below) // for ranges that do not require additional formatting (e.g., a range of // strings). struct NoFormatter : public AlphaNumFormatterImpl { … }; // Formats types to strings using the << operator. class StreamFormatterImpl { … }; // Formats a std::pair<>. The 'first' member is formatted using f1_ and the // 'second' member is formatted using f2_. sep_ is the separator. template <typename F1, typename F2> class PairFormatterImpl { … }; // Wraps another formatter and dereferences the argument to operator() then // passes the dereferenced argument to the wrapped formatter. This can be // useful, for example, to join a std::vector<int*>. template <typename Formatter> class DereferenceFormatterImpl { … }; // DefaultFormatter<T> is a traits class that selects a default Formatter to use // for the given type T. The ::Type member names the Formatter to use. This is // used by the strings::Join() functions that do NOT take a Formatter argument, // in which case a default Formatter must be chosen. // // AlphaNumFormatterImpl is the default in the base template, followed by // specializations for other types. template <typename ValueType> struct DefaultFormatter { … }; template <> struct DefaultFormatter<const char*> { … }; template <> struct DefaultFormatter<char*> { … }; template <> struct DefaultFormatter<std::string> { … }; template <> struct DefaultFormatter<absl::string_view> { … }; DefaultFormatter<ValueType *>; DefaultFormatter<std::unique_ptr<ValueType>>; // // JoinAlgorithm() functions // // The main joining algorithm. This simply joins the elements in the given // iterator range, each separated by the given separator, into an output string, // and formats each element using the provided Formatter object. template <typename Iterator, typename Formatter> std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s, Formatter&& f) { … } // A joining algorithm that's optimized for a forward iterator range of // string-like objects that do not need any additional formatting. This is to // optimize the common case of joining, say, a std::vector<string> or a // std::vector<absl::string_view>. // // This is an overload of the previous JoinAlgorithm() function. Here the // Formatter argument is of type NoFormatter. Since NoFormatter is an internal // type, this overload is only invoked when strings::Join() is called with a // range of string-like objects (e.g., std::string, absl::string_view), and an // explicit Formatter argument was NOT specified. // // The optimization is that the needed space will be reserved in the output // string to avoid the need to resize while appending. To do this, the iterator // range will be traversed twice: once to calculate the total needed size, and // then again to copy the elements and delimiters to the output string. template <typename Iterator, typename = typename std::enable_if<std::is_convertible< typename std::iterator_traits<Iterator>::iterator_category, std::forward_iterator_tag>::value>::type> std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s, NoFormatter) { … } // JoinTupleLoop implements a loop over the elements of a std::tuple, which // are heterogeneous. The primary template matches the tuple interior case. It // continues the iteration after appending a separator (for nonzero indices) // and formatting an element of the tuple. The specialization for the I=N case // matches the end-of-tuple, and terminates the iteration. template <size_t I, size_t N> struct JoinTupleLoop { … }; JoinTupleLoop<N, N>; template <typename... T, typename Formatter> std::string JoinAlgorithm(const std::tuple<T...>& tup, absl::string_view sep, Formatter&& fmt) { … } template <typename Iterator> std::string JoinRange(Iterator first, Iterator last, absl::string_view separator) { … } template <typename Range, typename Formatter> std::string JoinRange(const Range& range, absl::string_view separator, Formatter&& fmt) { … } template <typename Range> std::string JoinRange(const Range& range, absl::string_view separator) { … } template <typename Tuple, std::size_t... I> std::string JoinTuple(const Tuple& value, absl::string_view separator, std::index_sequence<I...>) { … } } // namespace strings_internal ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_