Bug Summary

File:usr/include/boost/algorithm/string/detail/classification.hpp
Warning:line 139, column 25
Attempt to release already released memory

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name str.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/fedora/workspace/kea-dev/clang-static-analyzer/build/meson-private/tmpz0p224zs -fcoverage-compilation-dir=/home/fedora/workspace/kea-dev/clang-static-analyzer/build/meson-private/tmpz0p224zs -resource-dir /usr/bin/../lib/clang/22 -I src/lib/util/libkea-util.so.118.0.0.p -I src/lib/util -I ../../../src/lib/util -I . -I ../../.. -I src -I ../../../src -I src/bin -I ../../../src/bin -I src/lib -I ../../../src/lib -I /usr/include -D _GLIBCXX_ASSERTIONS=1 -D _FILE_OFFSET_BITS=64 -D BOOST_ALL_NO_LIB -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/backward -internal-isystem /usr/bin/../lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-missing-field-initializers -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /home/fedora/workspace/kea-dev/clang-static-analyzer/build/meson-logs/scanbuild/2026-06-18-163926-5114-1 -x c++ ../../../src/lib/util/str.cc

../../../src/lib/util/str.cc

1// Copyright (C) 2011-2025 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <util/encode/encode.h>
10#include <util/str.h>
11
12#include <cstddef>
13#include <cstdint>
14#include <exception>
15#include <iomanip>
16#include <regex>
17#include <sstream>
18#include <string>
19#include <vector>
20
21#include <boost/algorithm/string/classification.hpp>
22#include <boost/algorithm/string/constants.hpp>
23#include <boost/algorithm/string/split.hpp>
24
25using namespace std;
26
27namespace isc {
28namespace util {
29namespace str {
30
31string
32trim(const string& input) {
33 if (input.empty()) {
34 return (string());
35 }
36 static const char* blanks = " \t\n";
37
38 // Search for first non-blank character in the string.
39 size_t const first(input.find_first_not_of(blanks));
40 if (first == string::npos) {
41 return (string());
42 }
43
44 // String not all blanks, so look for last character.
45 size_t const last(input.find_last_not_of(blanks));
46
47 // Extract the trimmed substring.
48 return (input.substr(first, (last - first + 1)));
49}
50
51vector<string>
52tokens(const string& text, const string& delim, bool escape) {
53 vector<string> result;
54 string token;
55 bool in_token = false;
56 bool escaped = false;
57 for (auto const& c : text) {
58 if (delim.find(c) != string::npos) {
59 // Current character is a delimiter
60 if (!in_token) {
61 // Two or more delimiters, eat them
62 } else if (escaped) {
63 // Escaped delimiter in a token: reset escaped and keep it
64 escaped = false;
65 token.push_back(c);
66 } else {
67 // End of the current token: save it if not empty
68 if (!token.empty()) {
69 result.push_back(token);
70 }
71 // Reset state
72 in_token = false;
73 token.clear();
74 }
75 } else if (escape && (c == '\\')) {
76 // Current character is the escape character
77 if (!in_token) {
78 // The escape character is the first character of a new token
79 in_token = true;
80 }
81 if (escaped) {
82 // Escaped escape: reset escaped and keep one character
83 escaped = false;
84 token.push_back(c);
85 } else {
86 // Remember to keep the next character
87 escaped = true;
88 }
89 } else {
90 // Not a delimiter nor an escape
91 if (!in_token) {
92 // First character of a new token
93 in_token = true;
94 }
95 if (escaped) {
96 // Escaped common character: as escape was false
97 escaped = false;
98 token.push_back('\\');
99 token.push_back(c);
100 } else {
101 // The common case: keep it
102 token.push_back(c);
103 }
104 }
105 }
106 // End of input: close and save the current token if not empty
107 if (escaped) {
108 // Pending escape
109 token.push_back('\\');
110 }
111 if (!token.empty()) {
112 result.push_back(token);
113 }
114
115 return (result);
116}
117
118char
119toUpper(char const chr) {
120 return (toupper(chr));
121}
122
123void
124uppercase(string& text) {
125 transform(text.begin(), text.end(), text.begin(), toUpper);
126}
127
128char
129toLower(char const chr) {
130 return (tolower(static_cast<int>(chr)));
131}
132
133void
134lowercase(string& text) {
135 transform(text.begin(), text.end(), text.begin(), toLower);
136}
137
138vector<uint8_t>
139quotedStringToBinary(const string& quoted_string) {
140 vector<uint8_t> binary;
141 // Remove whitespace before and after the quotes.
142 string trimmed_string = trim(quoted_string);
143
144 // We require two quote characters, so the length of the string must be
145 // equal to 2 at minimum, and it must start and end with quotes.
146 if ((trimmed_string.length() > 1) &&
147 ((trimmed_string[0] == '\'') && (trimmed_string[trimmed_string.length() - 1] == '\''))) {
148 // Remove quotes and trim the text inside the quotes.
149 trimmed_string = trim(trimmed_string.substr(1, trimmed_string.length() - 2));
150 // Copy string contents into the vector.
151 binary.assign(trimmed_string.begin(), trimmed_string.end());
152 }
153 // Return resulting vector or empty vector.
154 return (binary);
155}
156
157void
158decodeColonSeparatedHexString(const string& hex_string, vector<uint8_t>& binary) {
159 decodeSeparatedHexString(hex_string, ":", binary);
160}
161
162void
163decodeSeparatedHexString(const string& hex_string, const string& sep, vector<uint8_t>& binary) {
164 vector<string> split_text;
165 boost::split(split_text, hex_string, boost::is_any_of(sep),
4
Calling 'split<std::vector<std::basic_string<char>>, const std::basic_string<char> &, boost::algorithm::detail::is_any_ofF<char>>'
166 boost::algorithm::token_compress_off);
167
168 vector<uint8_t> binary_vec;
169 for (size_t i = 0; i < split_text.size(); ++i) {
170 // If there are multiple tokens and the current one is empty, it
171 // means that two consecutive colons were specified. This is not
172 // allowed.
173 if ((split_text.size() > 1) && split_text[i].empty()) {
174 isc_throw(BadValue, "two consecutive separators ('"do { std::ostringstream oss__; oss__ << "two consecutive separators ('"
<< sep << "') specified in a decoded string '" <<
hex_string << "'"; throw BadValue("../../../src/lib/util/str.cc"
, 176, oss__.str().c_str()); } while (1)
175 << sep << "') specified in a decoded string '" << hex_stringdo { std::ostringstream oss__; oss__ << "two consecutive separators ('"
<< sep << "') specified in a decoded string '" <<
hex_string << "'"; throw BadValue("../../../src/lib/util/str.cc"
, 176, oss__.str().c_str()); } while (1)
176 << "'")do { std::ostringstream oss__; oss__ << "two consecutive separators ('"
<< sep << "') specified in a decoded string '" <<
hex_string << "'"; throw BadValue("../../../src/lib/util/str.cc"
, 176, oss__.str().c_str()); } while (1)
;
177
178 // Between a colon we expect at most two characters.
179 } else if (split_text[i].size() > 2) {
180 isc_throw(BadValue, "invalid format of the decoded string"do { std::ostringstream oss__; oss__ << "invalid format of the decoded string"
<< " '" << hex_string << "'"; throw BadValue
("../../../src/lib/util/str.cc", 181, oss__.str().c_str()); }
while (1)
181 << " '" << hex_string << "'")do { std::ostringstream oss__; oss__ << "invalid format of the decoded string"
<< " '" << hex_string << "'"; throw BadValue
("../../../src/lib/util/str.cc", 181, oss__.str().c_str()); }
while (1)
;
182
183 } else if (!split_text[i].empty()) {
184 stringstream s;
185 s << "0x";
186
187 for (unsigned int j = 0; j < split_text[i].length(); ++j) {
188 // Check if we're dealing with hexadecimal digit.
189 if (!isxdigit(split_text[i][j])) {
190 isc_throw(BadValue, "'" << split_text[i][j]do { std::ostringstream oss__; oss__ << "'" << split_text
[i][j] << "' is not a valid hexadecimal digit in" <<
" decoded string '" << hex_string << "'"; throw BadValue
("../../../src/lib/util/str.cc", 192, oss__.str().c_str()); }
while (1)
191 << "' is not a valid hexadecimal digit in"do { std::ostringstream oss__; oss__ << "'" << split_text
[i][j] << "' is not a valid hexadecimal digit in" <<
" decoded string '" << hex_string << "'"; throw BadValue
("../../../src/lib/util/str.cc", 192, oss__.str().c_str()); }
while (1)
192 << " decoded string '" << hex_string << "'")do { std::ostringstream oss__; oss__ << "'" << split_text
[i][j] << "' is not a valid hexadecimal digit in" <<
" decoded string '" << hex_string << "'"; throw BadValue
("../../../src/lib/util/str.cc", 192, oss__.str().c_str()); }
while (1)
;
193 }
194 s << split_text[i][j];
195 }
196
197 // The stream should now have one or two hexadecimal digits.
198 // Let's convert it to a number and store in a temporary
199 // vector.
200 unsigned int binary_value;
201 s >> hex >> binary_value;
202
203 binary_vec.push_back(static_cast<uint8_t>(binary_value));
204 }
205 }
206
207 // All ok, replace the data in the output vector with a result.
208 binary.swap(binary_vec);
209}
210
211void
212decodeFormattedHexString(const string& hex_string, vector<uint8_t>& binary) {
213 // If there is at least one colon we assume that the string
214 // comprises octets separated by colons (e.g. MAC address notation).
215 if (hex_string.find(':') != string::npos) {
1
Assuming the condition is true
2
Taking true branch
216 decodeSeparatedHexString(hex_string, ":", binary);
3
Calling 'decodeSeparatedHexString'
217 } else if (hex_string.find(' ') != string::npos) {
218 decodeSeparatedHexString(hex_string, " ", binary);
219 } else {
220 ostringstream s;
221
222 // If we have odd number of digits we'll have to prepend '0'.
223 if (hex_string.length() % 2 != 0) {
224 s << "0";
225 }
226
227 // It is ok to use '0x' prefix in a string.
228 if ((hex_string.length() > 2) && (hex_string.substr(0, 2) == "0x")) {
229 // Exclude '0x' from the decoded string.
230 s << hex_string.substr(2);
231
232 } else {
233 // No '0x', so decode the whole string.
234 s << hex_string;
235 }
236
237 try {
238 // Decode the hex string.
239 encode::decodeHex(s.str(), binary);
240
241 } catch (...) {
242 isc_throw(BadValue, "'" << hex_stringdo { std::ostringstream oss__; oss__ << "'" << hex_string
<< "' is not a valid" " string of hexadecimal digits";
throw BadValue("../../../src/lib/util/str.cc", 244, oss__.str
().c_str()); } while (1)
243 << "' is not a valid"do { std::ostringstream oss__; oss__ << "'" << hex_string
<< "' is not a valid" " string of hexadecimal digits";
throw BadValue("../../../src/lib/util/str.cc", 244, oss__.str
().c_str()); } while (1)
244 " string of hexadecimal digits")do { std::ostringstream oss__; oss__ << "'" << hex_string
<< "' is not a valid" " string of hexadecimal digits";
throw BadValue("../../../src/lib/util/str.cc", 244, oss__.str
().c_str()); } while (1)
;
245 }
246 }
247}
248
249class StringSanitizerImpl {
250public:
251 /// @brief Constructor.
252 StringSanitizerImpl(const string& char_set, const string& char_replacement)
253 : char_set_(char_set), char_replacement_(char_replacement) {
254 if (char_set.size() > StringSanitizer::MAX_DATA_SIZE) {
255 isc_throw(BadValue, "char set size: '" << char_set.size() << "' exceeds max size: '"do { std::ostringstream oss__; oss__ << "char set size: '"
<< char_set.size() << "' exceeds max size: '" <<
StringSanitizer::MAX_DATA_SIZE << "'"; throw BadValue(
"../../../src/lib/util/str.cc", 256, oss__.str().c_str()); } while
(1)
256 << StringSanitizer::MAX_DATA_SIZE << "'")do { std::ostringstream oss__; oss__ << "char set size: '"
<< char_set.size() << "' exceeds max size: '" <<
StringSanitizer::MAX_DATA_SIZE << "'"; throw BadValue(
"../../../src/lib/util/str.cc", 256, oss__.str().c_str()); } while
(1)
;
257 }
258
259 if (char_replacement.size() > StringSanitizer::MAX_DATA_SIZE) {
260 isc_throw(BadValue, "char replacement size: '"do { std::ostringstream oss__; oss__ << "char replacement size: '"
<< char_replacement.size() << "' exceeds max size: '"
<< StringSanitizer::MAX_DATA_SIZE << "'"; throw BadValue
("../../../src/lib/util/str.cc", 262, oss__.str().c_str()); }
while (1)
261 << char_replacement.size() << "' exceeds max size: '"do { std::ostringstream oss__; oss__ << "char replacement size: '"
<< char_replacement.size() << "' exceeds max size: '"
<< StringSanitizer::MAX_DATA_SIZE << "'"; throw BadValue
("../../../src/lib/util/str.cc", 262, oss__.str().c_str()); }
while (1)
262 << StringSanitizer::MAX_DATA_SIZE << "'")do { std::ostringstream oss__; oss__ << "char replacement size: '"
<< char_replacement.size() << "' exceeds max size: '"
<< StringSanitizer::MAX_DATA_SIZE << "'"; throw BadValue
("../../../src/lib/util/str.cc", 262, oss__.str().c_str()); }
while (1)
;
263 }
264 try {
265 scrub_exp_ = regex(char_set, regex::extended);
266 } catch (const exception& ex) {
267 isc_throw(BadValue, "invalid regex: '" << char_set_ << "', " << ex.what())do { std::ostringstream oss__; oss__ << "invalid regex: '"
<< char_set_ << "', " << ex.what(); throw BadValue
("../../../src/lib/util/str.cc", 267, oss__.str().c_str()); }
while (1)
;
268 }
269 }
270
271 string scrub(const string& original) {
272 stringstream result;
273 try {
274 regex_replace(ostream_iterator<char>(result), original.begin(), original.end(),
275 scrub_exp_, char_replacement_);
276 } catch (const exception& ex) {
277 isc_throw(BadValue, "replacing '" << char_set_ << "' with '" << char_replacement_do { std::ostringstream oss__; oss__ << "replacing '" <<
char_set_ << "' with '" << char_replacement_ <<
"' in '" << original << "' failed: ," << ex
.what(); throw BadValue("../../../src/lib/util/str.cc", 279, oss__
.str().c_str()); } while (1)
278 << "' in '" << original << "' failed: ,"do { std::ostringstream oss__; oss__ << "replacing '" <<
char_set_ << "' with '" << char_replacement_ <<
"' in '" << original << "' failed: ," << ex
.what(); throw BadValue("../../../src/lib/util/str.cc", 279, oss__
.str().c_str()); } while (1)
279 << ex.what())do { std::ostringstream oss__; oss__ << "replacing '" <<
char_set_ << "' with '" << char_replacement_ <<
"' in '" << original << "' failed: ," << ex
.what(); throw BadValue("../../../src/lib/util/str.cc", 279, oss__
.str().c_str()); } while (1)
;
280 }
281
282 return (result.str());
283 }
284
285private:
286 /// @brief The char set data for regex.
287 string char_set_;
288
289 /// @brief The char replacement data for regex.
290 string char_replacement_;
291
292 regex scrub_exp_;
293};
294
295// @note The regex engine is implemented using recursion and can cause
296// stack overflow if the input data is too large. An arbitrary size of
297// 4096 should be enough for all cases.
298const uint32_t StringSanitizer::MAX_DATA_SIZE = 4096;
299
300StringSanitizer::StringSanitizer(const string& char_set, const string& char_replacement)
301 : impl_(new StringSanitizerImpl(char_set, char_replacement)) {
302}
303
304string
305StringSanitizer::scrub(const string& original) {
306 return (impl_->scrub(original));
307}
308
309bool
310isPrintable(const string& content) {
311 for (char const ch : content) {
312 if (isprint(ch) == 0) {
313 return (false);
314 }
315 }
316 return (true);
317}
318
319bool
320isPrintable(const vector<uint8_t>& content) {
321 for (uint8_t const ch : content) {
322 if (isprint(ch) == 0) {
323 return (false);
324 }
325 }
326 return (true);
327}
328
329string
330dumpAsHex(const uint8_t* data, size_t length) {
331 stringstream output;
332 for (size_t i = 0; i < length; ++i) {
333 if (i) {
334 output << ":";
335 }
336
337 output << setfill('0') << setw(2) << hex << static_cast<unsigned short>(data[i]);
338 }
339
340 return (output.str());
341}
342
343string
344dumpDouble(double val, size_t precision) {
345 std::stringstream oss;
346 oss << setprecision(precision) << val;
347 return (oss.str());
348}
349
350std::string
351printOrDump(const std::vector<uint8_t>& data, size_t max_dump) {
352 if (data.empty()) {
353 return ("");
354 }
355
356 auto it = data.begin();
357 bool print_it = true;
358 for ( ; it != data.end() && *it != 0; ++it) {
359 if (!isprint(*it)) {
360 print_it = false;
361 break;
362 }
363 }
364
365 if (print_it && it != data.begin()) {
366 return (std::string(data.begin(), it));
367 }
368
369 bool zeros = true;
370 for (auto zit = data.begin(); zit < data.end(); ++zit) {
371 if (*zit != 0) {
372 zeros = false;
373 break;
374 }
375 }
376
377 if (!zeros) {
378 if (data.size() > max_dump) {
379 return (dumpAsHex(&data[0], max_dump) + "..");
380 }
381
382 return (dumpAsHex(&data[0], data.size()));
383 }
384
385 return ("");
386}
387
388} // namespace str
389} // namespace util
390} // namespace isc

/usr/include/boost/algorithm/string/split.hpp

