Coverage Report

Created: 2024-11-21 14:31

/root/doris/be/src/gutil/strings/join.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2008 and onwards Google, Inc.
2
//
3
// #status: RECOMMENDED
4
// #category: operations on strings
5
// #summary: Functions for joining strings and numbers using a delimiter.
6
//
7
#pragma once
8
9
#include <iterator>
10
// IWYU pragma: no_include <ext/type_traits>
11
#include <type_traits> // IWYU pragma: keep
12
13
using std::back_insert_iterator;
14
using std::iterator_traits;
15
#include <map>
16
17
using std::map;
18
using std::multimap;
19
#include <set>
20
21
using std::multiset;
22
using std::set;
23
#include <string>
24
25
using std::string;
26
#include <utility>
27
28
using std::make_pair;
29
using std::pair;
30
#include <vector>
31
32
using std::vector;
33
34
#include "gutil/strings/strcat.h" // For backward compatibility.
35
#include "gutil/strings/stringpiece.h"
36
37
// ----------------------------------------------------------------------
38
// JoinUsing()
39
//    This concatenates a vector of strings "components" into a new char[]
40
//    buffer, using the C-string "delim" as a separator between components.
41
//
42
//    This is essentially the same as JoinUsingToBuffer except
43
//    the return result is dynamically allocated using "new char[]".
44
//    It is the caller's responsibility to "delete []" the char* that is
45
//    returned.
46
//
47
//    If result_length_p is not NULL, it will contain the length of the
48
//    result string (not including the trailing '\0').
49
// ----------------------------------------------------------------------
50
char* JoinUsing(const vector<const char*>& components, const char* delim, int* result_length_p);
51
52
// ----------------------------------------------------------------------
53
// JoinUsingToBuffer()
54
//    This concatenates a vector of strings "components" into a given char[]
55
//    buffer, using the C-string "delim" as a separator between components.
56
//    User supplies the result buffer with specified buffer size.
57
//    The result is also returned for convenience.
58
//
59
//    If result_length_p is not NULL, it will contain the length of the
60
//    result string (not including the trailing '\0').
61
// ----------------------------------------------------------------------
62
char* JoinUsingToBuffer(const vector<const char*>& components, const char* delim,
63
                        int result_buffer_size, char* result_buffer, int* result_length_p);
64
65
// ----------------------------------------------------------------------
66
// JoinStrings(), JoinStringsIterator(), JoinStringsInArray()
67
//
68
//    JoinStrings concatenates a container of strings into a C++ string,
69
//    using the string "delim" as a separator between components.
70
//    "components" can be any sequence container whose values are C++ strings
71
//    or StringPieces. More precisely, "components" must support STL container
72
//    iteration; i.e. it must have begin() and end() methods with appropriate
73
//    semantics, which return forward iterators whose value type is
74
//    string or StringPiece. Repeated string fields of protocol messages
75
//    satisfy these requirements.
76
//
77
//    JoinStringsIterator is the same as JoinStrings, except that the input
78
//    strings are specified with a pair of iterators. The requirements on
79
//    the iterators are the same as the requirements on components.begin()
80
//    and components.end() for JoinStrings.
81
//
82
//    JoinStringsInArray is the same as JoinStrings, but operates on
83
//    an array of C++ strings or string pointers.
84
//
85
//    There are two flavors of each function, one flavor returns the
86
//    concatenated string, another takes a pointer to the target string. In
87
//    the latter case the target string is cleared and overwritten.
88
// ----------------------------------------------------------------------
89
template <class CONTAINER>
90
void JoinStrings(const CONTAINER& components, const StringPiece& delim, string* result);
91
template <class CONTAINER>
92
string JoinStrings(const CONTAINER& components, const StringPiece& delim);
93
94
template <class ITERATOR>
95
void JoinStringsIterator(const ITERATOR& start, const ITERATOR& end, const StringPiece& delim,
96
                         string* result);
