libpqxx 7.7.0
separated_list.hxx
1/* Helper similar to Python's `str.join()`.
2 *
3 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/separated_list instead.
4 *
5 * Copyright (c) 2000-2022, Jeroen T. Vermeulen.
6 *
7 * See COPYING for copyright license. If you did not receive a file called
8 * COPYING with this source code, please notify the distributor of this
9 * mistake, or contact the author.
10 */
11#ifndef PQXX_H_SEPARATED_LIST
12#define PQXX_H_SEPARATED_LIST
13
14#include <algorithm>
15#include <numeric>
16
17#include "pqxx/strconv.hxx"
18
19// C++20: Simplify using std::ranges::range.
20// C++20: Optimise buffer allocation using random_access_range/iterator.
21namespace pqxx
22{
27
29
37template<typename ITER, typename ACCESS>
38[[nodiscard]] inline std::string
39separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
40{
41 if (end == begin)
42 return {};
43 auto next{begin};
44 ++next;
45 if (next == end)
46 return to_string(access(begin));
47
48 // From here on, we've got at least 2 elements -- meaning that we need sep.
49 using elt_type = strip_t<decltype(access(begin))>;
50 using traits = string_traits<elt_type>;
51
52 std::size_t budget{0};
53 for (ITER cnt{begin}; cnt != end; ++cnt)
54 budget += traits::size_buffer(access(cnt));
55 budget +=
56 static_cast<std::size_t>(std::distance(begin, end)) * std::size(sep);
57
58 std::string result;
59 result.resize(budget);
60
61 char *const data{result.data()};
62 char *here{data};
63 char *stop{data + budget};
64 here = traits::into_buf(here, stop, access(begin)) - 1;
65 for (++begin; begin != end; ++begin)
66 {
67 here += sep.copy(here, std::size(sep));
68 here = traits::into_buf(here, stop, access(begin)) - 1;
69 }
70 result.resize(static_cast<std::size_t>(here - data));
71 return result;
72}
73
74
76template<typename ITER>
77[[nodiscard]] inline std::string
78separated_list(std::string_view sep, ITER begin, ITER end)
79{
80 return separated_list(sep, begin, end, [](ITER i) { return *i; });
81}
82
83
85template<typename CONTAINER>
86[[nodiscard]] inline auto
87separated_list(std::string_view sep, CONTAINER const &c)
88 /*
89 Always std::string; necessary because SFINAE doesn't work with the
90 contents of function bodies, so the check for iterability has to be in
91 the signature.
92 */
93 -> typename std::enable_if<
94 (not std::is_void<decltype(std::begin(c))>::value and
95 not std::is_void<decltype(std::end(c))>::value),
96 std::string>::type
97{
98 return separated_list(sep, std::begin(c), std::end(c));
99}
100
101
103template<
104 typename TUPLE, std::size_t INDEX = 0, typename ACCESS,
105 typename std::enable_if<
106 (INDEX == std::tuple_size<TUPLE>::value - 1), int>::type = 0>
107[[nodiscard]] inline std::string separated_list(
108 std::string_view /* sep */, TUPLE const &t, ACCESS const &access)
109{
110 return to_string(access(&std::get<INDEX>(t)));
111}
112
113template<
114 typename TUPLE, std::size_t INDEX = 0, typename ACCESS,
115 typename std::enable_if<
116 (INDEX < std::tuple_size<TUPLE>::value - 1), int>::type = 0>
117[[nodiscard]] inline std::string
118separated_list(std::string_view sep, TUPLE const &t, ACCESS const &access)
119{
120 std::string out{to_string(access(&std::get<INDEX>(t)))};
121 out.append(sep);
122 out.append(separated_list<TUPLE, INDEX + 1>(sep, t, access));
123 return out;
124}
125
126template<
127 typename TUPLE, std::size_t INDEX = 0,
128 typename std::enable_if<
129 (INDEX <= std::tuple_size<TUPLE>::value), int>::type = 0>
130[[nodiscard]] inline std::string
131separated_list(std::string_view sep, TUPLE const &t)
132{
133 // TODO: Optimise allocation.
134 return separated_list(sep, t, [](TUPLE const &tup) { return *tup; });
135}
137} // namespace pqxx
138#endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:23
std::string separated_list(std::string_view sep, ITER begin, ITER end, ACCESS access)
Represent sequence of values as a string, joined by a given separator.
Definition: separated_list.hxx:39
std::remove_cv_t< std::remove_reference_t< TYPE > > strip_t
Remove any constness, volatile, and reference-ness from a type.
Definition: types.hxx:87
std::string to_string(field const &value)
Convert a field to a string.
Definition: result.cxx:528
Result set containing data returned by a query or command.
Definition: result.hxx:68
Traits class for use in string conversions.
Definition: strconv.hxx:153