1// Boost string_algo library split.hpp header file ---------------------------//
2
3// Copyright Pavol Droba 2002-2006.
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9// See http://www.boost.org/ for updates, documentation, and revision history.
10
11#ifndef BOOST_STRING_SPLIT_HPP
12#define BOOST_STRING_SPLIT_HPP
13
14#include <boost/algorithm/string/config.hpp>
15
16#include <boost/algorithm/string/iter_find.hpp>
17#include <boost/algorithm/string/finder.hpp>
18#include <boost/algorithm/string/compare.hpp>
19
20/*! \file
21 Defines basic split algorithms.
22 Split algorithms can be used to divide a string
23 into several parts according to given criteria.
24
25 Each part is copied and added as a new element to the
26 output container.
27 Thus the result container must be able to hold copies
28 of the matches (in a compatible structure like std::string) or
29 a reference to it (e.g. using the iterator range class).
30 Examples of such a container are \c std::vector<std::string>
31 or \c std::list<boost::iterator_range<std::string::iterator>>
32*/
33
34namespace boost {
35 namespace algorithm {
36
37// find_all ------------------------------------------------------------//
38
39 //! Find all algorithm
40 /*!
41 This algorithm finds all occurrences of the search string
42 in the input.
43
44 Each part is copied and added as a new element to the
45 output container.
46 Thus the result container must be able to hold copies
47 of the matches (in a compatible structure like std::string) or
48 a reference to it (e.g. using the iterator range class).
49 Examples of such a container are \c std::vector<std::string>
50 or \c std::list<boost::iterator_range<std::string::iterator>>
51
52 \param Result A container that can hold copies of references to the substrings
53 \param Input A container which will be searched.
54 \param Search A substring to be searched for.
55 \return A reference the result
56
57 \note Prior content of the result will be overwritten.
58
59 \note This function provides the strong exception-safety guarantee
60 */
61 template< typename SequenceSequenceT, typename Range1T, typename Range2T >
62 inline SequenceSequenceT& find_all(
63 SequenceSequenceT& Result,
64#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
65 Range1T&& Input,
66#else
67 Range1T& Input,
68#endif
69 const Range2T& Search)
70 {
71 return ::boost::algorithm::iter_find(
72 Result,
73 Input,
74 ::boost::algorithm::first_finder(Search) );
75 }
76
77 //! Find all algorithm ( case insensitive )
78 /*!
79 This algorithm finds all occurrences of the search string
80 in the input.
81 Each part is copied and added as a new element to the
82 output container. Thus the result container must be able to hold copies
83 of the matches (in a compatible structure like std::string) or
84 a reference to it (e.g. using the iterator range class).
85 Examples of such a container are \c std::vector<std::string>
86 or \c std::list<boost::iterator_range<std::string::iterator>>
87
88 Searching is case insensitive.
89
90 \param Result A container that can hold copies of references to the substrings
91 \param Input A container which will be searched.
92 \param Search A substring to be searched for.
93 \param Loc A locale used for case insensitive comparison
94 \return A reference the result
95
96 \note Prior content of the result will be overwritten.
97
98 \note This function provides the strong exception-safety guarantee
99 */
100 template< typename SequenceSequenceT, typename Range1T, typename Range2T >
101 inline SequenceSequenceT& ifind_all(
102 SequenceSequenceT& Result,
103#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
104 Range1T&& Input,
105#else
106 Range1T& Input,
107#endif
108 const Range2T& Search,
109 const std::locale& Loc=std::locale() )
110 {
111 return ::boost::algorithm::iter_find(
112 Result,
113 Input,
114 ::boost::algorithm::first_finder(Search, is_iequal(Loc) ) );
115 }
116
117
118// tokenize -------------------------------------------------------------//
119
120 //! Split algorithm
121 /*!
122 Tokenize expression. This function is equivalent to C strtok. Input
123 sequence is split into tokens, separated by separators. Separators
124 are given by means of the predicate.
125
126 Each part is copied and added as a new element to the
127 output container.
128 Thus the result container must be able to hold copies
129 of the matches (in a compatible structure like std::string) or
130 a reference to it (e.g. using the iterator range class).
131 Examples of such a container are \c std::vector<std::string>
132 or \c std::list<boost::iterator_range<std::string::iterator>>
133
134 \param Result A container that can hold copies of references to the substrings
135 \param Input A container which will be searched.
136 \param Pred A predicate to identify separators. This predicate is
137 supposed to return true if a given element is a separator.
138 \param eCompress If eCompress argument is set to token_compress_on, adjacent
139 separators are merged together. Otherwise, every two separators
140 delimit a token.
141 \return A reference the result
142
143 \note Prior content of the result will be overwritten.
144
145 \note This function provides the strong exception-safety guarantee
146 */
147 template< typename SequenceSequenceT, typename RangeT, typename PredicateT >
148 inline SequenceSequenceT& split(
149 SequenceSequenceT& Result,
150#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
151 RangeT&& Input,
152#else
153 RangeT& Input,
154#endif
155 PredicateT Pred,
156 token_compress_mode_type eCompress=token_compress_off )
157 {
158 return ::boost::algorithm::iter_split(
5
Calling 'iter_split<std::vector<std::basic_string<char>>, const std::basic_string<char> &, boost::algorithm::detail::token_finderF<boost::algorithm::detail::is_any_ofF<char>>>'
12
Returning; memory was released
159 Result,
160 Input,
161 ::boost::algorithm::token_finder( Pred, eCompress ) );
13
Calling implicit destructor for 'token_finderF<boost::algorithm::detail::is_any_ofF<char>>'
14
Calling '~is_any_ofF'
162 }
163
164 } // namespace algorithm
165
166 // pull names to the boost namespace
167 using algorithm::find_all;
168 using algorithm::ifind_all;
169 using algorithm::split;
170
171} // namespace boost
172
173
174#endif // BOOST_STRING_SPLIT_HPP
175

/usr/include/boost/algorithm/string/iter_find.hpp

1// Boost string_algo library iter_find.hpp header file ---------------------------//
2
3// Copyright Pavol Droba 2002-2003.
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9// See http://www.boost.org/ for updates, documentation, and revision history.
10
11#ifndef BOOST_STRING_ITER_FIND_HPP
12#define BOOST_STRING_ITER_FIND_HPP
13
14#include <boost/algorithm/string/config.hpp>
15#include <algorithm>
16#include <iterator>
17#include <boost/iterator/transform_iterator.hpp>
18
19#include <boost/range/iterator_range_core.hpp>
20#include <boost/range/begin.hpp>
21#include <boost/range/end.hpp>
22#include <boost/range/iterator.hpp>
23#include <boost/range/value_type.hpp>
24#include <boost/range/as_literal.hpp>
25
26#include <boost/algorithm/string/concept.hpp>
27#include <boost/algorithm/string/find_iterator.hpp>
28#include <boost/algorithm/string/detail/util.hpp>
29
30/*! \file
31 Defines generic split algorithms. Split algorithms can be
32 used to divide a sequence into several part according
33 to a given criteria. Result is given as a 'container
34 of containers' where elements are copies or references
35 to extracted parts.
36
37 There are two algorithms provided. One iterates over matching
38 substrings, the other one over the gaps between these matches.
39*/
40
41namespace boost {
42 namespace algorithm {
43
44// iterate find ---------------------------------------------------//
45
46 //! Iter find algorithm
47 /*!
48 This algorithm executes a given finder in iteration on the input,
49 until the end of input is reached, or no match is found.
50 Iteration is done using built-in find_iterator, so the real
51 searching is performed only when needed.
52 In each iteration new match is found and added to the result.
53
54 \param Result A 'container container' to contain the result of search.
55 Both outer and inner container must have constructor taking a pair
56 of iterators as an argument.
57 Typical type of the result is
58 \c std::vector<boost::iterator_range<iterator>>
59 (each element of such a vector will container a range delimiting
60 a match).
61 \param Input A container which will be searched.
62 \param Finder A Finder object used for searching
63 \return A reference to the result
64
65 \note Prior content of the result will be overwritten.
66 */
67 template<
68 typename SequenceSequenceT,
69 typename RangeT,
70 typename FinderT >
71 inline SequenceSequenceT&
72 iter_find(
73 SequenceSequenceT& Result,
74#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
75 RangeT&& Input,
76#else
77 RangeT& Input,
78#endif
79 FinderT Finder )
80 {
81 BOOST_CONCEPT_ASSERT((typedef ::boost::concepts::detail::instantiate< &::boost
::concepts::requirement_<void(*)( FinderConcept< FinderT
, typename range_iterator<RangeT>::type> )>::failed
> boost_concept_check85 __attribute__((__unused__))
82 FinderConcept<typedef ::boost::concepts::detail::instantiate< &::boost
::concepts::requirement_<void(*)( FinderConcept< FinderT
, typename range_iterator<RangeT>::type> )>::failed
> boost_concept_check85 __attribute__((__unused__))
83 FinderT,typedef ::boost::concepts::detail::instantiate< &::boost
::concepts::requirement_<void(*)( FinderConcept< FinderT
, typename range_iterator<RangeT>::type> )>::failed
> boost_concept_check85 __attribute__((__unused__))
84 BOOST_STRING_TYPENAME range_iterator<RangeT>::type>typedef ::boost::concepts::detail::instantiate< &::boost
::concepts::requirement_<void(*)( FinderConcept< FinderT
, typename range_iterator<RangeT>::type> )>::failed
> boost_concept_check85 __attribute__((__unused__))
85 ))typedef ::boost::concepts::detail::instantiate< &::boost
::concepts::requirement_<void(*)( FinderConcept< FinderT
, typename range_iterator<RangeT>::type> )>::failed
> boost_concept_check85 __attribute__((__unused__))
;
86
87 iterator_range<BOOST_STRING_TYPENAMEtypename range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
88
89 typedef BOOST_STRING_TYPENAMEtypename
90 range_iterator<RangeT>::type input_iterator_type;
91 typedef find_iterator<input_iterator_type> find_iterator_type;
92 typedef detail::copy_iterator_rangeF<
93 BOOST_STRING_TYPENAMEtypename
94 range_value<SequenceSequenceT>::type,
95 input_iterator_type> copy_range_type;
96
97 input_iterator_type InputEnd=::boost::end(lit_input);
98
99 typedef transform_iterator<copy_range_type, find_iterator_type>
100 transform_iter_type;
101
102 transform_iter_type itBegin=
103 ::boost::make_transform_iterator(
104 find_iterator_type( ::boost::begin(lit_input), InputEnd, Finder ),
105 copy_range_type());
106
107 transform_iter_type itEnd=
108 ::boost::make_transform_iterator(
109 find_iterator_type(),
110 copy_range_type());
111
112 SequenceSequenceT Tmp(itBegin, itEnd);
113
114 Result.swap(Tmp);
115 return Result;
116 }
117
118// iterate split ---------------------------------------------------//
119
120 //! Split find algorithm
121 /*!
122 This algorithm executes a given finder in iteration on the input,
123 until the end of input is reached, or no match is found.
124 Iteration is done using built-in find_iterator, so the real
125 searching is performed only when needed.
126 Each match is used as a separator of segments. These segments are then
127 returned in the result.
128
129 \param Result A 'container container' to contain the result of search.
130 Both outer and inner container must have constructor taking a pair
131 of iterators as an argument.
132 Typical type of the result is
133 \c std::vector<boost::iterator_range<iterator>>
134 (each element of such a vector will container a range delimiting
135 a match).
136 \param Input A container which will be searched.
137 \param Finder A finder object used for searching
138 \return A reference to the result
139
140 \note Prior content of the result will be overwritten.
141 */
142 template<
143 typename SequenceSequenceT,
144 typename RangeT,
145 typename FinderT >
146 inline SequenceSequenceT&
147 iter_split(
148 SequenceSequenceT& Result,
149#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
150 RangeT&& Input,
151#else
152 RangeT& Input,
153#endif
154 FinderT Finder )
155 {
156 BOOST_CONCEPT_ASSERT((typedef ::boost::concepts::detail::instantiate< &::boost
::concepts::requirement_<void(*)( FinderConcept<FinderT
, typename range_iterator<RangeT>::type> )>::failed
> boost_concept_check159 __attribute__((__unused__))
157 FinderConcept<FinderT,typedef ::boost::concepts::detail::instantiate< &::boost
::concepts::requirement_<void(*)( FinderConcept<FinderT
, typename range_iterator<RangeT>::type> )>::failed
> boost_concept_check159 __attribute__((__unused__))
158 BOOST_STRING_TYPENAME range_iterator<RangeT>::type>typedef ::boost::concepts::detail::instantiate< &::boost
::concepts::requirement_<void(*)( FinderConcept<FinderT
, typename range_iterator<RangeT>::type> )>::failed
> boost_concept_check159 __attribute__((__unused__))
159 ))typedef ::boost::concepts::detail::instantiate< &::boost
::concepts::requirement_<void(*)( FinderConcept<FinderT
, typename range_iterator<RangeT>::type> )>::failed
> boost_concept_check159 __attribute__((__unused__))
;
160
161 iterator_range<BOOST_STRING_TYPENAMEtypename range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input));
162
163 typedef BOOST_STRING_TYPENAMEtypename
164 range_iterator<RangeT>::type input_iterator_type;
165 typedef split_iterator<input_iterator_type> find_iterator_type;
166 typedef detail::copy_iterator_rangeF<
167 BOOST_STRING_TYPENAMEtypename
168 range_value<SequenceSequenceT>::type,
169 input_iterator_type> copy_range_type;
170
171 input_iterator_type InputEnd=::boost::end(lit_input);
172
173 typedef transform_iterator<copy_range_type, find_iterator_type>
174 transform_iter_type;
175
176 transform_iter_type itBegin=
177 ::boost::make_transform_iterator(
178 find_iterator_type( ::boost::begin(lit_input), InputEnd, Finder ),
179 copy_range_type() );
180
181 transform_iter_type itEnd=
182 ::boost::make_transform_iterator(
183 find_iterator_type(),
184 copy_range_type() );
185
186 SequenceSequenceT Tmp(itBegin, itEnd);
187
188 Result.swap(Tmp);
189 return Result;
6
Calling implicit destructor for 'token_finderF<boost::algorithm::detail::is_any_ofF<char>>'
7
Calling '~is_any_ofF'
10
Returning from '~is_any_ofF'
11
Returning from destructor for 'token_finderF<boost::algorithm::detail::is_any_ofF<char>>'
190 }
191
192 } // namespace algorithm
193
194 // pull names to the boost namespace
195 using algorithm::iter_find;
196 using algorithm::iter_split;
197
198} // namespace boost
199
200
201#endif // BOOST_STRING_ITER_FIND_HPP

/usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/bits/stl_vector.h