97
template <class ITERATOR>
98
string JoinStringsIterator(const ITERATOR& start, const ITERATOR& end, const StringPiece& delim);
99
100
// Join the keys of a map using the specified delimiter.
101
template <typename ITERATOR>
102
void JoinKeysIterator(const ITERATOR& start, const ITERATOR& end, const StringPiece& delim,
103
                      string* result) {
104
    result->clear();
105
    for (ITERATOR iter = start; iter != end; ++iter) {
106
        if (iter == start) {
107
            StrAppend(result, iter->first);
108
        } else {
109
            StrAppend(result, delim, iter->first);
110
        }
111
    }
112
}
113
114
template <typename ITERATOR>
115
string JoinKeysIterator(const ITERATOR& start, const ITERATOR& end, const StringPiece& delim) {
116
    string result;
117
    JoinKeysIterator(start, end, delim, &result);
118
    return result;
119
}
120
121
// Join the keys and values of a map using the specified delimiters.
122
template <typename ITERATOR>
123
void JoinKeysAndValuesIterator(const ITERATOR& start, const ITERATOR& end,
124
                               const StringPiece& intra_delim, const StringPiece& inter_delim,
125
                               string* result) {
126
    result->clear();
127
    for (ITERATOR iter = start; iter != end; ++iter) {
128
        if (iter == start) {
129
            StrAppend(result, iter->first, intra_delim, iter->second);
130
        } else {
131
            StrAppend(result, inter_delim, iter->first, intra_delim, iter->second);
132
        }
133
    }
134
}
135
136
template <typename ITERATOR>
137
string JoinKeysAndValuesIterator(const ITERATOR& start, const ITERATOR& end,
138
                                 const StringPiece& intra_delim, const StringPiece& inter_delim) {
139
    string result;
140
    JoinKeysAndValuesIterator(start, end, intra_delim, inter_delim, &result);
141
    return result;
142
}
143
144
void JoinStringsInArray(string const* const* components, int num_components, const char* delim,
145
                        string* result);
146
void JoinStringsInArray(string const* components, int num_components, const char* delim,
147
                        string* result);
148
string JoinStringsInArray(string const* const* components, int num_components, const char* delim);
149
string JoinStringsInArray(string const* components, int num_components, const char* delim);
150
151
// ----------------------------------------------------------------------
152
// Definitions of above JoinStrings* methods
153
// ----------------------------------------------------------------------
154
template <class CONTAINER>
155
void JoinStrings(const CONTAINER& components, const StringPiece& delim, string* result) {
156
    JoinStringsIterator(components.begin(), components.end(), delim, result);
157
}
158
159
template <class CONTAINER>
160
string JoinStrings(const CONTAINER& components, const StringPiece& delim) {
161
    string result;
162
    JoinStrings(components, delim, &result);
163
    return result;
164
}
165
166
// Join the strings produced by calling 'functor' on each element of
167
// 'components'.
168
template <class CONTAINER, typename FUNC>
169
string JoinMapped(const CONTAINER& components, const FUNC& functor, const StringPiece& delim) {
170
    string result;
171
    for (typename CONTAINER::const_iterator iter = components.begin(); iter != components.end();
172
         iter++) {
173
        if (iter != components.begin()) {
174
            result.append(delim.data(), delim.size());
175
        }
176
        result.append(functor(*iter));
177
    }
178
    return result;
179
}
180
181
template <class ITERATOR>
182
void JoinStringsIterator(const ITERATOR& start, const ITERATOR& end, const StringPiece& delim,
183
                         string* result) {
184
    result->clear();
185
186
    // Precompute resulting length so we can reserve() memory in one shot.
187
    if (start != end) {
188
        int length = delim.size() * (distance(start, end) - 1);
189
        for (ITERATOR iter = start; iter != end; ++iter) {
190
            length += iter->size();
191
        }
192
        result->reserve(length);
193
    }
194
195
    // Now combine everything.
196
    for (ITERATOR iter = start; iter != end; ++iter) {
197
        if (iter != start) {
198
            result->append(delim.data(), delim.size());
199
        }
200
        result->append(iter->data(), iter->size());
201
    }
202
}
203
204
template <class ITERATOR>
205
string JoinStringsIterator(const ITERATOR& start, const ITERATOR& end, const StringPiece& delim) {
206
    string result;
207
    JoinStringsIterator(start, end, delim, &result);
208
    return result;
209
}
210
211
inline string JoinStringsInArray(string const* const* components, int num_components,
212
0
                                 const char* delim) {
213
0
    string result;
214
0
    JoinStringsInArray(components, num_components, delim, &result);
215
0
    return result;
216
0
}
217
218
0
inline string JoinStringsInArray(string const* components, int num_components, const char* delim) {
219
0
    string result;
220
0
    JoinStringsInArray(components, num_components, delim, &result);
221
0
    return result;
222
0
}
223
224
// ----------------------------------------------------------------------
225
// JoinMapKeysAndValues()
226
// JoinHashMapKeysAndValues()
227
// JoinVectorKeysAndValues()
228
//    This merges the keys and values of a string -> string map or pair
229
//    of strings vector, with one delim (intra_delim) between each key
230
//    and its associated value and another delim (inter_delim) between
231
//    each key/value pair.  The result is returned in a string (passed
232
//    as the last argument).
233
// ----------------------------------------------------------------------
234
235
void JoinMapKeysAndValues(const map<string, string>& components, const StringPiece& intra_delim,
236
                          const StringPiece& inter_delim, string* result);