1// Vector implementation -*- C++ -*-
2
3// Copyright (C) 2001-2026 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/*
26 *
27 * Copyright (c) 1994
28 * Hewlett-Packard Company
29 *
30 * Permission to use, copy, modify, distribute and sell this software
31 * and its documentation for any purpose is hereby granted without fee,
32 * provided that the above copyright notice appear in all copies and
33 * that both that copyright notice and this permission notice appear
34 * in supporting documentation. Hewlett-Packard Company makes no
35 * representations about the suitability of this software for any
36 * purpose. It is provided "as is" without express or implied warranty.
37 *
38 *
39 * Copyright (c) 1996
40 * Silicon Graphics Computer Systems, Inc.
41 *
42 * Permission to use, copy, modify, distribute and sell this software
43 * and its documentation for any purpose is hereby granted without fee,
44 * provided that the above copyright notice appear in all copies and
45 * that both that copyright notice and this permission notice appear
46 * in supporting documentation. Silicon Graphics makes no
47 * representations about the suitability of this software for any
48 * purpose. It is provided "as is" without express or implied warranty.
49 */
50
51/** @file bits/stl_vector.h
52 * This is an internal header file, included by other library headers.
53 * Do not attempt to use it directly. @headername{vector}
54 */
55
56#ifndef _STL_VECTOR_H1
57#define _STL_VECTOR_H1 1
58
59#include <bits/stl_iterator_base_funcs.h>
60#include <bits/stdexcept_throw.h>
61#include <bits/concept_check.h>
62#if __cplusplus201703L >= 201103L
63#include <initializer_list>
64#endif
65#if __cplusplus201703L >= 202002L
66# include <compare>
67#endif
68#if __glibcxx_concepts // C++ >= C++20
69# include <bits/ranges_base.h> // ranges::distance
70#endif
71#if __glibcxx_containers_ranges // C++ >= 23
72# include <bits/ranges_algobase.h> // ranges::copy
73# include <bits/ranges_util.h> // ranges::subrange
74#endif
75
76#include <debug/assertions.h>
77
78#if _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR
79extern "C" void
80__sanitizer_annotate_contiguous_container(const void*, const void*,
81 const void*, const void*);
82#endif
83
84namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
85{
86_GLIBCXX_BEGIN_NAMESPACE_VERSION
87_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
88
89 /// See bits/stl_deque.h's _Deque_base for an explanation.
90 template<typename _Tp, typename _Alloc>
91 struct _Vector_base
92 {
93 typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
94 rebind<_Tp>::other _Tp_alloc_type;
95 typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer
96 pointer;
97
98 struct _Vector_impl_data
99 {
100 pointer _M_start;
101 pointer _M_finish;
102 pointer _M_end_of_storage;
103
104 _GLIBCXX20_CONSTEXPR
105 _Vector_impl_data() _GLIBCXX_NOEXCEPTnoexcept
106 : _M_start(), _M_finish(), _M_end_of_storage()
107 { }
108
109#if __cplusplus201703L >= 201103L
110 _GLIBCXX20_CONSTEXPR
111 _Vector_impl_data(_Vector_impl_data&& __x) noexcept
112 : _M_start(__x._M_start), _M_finish(__x._M_finish),
113 _M_end_of_storage(__x._M_end_of_storage)
114 { __x._M_start = __x._M_finish = __x._M_end_of_storage = pointer(); }
115#endif
116
117 _GLIBCXX20_CONSTEXPR
118 void
119 _M_copy_data(_Vector_impl_data const& __x) _GLIBCXX_NOEXCEPTnoexcept
120 {
121 _M_start = __x._M_start;
122 _M_finish = __x._M_finish;
123 _M_end_of_storage = __x._M_end_of_storage;
124 }
125
126 _GLIBCXX20_CONSTEXPR
127 void
128 _M_swap_data(_Vector_impl_data& __x) _GLIBCXX_NOEXCEPTnoexcept
129 {
130 // Do not use std::swap(_M_start, __x._M_start), etc as it loses
131 // information used by TBAA.
132 _Vector_impl_data __tmp;
133 __tmp._M_copy_data(*this);
134 _M_copy_data(__x);
135 __x._M_copy_data(__tmp);
136 }
137 };
138
139 struct _Vector_impl
140 : public _Tp_alloc_type, public _Vector_impl_data
141 {
142 _GLIBCXX20_CONSTEXPR
143 _Vector_impl() _GLIBCXX_NOEXCEPT_IF(noexcept(is_nothrow_default_constructible<_Tp_alloc_type>
::value)
144 is_nothrow_default_constructible<_Tp_alloc_type>::value)noexcept(is_nothrow_default_constructible<_Tp_alloc_type>
::value)
145#if __cpp_lib_concepts
146 requires is_default_constructible_v<_Tp_alloc_type>
147#endif
148 : _Tp_alloc_type()
149 { }
150
151 _GLIBCXX20_CONSTEXPR
152 _Vector_impl(_Tp_alloc_type const& __a) _GLIBCXX_NOEXCEPTnoexcept
153 : _Tp_alloc_type(__a)
154 { }
155
156#if __cplusplus201703L >= 201103L
157 // Not defaulted, to enforce noexcept(true) even when
158 // !is_nothrow_move_constructible<_Tp_alloc_type>.
159 _GLIBCXX20_CONSTEXPR
160 _Vector_impl(_Vector_impl&& __x) noexcept
161 : _Tp_alloc_type(std::move(__x)), _Vector_impl_data(std::move(__x))
162 { }
163
164 _GLIBCXX20_CONSTEXPR
165 _Vector_impl(_Tp_alloc_type&& __a) noexcept
166 : _Tp_alloc_type(std::move(__a))
167 { }
168
169 _GLIBCXX20_CONSTEXPR
170 _Vector_impl(_Tp_alloc_type&& __a, _Vector_impl&& __rv) noexcept
171 : _Tp_alloc_type(std::move(__a)), _Vector_impl_data(std::move(__rv))
172 { }
173#endif
174
175#if _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR
176 template<typename = _Tp_alloc_type>
177 struct _Asan
178 {
179 typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>
180 ::size_type size_type;
181
182 static _GLIBCXX20_CONSTEXPR void
183 _S_shrink(_Vector_impl&, size_type) { }
184 static _GLIBCXX20_CONSTEXPR void
185 _S_on_dealloc(_Vector_impl&) { }
186
187 typedef _Vector_impl& _Reinit;
188
189 struct _Grow
190 {
191 _GLIBCXX20_CONSTEXPR _Grow(_Vector_impl&, size_type) { }
192 _GLIBCXX20_CONSTEXPR void _M_grew(size_type) { }
193 };
194 };
195
196 // Enable ASan annotations for memory obtained from std::allocator.
197 template<typename _Up>
198 struct _Asan<allocator<_Up> >
199 {
200 typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>
201 ::size_type size_type;
202
203 // Adjust ASan annotation for [_M_start, _M_end_of_storage) to
204 // mark end of valid region as __curr instead of __prev.
205 static _GLIBCXX20_CONSTEXPR void
206 _S_adjust(_Vector_impl& __impl, pointer __prev, pointer __curr)
207 {
208#if __cpp_lib_is_constant_evaluated
209 if (std::is_constant_evaluated())
210 return;
211#endif
212 __sanitizer_annotate_contiguous_container(__impl._M_start,
213 __impl._M_end_of_storage, __prev, __curr);
214 }
215
216 static _GLIBCXX20_CONSTEXPR void
217 _S_grow(_Vector_impl& __impl, size_type __n)
218 { _S_adjust(__impl, __impl._M_finish, __impl._M_finish + __n); }
219
220 static _GLIBCXX20_CONSTEXPR void
221 _S_shrink(_Vector_impl& __impl, size_type __n)
222 { _S_adjust(__impl, __impl._M_finish + __n, __impl._M_finish); }
223
224 static _GLIBCXX20_CONSTEXPR void
225 _S_on_dealloc(_Vector_impl& __impl)
226 {
227 if (__impl._M_start)
228 _S_adjust(__impl, __impl._M_finish, __impl._M_end_of_storage);
229 }
230
231 // Used on reallocation to tell ASan unused capacity is invalid.
232 struct _Reinit
233 {
234 explicit _GLIBCXX20_CONSTEXPR
235 _Reinit(_Vector_impl& __impl) : _M_impl(__impl)
236 {
237 // Mark unused capacity as valid again before deallocating it.
238 _S_on_dealloc(_M_impl);
239 }
240
241 _GLIBCXX20_CONSTEXPR
242 ~_Reinit()
243 {
244 // Mark unused capacity as invalid after reallocation.
245 if (_M_impl._M_start)
246 _S_adjust(_M_impl, _M_impl._M_end_of_storage,
247 _M_impl._M_finish);
248 }
249
250 _Vector_impl& _M_impl;
251
252#if __cplusplus201703L >= 201103L
253 _Reinit(const _Reinit&) = delete;
254 _Reinit& operator=(const _Reinit&) = delete;
255#endif
256 };
257
258 // Tell ASan when unused capacity is initialized to be valid.
259 struct _Grow
260 {
261 _GLIBCXX20_CONSTEXPR
262 _Grow(_Vector_impl& __impl, size_type __n)
263 : _M_impl(__impl), _M_n(__n)
264 { _S_grow(_M_impl, __n); }
265
266 _GLIBCXX20_CONSTEXPR
267 ~_Grow() { if (_M_n) _S_shrink(_M_impl, _M_n); }
268
269 _GLIBCXX20_CONSTEXPR
270 void _M_grew(size_type __n) { _M_n -= __n; }
271
272#if __cplusplus201703L >= 201103L
273 _Grow(const _Grow&) = delete;
274 _Grow& operator=(const _Grow&) = delete;
275#endif
276 private:
277 _Vector_impl& _M_impl;
278 size_type _M_n;
279 };
280 };
281
282#define _GLIBCXX_ASAN_ANNOTATE_REINIT \
283 typename _Base::_Vector_impl::template _Asan<>::_Reinit const \
284 __attribute__((__unused__)) __reinit_guard(this->_M_impl)
285#define _GLIBCXX_ASAN_ANNOTATE_GROW(n) \
286 typename _Base::_Vector_impl::template _Asan<>::_Grow \
287 __attribute__((__unused__)) __grow_guard(this->_M_impl, (n))
288#define _GLIBCXX_ASAN_ANNOTATE_GREW(n) __grow_guard._M_grew(n)
289#define _GLIBCXX_ASAN_ANNOTATE_SHRINK(n) \
290 _Base::_Vector_impl::template _Asan<>::_S_shrink(this->_M_impl, n)
291#define _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC \
292 _Base::_Vector_impl::template _Asan<>::_S_on_dealloc(this->_M_impl)
293#else // ! (_GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR)
294#define _GLIBCXX_ASAN_ANNOTATE_REINIT
295#define _GLIBCXX_ASAN_ANNOTATE_GROW(n)
296#define _GLIBCXX_ASAN_ANNOTATE_GREW(n)
297#define _GLIBCXX_ASAN_ANNOTATE_SHRINK(n)
298#define _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC
299#endif // _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR
300 };
301
302 public:
303 typedef _Alloc allocator_type;
304
305 _GLIBCXX20_CONSTEXPR
306 _Tp_alloc_type&
307 _M_get_Tp_allocator() _GLIBCXX_NOEXCEPTnoexcept
308 { return this->_M_impl; }
309
310 _GLIBCXX20_CONSTEXPR
311 const _Tp_alloc_type&
312 _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPTnoexcept
313 { return this->_M_impl; }
314
315 _GLIBCXX20_CONSTEXPR
316 allocator_type
317 get_allocator() const _GLIBCXX_NOEXCEPTnoexcept
318 { return allocator_type(_M_get_Tp_allocator()); }
319
320#if __cplusplus201703L >= 201103L
321 _Vector_base() = default;
322#else
323 _Vector_base() { }
324#endif
325
326 _GLIBCXX20_CONSTEXPR
327 _Vector_base(const allocator_type& __a) _GLIBCXX_NOEXCEPTnoexcept
328 : _M_impl(__a) { }
329
330 // Kept for ABI compatibility.
331#if !_GLIBCXX_INLINE_VERSION0
332 _GLIBCXX20_CONSTEXPR
333 _Vector_base(size_t __n)
334 : _M_impl()
335 { _M_create_storage(__n); }
336#endif
337
338 _GLIBCXX20_CONSTEXPR
339 _Vector_base(size_t __n, const allocator_type& __a)
340 : _M_impl(__a)
341 { _M_create_storage(__n); }
342
343#if __cplusplus201703L >= 201103L
344 _Vector_base(_Vector_base&&) = default;
345
346 // Kept for ABI compatibility.
347# if !_GLIBCXX_INLINE_VERSION0
348 _GLIBCXX20_CONSTEXPR
349 _Vector_base(_Tp_alloc_type&& __a) noexcept
350 : _M_impl(std::move(__a)) { }
351
352 _GLIBCXX20_CONSTEXPR
353 _Vector_base(_Vector_base&& __x, const allocator_type& __a)
354 : _M_impl(__a)
355 {
356 if (__x.get_allocator() == __a)
357 this->_M_impl._M_swap_data(__x._M_impl);
358 else
359 {
360 size_t __n = __x._M_impl._M_finish - __x._M_impl._M_start;
361 _M_create_storage(__n);
362 }
363 }
364# endif
365
366 _GLIBCXX20_CONSTEXPR
367 _Vector_base(const allocator_type& __a, _Vector_base&& __x)
368 : _M_impl(_Tp_alloc_type(__a), std::move(__x._M_impl))
369 { }
370#endif
371
372 _GLIBCXX20_CONSTEXPR
373 ~_Vector_base() _GLIBCXX_NOEXCEPTnoexcept
374 {
375 ptrdiff_t __n = _M_impl._M_end_of_storage - _M_impl._M_start;
376 if (__n < 0)
377 __builtin_unreachable();
378 _M_deallocate(_M_impl._M_start, size_t(__n));
379 }
380
381 public:
382 _Vector_impl _M_impl;
383
384 _GLIBCXX20_CONSTEXPR
385 pointer
386 _M_allocate(size_t __n)
387 {
388 typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr;
389 return __n != 0 ? _Tr::allocate(_M_impl, __n) : pointer();
390 }
391
392 _GLIBCXX20_CONSTEXPR
393 void
394 _M_deallocate(pointer __p, size_t __n)
395 {
396 typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr;
397 if (__p)
398 _Tr::deallocate(_M_impl, __p, __n);
399 }
400
401 protected:
402
403 _GLIBCXX20_CONSTEXPR
404 void
405 _M_create_storage(size_t __n)
406 {
407 this->_M_impl._M_start = this->_M_allocate(__n);
408 this->_M_impl._M_finish = this->_M_impl._M_start;
409 this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;
410 }
411
412#if __glibcxx_containers_ranges // C++ >= 23
413 // Called by insert_range, and indirectly by assign_range, append_range.
414 // Initializes new elements in storage at __ptr and updates __ptr to
415 // point after the last new element.
416 // Provides strong exception safety guarantee.
417 // Requires [ptr, ptr+distance(rg)) is a valid range.
418 template<ranges::input_range _Rg>
419 constexpr void
420 _M_append_range_to(_Rg&& __rg, pointer& __ptr)
421 {
422 __ptr = std::__uninitialized_copy_a(ranges::begin(__rg),
423 ranges::end(__rg),
424 __ptr, _M_get_Tp_allocator());
425 }
426
427 // Called by assign_range, append_range, insert_range.
428 // Requires capacity() >= size()+distance(rg).
429 template<ranges::input_range _Rg>
430 constexpr void
431 _M_append_range(_Rg&& __rg)
432 { _M_append_range_to(std::forward<_Rg>(__rg), _M_impl._M_finish); }
433#endif
434 };
435
436 /**
437 * @brief A standard container which offers fixed time access to
438 * individual elements in any order.
439 *
440 * @ingroup sequences
441 * @headerfile vector
442 * @since C++98
443 *
444 * @tparam _Tp Type of element.
445 * @tparam _Alloc Allocator type, defaults to allocator<_Tp>.
446 *
447 * Meets the requirements of a <a href="tables.html#65">container</a>, a
448 * <a href="tables.html#66">reversible container</a>, and a
449 * <a href="tables.html#67">sequence</a>, including the
450 * <a href="tables.html#68">optional sequence requirements</a> with the
451 * %exception of @c push_front and @c pop_front.
452 *
453 * In some terminology a %vector can be described as a dynamic
454 * C-style array, it offers fast and efficient access to individual
455 * elements in any order and saves the user from worrying about
456 * memory and size allocation. Subscripting ( @c [] ) access is
457 * also provided as with C-style arrays.
458 */
459 template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
460 class vector : protected _Vector_base<_Tp, _Alloc>
461 {
462#ifdef _GLIBCXX_CONCEPT_CHECKS
463 // Concept requirements.
464 typedef typename _Alloc::value_type _Alloc_value_type;
465# if __cplusplus201703L < 201103L
466 __glibcxx_class_requires(_Tp, _SGIAssignableConcept)
467# endif
468 __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept)
469#endif
470
471#if __cplusplus201703L >= 201103L
472 static_assert(is_same<typename remove_cv<_Tp>::type, _Tp>::value,
473 "std::vector must have a non-const, non-volatile value_type");
474# if __cplusplus201703L > 201703L || defined __STRICT_ANSI__
475 static_assert(is_same<typename _Alloc::value_type, _Tp>::value,
476 "std::vector must have the same value_type as its allocator");
477# endif
478#endif
479
480 typedef _Vector_base<_Tp, _Alloc> _Base;
481 typedef typename _Base::_Tp_alloc_type _Tp_alloc_type;
482 typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits;
483
484 public:
485 typedef _Tp value_type;
486 typedef typename _Base::pointer pointer;
487 typedef typename _Alloc_traits::const_pointer const_pointer;
488 typedef typename _Alloc_traits::reference reference;
489 typedef typename _Alloc_traits::const_reference const_reference;
490 typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;
491 typedef __gnu_cxx::__normal_iterator<const_pointer, vector>
492 const_iterator;
493 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
494 typedef std::reverse_iterator<iterator> reverse_iterator;
495 typedef size_t size_type;
496 typedef ptrdiff_t difference_type;
497 typedef _Alloc allocator_type;
498
499 private:
500#if __cplusplus201703L >= 201103L
501 static constexpr bool
502 _S_nothrow_relocate(true_type)
503 {
504 return noexcept(std::__relocate_a(std::declval<pointer>(),
505 std::declval<pointer>(),
506 std::declval<pointer>(),
507 std::declval<_Tp_alloc_type&>()));
508 }
509
510 static constexpr bool
511 _S_nothrow_relocate(false_type)
512 { return false; }
513
514 static constexpr bool
515 _S_use_relocate()
516 {
517 // Instantiating std::__relocate_a might cause an error outside the
518 // immediate context (in __relocate_object_a's noexcept-specifier),
519 // so only do it if we know the type can be move-inserted into *this.
520 return _S_nothrow_relocate(__is_move_insertable<_Tp_alloc_type>{});
521 }
522
523 static _GLIBCXX20_CONSTEXPR pointer
524 _S_relocate(pointer __first, pointer __last, pointer __result,
525 _Tp_alloc_type& __alloc) noexcept
526 {
527#pragma GCC diagnostic push
528#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
529 if constexpr (_S_use_relocate())
530 return std::__relocate_a(__first, __last, __result, __alloc);
531 else
532 return __result;
533#pragma GCC diagnostic pop
534 }
535#endif // C++11
536
537 protected:
538 using _Base::_M_allocate;
539 using _Base::_M_deallocate;
540 using _Base::_M_impl;
541 using _Base::_M_get_Tp_allocator;
542
543 public:
544 // [23.2.4.1] construct/copy/destroy
545 // (assign() and get_allocator() are also listed in this section)
546
547 /**
548 * @brief Creates a %vector with no elements.
549 */
550#if __cplusplus201703L >= 201103L
551 vector() = default;
552#else
553 vector() { }
554#endif
555
556 /**
557 * @brief Creates a %vector with no elements.
558 * @param __a An allocator object.
559 */
560 explicit
561 _GLIBCXX20_CONSTEXPR
562 vector(const allocator_type& __a) _GLIBCXX_NOEXCEPTnoexcept
563 : _Base(__a) { }
564
565#if __cplusplus201703L >= 201103L
566 /**
567 * @brief Creates a %vector with default constructed elements.
568 * @param __n The number of elements to initially create.
569 * @param __a An allocator.
570 *
571 * This constructor fills the %vector with @a __n default
572 * constructed elements.
573 */
574 explicit
575 _GLIBCXX20_CONSTEXPR
576 vector(size_type __n, const allocator_type& __a = allocator_type())
577 : _Base(_S_check_init_len(__n, __a), __a)
578 { _M_default_initialize(__n); }
579
580 /**
581 * @brief Creates a %vector with copies of an exemplar element.
582 * @param __n The number of elements to initially create.
583 * @param __value An element to copy.
584 * @param __a An allocator.
585 *
586 * This constructor fills the %vector with @a __n copies of @a __value.
587 */
588 _GLIBCXX20_CONSTEXPR
589 vector(size_type __n, const value_type& __value,
590 const allocator_type& __a = allocator_type())
591 : _Base(_S_check_init_len(__n, __a), __a)
592 { _M_fill_initialize(__n, __value); }
593#else
594 /**
595 * @brief Creates a %vector with copies of an exemplar element.
596 * @param __n The number of elements to initially create.
597 * @param __value An element to copy.
598 * @param __a An allocator.
599 *
600 * This constructor fills the %vector with @a __n copies of @a __value.
601 */
602 explicit
603 vector(size_type __n, const value_type& __value = value_type(),
604 const allocator_type& __a = allocator_type())
605 : _Base(_S_check_init_len(__n, __a), __a)
606 { _M_fill_initialize(__n, __value); }
607#endif
608
609 /**
610 * @brief %Vector copy constructor.
611 * @param __x A %vector of identical element and allocator types.
612 *
613 * All the elements of @a __x are copied, but any unused capacity in
614 * @a __x will not be copied
615 * (i.e. capacity() == size() in the new %vector).
616 *
617 * The newly-created %vector uses a copy of the allocator object used
618 * by @a __x (unless the allocator traits dictate a different object).
619 */
620 _GLIBCXX20_CONSTEXPR
621 vector(const vector& __x)
622 : _Base(__x.size(),
623 _Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator()))
624 {
625 this->_M_impl._M_finish =
626 std::__uninitialized_copy_a(__x.begin(), __x.end(),
627 this->_M_impl._M_start,
628 _M_get_Tp_allocator());
629 }
630
631#if __cplusplus201703L >= 201103L
632 /**
633 * @brief %Vector move constructor.
634 *
635 * The newly-created %vector contains the exact contents of the
636 * moved instance.
637 * The contents of the moved instance are a valid, but unspecified
638 * %vector.
639 */
640 vector(vector&&) noexcept = default;
641
642 /// Copy constructor with alternative allocator
643 _GLIBCXX20_CONSTEXPR
644 vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
645 : _Base(__x.size(), __a)
646 {
647 this->_M_impl._M_finish =
648 std::__uninitialized_copy_a(__x.begin(), __x.end(),
649 this->_M_impl._M_start,
650 _M_get_Tp_allocator());
651 }
652
653 private:
654 _GLIBCXX20_CONSTEXPR
655 vector(vector&& __rv, const allocator_type& __m, true_type) noexcept
656 : _Base(__m, std::move(__rv))
657 { }
658
659 _GLIBCXX20_CONSTEXPR
660 vector(vector&& __rv, const allocator_type& __m, false_type)
661 : _Base(__m)
662 {
663 if (__rv.get_allocator() == __m)
664 this->_M_impl._M_swap_data(__rv._M_impl);
665 else if (!__rv.empty())
666 {
667 this->_M_create_storage(__rv.size());
668 this->_M_impl._M_finish =
669 std::__uninitialized_move_a(__rv.begin(), __rv.end(),
670 this->_M_impl._M_start,
671 _M_get_Tp_allocator());
672 __rv.clear();
673 }
674 }
675
676 public:
677 /// Move constructor with alternative allocator
678 _GLIBCXX20_CONSTEXPR
679 vector(vector&& __rv, const __type_identity_t<allocator_type>& __m)
680 noexcept( noexcept(
681 vector(std::declval<vector&&>(), std::declval<const allocator_type&>(),
682 std::declval<typename _Alloc_traits::is_always_equal>())) )
683 : vector(std::move(__rv), __m, typename _Alloc_traits::is_always_equal{})
684 { }
685
686 /**
687 * @brief Builds a %vector from an initializer list.
688 * @param __l An initializer_list.
689 * @param __a An allocator.
690 *
691 * Create a %vector consisting of copies of the elements in the
692 * initializer_list @a __l.
693 *
694 * This will call the element type's copy constructor N times
695 * (where N is @a __l.size()) and do no memory reallocation.
696 */
697 _GLIBCXX20_CONSTEXPR
698 vector(initializer_list<value_type> __l,
699 const allocator_type& __a = allocator_type())
700 : _Base(__a)
701 {
702 _M_range_initialize_n(__l.begin(), __l.end(), __l.size());
703 }
704#endif
705
706 /**
707 * @brief Builds a %vector from a range.
708 * @param __first An input iterator.
709 * @param __last An input iterator.
710 * @param __a An allocator.
711 *
712 * Create a %vector consisting of copies of the elements from
713 * [first,last).
714 *
715 * If the iterators are forward, bidirectional, or
716 * random-access, then this will call the elements' copy
717 * constructor N times (where N is distance(first,last)) and do
718 * no memory reallocation. But if only input iterators are
719 * used, then this will do at most 2N calls to the copy
720 * constructor, and logN memory reallocations.
721 */
722#if __cplusplus201703L >= 201103L
723 template<typename _InputIterator,
724 typename = std::_RequireInputIter<_InputIterator>>
725 _GLIBCXX20_CONSTEXPR
726 vector(_InputIterator __first, _InputIterator __last,
727 const allocator_type& __a = allocator_type())
728 : _Base(__a)
729 {
730#if __glibcxx_concepts // C++ >= C++20
731 if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>
732 || forward_iterator<_InputIterator>)
733 {
734 const auto __n
735 = static_cast<size_type>(ranges::distance(__first, __last));
736 _M_range_initialize_n(__first, __last, __n);
737 return;
738 }
739 else
740#endif
741 _M_range_initialize(__first, __last,
742 std::__iterator_category(__first));
743 }
744#else
745 template<typename _InputIterator>
746 vector(_InputIterator __first, _InputIterator __last,
747 const allocator_type& __a = allocator_type())
748 : _Base(__a)
749 {
750 // Check whether it's an integral type. If so, it's not an iterator.
751 typedef typename std::__is_integer<_InputIterator>::__type _Integral;
752 _M_initialize_dispatch(__first, __last, _Integral());
753 }
754#endif
755
756#if __glibcxx_containers_ranges // C++ >= 23
757 /**
758 * @brief Construct a vector from a range.
759 * @param __rg A range of values that are convertible to `bool`.
760 * @since C++23
761 */
762 template<__detail::__container_compatible_range<_Tp> _Rg>
763 constexpr
764 vector(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())
765 : vector(__a)
766 {
767 if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
768 {
769 const auto __n = static_cast<size_type>(ranges::distance(__rg));
770 _M_range_initialize_n(ranges::begin(__rg), ranges::end(__rg),
771 __n);
772 }
773 else
774 {
775 auto __first = ranges::begin(__rg);
776 const auto __last = ranges::end(__rg);
777 for (; __first != __last; ++__first)
778 emplace_back(*__first);
779 }
780 }
781#endif
782
783 /**
784 * The dtor only erases the elements, and note that if the
785 * elements themselves are pointers, the pointed-to memory is
786 * not touched in any way. Managing the pointer is the user's
787 * responsibility.
788 */
789 _GLIBCXX20_CONSTEXPR
790 ~vector() _GLIBCXX_NOEXCEPTnoexcept
791 {
792 std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
793 _M_get_Tp_allocator());
794 _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC;
795 }
796
797 /**
798 * @brief %Vector assignment operator.
799 * @param __x A %vector of identical element and allocator types.
800 *
801 * All the elements of @a __x are copied, but any unused capacity in
802 * @a __x will not be copied.
803 *
804 * Whether the allocator is copied depends on the allocator traits.
805 */
806 _GLIBCXX20_CONSTEXPR
807 vector&
808 operator=(const vector& __x);
809
810#if __cplusplus201703L >= 201103L
811 /**
812 * @brief %Vector move assignment operator.
813 * @param __x A %vector of identical element and allocator types.
814 *
815 * The contents of @a __x are moved into this %vector (without copying,
816 * if the allocators permit it).
817 * Afterwards @a __x is a valid, but unspecified %vector.
818 *
819 * Whether the allocator is moved depends on the allocator traits.
820 */
821 _GLIBCXX20_CONSTEXPR
822 vector&
823 operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
824 {
825 constexpr bool __move_storage =
826 _Alloc_traits::_S_propagate_on_move_assign()
827 || _Alloc_traits::_S_always_equal();
828 _M_move_assign(std::move(__x), __bool_constant<__move_storage>());
829 return *this;
830 }
831
832 /**
833 * @brief %Vector list assignment operator.
834 * @param __l An initializer_list.
835 *
836 * This function fills a %vector with copies of the elements in the
837 * initializer list @a __l.
838 *
839 * Note that the assignment completely changes the %vector and
840 * that the resulting %vector's size is the same as the number
841 * of elements assigned.
842 */
843 _GLIBCXX20_CONSTEXPR
844 vector&
845 operator=(initializer_list<value_type> __l)
846 {
847 this->_M_assign_aux(__l.begin(), __l.end(),
848 random_access_iterator_tag());
849 return *this;
850 }
851#endif
852
853 /**
854 * @brief Assigns a given value to a %vector.
855 * @param __n Number of elements to be assigned.
856 * @param __val Value to be assigned.
857 *
858 * This function fills a %vector with @a __n copies of the given
859 * value. Note that the assignment completely changes the
860 * %vector and that the resulting %vector's size is the same as
861 * the number of elements assigned.
862 */
863 _GLIBCXX20_CONSTEXPR
864 void
865 assign(size_type __n, const value_type& __val)
866 { _M_fill_assign(__n, __val); }
867
868 /**
869 * @brief Assigns a range to a %vector.
870 * @param __first An input iterator.
871 * @param __last An input iterator.
872 *
873 * This function fills a %vector with copies of the elements in the
874 * range [__first,__last).
875 *
876 * Note that the assignment completely changes the %vector and
877 * that the resulting %vector's size is the same as the number
878 * of elements assigned.
879 */
880#if __cplusplus201703L >= 201103L
881 template<typename _InputIterator,
882 typename = std::_RequireInputIter<_InputIterator>>
883 _GLIBCXX20_CONSTEXPR
884 void
885 assign(_InputIterator __first, _InputIterator __last)
886 { _M_assign_aux(__first, __last, std::__iterator_category(__first)); }
887#else
888 template<typename _InputIterator>
889 void
890 assign(_InputIterator __first, _InputIterator __last)
891 {
892 // Check whether it's an integral type. If so, it's not an iterator.
893 typedef typename std::__is_integer<_InputIterator>::__type _Integral;
894 _M_assign_dispatch(__first, __last, _Integral());
895 }
896#endif
897
898#if __cplusplus201703L >= 201103L
899 /**
900 * @brief Assigns an initializer list to a %vector.
901 * @param __l An initializer_list.
902 *
903 * This function fills a %vector with copies of the elements in the
904 * initializer list @a __l.
905 *
906 * Note that the assignment completely changes the %vector and
907 * that the resulting %vector's size is the same as the number
908 * of elements assigned.
909 */
910 _GLIBCXX20_CONSTEXPR
911 void
912 assign(initializer_list<value_type> __l)
913 {
914 this->_M_assign_aux(__l.begin(), __l.end(),
915 random_access_iterator_tag());
916 }
917#endif
918
919#if __glibcxx_containers_ranges // C++ >= 23
920 /**
921 * @brief Assign a range to the vector.
922 * @param __rg A range of values that are convertible to `value_type`.
923 * @pre `__rg` and `*this` do not overlap.
924 * @since C++23
925 */
926 template<__detail::__container_compatible_range<_Tp> _Rg>
927 constexpr void
928 assign_range(_Rg&& __rg)
929 {
930 static_assert(assignable_from<_Tp&, ranges::range_reference_t<_Rg>>);
931
932 if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
933 {
934 const auto __n = size_type(ranges::distance(__rg));
935 if (__n <= size())
936 {
937 auto __res = ranges::copy(__rg, this->_M_impl._M_start);
938 _M_erase_at_end(__res.out);
939 return;
940 }
941
942 reserve(__n);
943 auto __first = ranges::copy_n(ranges::begin(__rg), size(),
944 this->_M_impl._M_start).in;
945 [[maybe_unused]] const auto __diff = __n - size();
946 _GLIBCXX_ASAN_ANNOTATE_GROW(__diff);
947 _Base::_M_append_range(ranges::subrange(std::move(__first),
948 ranges::end(__rg)));
949 _GLIBCXX_ASAN_ANNOTATE_GREW(__diff);
950 }
951 else // input_range<_Rg> && !sized_range<_Rg>
952 {
953 auto __first = ranges::begin(__rg);
954 const auto __last = ranges::end(__rg);
955 pointer __ptr = this->_M_impl._M_start;
956 pointer const __end = this->_M_impl._M_finish;
957
958 while (__ptr < __end && __first != __last)
959 {
960 *__ptr = *__first;
961 ++__ptr;
962 ++__first;
963 }
964
965 if (__first == __last)
966 _M_erase_at_end(__ptr);
967 else
968 {
969 do
970 emplace_back(*__first);
971 while (++__first != __last);
972 }
973 }
974 }
975#endif // containers_ranges
976
977 /// Get a copy of the memory allocation object.
978 using _Base::get_allocator;
979
980 // iterators
981 /**
982 * Returns a read/write iterator that points to the first
983 * element in the %vector. Iteration is done in ordinary
984 * element order.
985 */
986 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
987 iterator
988 begin() _GLIBCXX_NOEXCEPTnoexcept
989 { return iterator(this->_M_impl._M_start); }
990
991 /**
992 * Returns a read-only (constant) iterator that points to the
993 * first element in the %vector. Iteration is done in ordinary
994 * element order.
995 */
996 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
997 const_iterator
998 begin() const _GLIBCXX_NOEXCEPTnoexcept
999 { return const_iterator(this->_M_impl._M_start); }
1000
1001 /**
1002 * Returns a read/write iterator that points one past the last
1003 * element in the %vector. Iteration is done in ordinary
1004 * element order.
1005 */
1006 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1007 iterator
1008 end() _GLIBCXX_NOEXCEPTnoexcept
1009 { return iterator(this->_M_impl._M_finish); }
1010
1011 /**
1012 * Returns a read-only (constant) iterator that points one past
1013 * the last element in the %vector. Iteration is done in
1014 * ordinary element order.
1015 */
1016 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1017 const_iterator
1018 end() const _GLIBCXX_NOEXCEPTnoexcept
1019 { return const_iterator(this->_M_impl._M_finish); }
1020
1021 /**
1022 * Returns a read/write reverse iterator that points to the
1023 * last element in the %vector. Iteration is done in reverse
1024 * element order.
1025 */
1026 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1027 reverse_iterator
1028 rbegin() _GLIBCXX_NOEXCEPTnoexcept
1029 { return reverse_iterator(end()); }
1030
1031 /**
1032 * Returns a read-only (constant) reverse iterator that points
1033 * to the last element in the %vector. Iteration is done in
1034 * reverse element order.
1035 */
1036 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1037 const_reverse_iterator
1038 rbegin() const _GLIBCXX_NOEXCEPTnoexcept
1039 { return const_reverse_iterator(end()); }
1040
1041 /**
1042 * Returns a read/write reverse iterator that points to one
1043 * before the first element in the %vector. Iteration is done
1044 * in reverse element order.
1045 */
1046 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1047 reverse_iterator
1048 rend() _GLIBCXX_NOEXCEPTnoexcept
1049 { return reverse_iterator(begin()); }
1050
1051 /**
1052 * Returns a read-only (constant) reverse iterator that points
1053 * to one before the first element in the %vector. Iteration
1054 * is done in reverse element order.
1055 */
1056 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1057 const_reverse_iterator
1058 rend() const _GLIBCXX_NOEXCEPTnoexcept
1059 { return const_reverse_iterator(begin()); }
1060
1061#if __cplusplus201703L >= 201103L
1062 /**
1063 * Returns a read-only (constant) iterator that points to the
1064 * first element in the %vector. Iteration is done in ordinary
1065 * element order.
1066 */
1067 [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1068 const_iterator
1069 cbegin() const noexcept
1070 { return const_iterator(this->_M_impl._M_start); }
1071
1072 /**
1073 * Returns a read-only (constant) iterator that points one past
1074 * the last element in the %vector. Iteration is done in
1075 * ordinary element order.
1076 */
1077 [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1078 const_iterator
1079 cend() const noexcept
1080 { return const_iterator(this->_M_impl._M_finish); }
1081
1082 /**
1083 * Returns a read-only (constant) reverse iterator that points
1084 * to the last element in the %vector. Iteration is done in
1085 * reverse element order.
1086 */
1087 [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1088 const_reverse_iterator
1089 crbegin() const noexcept
1090 { return const_reverse_iterator(end()); }
1091
1092 /**
1093 * Returns a read-only (constant) reverse iterator that points
1094 * to one before the first element in the %vector. Iteration
1095 * is done in reverse element order.
1096 */
1097 [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1098 const_reverse_iterator
1099 crend() const noexcept
1100 { return const_reverse_iterator(begin()); }
1101#endif
1102
1103 // [23.2.4.2] capacity
1104 /** Returns the number of elements in the %vector. */
1105 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1106 size_type
1107 size() const _GLIBCXX_NOEXCEPTnoexcept
1108 {
1109 ptrdiff_t __dif = this->_M_impl._M_finish - this->_M_impl._M_start;
1110 if (__dif < 0)
1111 __builtin_unreachable();
1112 return size_type(__dif);
1113 }
1114
1115 /** Returns the size() of the largest possible %vector. */
1116 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1117 size_type
1118 max_size() const _GLIBCXX_NOEXCEPTnoexcept
1119 { return _S_max_size(_M_get_Tp_allocator()); }
1120
1121#if __cplusplus201703L >= 201103L
1122 /**
1123 * @brief Resizes the %vector to the specified number of elements.
1124 * @param __new_size Number of elements the %vector should contain.
1125 *
1126 * This function will %resize the %vector to the specified
1127 * number of elements. If the number is smaller than the
1128 * %vector's current size the %vector is truncated, otherwise
1129 * default constructed elements are appended.
1130 */
1131 _GLIBCXX20_CONSTEXPR
1132 void
1133 resize(size_type __new_size)
1134 {
1135 if (__new_size > size())
1136 _M_default_append(__new_size - size());
1137 else if (__new_size < size())
1138 _M_erase_at_end(this->_M_impl._M_start + __new_size);
1139 }
1140
1141 /**
1142 * @brief Resizes the %vector to the specified number of elements.
1143 * @param __new_size Number of elements the %vector should contain.
1144 * @param __x Data with which new elements should be populated.
1145 *
1146 * This function will %resize the %vector to the specified
1147 * number of elements. If the number is smaller than the
1148 * %vector's current size the %vector is truncated, otherwise
1149 * the %vector is extended and new elements are populated with
1150 * given data.
1151 */
1152 _GLIBCXX20_CONSTEXPR
1153 void
1154 resize(size_type __new_size, const value_type& __x)
1155 {
1156 if (__new_size > size())
1157 _M_fill_append(__new_size - size(), __x);
1158 else if (__new_size < size())
1159 _M_erase_at_end(this->_M_impl._M_start + __new_size);
1160 }
1161#else
1162 /**
1163 * @brief Resizes the %vector to the specified number of elements.
1164 * @param __new_size Number of elements the %vector should contain.
1165 * @param __x Data with which new elements should be populated.
1166 *
1167 * This function will %resize the %vector to the specified
1168 * number of elements. If the number is smaller than the
1169 * %vector's current size the %vector is truncated, otherwise
1170 * the %vector is extended and new elements are populated with
1171 * given data.
1172 */
1173 _GLIBCXX20_CONSTEXPR
1174 void
1175 resize(size_type __new_size, value_type __x = value_type())
1176 {
1177 if (__new_size > size())
1178 _M_fill_append(__new_size - size(), __x);
1179 else if (__new_size < size())
1180 _M_erase_at_end(this->_M_impl._M_start + __new_size);
1181 }
1182#endif
1183
1184#if __cplusplus201703L >= 201103L
1185 /** A non-binding request to reduce capacity() to size(). */
1186 _GLIBCXX20_CONSTEXPR
1187 void
1188 shrink_to_fit()
1189 { _M_shrink_to_fit(); }
1190#endif
1191
1192 /**
1193 * Returns the total number of elements that the %vector can
1194 * hold before needing to allocate more memory.
1195 */
1196 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1197 size_type
1198 capacity() const _GLIBCXX_NOEXCEPTnoexcept
1199 {
1200 ptrdiff_t __dif = this->_M_impl._M_end_of_storage
1201 - this->_M_impl._M_start;
1202 if (__dif < 0)
1203 __builtin_unreachable();
1204 return size_type(__dif);
1205 }
1206
1207 /**
1208 * Returns true if the %vector is empty. (Thus begin() would
1209 * equal end().)
1210 */
1211 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1212 bool
1213 empty() const _GLIBCXX_NOEXCEPTnoexcept
1214 { return begin() == end(); }
1215
1216 /**
1217 * @brief Attempt to preallocate enough memory for specified number of
1218 * elements.
1219 * @param __n Number of elements required.
1220 * @throw std::length_error If @a n exceeds @c max_size().
1221 *
1222 * This function attempts to reserve enough memory for the
1223 * %vector to hold the specified number of elements. If the
1224 * number requested is more than max_size(), length_error is
1225 * thrown.
1226 *
1227 * The advantage of this function is that if optimal code is a
1228 * necessity and the user can determine the number of elements
1229 * that will be required, the user can reserve the memory in
1230 * %advance, and thus prevent a possible reallocation of memory
1231 * and copying of %vector data.
1232 */
1233 _GLIBCXX20_CONSTEXPR
1234 void
1235 reserve(size_type __n);
1236
1237 // element access
1238 /**
1239 * @brief Subscript access to the data contained in the %vector.
1240 * @param __n The index of the element for which data should be
1241 * accessed.
1242 * @return Read/write reference to data.
1243 *
1244 * This operator allows for easy, array-style, data access.
1245 * Note that data access with this operator is unchecked and
1246 * out_of_range lookups are not defined. (For checked lookups
1247 * see at().)
1248 */
1249 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1250 reference
1251 operator[](size_type __n) _GLIBCXX_NOEXCEPTnoexcept
1252 {
1253 __glibcxx_requires_subscript(__n)do { if (__builtin_expect(!bool(__n < this->size()), false
)) std::__glibcxx_assert_fail("/usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/bits/stl_vector.h"
, 1253, __PRETTY_FUNCTION__, "__n < this->size()"); } while
(false)
;
1254 return *(this->_M_impl._M_start + __n);
1255 }
1256
1257 /**
1258 * @brief Subscript access to the data contained in the %vector.
1259 * @param __n The index of the element for which data should be
1260 * accessed.
1261 * @return Read-only (constant) reference to data.
1262 *
1263 * This operator allows for easy, array-style, data access.
1264 * Note that data access with this operator is unchecked and
1265 * out_of_range lookups are not defined. (For checked lookups
1266 * see at().)
1267 */
1268 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1269 const_reference
1270 operator[](size_type __n) const _GLIBCXX_NOEXCEPTnoexcept
1271 {
1272 __glibcxx_requires_subscript(__n)do { if (__builtin_expect(!bool(__n < this->size()), false
)) std::__glibcxx_assert_fail("/usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/bits/stl_vector.h"
, 1272, __PRETTY_FUNCTION__, "__n < this->size()"); } while
(false)
;
1273 return *(this->_M_impl._M_start + __n);
1274 }
1275
1276 protected:
1277 /// Safety check used only from at().
1278 _GLIBCXX20_CONSTEXPR
1279 void
1280 _M_range_check(size_type __n) const
1281 {
1282 if (__n >= this->size())
1283 __throw_out_of_range_fmt(__N("vector::_M_range_check: __n "("vector::_M_range_check: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
1284 "(which is %zu) >= this->size() "("vector::_M_range_check: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
1285 "(which is %zu)")("vector::_M_range_check: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
,
1286 __n, this->size());
1287 }
1288
1289 public:
1290 /**
1291 * @brief Provides access to the data contained in the %vector.
1292 * @param __n The index of the element for which data should be
1293 * accessed.
1294 * @return Read/write reference to data.
1295 * @throw std::out_of_range If @a __n is an invalid index.
1296 *
1297 * This function provides for safer data access. The parameter
1298 * is first checked that it is in the range of the vector. The
1299 * function throws out_of_range if the check fails.
1300 */
1301 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1302 reference
1303 at(size_type __n)
1304 {
1305 _M_range_check(__n);
1306 return (*this)[__n];
1307 }
1308
1309 /**
1310 * @brief Provides access to the data contained in the %vector.
1311 * @param __n The index of the element for which data should be
1312 * accessed.
1313 * @return Read-only (constant) reference to data.
1314 * @throw std::out_of_range If @a __n is an invalid index.
1315 *
1316 * This function provides for safer data access. The parameter
1317 * is first checked that it is in the range of the vector. The
1318 * function throws out_of_range if the check fails.
1319 */
1320 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1321 const_reference
1322 at(size_type __n) const
1323 {
1324 _M_range_check(__n);
1325 return (*this)[__n];
1326 }
1327
1328 /**
1329 * Returns a read/write reference to the data at the first
1330 * element of the %vector.
1331 */
1332 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1333 reference
1334 front() _GLIBCXX_NOEXCEPTnoexcept
1335 {
1336 __glibcxx_requires_nonempty()do { if (__builtin_expect(!bool(!this->empty()), false)) std
::__glibcxx_assert_fail("/usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/bits/stl_vector.h"
, 1336, __PRETTY_FUNCTION__, "!this->empty()"); } while (false
)
;
1337 return *begin();
1338 }
1339
1340 /**
1341 * Returns a read-only (constant) reference to the data at the first
1342 * element of the %vector.
1343 */
1344 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1345 const_reference
1346 front() const _GLIBCXX_NOEXCEPTnoexcept
1347 {
1348 __glibcxx_requires_nonempty()do { if (__builtin_expect(!bool(!this->empty()), false)) std
::__glibcxx_assert_fail("/usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/bits/stl_vector.h"
, 1348, __PRETTY_FUNCTION__, "!this->empty()"); } while (false
)
;
1349 return *begin();
1350 }
1351
1352 /**
1353 * Returns a read/write reference to the data at the last
1354 * element of the %vector.
1355 */
1356 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1357 reference
1358 back() _GLIBCXX_NOEXCEPTnoexcept
1359 {
1360 __glibcxx_requires_nonempty()do { if (__builtin_expect(!bool(!this->empty()), false)) std
::__glibcxx_assert_fail("/usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/bits/stl_vector.h"
, 1360, __PRETTY_FUNCTION__, "!this->empty()"); } while (false
)
;
1361 return *(end() - 1);
1362 }
1363
1364 /**
1365 * Returns a read-only (constant) reference to the data at the
1366 * last element of the %vector.
1367 */
1368 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1369 const_reference
1370 back() const _GLIBCXX_NOEXCEPTnoexcept
1371 {
1372 __glibcxx_requires_nonempty()do { if (__builtin_expect(!bool(!this->empty()), false)) std
::__glibcxx_assert_fail("/usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/bits/stl_vector.h"
, 1372, __PRETTY_FUNCTION__, "!this->empty()"); } while (false
)
;
1373 return *(end() - 1);
1374 }
1375
1376 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1377 // DR 464. Suggestion for new member functions in standard containers.
1378 // data access
1379 /**
1380 * Returns a pointer such that [data(), data() + size()) is a valid
1381 * range. For a non-empty %vector, data() == &front().
1382 */
1383 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1384 _Tp*
1385 data() _GLIBCXX_NOEXCEPTnoexcept
1386 { return _M_data_ptr(this->_M_impl._M_start); }
1387
1388 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1389 const _Tp*
1390 data() const _GLIBCXX_NOEXCEPTnoexcept
1391 { return _M_data_ptr(this->_M_impl._M_start); }
1392
1393 // [23.2.4.3] modifiers
1394 /**
1395 * @brief Add data to the end of the %vector.
1396 * @param __x Data to be added.
1397 *
1398 * This is a typical stack operation. The function creates an
1399 * element at the end of the %vector and assigns the given data
1400 * to it. Due to the nature of a %vector this operation can be
1401 * done in constant time if the %vector has preallocated space
1402 * available.
1403 */
1404 _GLIBCXX20_CONSTEXPR
1405 void
1406 push_back(const value_type& __x)
1407 {
1408 if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
1409 {
1410 _GLIBCXX_ASAN_ANNOTATE_GROW(1);
1411 _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
1412 __x);
1413 ++this->_M_impl._M_finish;
1414 _GLIBCXX_ASAN_ANNOTATE_GREW(1);
1415 }
1416 else
1417 _M_realloc_append(__x);
1418 }
1419
1420#if __cplusplus201703L >= 201103L
1421 _GLIBCXX20_CONSTEXPR
1422 void
1423 push_back(value_type&& __x)
1424 { emplace_back(std::move(__x)); }
1425
1426 template<typename... _Args>
1427#if __cplusplus201703L > 201402L
1428 _GLIBCXX20_CONSTEXPR
1429 reference
1430#else
1431 void
1432#endif
1433 emplace_back(_Args&&... __args);
1434#endif
1435
1436 /**
1437 * @brief Removes last element.
1438 *
1439 * This is a typical stack operation. It shrinks the %vector by one.
1440 *
1441 * Note that no data is returned, and if the last element's
1442 * data is needed, it should be retrieved before pop_back() is
1443 * called.
1444 */
1445 _GLIBCXX20_CONSTEXPR
1446 void
1447 pop_back() _GLIBCXX_NOEXCEPTnoexcept
1448 {
1449 __glibcxx_requires_nonempty()do { if (__builtin_expect(!bool(!this->empty()), false)) std
::__glibcxx_assert_fail("/usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/bits/stl_vector.h"
, 1449, __PRETTY_FUNCTION__, "!this->empty()"); } while (false
)
;
1450 --this->_M_impl._M_finish;
1451 _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish);
1452 _GLIBCXX_ASAN_ANNOTATE_SHRINK(1);
1453 }
1454
1455#if __cplusplus201703L >= 201103L
1456 /**
1457 * @brief Inserts an object in %vector before specified iterator.
1458 * @param __position A const_iterator into the %vector.
1459 * @param __args Arguments.
1460 * @return An iterator that points to the inserted data.
1461 *
1462 * This function will insert an object of type T constructed
1463 * with T(std::forward<Args>(args)...) before the specified location.
1464 * Note that this kind of operation could be expensive for a %vector
1465 * and if it is frequently used the user should consider using
1466 * std::list.
1467 */
1468 template<typename... _Args>
1469 _GLIBCXX20_CONSTEXPR
1470 iterator
1471 emplace(const_iterator __position, _Args&&... __args)
1472 { return _M_emplace_aux(__position, std::forward<_Args>(__args)...); }
1473
1474 /**
1475 * @brief Inserts given value into %vector before specified iterator.
1476 * @param __position A const_iterator into the %vector.
1477 * @param __x Data to be inserted.
1478 * @return An iterator that points to the inserted data.
1479 *
1480 * This function will insert a copy of the given value before
1481 * the specified location. Note that this kind of operation
1482 * could be expensive for a %vector and if it is frequently
1483 * used the user should consider using std::list.
1484 */
1485 _GLIBCXX20_CONSTEXPR
1486 iterator
1487 insert(const_iterator __position, const value_type& __x);
1488#else
1489 /**
1490 * @brief Inserts given value into %vector before specified iterator.
1491 * @param __position An iterator into the %vector.
1492 * @param __x Data to be inserted.
1493 * @return An iterator that points to the inserted data.
1494 *
1495 * This function will insert a copy of the given value before
1496 * the specified location. Note that this kind of operation
1497 * could be expensive for a %vector and if it is frequently
1498 * used the user should consider using std::list.
1499 */
1500 iterator
1501 insert(iterator __position, const value_type& __x);
1502#endif
1503
1504#if __cplusplus201703L >= 201103L
1505 /**
1506 * @brief Inserts given rvalue into %vector before specified iterator.
1507 * @param __position A const_iterator into the %vector.
1508 * @param __x Data to be inserted.
1509 * @return An iterator that points to the inserted data.
1510 *
1511 * This function will insert a copy of the given rvalue before
1512 * the specified location. Note that this kind of operation
1513 * could be expensive for a %vector and if it is frequently
1514 * used the user should consider using std::list.
1515 */
1516 _GLIBCXX20_CONSTEXPR
1517 iterator
1518 insert(const_iterator __position, value_type&& __x)
1519 { return _M_insert_rval(__position, std::move(__x)); }
1520
1521 /**
1522 * @brief Inserts an initializer_list into the %vector.
1523 * @param __position An iterator into the %vector.
1524 * @param __l An initializer_list.
1525 *
1526 * This function will insert copies of the data in the
1527 * initializer_list @a l into the %vector before the location
1528 * specified by @a position.
1529 *
1530 * Note that this kind of operation could be expensive for a
1531 * %vector and if it is frequently used the user should
1532 * consider using std::list.
1533 */
1534 _GLIBCXX20_CONSTEXPR
1535 iterator
1536 insert(const_iterator __position, initializer_list<value_type> __l)
1537 {
1538 auto __offset = __position - cbegin();
1539 _M_range_insert(begin() + __offset, __l.begin(), __l.end(),
1540 std::random_access_iterator_tag());
1541 return begin() + __offset;
1542 }
1543#endif
1544
1545#if __cplusplus201703L >= 201103L
1546 /**
1547 * @brief Inserts a number of copies of given data into the %vector.
1548 * @param __position A const_iterator into the %vector.
1549 * @param __n Number of elements to be inserted.
1550 * @param __x Data to be inserted.
1551 * @return An iterator that points to the inserted data.
1552 *
1553 * This function will insert a specified number of copies of
1554 * the given data before the location specified by @a position.
1555 *
1556 * Note that this kind of operation could be expensive for a
1557 * %vector and if it is frequently used the user should
1558 * consider using std::list.
1559 */
1560 _GLIBCXX20_CONSTEXPR
1561 iterator
1562 insert(const_iterator __position, size_type __n, const value_type& __x)
1563 {
1564 difference_type __offset = __position - cbegin();
1565 _M_fill_insert(begin() + __offset, __n, __x);
1566 return begin() + __offset;
1567 }
1568#else
1569 /**
1570 * @brief Inserts a number of copies of given data into the %vector.
1571 * @param __position An iterator into the %vector.
1572 * @param __n Number of elements to be inserted.
1573 * @param __x Data to be inserted.
1574 *
1575 * This function will insert a specified number of copies of
1576 * the given data before the location specified by @a position.
1577 *
1578 * Note that this kind of operation could be expensive for a
1579 * %vector and if it is frequently used the user should
1580 * consider using std::list.
1581 */
1582 void
1583 insert(iterator __position, size_type __n, const value_type& __x)
1584 { _M_fill_insert(__position, __n, __x); }
1585#endif
1586
1587#if __cplusplus201703L >= 201103L
1588 /**
1589 * @brief Inserts a range into the %vector.
1590 * @param __position A const_iterator into the %vector.
1591 * @param __first An input iterator.
1592 * @param __last An input iterator.
1593 * @return An iterator that points to the inserted data.
1594 *
1595 * This function will insert copies of the data in the range
1596 * [__first,__last) into the %vector before the location specified
1597 * by @a pos.
1598 *
1599 * Note that this kind of operation could be expensive for a
1600 * %vector and if it is frequently used the user should
1601 * consider using std::list.
1602 */
1603 template<typename _InputIterator,
1604 typename = std::_RequireInputIter<_InputIterator>>
1605 _GLIBCXX20_CONSTEXPR
1606 iterator
1607 insert(const_iterator __position, _InputIterator __first,
1608 _InputIterator __last)
1609 {
1610 difference_type __offset = __position - cbegin();
1611 _M_range_insert(begin() + __offset, __first, __last,
1612 std::__iterator_category(__first));
1613 return begin() + __offset;
1614 }
1615#else
1616 /**
1617 * @brief Inserts a range into the %vector.
1618 * @param __position An iterator into the %vector.
1619 * @param __first An input iterator.
1620 * @param __last An input iterator.
1621 *
1622 * This function will insert copies of the data in the range
1623 * [__first,__last) into the %vector before the location specified
1624 * by @a pos.
1625 *
1626 * Note that this kind of operation could be expensive for a
1627 * %vector and if it is frequently used the user should
1628 * consider using std::list.
1629 */
1630 template<typename _InputIterator>
1631 void
1632 insert(iterator __position, _InputIterator __first,
1633 _InputIterator __last)
1634 {
1635 // Check whether it's an integral type. If so, it's not an iterator.
1636 typedef typename std::__is_integer<_InputIterator>::__type _Integral;
1637 _M_insert_dispatch(__position, __first, __last, _Integral());
1638 }
1639#endif
1640
1641#if __glibcxx_containers_ranges // C++ >= 23
1642 /**
1643 * @brief Insert a range into the vector.
1644 * @param __rg A range of values that are convertible to `value_type`.
1645 * @return An iterator that points to the first new element inserted,
1646 * or to `__pos` if `__rg` is an empty range.
1647 * @pre `__rg` and `*this` do not overlap.
1648 * @since C++23
1649 */
1650 template<__detail::__container_compatible_range<_Tp> _Rg>
1651 constexpr iterator
1652 insert_range(const_iterator __pos, _Rg&& __rg);
1653
1654 /**
1655 * @brief Append a range at the end of the vector.
1656 * @param __rg A range of values that are convertible to `value_type`.
1657 * @since C++23
1658 */
1659 template<__detail::__container_compatible_range<_Tp> _Rg>
1660 constexpr void
1661 append_range(_Rg&& __rg)
1662 {
1663 // N.B. __rg may overlap with *this, so we must copy from __rg before
1664 // existing elements or iterators referring to *this are invalidated.
1665 // e.g. in v.append_range(views::concat(v, foo)) rg overlaps v.
1666 if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
1667 {
1668 const auto __n = size_type(ranges::distance(__rg));
1669
1670 // If there is no existing storage, there are no iterators that
1671 // can be referring to our storage, so it's safe to allocate now.
1672 if (capacity() == 0)
1673 reserve(__n);
1674
1675 const auto __sz = size();
1676 const auto __capacity = capacity();
1677 if ((__capacity - __sz) >= __n)
1678 {
1679 _GLIBCXX_ASAN_ANNOTATE_GROW(__n);
1680 _Base::_M_append_range(__rg);
1681 _GLIBCXX_ASAN_ANNOTATE_GREW(__n);
1682 return;
1683 }
1684
1685 const size_type __len = _M_check_len(__n, "vector::append_range");
1686
1687 pointer __old_start = this->_M_impl._M_start;
1688 pointer __old_finish = this->_M_impl._M_finish;
1689
1690 allocator_type& __a = _M_get_Tp_allocator();
1691 const pointer __start = this->_M_allocate(__len);
1692 const pointer __mid = __start + __sz;
1693 const pointer __back = __mid + __n;
1694 _Guard_alloc __guard(__start, __len, *this);
1695 std::__uninitialized_copy_a(ranges::begin(__rg),
1696 ranges::end(__rg),
1697 __mid, __a);
1698
1699 if constexpr (_S_use_relocate())
1700 _S_relocate(__old_start, __old_finish, __start, __a);
1701 else
1702 {
1703 // RAII type to destroy initialized elements.
1704 struct _Guard_elts
1705 {
1706 pointer _M_first, _M_last; // Elements to destroy
1707 _Tp_alloc_type& _M_alloc;
1708
1709 constexpr
1710 _Guard_elts(pointer __f, pointer __l, _Tp_alloc_type& __a)
1711 : _M_first(__f), _M_last(__l), _M_alloc(__a)
1712 { }
1713
1714 constexpr
1715 ~_Guard_elts()
1716 { std::_Destroy(_M_first, _M_last, _M_alloc); }
1717
1718 _Guard_elts(_Guard_elts&&) = delete;
1719 };
1720 _Guard_elts __guard_elts{__mid, __back, __a};
1721
1722 std::__uninitialized_move_a(__old_start, __old_finish,
1723 __start, __a);
1724
1725 // Let old elements get destroyed by __guard_elts:
1726 __guard_elts._M_first = __old_start;
1727 __guard_elts._M_last = __old_finish;
1728 }
1729
1730 // Now give ownership of old storage to __guard:
1731 __guard._M_storage = __old_start;
1732 __guard._M_len = __capacity;
1733 // Finally, take ownership of new storage:
1734 this->_M_impl._M_start = __start;
1735 this->_M_impl._M_finish = __back;
1736 this->_M_impl._M_end_of_storage = __start + __len;
1737 }
1738 else
1739 {
1740 auto __first = ranges::begin(__rg);
1741 const auto __last = ranges::end(__rg);
1742
1743 // Fill up to the end of current capacity.
1744 for (auto __free = capacity() - size();
1745 __first != __last && __free > 0;
1746 ++__first, (void) --__free)
1747 emplace_back(*__first);
1748
1749 if (__first == __last)
1750 return;
1751
1752 // Copy the rest of the range to a new vector.
1753 vector __tmp(_M_get_Tp_allocator());
1754 for (; __first != __last; ++__first)
1755 __tmp.emplace_back(*__first);
1756 reserve(_M_check_len(__tmp.size(), "vector::append_range"));
1757 ranges::subrange __r(std::make_move_iterator(__tmp.begin()),
1758 std::make_move_iterator(__tmp.end()));
1759 append_range(__r); // This will take the fast path above.
1760 }
1761 }
1762#endif // containers_ranges
1763
1764 /**
1765 * @brief Remove element at given position.
1766 * @param __position Iterator pointing to element to be erased.
1767 * @return An iterator pointing to the next element (or end()).
1768 *
1769 * This function will erase the element at the given position and thus
1770 * shorten the %vector by one.
1771 *
1772 * Note This operation could be expensive and if it is
1773 * frequently used the user should consider using std::list.
1774 * The user is also cautioned that this function only erases
1775 * the element, and that if the element is itself a pointer,
1776 * the pointed-to memory is not touched in any way. Managing
1777 * the pointer is the user's responsibility.
1778 */
1779 _GLIBCXX20_CONSTEXPR
1780 iterator
1781#if __cplusplus201703L >= 201103L
1782 erase(const_iterator __position)
1783 { return _M_erase(begin() + (__position - cbegin())); }
1784#else
1785 erase(iterator __position)
1786 { return _M_erase(__position); }
1787#endif
1788
1789 /**
1790 * @brief Remove a range of elements.
1791 * @param __first Iterator pointing to the first element to be erased.
1792 * @param __last Iterator pointing to one past the last element to be
1793 * erased.
1794 * @return An iterator pointing to the element pointed to by @a __last
1795 * prior to erasing (or end()).
1796 *
1797 * This function will erase the elements in the range
1798 * [__first,__last) and shorten the %vector accordingly.
1799 *
1800 * Note This operation could be expensive and if it is
1801 * frequently used the user should consider using std::list.
1802 * The user is also cautioned that this function only erases
1803 * the elements, and that if the elements themselves are
1804 * pointers, the pointed-to memory is not touched in any way.
1805 * Managing the pointer is the user's responsibility.
1806 */
1807 _GLIBCXX20_CONSTEXPR
1808 iterator
1809#if __cplusplus201703L >= 201103L
1810 erase(const_iterator __first, const_iterator __last)
1811 {
1812 const auto __beg = begin();
1813 const auto __cbeg = cbegin();
1814 return _M_erase(__beg + (__first - __cbeg), __beg + (__last - __cbeg));
1815 }
1816#else
1817 erase(iterator __first, iterator __last)
1818 { return _M_erase(__first, __last); }
1819#endif
1820
1821 /**
1822 * @brief Swaps data with another %vector.
1823 * @param __x A %vector of the same element and allocator types.
1824 *
1825 * This exchanges the elements between two vectors in constant time.
1826 * (Three pointers, so it should be quite fast.)
1827 * Note that the global std::swap() function is specialized such that
1828 * std::swap(v1,v2) will feed to this function.
1829 *
1830 * Whether the allocators are swapped depends on the allocator traits.
1831 */
1832 _GLIBCXX20_CONSTEXPR
1833 void
1834 swap(vector& __x) _GLIBCXX_NOEXCEPTnoexcept
1835 {
1836#if __cplusplus201703L >= 201103L
1837 __glibcxx_assert(_Alloc_traits::propagate_on_container_swap::valuedo { if (__builtin_expect(!bool(_Alloc_traits::propagate_on_container_swap
::value || _M_get_Tp_allocator() == __x._M_get_Tp_allocator()
), false)) std::__glibcxx_assert_fail("/usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/bits/stl_vector.h"
, 1838, __PRETTY_FUNCTION__, "_Alloc_traits::propagate_on_container_swap::value || _M_get_Tp_allocator() == __x._M_get_Tp_allocator()"
); } while (false)
1838 || _M_get_Tp_allocator() == __x._M_get_Tp_allocator())do { if (__builtin_expect(!bool(_Alloc_traits::propagate_on_container_swap
::value || _M_get_Tp_allocator() == __x._M_get_Tp_allocator()
), false)) std::__glibcxx_assert_fail("/usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/bits/stl_vector.h"
, 1838, __PRETTY_FUNCTION__, "_Alloc_traits::propagate_on_container_swap::value || _M_get_Tp_allocator() == __x._M_get_Tp_allocator()"
); } while (false)
;
1839#endif
1840 this->_M_impl._M_swap_data(__x._M_impl);
1841 _Alloc_traits::_S_on_swap(_M_get_Tp_allocator(),
1842 __x._M_get_Tp_allocator());
1843 }
1844
1845 /**
1846 * Erases all the elements. Note that this function only erases the
1847 * elements, and that if the elements themselves are pointers, the
1848 * pointed-to memory is not touched in any way. Managing the pointer is
1849 * the user's responsibility.
1850 */
1851 _GLIBCXX20_CONSTEXPR
1852 void
1853 clear() _GLIBCXX_NOEXCEPTnoexcept
1854 { _M_erase_at_end(this->_M_impl._M_start); }
1855
1856 private:
1857 // RAII guard for allocated storage.
1858 struct _Guard_alloc
1859 {
1860 pointer _M_storage; // Storage to deallocate
1861 size_type _M_len;
1862 _Base& _M_vect;
1863
1864 _GLIBCXX20_CONSTEXPR
1865 _Guard_alloc(pointer __s, size_type __l, _Base& __vect)
1866 : _M_storage(__s), _M_len(__l), _M_vect(__vect)
1867 { }
1868
1869 _GLIBCXX20_CONSTEXPR
1870 ~_Guard_alloc()
1871 {
1872 if (_M_storage)
1873 _M_vect._M_deallocate(_M_storage, _M_len);
1874 }
1875
1876 _GLIBCXX20_CONSTEXPR
1877 pointer
1878 _M_release()
1879 {
1880 pointer __res = _M_storage;
1881 _M_storage = pointer();
1882 return __res;
1883 }
1884
1885 private:
1886 _Guard_alloc(const _Guard_alloc&);
1887 };
1888
1889 protected:
1890 /**
1891 * Memory expansion handler. Uses the member allocation function to
1892 * obtain @a n bytes of memory, and then copies [first,last) into it.
1893 */
1894 template<typename _ForwardIterator>
1895 _GLIBCXX20_CONSTEXPR
1896 pointer
1897 _M_allocate_and_copy(size_type __n,
1898 _ForwardIterator __first, _ForwardIterator __last)
1899 {
1900 _Guard_alloc __guard(this->_M_allocate(__n), __n, *this);
1901 std::__uninitialized_copy_a
1902 (__first, __last, __guard._M_storage, _M_get_Tp_allocator());
1903 return __guard._M_release();
1904 }
1905
1906
1907 // Internal constructor functions follow.
1908
1909 // Called by the range constructor to implement [23.1.1]/9
1910
1911#if __cplusplus201703L < 201103L
1912 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1913 // 438. Ambiguity in the "do the right thing" clause
1914 template<typename _Integer>
1915 void
1916 _M_initialize_dispatch(_Integer __int_n, _Integer __value, __true_type)
1917 {
1918 const size_type __n = static_cast<size_type>(__int_n);
1919 pointer __start =
1920 _M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator()));
1921 this->_M_impl._M_start = __start;
1922 this->_M_impl._M_end_of_storage = __start + __n;
1923 _M_fill_initialize(__n, __value);
1924 }
1925
1926 // Called by the range constructor to implement [23.1.1]/9
1927 template<typename _InputIterator>
1928 void
1929 _M_initialize_dispatch(_InputIterator __first, _InputIterator __last,
1930 __false_type)
1931 {
1932 _M_range_initialize(__first, __last,
1933 std::__iterator_category(__first));
1934 }
1935#endif
1936
1937 // Called by the second initialize_dispatch above
1938 template<typename _InputIterator>
1939 _GLIBCXX20_CONSTEXPR
1940 void
1941 _M_range_initialize(_InputIterator __first, _InputIterator __last,
1942 std::input_iterator_tag)
1943 {
1944 __trytry {
1945 for (; __first != __last; ++__first)
1946#if __cplusplus201703L >= 201103L
1947 emplace_back(*__first);
1948#else
1949 push_back(*__first);
1950#endif
1951 } __catch(...)catch(...) {
1952 clear();
1953 __throw_exception_againthrow;
1954 }
1955 }
1956
1957 // Called by the second initialize_dispatch above
1958 template<typename _ForwardIterator>
1959 _GLIBCXX20_CONSTEXPR
1960 void
1961 _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last,
1962 std::forward_iterator_tag)
1963 {
1964 _M_range_initialize_n(__first, __last,
1965 std::distance(__first, __last));
1966 }
1967
1968 template<typename _Iterator, typename _Sentinel>
1969 _GLIBCXX20_CONSTEXPR
1970 void
1971 _M_range_initialize_n(_Iterator __first, _Sentinel __last,
1972 size_type __n)
1973 {
1974 pointer __start =
1975 this->_M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator()));
1976 this->_M_impl._M_start = this->_M_impl._M_finish = __start;
1977 this->_M_impl._M_end_of_storage = __start + __n;
1978 this->_M_impl._M_finish
1979 = std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first)std::move(__first), __last,
1980 __start, _M_get_Tp_allocator());
1981 }
1982
1983 // Called by the first initialize_dispatch above and by the
1984 // vector(n,value,a) constructor.
1985 _GLIBCXX20_CONSTEXPR
1986 void
1987 _M_fill_initialize(size_type __n, const value_type& __value)
1988 {
1989 this->_M_impl._M_finish =
1990 std::__uninitialized_fill_n_a(this->_M_impl._M_start, __n, __value,
1991 _M_get_Tp_allocator());
1992 }
1993
1994#if __cplusplus201703L >= 201103L
1995 // Called by the vector(n) constructor.
1996 _GLIBCXX20_CONSTEXPR
1997 void
1998 _M_default_initialize(size_type __n)
1999 {
2000 this->_M_impl._M_finish =
2001 std::__uninitialized_default_n_a(this->_M_impl._M_start, __n,
2002 _M_get_Tp_allocator());
2003 }
2004#endif
2005
2006 // Internal assign functions follow. The *_aux functions do the actual
2007 // assignment work for the range versions.
2008
2009 // Called by the range assign to implement [23.1.1]/9
2010
2011 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2012 // 438. Ambiguity in the "do the right thing" clause
2013 template<typename _Integer>
2014 _GLIBCXX20_CONSTEXPR
2015 void
2016 _M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
2017 { _M_fill_assign(__n, __val); }
2018
2019 // Called by the range assign to implement [23.1.1]/9
2020 template<typename _InputIterator>
2021 _GLIBCXX20_CONSTEXPR
2022 void
2023 _M_assign_dispatch(_InputIterator __first, _InputIterator __last,
2024 __false_type)
2025 { _M_assign_aux(__first, __last, std::__iterator_category(__first)); }
2026
2027 // Called by the second assign_dispatch above
2028 template<typename _InputIterator>
2029 _GLIBCXX20_CONSTEXPR
2030 void
2031 _M_assign_aux(_InputIterator __first, _InputIterator __last,
2032 std::input_iterator_tag);
2033
2034 // Called by the second assign_dispatch above
2035 template<typename _ForwardIterator>
2036 _GLIBCXX20_CONSTEXPR
2037 void
2038 _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
2039 std::forward_iterator_tag);
2040
2041 // Called by assign(n,t), and the range assign when it turns out
2042 // to be the same thing.
2043 _GLIBCXX20_CONSTEXPR
2044 void
2045 _M_fill_assign(size_type __n, const value_type& __val);
2046
2047 // Internal insert functions follow.
2048
2049 // Called by the range insert to implement [23.1.1]/9
2050
2051 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2052 // 438. Ambiguity in the "do the right thing" clause
2053 template<typename _Integer>
2054 _GLIBCXX20_CONSTEXPR
2055 void
2056 _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val,
2057 __true_type)
2058 { _M_fill_insert(__pos, __n, __val); }
2059
2060 // Called by the range insert to implement [23.1.1]/9
2061 template<typename _InputIterator>
2062 _GLIBCXX20_CONSTEXPR
2063 void
2064 _M_insert_dispatch(iterator __pos, _InputIterator __first,
2065 _InputIterator __last, __false_type)
2066 {
2067 _M_range_insert(__pos, __first, __last,
2068 std::__iterator_category(__first));
2069 }
2070
2071 // Called by the second insert_dispatch above
2072 template<typename _InputIterator>
2073 _GLIBCXX20_CONSTEXPR
2074 void
2075 _M_range_insert(iterator __pos, _InputIterator __first,
2076 _InputIterator __last, std::input_iterator_tag);
2077
2078 // Called by the second insert_dispatch above
2079 template<typename _ForwardIterator>
2080 _GLIBCXX20_CONSTEXPR
2081 void
2082 _M_range_insert(iterator __pos, _ForwardIterator __first,
2083 _ForwardIterator __last, std::forward_iterator_tag);
2084
2085 // Called by insert(p,n,x), and the range insert when it turns out to be
2086 // the same thing.
2087 _GLIBCXX20_CONSTEXPR
2088 void
2089 _M_fill_insert(iterator __pos, size_type __n, const value_type& __x);
2090
2091 // Called by resize(n,x), and the _M_fill_insert(end(), n, x)
2092 _GLIBCXX20_CONSTEXPR
2093 void
2094 _M_fill_append(size_type __n, const value_type& __x);
2095
2096#if __cplusplus201703L >= 201103L
2097 // Called by resize(n).
2098 _GLIBCXX20_CONSTEXPR
2099 void
2100 _M_default_append(size_type __n);
2101
2102 _GLIBCXX20_CONSTEXPR
2103 bool
2104 _M_shrink_to_fit();
2105#endif
2106
2107#if __cplusplus201703L < 201103L
2108 // Called by insert(p,x)
2109 void
2110 _M_insert_aux(iterator __position, const value_type& __x);
2111
2112 void
2113 _M_realloc_insert(iterator __position, const value_type& __x);
2114
2115 void
2116 _M_realloc_append(const value_type& __x);
2117#else
2118 // A value_type object constructed with _Alloc_traits::construct()
2119 // and destroyed with _Alloc_traits::destroy().
2120 struct _Temporary_value
2121 {
2122 template<typename... _Args>
2123 _GLIBCXX20_CONSTEXPR explicit
2124 _Temporary_value(vector* __vec, _Args&&... __args) : _M_this(__vec)
2125 {
2126 _Alloc_traits::construct(_M_this->_M_impl, _M_ptr(),
2127 std::forward<_Args>(__args)...);
2128 }
2129
2130 _GLIBCXX20_CONSTEXPR
2131 ~_Temporary_value()
2132 { _Alloc_traits::destroy(_M_this->_M_impl, _M_ptr()); }
2133
2134 _GLIBCXX20_CONSTEXPR value_type&
2135 _M_val() noexcept { return _M_storage._M_val; }
2136
2137 private:
2138 _GLIBCXX20_CONSTEXPR _Tp*
2139 _M_ptr() noexcept { return std::__addressof(_M_storage._M_val); }
2140
2141 union _Storage
2142 {
2143 constexpr _Storage() : _M_byte() { }
2144 _GLIBCXX20_CONSTEXPR ~_Storage() { }
2145 _Storage& operator=(const _Storage&) = delete;
2146 unsigned char _M_byte;
2147 _Tp _M_val;
2148 };
2149
2150 vector* _M_this;
2151 _Storage _M_storage;
2152 };
2153
2154 // Called by insert(p,x) and other functions when insertion needs to
2155 // reallocate or move existing elements. _Arg is either _Tp& or _Tp.
2156 template<typename _Arg>
2157 _GLIBCXX20_CONSTEXPR
2158 void
2159 _M_insert_aux(iterator __position, _Arg&& __arg);
2160
2161 template<typename... _Args>
2162 _GLIBCXX20_CONSTEXPR
2163 void
2164 _M_realloc_insert(iterator __position, _Args&&... __args);
2165
2166 template<typename... _Args>
2167 _GLIBCXX20_CONSTEXPR
2168 void
2169 _M_realloc_append(_Args&&... __args);
2170
2171 // Either move-construct at the end, or forward to _M_insert_aux.
2172 _GLIBCXX20_CONSTEXPR
2173 iterator
2174 _M_insert_rval(const_iterator __position, value_type&& __v);
2175
2176 // Try to emplace at the end, otherwise forward to _M_insert_aux.
2177 template<typename... _Args>
2178 _GLIBCXX20_CONSTEXPR
2179 iterator
2180 _M_emplace_aux(const_iterator __position, _Args&&... __args);
2181
2182 // Emplacing an rvalue of the correct type can use _M_insert_rval.
2183 _GLIBCXX20_CONSTEXPR
2184 iterator
2185 _M_emplace_aux(const_iterator __position, value_type&& __v)
2186 { return _M_insert_rval(__position, std::move(__v)); }
2187#endif
2188
2189 // Called by _M_fill_insert, _M_insert_aux etc.
2190 _GLIBCXX20_CONSTEXPR
2191 size_type
2192 _M_check_len(size_type __n, const char* __s) const
2193 {
2194 if (max_size() - size() < __n)
2195 __throw_length_error(__N(__s)(__s));
2196
2197 const size_type __len = size() + (std::max)(size(), __n);
2198 return (__len < size() || __len > max_size()) ? max_size() : __len;
2199 }
2200
2201 // Called by constructors to check initial size.
2202 static _GLIBCXX20_CONSTEXPR size_type
2203 _S_check_init_len(size_type __n, const allocator_type& __a)
2204 {
2205 if (__n > _S_max_size(_Tp_alloc_type(__a)))
2206 __throw_length_error(
2207 __N("cannot create std::vector larger than max_size()")("cannot create std::vector larger than max_size()"));
2208 return __n;
2209 }
2210
2211 static _GLIBCXX20_CONSTEXPR size_type
2212 _S_max_size(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPTnoexcept
2213 {
2214 // std::distance(begin(), end()) cannot be greater than PTRDIFF_MAX,
2215 // and realistically we can't store more than PTRDIFF_MAX/sizeof(T)
2216 // (even if std::allocator_traits::max_size says we can).
2217 const size_t __diffmax
2218 = __gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(_Tp);
2219 const size_t __allocmax = _Alloc_traits::max_size(__a);
2220 return (std::min)(__diffmax, __allocmax);
2221 }
2222
2223 // Internal erase functions follow.
2224
2225 // Called by erase(q1,q2), clear(), resize(), _M_fill_assign,
2226 // _M_assign_aux.
2227 _GLIBCXX20_CONSTEXPR
2228 void
2229 _M_erase_at_end(pointer __pos) _GLIBCXX_NOEXCEPTnoexcept
2230 {
2231 if (size_type __n = this->_M_impl._M_finish - __pos)
2232 {
2233 std::_Destroy(__pos, this->_M_impl._M_finish,
2234 _M_get_Tp_allocator());
2235 this->_M_impl._M_finish = __pos;
2236 _GLIBCXX_ASAN_ANNOTATE_SHRINK(__n);
2237 }
2238 }
2239
2240 _GLIBCXX20_CONSTEXPR
2241 iterator
2242 _M_erase(iterator __position);
2243
2244 _GLIBCXX20_CONSTEXPR
2245 iterator
2246 _M_erase(iterator __first, iterator __last);
2247
2248#if __cplusplus201703L >= 201103L
2249 private:
2250 // Constant-time move assignment when source object's memory can be
2251 // moved, either because the source's allocator will move too
2252 // or because the allocators are equal.
2253 _GLIBCXX20_CONSTEXPR
2254 void
2255 _M_move_assign(vector&& __x, true_type) noexcept
2256 {
2257 vector __tmp(get_allocator());
2258 this->_M_impl._M_swap_data(__x._M_impl);
2259 __tmp._M_impl._M_swap_data(__x._M_impl);
2260 std::__alloc_on_move(_M_get_Tp_allocator(), __x._M_get_Tp_allocator());
2261 }
2262
2263 // Do move assignment when it might not be possible to move source
2264 // object's memory, resulting in a linear-time operation.
2265 _GLIBCXX20_CONSTEXPR
2266 void
2267 _M_move_assign(vector&& __x, false_type)
2268 {
2269 if (__x._M_get_Tp_allocator() == this->_M_get_Tp_allocator())
2270 _M_move_assign(std::move(__x), true_type());
2271 else
2272 {
2273 // The rvalue's allocator cannot be moved and is not equal,
2274 // so we need to individually move each element.
2275 this->_M_assign_aux(std::make_move_iterator(__x.begin()),
2276 std::make_move_iterator(__x.end()),
2277 std::random_access_iterator_tag());
2278 __x.clear();
2279 }
2280 }
2281#endif
2282
2283 template<typename _Up>
2284 _GLIBCXX20_CONSTEXPR
2285 _Up*
2286 _M_data_ptr(_Up* __ptr) const _GLIBCXX_NOEXCEPTnoexcept
2287 { return __ptr; }
2288
2289#if __cplusplus201703L >= 201103L
2290 template<typename _Ptr>
2291 _GLIBCXX20_CONSTEXPR
2292 typename std::pointer_traits<_Ptr>::element_type*
2293 _M_data_ptr(_Ptr __ptr) const
2294 { return empty() ? nullptr : std::__to_address(__ptr); }
2295#else
2296 template<typename _Ptr>
2297 value_type*
2298 _M_data_ptr(_Ptr __ptr) const
2299 { return empty() ? (value_type*)0 : __ptr.operator->(); }
2300#endif
2301 };
2302
2303#if __cpp_deduction_guides201703L >= 201606
2304 template<typename _InputIterator, typename _ValT
2305 = typename iterator_traits<_InputIterator>::value_type,
2306 typename _Allocator = allocator<_ValT>,
2307 typename = _RequireInputIter<_InputIterator>,
2308 typename = _RequireAllocator<_Allocator>>
2309 vector(_InputIterator, _InputIterator, _Allocator = _Allocator())
2310 -> vector<_ValT, _Allocator>;
2311
2312#if __glibcxx_containers_ranges // C++ >= 23
2313 template<ranges::input_range _Rg,
2314 typename _Alloc = allocator<ranges::range_value_t<_Rg>>>
2315 vector(from_range_t, _Rg&&, _Alloc = _Alloc())
2316 -> vector<ranges::range_value_t<_Rg>, _Alloc>;
2317#endif
2318#endif
2319
2320 /**
2321 * @brief Vector equality comparison.
2322 * @param __x A %vector.
2323 * @param __y A %vector of the same type as @a __x.
2324 * @return True iff the size and elements of the vectors are equal.
2325 *
2326 * This is an equivalence relation. It is linear in the size of the
2327 * vectors. Vectors are considered equivalent if their sizes are equal,
2328 * and if corresponding elements compare equal.
2329 */
2330 template<typename _Tp, typename _Alloc>
2331 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2332 inline bool
2333 operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
2334 { return (__x.size() == __y.size()
2335 && std::equal(__x.begin(), __x.end(), __y.begin())); }
2336
2337#if __cpp_lib_three_way_comparison // >= C++20
2338 /**
2339 * @brief Vector ordering relation.
2340 * @param __x A `vector`.
2341 * @param __y A `vector` of the same type as `__x`.
2342 * @return A value indicating whether `__x` is less than, equal to,
2343 * greater than, or incomparable with `__y`.
2344 *
2345 * See `std::lexicographical_compare_three_way()` for how the determination
2346 * is made. This operator is used to synthesize relational operators like
2347 * `<` and `>=` etc.
2348 */
2349 template<typename _Tp, typename _Alloc>
2350 [[nodiscard]]
2351 constexpr __detail::__synth3way_t<_Tp>
2352 operator<=>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
2353 {
2354 return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
2355 __y.begin(), __y.end(),
2356 __detail::__synth3way);
2357 }
2358#else
2359 /**
2360 * @brief Vector ordering relation.
2361 * @param __x A %vector.
2362 * @param __y A %vector of the same type as @a __x.
2363 * @return True iff @a __x is lexicographically less than @a __y.
2364 *
2365 * This is a total ordering relation. It is linear in the size of the
2366 * vectors. The elements must be comparable with @c <.
2367 *
2368 * See std::lexicographical_compare() for how the determination is made.
2369 */
2370 template<typename _Tp, typename _Alloc>
2371 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
2372 operator<(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
2373 { return std::lexicographical_compare(__x.begin(), __x.end(),
2374 __y.begin(), __y.end()); }
2375
2376 /// Based on operator==
2377 template<typename _Tp, typename _Alloc>
2378 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
2379 operator!=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
2380 { return !(__x == __y); }
2381
2382 /// Based on operator<
2383 template<typename _Tp, typename _Alloc>
2384 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
2385 operator>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
2386 { return __y < __x; }
2387
2388 /// Based on operator<
2389 template<typename _Tp, typename _Alloc>
2390 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
2391 operator<=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
2392 { return !(__y < __x); }
2393
2394 /// Based on operator<
2395 template<typename _Tp, typename _Alloc>
2396 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
2397 operator>=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
2398 { return !(__x < __y); }
2399#endif // three-way comparison
2400
2401 /// See std::vector::swap().
2402 template<typename _Tp, typename _Alloc>
2403 _GLIBCXX20_CONSTEXPR
2404 inline void
2405 swap(vector<_Tp, _Alloc>& __x, vector<_Tp, _Alloc>& __y)
2406 _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y)))noexcept(noexcept(__x.swap(__y)))
2407 { __x.swap(__y); }
2408
2409_GLIBCXX_END_NAMESPACE_CONTAINER
2410
2411#if __cplusplus201703L >= 201703L
2412 namespace __detail::__variant
2413 {
2414 template<typename> struct _Never_valueless_alt; // see <variant>
2415
2416 // Provide the strong exception-safety guarantee when emplacing a
2417 // vector into a variant, but only if move assignment cannot throw.
2418 template<typename _Tp, typename _Alloc>
2419 struct _Never_valueless_alt<_GLIBCXX_STD_Cstd::vector<_Tp, _Alloc>>
2420 : std::is_nothrow_move_assignable<_GLIBCXX_STD_Cstd::vector<_Tp, _Alloc>>
2421 { };
2422 } // namespace __detail::__variant
2423#endif // C++17
2424
2425_GLIBCXX_END_NAMESPACE_VERSION
2426} // namespace std
2427
2428#endif /* _STL_VECTOR_H */