237
void JoinVectorKeysAndValues(const vector<pair<string, string>>& components,
238
                             const StringPiece& intra_delim, const StringPiece& inter_delim,
239
                             string* result);
240
241
// DEPRECATED(jyrki): use JoinKeysAndValuesIterator directly.
242
template <typename T>
243
void JoinHashMapKeysAndValues(const T& container, const StringPiece& intra_delim,
244
                              const StringPiece& inter_delim, string* result) {
245
    JoinKeysAndValuesIterator(container.begin(), container.end(), intra_delim, inter_delim, result);
246
}
247
248
// ----------------------------------------------------------------------
249
// JoinCSVLineWithDelimiter()
250
//    This function is the inverse of SplitCSVLineWithDelimiter() in that the
251
//    string returned by JoinCSVLineWithDelimiter() can be passed to
252
//    SplitCSVLineWithDelimiter() to get the original string vector back.
253
//    Quotes and escapes the elements of original_cols according to CSV quoting
254
//    rules, and the joins the escaped quoted strings with commas using
255
//    JoinStrings().  Note that JoinCSVLineWithDelimiter() will not necessarily
256
//    return the same string originally passed in to
257
//    SplitCSVLineWithDelimiter(), since SplitCSVLineWithDelimiter() can handle
258
//    gratuitous spacing and quoting. 'output' must point to an empty string.
259
//
260
//    Example:
261
//     [Google], [x], [Buchheit, Paul], [string with " quoite in it], [ space ]
262
//     --->  [Google,x,"Buchheit, Paul","string with "" quote in it"," space "]
263
//
264
// JoinCSVLine()
265
//    A convenience wrapper around JoinCSVLineWithDelimiter which uses
266
//    ',' as the delimiter.
267
// ----------------------------------------------------------------------
268
void JoinCSVLine(const vector<string>& original_cols, string* output);
269
string JoinCSVLine(const vector<string>& original_cols);
270
void JoinCSVLineWithDelimiter(const vector<string>& original_cols, char delimiter, string* output);
271
272
// ----------------------------------------------------------------------
273
// JoinElements()
274
//    This merges a container of any type supported by StrAppend() with delim
275
//    inserted as separators between components.  This is essentially a
276
//    templatize version of JoinUsingToBuffer().
277
//
278
// JoinElementsIterator()
279
//    Same as JoinElements(), except that the input elements are specified
280
//    with a pair of forward iterators.
281
// ----------------------------------------------------------------------
282
283
template <class ITERATOR>
284
0
void JoinElementsIterator(ITERATOR first, ITERATOR last, StringPiece delim, string* result) {
285
0
    result->clear();
286
0
    for (ITERATOR it = first; it != last; ++it) {
287
0
        if (it != first) {
288
0
            StrAppend(result, delim);
289
0
        }
290
0
        StrAppend(result, *it);
291
0
    }
292
0
}
293
294
template <class ITERATOR>
295
string JoinElementsIterator(ITERATOR first, ITERATOR last, StringPiece delim) {
296
    string result;
297
    JoinElementsIterator(first, last, delim, &result);
298
    return result;
299
}
300
301
template <class CONTAINER>
302
0
void JoinElements(const CONTAINER& components, StringPiece delim, string* result) {
303
0
    JoinElementsIterator(components.begin(), components.end(), delim, result);
304
0
}
305
306
template <class CONTAINER>
307
0
string JoinElements(const CONTAINER& components, StringPiece delim) {
308
0
    string result;
309
0
    JoinElements(components, delim, &result);
310
0
    return result;
311
0
}
312
313
template <class CONTAINER>
314
void JoinInts(const CONTAINER& components, const char* delim, string* result) {
315
    JoinElements(components, delim, result);
316
}
317
318
template <class CONTAINER>
319
string JoinInts(const CONTAINER& components, const char* delim) {
320
    return JoinElements(components, delim);
321
}