/usr/include/boost/algorithm/string/detail/finder.hpp

1// Boost string_algo library finder.hpp header file ---------------------------//
2
3// Copyright Pavol Droba 2002-2006.
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9// See http://www.boost.org/ for updates, documentation, and revision history.
10
11#ifndef BOOST_STRING_FINDER_DETAIL_HPP
12#define BOOST_STRING_FINDER_DETAIL_HPP
13
14#include <boost/algorithm/string/config.hpp>
15#include <boost/algorithm/string/constants.hpp>
16#include <iterator>
17
18#include <boost/range/iterator_range_core.hpp>
19#include <boost/range/begin.hpp>
20#include <boost/range/end.hpp>
21#include <boost/range/empty.hpp>
22#include <boost/range/as_literal.hpp>
23
24namespace boost {
25 namespace algorithm {
26 namespace detail {
27
28
29// find first functor -----------------------------------------------//
30
31 // find a subsequence in the sequence ( functor )
32 /*
33 Returns a pair <begin,end> marking the subsequence in the sequence.
34 If the find fails, functor returns <End,End>
35 */
36 template<typename SearchIteratorT,typename PredicateT>
37 struct first_finderF
38 {
39 typedef SearchIteratorT search_iterator_type;
40
41 // Construction
42 template< typename SearchT >
43 first_finderF( const SearchT& Search, PredicateT Comp ) :
44 m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {}
45 first_finderF(
46 search_iterator_type SearchBegin,
47 search_iterator_type SearchEnd,
48 PredicateT Comp ) :
49 m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {}
50
51 // Operation
52 template< typename ForwardIteratorT >
53 iterator_range<ForwardIteratorT>
54 operator()(
55 ForwardIteratorT Begin,
56 ForwardIteratorT End ) const
57 {
58 typedef iterator_range<ForwardIteratorT> result_type;
59 typedef ForwardIteratorT input_iterator_type;
60
61 // Outer loop
62 for(input_iterator_type OuterIt=Begin;
63 OuterIt!=End;
64 ++OuterIt)
65 {
66 // Sanity check
67 if( boost::empty(m_Search) )
68 return result_type( End, End );
69
70 input_iterator_type InnerIt=OuterIt;
71 search_iterator_type SubstrIt=m_Search.begin();
72 for(;
73 InnerIt!=End && SubstrIt!=m_Search.end();
74 ++InnerIt,++SubstrIt)
75 {
76 if( !( m_Comp(*InnerIt,*SubstrIt) ) )
77 break;
78 }
79
80 // Substring matching succeeded
81 if ( SubstrIt==m_Search.end() )
82 return result_type( OuterIt, InnerIt );
83 }
84
85 return result_type( End, End );
86 }
87
88 private:
89 iterator_range<search_iterator_type> m_Search;
90 PredicateT m_Comp;
91 };
92
93// find last functor -----------------------------------------------//
94
95 // find the last match a subsequence in the sequence ( functor )
96 /*
97 Returns a pair <begin,end> marking the subsequence in the sequence.
98 If the find fails, returns <End,End>
99 */
100 template<typename SearchIteratorT, typename PredicateT>
101 struct last_finderF
102 {
103 typedef SearchIteratorT search_iterator_type;
104 typedef first_finderF<
105 search_iterator_type,
106 PredicateT> first_finder_type;
107
108 // Construction
109 template< typename SearchT >
110 last_finderF( const SearchT& Search, PredicateT Comp ) :
111 m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {}
112 last_finderF(
113 search_iterator_type SearchBegin,
114 search_iterator_type SearchEnd,
115 PredicateT Comp ) :
116 m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {}
117
118 // Operation
119 template< typename ForwardIteratorT >
120 iterator_range<ForwardIteratorT>
121 operator()(
122 ForwardIteratorT Begin,
123 ForwardIteratorT End ) const
124 {
125 typedef iterator_range<ForwardIteratorT> result_type;
126
127 if( boost::empty(m_Search) )
128 return result_type( End, End );
129
130 typedef BOOST_STRING_TYPENAMEtypename
131 std::iterator_traits<ForwardIteratorT>::iterator_category category;
132
133 return findit( Begin, End, category() );
134 }
135
136 private:
137 // forward iterator
138 template< typename ForwardIteratorT >
139 iterator_range<ForwardIteratorT>
140 findit(
141 ForwardIteratorT Begin,
142 ForwardIteratorT End,
143 std::forward_iterator_tag ) const
144 {
145 typedef iterator_range<ForwardIteratorT> result_type;
146
147 first_finder_type first_finder(
148 m_Search.begin(), m_Search.end(), m_Comp );
149
150 result_type M=first_finder( Begin, End );
151 result_type Last=M;
152
153 while( M )
154 {
155 Last=M;
156 M=first_finder( ::boost::end(M), End );
157 }
158
159 return Last;
160 }
161
162 // bidirectional iterator
163 template< typename ForwardIteratorT >
164 iterator_range<ForwardIteratorT>
165 findit(
166 ForwardIteratorT Begin,
167 ForwardIteratorT End,
168 std::bidirectional_iterator_tag ) const
169 {
170 typedef iterator_range<ForwardIteratorT> result_type;
171 typedef ForwardIteratorT input_iterator_type;
172
173 // Outer loop
174 for(input_iterator_type OuterIt=End;
175 OuterIt!=Begin; )
176 {
177 input_iterator_type OuterIt2=--OuterIt;
178
179 input_iterator_type InnerIt=OuterIt2;
180 search_iterator_type SubstrIt=m_Search.begin();
181 for(;
182 InnerIt!=End && SubstrIt!=m_Search.end();
183 ++InnerIt,++SubstrIt)
184 {
185 if( !( m_Comp(*InnerIt,*SubstrIt) ) )
186 break;
187 }
188
189 // Substring matching succeeded
190 if( SubstrIt==m_Search.end() )
191 return result_type( OuterIt2, InnerIt );
192 }
193
194 return result_type( End, End );
195 }
196
197 private:
198 iterator_range<search_iterator_type> m_Search;
199 PredicateT m_Comp;
200 };
201
202// find n-th functor -----------------------------------------------//
203
204 // find the n-th match of a subsequence in the sequence ( functor )
205 /*
206 Returns a pair <begin,end> marking the subsequence in the sequence.
207 If the find fails, returns <End,End>
208 */
209 template<typename SearchIteratorT, typename PredicateT>
210 struct nth_finderF
211 {
212 typedef SearchIteratorT search_iterator_type;
213 typedef first_finderF<
214 search_iterator_type,
215 PredicateT> first_finder_type;
216 typedef last_finderF<
217 search_iterator_type,
218 PredicateT> last_finder_type;
219
220 // Construction
221 template< typename SearchT >
222 nth_finderF(
223 const SearchT& Search,
224 int Nth,
225 PredicateT Comp) :
226 m_Search(::boost::begin(Search), ::boost::end(Search)),
227 m_Nth(Nth),
228 m_Comp(Comp) {}
229 nth_finderF(
230 search_iterator_type SearchBegin,
231 search_iterator_type SearchEnd,
232 int Nth,
233 PredicateT Comp) :
234 m_Search(SearchBegin, SearchEnd),
235 m_Nth(Nth),
236 m_Comp(Comp) {}
237
238 // Operation
239 template< typename ForwardIteratorT >
240 iterator_range<ForwardIteratorT>
241 operator()(
242 ForwardIteratorT Begin,
243 ForwardIteratorT End ) const
244 {
245 if(m_Nth>=0)
246 {
247 return find_forward(Begin, End, m_Nth);
248 }
249 else
250 {
251 return find_backward(Begin, End, -m_Nth);
252 }
253
254 }
255
256 private:
257 // Implementation helpers
258 template< typename ForwardIteratorT >
259 iterator_range<ForwardIteratorT>
260 find_forward(
261 ForwardIteratorT Begin,
262 ForwardIteratorT End,
263 unsigned int N) const
264 {
265 typedef iterator_range<ForwardIteratorT> result_type;
266
267 // Sanity check
268 if( boost::empty(m_Search) )
269 return result_type( End, End );
270
271 // Instantiate find functor
272 first_finder_type first_finder(
273 m_Search.begin(), m_Search.end(), m_Comp );
274
275 result_type M( Begin, Begin );
276
277 for( unsigned int n=0; n<=N; ++n )
278 {
279 // find next match
280 M=first_finder( ::boost::end(M), End );
281
282 if ( !M )
283 {
284 // Subsequence not found, return
285 return M;
286 }
287 }
288
289 return M;
290 }
291
292 template< typename ForwardIteratorT >
293 iterator_range<ForwardIteratorT>
294 find_backward(
295 ForwardIteratorT Begin,
296 ForwardIteratorT End,
297 unsigned int N) const
298 {
299 typedef iterator_range<ForwardIteratorT> result_type;
300
301 // Sanity check
302 if( boost::empty(m_Search) )
303 return result_type( End, End );
304
305 // Instantiate find functor
306 last_finder_type last_finder(
307 m_Search.begin(), m_Search.end(), m_Comp );
308
309 result_type M( End, End );
310
311 for( unsigned int n=1; n<=N; ++n )
312 {
313 // find next match
314 M=last_finder( Begin, ::boost::begin(M) );
315
316 if ( !M )
317 {
318 // Subsequence not found, return
319 return M;
320 }
321 }
322
323 return M;
324 }
325
326
327 private:
328 iterator_range<search_iterator_type> m_Search;
329 int m_Nth;
330 PredicateT m_Comp;
331 };
332
333// find head/tail implementation helpers ---------------------------//
334
335 template<typename ForwardIteratorT>
336 iterator_range<ForwardIteratorT>
337 find_head_impl(
338 ForwardIteratorT Begin,
339 ForwardIteratorT End,
340 unsigned int N,
341 std::forward_iterator_tag )
342 {
343 typedef ForwardIteratorT input_iterator_type;
344 typedef iterator_range<ForwardIteratorT> result_type;
345
346 input_iterator_type It=Begin;
347 for( unsigned int Index=0; Index<N && It!=End; ++Index,++It )
348 ;
349
350 return result_type( Begin, It );
351 }
352
353 template< typename ForwardIteratorT >
354 iterator_range<ForwardIteratorT>
355 find_head_impl(
356 ForwardIteratorT Begin,
357 ForwardIteratorT End,
358 unsigned int N,
359 std::random_access_iterator_tag )
360 {
361 typedef iterator_range<ForwardIteratorT> result_type;
362
363 if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) )
364 return result_type( Begin, End );
365
366 return result_type(Begin,Begin+N);
367 }
368
369 // Find head implementation
370 template<typename ForwardIteratorT>
371 iterator_range<ForwardIteratorT>
372 find_head_impl(
373 ForwardIteratorT Begin,
374 ForwardIteratorT End,
375 unsigned int N )
376 {
377 typedef BOOST_STRING_TYPENAMEtypename
378 std::iterator_traits<ForwardIteratorT>::iterator_category category;
379
380 return ::boost::algorithm::detail::find_head_impl( Begin, End, N, category() );
381 }
382
383 template< typename ForwardIteratorT >
384 iterator_range<ForwardIteratorT>
385 find_tail_impl(
386 ForwardIteratorT Begin,
387 ForwardIteratorT End,
388 unsigned int N,
389 std::forward_iterator_tag )
390 {
391 typedef ForwardIteratorT input_iterator_type;
392 typedef iterator_range<ForwardIteratorT> result_type;
393
394 unsigned int Index=0;
395 input_iterator_type It=Begin;
396 input_iterator_type It2=Begin;
397
398 // Advance It2 by N increments
399 for( Index=0; Index<N && It2!=End; ++Index,++It2 )
400 ;
401
402 // Advance It, It2 to the end
403 for(; It2!=End; ++It,++It2 )
404 ;
405
406 return result_type( It, It2 );
407 }
408
409 template< typename ForwardIteratorT >
410 iterator_range<ForwardIteratorT>
411 find_tail_impl(
412 ForwardIteratorT Begin,
413 ForwardIteratorT End,
414 unsigned int N,
415 std::bidirectional_iterator_tag )
416 {
417 typedef ForwardIteratorT input_iterator_type;
418 typedef iterator_range<ForwardIteratorT> result_type;
419
420 input_iterator_type It=End;
421 for( unsigned int Index=0; Index<N && It!=Begin; ++Index,--It )
422 ;
423
424 return result_type( It, End );
425 }
426
427 template< typename ForwardIteratorT >
428 iterator_range<ForwardIteratorT>
429 find_tail_impl(
430 ForwardIteratorT Begin,
431 ForwardIteratorT End,
432 unsigned int N,
433 std::random_access_iterator_tag )
434 {
435 typedef iterator_range<ForwardIteratorT> result_type;
436
437 if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) )
438 return result_type( Begin, End );
439
440 return result_type( End-N, End );
441 }
442
443 // Operation
444 template< typename ForwardIteratorT >
445 iterator_range<ForwardIteratorT>
446 find_tail_impl(
447 ForwardIteratorT Begin,
448 ForwardIteratorT End,
449 unsigned int N )
450 {
451 typedef BOOST_STRING_TYPENAMEtypename
452 std::iterator_traits<ForwardIteratorT>::iterator_category category;
453
454 return ::boost::algorithm::detail::find_tail_impl( Begin, End, N, category() );
455 }
456
457
458
459// find head functor -----------------------------------------------//
460
461
462 // find a head in the sequence ( functor )
463 /*
464 This functor find a head of the specified range. For
465 a specified N, the head is a subsequence of N starting
466 elements of the range.
467 */
468 struct head_finderF
469 {
470 // Construction
471 head_finderF( int N ) : m_N(N) {}
472
473 // Operation
474 template< typename ForwardIteratorT >
475 iterator_range<ForwardIteratorT>
476 operator()(
477 ForwardIteratorT Begin,
478 ForwardIteratorT End ) const
479 {
480 if(m_N>=0)
481 {
482 return ::boost::algorithm::detail::find_head_impl( Begin, End, m_N );
483 }
484 else
485 {
486 iterator_range<ForwardIteratorT> Res=
487 ::boost::algorithm::detail::find_tail_impl( Begin, End, -m_N );
488
489 return ::boost::make_iterator_range(Begin, Res.begin());
490 }
491 }
492
493 private:
494 int m_N;
495 };
496
497// find tail functor -----------------------------------------------//
498
499
500 // find a tail in the sequence ( functor )
501 /*
502 This functor find a tail of the specified range. For
503 a specified N, the head is a subsequence of N starting
504 elements of the range.
505 */
506 struct tail_finderF
507 {
508 // Construction
509 tail_finderF( int N ) : m_N(N) {}
510
511 // Operation
512 template< typename ForwardIteratorT >
513 iterator_range<ForwardIteratorT>
514 operator()(
515 ForwardIteratorT Begin,
516 ForwardIteratorT End ) const
517 {
518 if(m_N>=0)
519 {
520 return ::boost::algorithm::detail::find_tail_impl( Begin, End, m_N );
521 }
522 else
523 {
524 iterator_range<ForwardIteratorT> Res=
525 ::boost::algorithm::detail::find_head_impl( Begin, End, -m_N );
526
527 return ::boost::make_iterator_range(Res.end(), End);
528 }
529 }
530
531 private:
532 int m_N;
533 };
534
535// find token functor -----------------------------------------------//
536
537 // find a token in a sequence ( functor )
538 /*
539 This find functor finds a token specified be a predicate
540 in a sequence. It is equivalent of std::find algorithm,
541 with an exception that it return range instead of a single
542 iterator.
543
544 If bCompress is set to true, adjacent matching tokens are
545 concatenated into one match.
546 */
547 template< typename PredicateT >
548 struct token_finderF
549 {
550 // Construction
551 token_finderF(
552 PredicateT Pred,
553 token_compress_mode_type eCompress=token_compress_off ) :
554 m_Pred(Pred), m_eCompress(eCompress) {}
555
556 // Operation
557 template< typename ForwardIteratorT >
558 iterator_range<ForwardIteratorT>
559 operator()(
560 ForwardIteratorT Begin,
561 ForwardIteratorT End ) const
562 {
563 typedef iterator_range<ForwardIteratorT> result_type;
564
565 ForwardIteratorT It=std::find_if( Begin, End, m_Pred );
566
567 if( It==End )
568 {
569 return result_type( End, End );
570 }
571 else
572 {
573 ForwardIteratorT It2=It;
574
575 if( m_eCompress==token_compress_on )
576 {
577 // Find first non-matching character
578 while( It2!=End && m_Pred(*It2) ) ++It2;
579 }
580 else
581 {
582 // Advance by one position
583 ++It2;
584 }
585
586 return result_type( It, It2 );
587 }
588 }
589
590 private:
591 PredicateT m_Pred;
592 token_compress_mode_type m_eCompress;
593 };
594
595// find range functor -----------------------------------------------//
596
597 // find a range in the sequence ( functor )
598 /*
599 This functor actually does not perform any find operation.
600 It always returns given iterator range as a result.
601 */
602 template<typename ForwardIterator1T>
603 struct range_finderF
604 {
605 typedef ForwardIterator1T input_iterator_type;
606 typedef iterator_range<input_iterator_type> result_type;
607
608 // Construction
609 range_finderF(
610 input_iterator_type Begin,
611 input_iterator_type End ) : m_Range(Begin, End) {}
612
613 range_finderF(const iterator_range<input_iterator_type>& Range) :
614 m_Range(Range) {}
615
616 // Operation
617 template< typename ForwardIterator2T >
618 iterator_range<ForwardIterator2T>
619 operator()(
620 ForwardIterator2T,
621 ForwardIterator2T ) const
622 {
623#if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 )((1 + 0 == 0) && (__MWERKS__ != 0) && (1 % ((
(__MWERKS__ <= 0x3003) ) + 1)))
624 return iterator_range<const ForwardIterator2T>(this->m_Range);
625#else
626 return m_Range;
627#endif
628 }
629
630 private:
631 iterator_range<input_iterator_type> m_Range;
632 };
633
634
635 } // namespace detail
636 } // namespace algorithm
637} // namespace boost
638
639#endif // BOOST_STRING_FINDER_DETAIL_HPP

/usr/include/boost/algorithm/string/detail/classification.hpp

1// Boost string_algo library classification.hpp header file ---------------------------//
2
3// Copyright Pavol Droba 2002-2003.
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9// See http://www.boost.org/ for updates, documentation, and revision history.
10
11#ifndef BOOST_STRING_CLASSIFICATION_DETAIL_HPP
12#define BOOST_STRING_CLASSIFICATION_DETAIL_HPP
13
14#include <boost/algorithm/string/config.hpp>
15#include <algorithm>
16#include <cstring>
17#include <functional>
18#include <locale>
19
20#include <boost/range/begin.hpp>
21#include <boost/range/distance.hpp>
22#include <boost/range/end.hpp>
23
24#include <boost/algorithm/string/predicate_facade.hpp>
25#include <boost/type_traits/remove_const.hpp>
26
27namespace boost {
28 namespace algorithm {
29 namespace detail {
30
31// classification functors -----------------------------------------------//
32
33 // is_classified functor
34 struct is_classifiedF :
35 public predicate_facade<is_classifiedF>
36 {
37 // Boost.ResultOf support
38 typedef bool result_type;
39
40 // Constructor from a locale
41 is_classifiedF(std::ctype_base::mask Type, std::locale const & Loc = std::locale()) :
42 m_Type(Type), m_Locale(Loc) {}
43 // Operation
44 template<typename CharT>
45 bool operator()( CharT Ch ) const
46 {
47 return std::use_facet< std::ctype<CharT> >(m_Locale).is( m_Type, Ch );
48 }
49
50 #if defined(BOOST_BORLANDC) && (BOOST_BORLANDC >= 0x560) && (BOOST_BORLANDC <= 0x582) && !defined(_USE_OLD_RW_STL)
51 template<>
52 bool operator()( char const Ch ) const
53 {
54 return std::use_facet< std::ctype<char> >(m_Locale).is( m_Type, Ch );
55 }
56 #endif
57
58 private:
59 std::ctype_base::mask m_Type;
60 std::locale m_Locale;
61 };
62
63
64 // is_any_of functor
65 /*
66 returns true if the value is from the specified set
67 */
68 template<typename CharT>
69 struct is_any_ofF :
70 public predicate_facade<is_any_ofF<CharT> >
71 {
72 private:
73 // set cannot operate on const value-type
74 typedef typename ::boost::remove_const<CharT>::type set_value_type;
75
76 public:
77 // Boost.ResultOf support
78 typedef bool result_type;
79
80 // Constructor
81 template<typename RangeT>
82 is_any_ofF( const RangeT& Range ) : m_Size(0)
83 {
84 // Prepare storage
85 m_Storage.m_dynSet=0;
86
87 std::size_t Size=::boost::distance(Range);
88 m_Size=Size;
89 set_value_type* Storage=0;
90
91 if(use_fixed_storage(m_Size))
92 {
93 // Use fixed storage
94 Storage=&m_Storage.m_fixSet[0];
95 }
96 else
97 {
98 // Use dynamic storage
99 m_Storage.m_dynSet=new set_value_type[m_Size];
100 Storage=m_Storage.m_dynSet;
101 }
102
103 // Use fixed storage
104 ::std::copy(::boost::begin(Range), ::boost::end(Range), Storage);
105 ::std::sort(Storage, Storage+m_Size);
106 }
107
108 // Copy constructor
109 is_any_ofF(const is_any_ofF& Other) : m_Size(Other.m_Size)
110 {
111 // Prepare storage
112 m_Storage.m_dynSet=0;
113 const set_value_type* SrcStorage=0;
114 set_value_type* DestStorage=0;
115
116 if(use_fixed_storage(m_Size))
117 {
118 // Use fixed storage
119 DestStorage=&m_Storage.m_fixSet[0];
120 SrcStorage=&Other.m_Storage.m_fixSet[0];
121 }
122 else
123 {
124 // Use dynamic storage
125 m_Storage.m_dynSet=new set_value_type[m_Size];
126 DestStorage=m_Storage.m_dynSet;
127 SrcStorage=Other.m_Storage.m_dynSet;
128 }
129
130 // Use fixed storage
131 ::std::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size);
132 }
133
134 // Destructor
135 ~is_any_ofF()
136 {
137 if(!use_fixed_storage(m_Size) && m_Storage.m_dynSet
7.1
Field 'm_dynSet' is not equal to null
14.1
Field 'm_dynSet' is not equal to null
7.1
Field 'm_dynSet' is not equal to null
14.1
Field 'm_dynSet' is not equal to null
7.1
Field 'm_dynSet' is not equal to null
14.1
Field 'm_dynSet' is not equal to null
7.1
Field 'm_dynSet' is not equal to null
14.1
Field 'm_dynSet' is not equal to null
7.1
Field 'm_dynSet' is not equal to null
14.1
Field 'm_dynSet' is not equal to null
7.1
Field 'm_dynSet' is not equal to null
14.1
Field 'm_dynSet' is not equal to null
!=0)
8
Taking true branch
15
Taking true branch
138 {
139 delete [] m_Storage.m_dynSet;
9
Memory is released
16
Attempt to release already released memory
140 }
141 }
142
143 // Assignment
144 is_any_ofF& operator=(const is_any_ofF& Other)
145 {
146 // Handle self assignment
147 if(this==&Other) return *this;
148
149 // Prepare storage
150 const set_value_type* SrcStorage;
151 set_value_type* DestStorage;
152
153 if(use_fixed_storage(Other.m_Size))
154 {
155 // Use fixed storage
156 DestStorage=&m_Storage.m_fixSet[0];
157 SrcStorage=&Other.m_Storage.m_fixSet[0];
158
159 // Delete old storage if was present
160 if(!use_fixed_storage(m_Size) && m_Storage.m_dynSet!=0)
161 {
162 delete [] m_Storage.m_dynSet;
163 }
164
165 // Set new size
166 m_Size=Other.m_Size;
167 }
168 else
169 {
170 // Other uses dynamic storage
171 SrcStorage=Other.m_Storage.m_dynSet;
172
173 // Check what kind of storage are we using right now
174 if(use_fixed_storage(m_Size))
175 {
176 // Using fixed storage, allocate new
177 set_value_type* pTemp=new set_value_type[Other.m_Size];
178 DestStorage=pTemp;
179 m_Storage.m_dynSet=pTemp;
180 m_Size=Other.m_Size;
181 }
182 else
183 {
184 // Using dynamic storage, check if can reuse
185 if(m_Storage.m_dynSet!=0 && m_Size>=Other.m_Size && m_Size<Other.m_Size*2)
186 {
187 // Reuse the current storage
188 DestStorage=m_Storage.m_dynSet;
189 m_Size=Other.m_Size;
190 }
191 else
192 {
193 // Allocate the new one
194 set_value_type* pTemp=new set_value_type[Other.m_Size];
195 DestStorage=pTemp;
196
197 // Delete old storage if necessary
198 if(m_Storage.m_dynSet!=0)
199 {
200 delete [] m_Storage.m_dynSet;
201 }
202 // Store the new storage
203 m_Storage.m_dynSet=pTemp;
204 // Set new size
205 m_Size=Other.m_Size;
206 }
207 }
208 }
209
210 // Copy the data
211 ::std::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size);
212
213 return *this;
214 }
215
216 // Operation
217 template<typename Char2T>
218 bool operator()( Char2T Ch ) const
219 {
220 const set_value_type* Storage=
221 (use_fixed_storage(m_Size))
222 ? &m_Storage.m_fixSet[0]
223 : m_Storage.m_dynSet;
224
225 return ::std::binary_search(Storage, Storage+m_Size, Ch);
226 }
227 private:
228 // check if the size is eligible for fixed storage
229 static bool use_fixed_storage(std::size_t size)
230 {
231 return size<=sizeof(set_value_type*)*2;
232 }
233
234
235 private:
236 // storage
237 // The actual used storage is selected on the type
238 union
239 {
240 set_value_type* m_dynSet;
241 set_value_type m_fixSet[sizeof(set_value_type*)*2];
242 }
243 m_Storage;
244
245 // storage size
246 ::std::size_t m_Size;
247 };
248
249 // is_from_range functor
250 /*
251 returns true if the value is from the specified range.
252 (i.e. x>=From && x>=To)
253 */
254 template<typename CharT>
255 struct is_from_rangeF :
256 public predicate_facade< is_from_rangeF<CharT> >
257 {
258 // Boost.ResultOf support
259 typedef bool result_type;
260
261 // Constructor
262 is_from_rangeF( CharT From, CharT To ) : m_From(From), m_To(To) {}
263
264 // Operation
265 template<typename Char2T>
266 bool operator()( Char2T Ch ) const
267 {
268 return ( m_From <= Ch ) && ( Ch <= m_To );
269 }
270
271 private:
272 CharT m_From;
273 CharT m_To;
274 };
275
276 // class_and composition predicate
277 template<typename Pred1T, typename Pred2T>
278 struct pred_andF :
279 public predicate_facade< pred_andF<Pred1T,Pred2T> >
280 {
281 public:
282
283 // Boost.ResultOf support
284 typedef bool result_type;
285
286 // Constructor
287 pred_andF( Pred1T Pred1, Pred2T Pred2 ) :
288 m_Pred1(Pred1), m_Pred2(Pred2) {}
289
290 // Operation
291 template<typename CharT>
292 bool operator()( CharT Ch ) const
293 {
294 return m_Pred1(Ch) && m_Pred2(Ch);
295 }
296
297 private:
298 Pred1T m_Pred1;
299 Pred2T m_Pred2;
300 };
301
302 // class_or composition predicate
303 template<typename Pred1T, typename Pred2T>
304 struct pred_orF :
305 public predicate_facade< pred_orF<Pred1T,Pred2T> >
306 {
307 public:
308 // Boost.ResultOf support
309 typedef bool result_type;
310
311 // Constructor
312 pred_orF( Pred1T Pred1, Pred2T Pred2 ) :
313 m_Pred1(Pred1), m_Pred2(Pred2) {}
314
315 // Operation
316 template<typename CharT>
317 bool operator()( CharT Ch ) const
318 {
319 return m_Pred1(Ch) || m_Pred2(Ch);
320 }
321
322 private:
323 Pred1T m_Pred1;
324 Pred2T m_Pred2;
325 };
326
327 // class_not composition predicate
328 template< typename PredT >
329 struct pred_notF :
330 public predicate_facade< pred_notF<PredT> >
331 {
332 public:
333 // Boost.ResultOf support
334 typedef bool result_type;
335
336 // Constructor
337 pred_notF( PredT Pred ) : m_Pred(Pred) {}
338
339 // Operation
340 template<typename CharT>
341 bool operator()( CharT Ch ) const
342 {
343 return !m_Pred(Ch);
344 }
345
346 private:
347 PredT m_Pred;
348 };
349
350 } // namespace detail
351 } // namespace algorithm
352} // namespace boost
353
354
355#endif // BOOST_STRING_CLASSIFICATION_DETAIL_HPP