BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslstl_string.h
Go to the documentation of this file.
1/// @file bslstl_string.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_string.h -*-C++-*-
8
9#ifndef INCLUDED_BSLSTL_STRING
10#define INCLUDED_BSLSTL_STRING
11
12#include <bsls_ident.h>
13BSLS_IDENT("$Id: $")
14
15/// @defgroup bslstl_string bslstl_string
16/// @brief Provide a standard-compliant `basic_string` class template.
17/// @addtogroup bsl
18/// @{
19/// @addtogroup bslstl
20/// @{
21/// @addtogroup bslstl_string
22/// @{
23///
24/// <h1> Outline </h1>
25/// * <a href="#bslstl_string-purpose"> Purpose</a>
26/// * <a href="#bslstl_string-classes"> Classes </a>
27/// * <a href="#bslstl_string-canonical-header"> Canonical Header </a>
28/// * <a href="#bslstl_string-description"> Description </a>
29/// * <a href="#bslstl_string-memory-allocation"> Memory Allocation </a>
30/// * <a href="#bslstl_string-bslma-style-allocators"> bslma-Style Allocators </a>
31/// * <a href="#bslstl_string-short-string-optimization"> Short String Optimization (SSO) </a>
32/// * <a href="#bslstl_string-lexicographical-comparisons"> Lexicographical Comparisons </a>
33/// * <a href="#bslstl_string-operations"> Operations </a>
34/// * <a href="#bslstl_string-user-defined-literals"> User-defined literals </a>
35/// * <a href="#bslstl_string-memory-allocation-for-a-file-scope-strings"> Memory Allocation For a File-Scope Strings </a>
36/// * <a href="#bslstl_string-usage"> Usage </a>
37/// * <a href="#bslstl_string-example-1-basic-syntax"> Example 1: Basic Syntax </a>
38/// * <a href="#bslstl_string-example-2-string-as-a-data-member"> Example 2: string as a data member </a>
39/// * <a href="#bslstl_string-example-3-a-stream-text-replacement-filter"> Example 3: A stream text replacement filter </a>
40///
41/// # Purpose {#bslstl_string-purpose}
42/// Provide a standard-compliant @ref basic_string class template.
43///
44/// # Classes {#bslstl_string-classes}
45///
46/// - bsl::basic_string: C++ standard compliant @ref basic_string implementation
47/// - bsl::string: `typedef` for `bsl::basic_string<char>`
48/// - bsl::wstring: `typedef` for `bsl::basic_string<wchar_t>`
49///
50/// # Canonical Header {#bslstl_string-canonical-header}
51/// bsl_string.h
52///
53/// @see ISO C++ Standard, Section 21 [strings]
54///
55/// # Description {#bslstl_string-description}
56/// This component defines a single class template @ref basic_string ,
57/// implementing standard containers, `std::string` and `std::wstring`, that
58/// hold a sequence of characters.
59///
60/// An instantiation of @ref basic_string is an allocator-aware, value-semantic
61/// type whose salient attributes are its size (number of characters) and the
62/// sequence of characters that the string contains. The @ref basic_string `class`
63/// is parameterized by the character type, `CHAR_TYPE`, that character type's
64/// traits, `CHAR_TRAITS`, and an allocator, `ALLOCATOR`. The traits for each
65/// character type provide functions that assign, compare, and copy a sequence
66/// of those characters.
67///
68/// A @ref basic_string meets the requirements of a sequential container with
69/// random access iterators as specified in the [basic.string] section of the
70/// C++ standard [21.4]. The @ref basic_string implemented here adheres to the
71/// C++11 standard, except that it does not have template specializations
72/// `std::u16string` and `std::u32string`. Note that excluded C++11 features
73/// are those that require (or are greatly simplified by) C++11 compiler
74/// support.
75///
76/// ## Memory Allocation {#bslstl_string-memory-allocation}
77///
78///
79/// The type supplied as a @ref basic_string s `ALLOCATOR` template parameter
80/// determines how that @ref basic_string will allocate memory. The @ref basic_string
81/// template supports allocators meeting the requirements of the C++11 standard,
82/// in addition it supports scoped-allocators derived from the
83/// `bslma::Allocator` memory allocation protocol. Clients intending to use
84/// `bslma` style allocators should use the template's default `ALLOCATOR` type:
85/// The default type for the `ALLOCATOR` template parameter, `bsl::allocator`,
86/// provides a C++11 standard-compatible adapter for a `bslma::Allocator`
87/// object.
88///
89/// ### bslma-Style Allocators {#bslstl_string-bslma-style-allocators}
90///
91///
92/// If the (template parameter) type `ALLOCATOR` of an @ref basic_string
93/// instantiation is `bsl::allocator`, then objects of that @ref basic_string type
94/// will conform to the standard behavior of a `bslma`-allocator-enabled type.
95/// Such a @ref basic_string accepts an optional `bslma::Allocator` argument at
96/// construction. If the address of a `bslma::Allocator` object is explicitly
97/// supplied at construction, it is used to supply memory for the @ref basic_string
98/// throughout its lifetime; otherwise, the @ref basic_string will use the default
99/// allocator installed at the time of the @ref basic_string 's construction (see
100/// @ref bslma_default ).
101///
102/// ### Short String Optimization (SSO) {#bslstl_string-short-string-optimization}
103///
104///
105/// The implementation of `bsl::string` avoids dynamic memory allocation when
106/// the length of the string's content is short enough to be contained in the
107/// footprint of the string object. This is done to:
108///
109/// * Vastly improve the efficiency of creating, destroying, copying, or moving
110/// a short `bsl::string` object.
111/// * Improve locality by placing the string contents adjacent to the data that
112/// manage that content (e.g., size, capacity).
113///
114/// Short string optimization (SSO) is a feature common to many implementations
115/// of `std::string`. The size of the in-footprint buffer depends on the
116/// platform, the compiler used, and build parameters (e.g. 64 bit build). One
117/// can readily discover that limit by evaluating the capacity of a newly
118/// created (empty) string.
119/// @code
120/// const bsl::size_t ssoLimit = bsl::string()::capacity();
121/// @endcode
122///
123/// Awareness of the SSO is significant when:
124///
125/// * Analysing patterns of allocations by string objects. {Example 1} shows
126/// how SSO becomes visible when using `bslma::TestAllocator`.
127///
128/// * Using a debugger look for the contents of string within the string object
129/// when `size()` is less than the SSO limit; otherwise, follow the data
130/// pointer to the allocated memory.
131///
132/// * Users of the `gdb` debugger may want to use `contrib/gdb-printers` of
133/// the `bde-tools` repository. That facility implicitly handles the SSO
134/// details when showing the contents of a `bsl::string` (and handles other
135/// types as well).
136///
137/// ## Lexicographical Comparisons {#bslstl_string-lexicographical-comparisons}
138///
139///
140/// Two @ref basic_string s `lhs` and `rhs` are lexicographically compared by first
141/// determining `N`, the smaller of the lengths of `lhs` and `rhs`, and
142/// comparing characters at each position between 0 and `N - 1`, using
143/// `CHAR_TRAITS::lt` in lexicographical fashion. If `CHAR_TRAITS::lt`
144/// determines that strings are non-equal (smaller or larger), then this is the
145/// result. Otherwise, the lengths of the strings are compared and the shorter
146/// string is declared the smaller. Lexicographical comparison returns equality
147/// only when both strings have the same length and the same character value in
148/// each respective position.
149///
150/// ## Operations {#bslstl_string-operations}
151///
152///
153/// This section describes the run-time complexity of operations on instances of
154/// @ref basic_string :
155/// @code
156/// Legend
157/// ------
158/// 'V' - the 'CHAR_TYPE' template parameter type of the
159/// 'basic_string'
160/// 'a', 'b' - two distinct objects of type 'basic_string<V>'
161/// 'k' - an integral number
162/// 'al' - an STL-style memory allocator
163/// 'i1', 'i2' - two iterators defining a sequence of 'CHAR_TYPE'
164/// characters
165/// 'v' - an object of type 'V'
166/// 'p1', 'p2' - two iterators belonging to 'a'
167/// distance(i1,i2) - the number of values in the range [i1, i2)
168///
169/// +-----------------------------------------+-------------------------------+
170/// | Operation | Complexity |
171/// |=========================================+===============================|
172/// | basic_string<V> a (default construction)| O[1] |
173/// | basic_string<V> a(al) | |
174/// |-----------------------------------------+-------------------------------|
175/// | basic_string<V> a(b) (copy construction)| O[n] |
176/// | basic_string<V> a(b, al) | |
177/// |-----------------------------------------+-------------------------------|
178/// | basic_string<V> a(std::move(b)) | O[1] |
179/// | (move construction) | |
180/// |-----------------------------------------+-------------------------------|
181/// | basic_string<V> a(std::move(b), a1) | O[n] |
182/// | (extended move construction) | |
183/// |-----------------------------------------+-------------------------------|
184/// | basic_string<V> a(k) | O[n] |
185/// | basic_string<V> a(k, al) | |
186/// |-----------------------------------------+-------------------------------|
187/// | basic_string<V> a(i1, i2) | O[distance(i1,i2)] |
188/// | basic_string<V> a(i1, i2, al) | |
189/// |-----------------------------------------+-------------------------------|
190/// | a.~basic_string<V>() (destruction) | O[1] |
191/// |-----------------------------------------+-------------------------------|
192/// | get_allocator() | O[1] |
193/// |-----------------------------------------+-------------------------------|
194/// | a.begin(), a.end(), | O[1] |
195/// | a.cbegin(), a.cend(), | |
196/// | a.rbegin(), a.rend(), | |
197/// | a.crbegin(), a.crend() | |
198/// |-----------------------------------------+-------------------------------|
199/// | a.size() | O[1] |
200/// |-----------------------------------------+-------------------------------|
201/// | a.max_size() | O[1] |
202/// |-----------------------------------------+-------------------------------|
203/// | a.resize(k) | O[k] |
204/// | a.resize(k, v) | |
205/// |-----------------------------------------+-------------------------------|
206/// | a.resize_and_overwrite(k, op) | O[k] |
207/// |-----------------------------------------+-------------------------------|
208/// | a.empty() | O[1] |
209/// |-----------------------------------------+-------------------------------|
210/// | a.reserve(k) | O[1] |
211/// |-----------------------------------------+-------------------------------|
212/// | a.shrink_to_fit() | O[n] |
213/// |-----------------------------------------+-------------------------------|
214/// | a[k] | O[1] |
215/// |-----------------------------------------+-------------------------------|
216/// | a.at(k) | O[1] |
217/// |-----------------------------------------+-------------------------------|
218/// | a.front() | O[1] |
219/// |-----------------------------------------+-------------------------------|
220/// | a.back() | O[1] |
221/// |-----------------------------------------+-------------------------------|
222/// | a.push_back() | O[1] |
223/// |-----------------------------------------+-------------------------------|
224/// | a.pop_back() | O[1] |
225/// |-----------------------------------------+-------------------------------|
226/// | a += b; | O[n] |
227/// |-----------------------------------------+-------------------------------|
228/// | a.append(b); | O[n] |
229/// |-----------------------------------------+-------------------------------|
230/// | a.assign(b); | O[n] |
231/// |-----------------------------------------+-------------------------------|
232/// | a.assign(std::move(b)); | O[1] if the allocator can be |
233/// | | propagated on container move |
234/// | | assignment or 'a' and 'b' use |
235/// | | the same allocator; O[n] |
236/// | | otherwise |
237/// |-----------------------------------------+-------------------------------|
238/// | a.assign(k, v) | O[k] |
239/// |-----------------------------------------+-------------------------------|
240/// | a.assign(i1, i2) | O[distance(i1,i2)] |
241/// |-----------------------------------------+-------------------------------|
242/// | a.assign_range(range)) | O[distance(range)] |
243/// |-----------------------------------------+-------------------------------|
244/// | a.insert(p1, v) | O[1 + distance(p1, a.end())] |
245/// |-----------------------------------------+-------------------------------|
246/// | a.insert(p1, k, v) | O[k + distance(p1, a.end())] |
247/// |-----------------------------------------+-------------------------------|
248/// | a.insert(p1, i1, i2) | O[distance(i1, i2) |
249/// | | + distance(p1, a.end())] |
250/// |-----------------------------------------+-------------------------------|
251/// | a.insert_range(p1, range) | O[distance(range) |
252/// | | + distance(p1, a.end())] |
253/// |-----------------------------------------+-------------------------------|
254/// | a.erase(p1) | O[1 + distance(p1, a.end())] |
255/// |-----------------------------------------+-------------------------------|
256/// | a.erase(p1, p2) | O[1 + distance(p1, a.end())] |
257/// |-----------------------------------------+-------------------------------|
258/// | a.swap(b), swap(a, b) | O[1] if 'a' and 'b' allocators|
259/// | | compare equal, O[n + m] |
260/// | | otherwise |
261/// |-----------------------------------------+-------------------------------|
262/// | a.clear() | O[1] |
263/// |-----------------------------------------+-------------------------------|
264/// | a = b; (assignment) | O[n] |
265/// |-----------------------------------------+-------------------------------|
266/// | a = std::move(b); (move assignment) | O[1] if the allocator can be |
267/// | | propagated on container move |
268/// | | assignment or 'a' and 'b' use |
269/// | | the same allocator; O[n] |
270/// | | otherwise |
271/// |-----------------------------------------+-------------------------------|
272/// | a == b, a != b | O[n] |
273/// |-----------------------------------------+-------------------------------|
274/// | a < b, a <= b, a > b, a >= b | O[n] |
275/// +-----------------------------------------+-------------------------------+
276/// @endcode
277///
278/// ## User-defined literals {#bslstl_string-user-defined-literals}
279///
280///
281/// The user-defined literal operators are declared for the `bsl::string` and
282/// `bsl::wstring` types. The ud-suffix `_s` is chosen to distinguish between
283/// the `bsl`-string's user-defined literal operators and the `std`-string's
284/// user-defined literal `operator ""s` introduced in the C++14 standard and
285/// implemented in the standard library provided by the compiler vendor. Note
286/// that the `bsl`-string's `operator""_s`, unlike the `std`-string's
287/// `operator ""s`, can be used in a client's code if the compiler supports the
288/// C++11 standard. Also note that if the compiler supports the C++14 standard
289/// then the `std`-string's `operator ""s` can be used to initialize a
290/// `bsl`-string as follows:
291/// @code
292/// using namespace std::string_literals;
293/// bsl::string str = "test"s;
294/// @endcode
295/// however such initialization introduces significant performance overhead due
296/// to extra `std`-string object creation/destruction.
297///
298/// Also note that `bsl`-string's user-defined literal operators are declared in
299/// the `bsl::literals::string_literals` namespace, where `literals` and
300/// @ref string_literals are inline namespaces. Access to these operators can be
301/// gained with either `using namespace bsl::literals`,
302/// `using namespace bsl::string_literals` or
303/// `using namespace bsl::literals::string_literals`. But we recommend
304/// `using namespace bsl::string_literals` to minimize the scope of the using
305/// declaration:
306/// @code
307/// using namespace bsl::string_literals;
308/// bsl::string str = "test"_s;
309/// @endcode
310///
311/// ### Memory Allocation For a File-Scope Strings {#bslstl_string-memory-allocation-for-a-file-scope-strings}
312///
313///
314/// The `operator""_s` uses the currently installed default allocator to
315/// supply memory. Note that the default allocator can become locked prior to
316/// entering `main` as a side-effect of initializing a file-scope static string
317/// object using `operator""_s`. To avoid the default allocator locking an
318/// `operator""_S` can be used instead. This operator uses the global
319/// allocator to supply memory and has no side-effects. (See the "Default
320/// Allocator" section in the `bslma::Default` component-level documentation for
321/// details.) For Example:
322/// @code
323/// using namespace bsl::string_literals;
324/// static const bsl::string s = "Use '_S' to initialize a file-scope string"_S;
325/// @endcode
326///
327/// ## Usage {#bslstl_string-usage}
328///
329///
330/// In this section we show intended use of this component.
331///
332/// ### Example 1: Basic Syntax {#bslstl_string-example-1-basic-syntax}
333///
334///
335/// In this example, we will show how to create and use the `string` typedef.
336///
337/// First, we will default-construct a `string` object:
338/// @code
339/// bsl::string s;
340/// assert(s.empty());
341/// assert(0 == s.size());
342/// assert("" == s);
343/// @endcode
344/// Then, we will construct a `string` object from a string literal:
345/// @code
346/// bsl::string t = "Hello World";
347/// assert(!t.empty());
348/// assert(11 == t.size());
349/// assert("Hello World" == t);
350/// @endcode
351/// Next, we will clear the contents of `t` and assign it a couple of values:
352/// first from a string literal; and second from another `string` object:
353/// @code
354/// t.clear();
355/// assert(t.empty());
356/// assert("" == t);
357///
358/// t = "Good Morning";
359/// assert(!t.empty());
360/// assert("Good Morning" == t);
361///
362/// t = s;
363/// assert(t.empty());
364/// assert("" == t);
365/// assert(t == s);
366/// @endcode
367/// Then, we will create three `string` objects: the first representing a street
368/// name, the second a state, and the third a ZIP code. We will then
369/// concatenate them into a single address `string` and print the contents of
370/// that `string` on standard output:
371/// @code
372/// const bsl::string street = "731 Lexington Avenue";
373/// const bsl::string state = "NY";
374/// const bsl::string zipCode = "10022";
375///
376/// const bsl::string fullAddress = street + " " + state + " " + zipCode;
377///
378/// bsl::cout << fullAddress << bsl::endl;
379/// @endcode
380/// The above print statement should produce a single line of output:
381/// @code
382/// 731 Lexington Avenue NY 10022
383/// @endcode
384/// Then, we search the contents of `address` (using the `find` function) to
385/// determine if it lies on a specified street:
386/// @code
387/// const bsl::string streetName = "Lexington";
388///
389/// if (bsl::string::npos != fullAddress.find(streetName, 0)) {
390/// bsl::cout << "The address " << fullAddress << " is located on "
391/// << streetName << "." << bsl::endl;
392/// }
393/// @endcode
394/// Next, we show how to get a reference providing modifiable access to the
395/// null-terminated string literal stored by a `string` object using the `c_str`
396/// function. Note that the returned string literal can be passed to various
397/// standard functions expecting a null-terminated string:
398/// @code
399/// const bsl::string v = "Another string";
400/// const char *cs = v.c_str();
401/// assert(bsl::strlen(cs) == v.size());
402/// @endcode
403/// Then, we construct two `string` objects, `x` and `y`, using a user-specified
404/// allocator:
405/// @code
406/// bslma::TestAllocator allocator1, allocator2;
407///
408/// const char *SHORT_STRING = "A small string";
409/// const char *LONG_STRING = "This long string would definitely cause "
410/// "memory to be allocated on creation";
411///
412/// const bsl::string x(SHORT_STRING, &allocator1);
413/// const bsl::string y(LONG_STRING, &allocator2);
414///
415/// assert(SHORT_STRING == x);
416/// assert(LONG_STRING == y);
417/// @endcode
418/// Notice that, no memory was allocated from the allocator for object `x`
419/// because of the short-string optimization used in the `string` type.
420///
421/// Finally, we can track memory usage of `x` and `y` using `allocator1` and
422/// `allocator2` and check that memory was allocated only by `allocator2`:
423/// @code
424/// assert(0 == allocator1.numBlocksInUse());
425/// assert(1 == allocator2.numBlocksInUse());
426/// @endcode
427///
428/// ### Example 2: string as a data member {#bslstl_string-example-2-string-as-a-data-member}
429///
430///
431/// The most common use of `string` objects are as data members in user-defined
432/// classes. In this example, we will show how `string` objects can be used as
433/// data members.
434///
435/// First, we begin to define a `class`, `Employee`, that represents the data
436/// corresponding to an employee of a company:
437/// @code
438/// /// This simply constrained (value-semantic) attribute class represents
439/// /// the information about an employee. An employee's first and last
440/// /// name are represented as `string` objects and their employee
441/// /// identification number is represented by an `int`. Note that the
442/// /// class invariants are identically the constraints on the individual
443/// /// attributes.
444/// ///
445/// /// This class:
446/// /// * supports a complete set of *value-semantic* operations
447/// /// - except for BDEX serialization
448/// /// * is **exception-neutral** (agnostic)
449/// /// * is **alias-safe**
450/// /// * is `const` **thread-safe**
451/// class Employee {
452///
453/// // DATA
454/// bsl::string d_firstName; // first name
455/// bsl::string d_lastName; // last name
456/// int d_id; // identification number
457/// @endcode
458/// Next, we define the creators for this class:
459/// @code
460/// public:
461/// // CREATORS
462///
463/// /// Create a `Employee` object having the (default) attribute
464/// /// values:
465/// /// ```
466/// /// firstName() == ""
467/// /// lastName() == ""
468/// /// id() == 0
469/// /// ```
470/// /// Optionally specify a `basicAllocator` used to supply memory. If
471/// /// `basicAllocator` is 0, the currently installed default
472/// /// allocator is used.
473/// Employee(bslma::Allocator *basicAllocator = 0);
474///
475/// /// Create a `Employee` object having the specified `firstName`,
476/// /// `lastName`, and `id` attribute values. Optionally specify a
477/// /// `basicAllocator` used to supply memory. If `basicAllocator` is
478/// /// 0, the currently installed default allocator is used.
479/// Employee(const bsl::string_view& firstName,
480/// const bsl::string_view& lastName,
481/// int id,
482/// bslma::Allocator *basicAllocator = 0);
483///
484/// /// Create a `Employee` object having the same value as the
485/// /// specified `original` object. Optionally specify a
486/// /// `basicAllocator` used to supply memory. If `basicAllocator` is
487/// /// 0, the currently installed default allocator is used.
488/// Employee(const Employee& original,
489/// bslma::Allocator *basicAllocator = 0);
490///
491/// /// Destroy this object.
492/// //! ~Employee() = default;
493/// @endcode
494/// Notice that all constructors of the `Employee` class are optionally provided
495/// an allocator that is then passed through to the `string` data members of
496/// `Employee`. This allows the user to control how memory is allocated by
497/// `Employee` objects. Also note that the type of the `firstName` and
498/// `lastName` arguments of the value constructor is `bsl::string_view`. The
499/// `bsl::string_view` allows specifying a `string` or a `const char *` to
500/// represent a string value. For the sake of brevity its implementation is
501/// not explored here.
502///
503/// Then, declare the remaining methods of the class:
504/// @code
505/// // MANIPULATORS
506///
507/// /// Assign to this object the value of the specified `rhs` object,
508/// /// and return a reference providing modifiable access to this
509/// /// object.
510/// Employee& operator=(const Employee& rhs);
511///
512/// /// Set the `firstName` attribute of this object to the specified
513/// /// `value`.
514/// void setFirstName(const bsl::string_view& value);
515///
516/// /// Set the `lastName` attribute of this object to the specified
517/// /// `value`.
518/// void setLastName(const bsl::string_view& value);
519///
520/// /// Set the `id` attribute of this object to the specified `value`.
521/// void setId(int value);
522///
523/// // ACCESSORS
524///
525/// /// Return a reference providing non-modifiable access to the
526/// /// `firstName` attribute of this object.
527/// const bsl::string& firstName() const;
528///
529/// /// Return a reference providing non-modifiable access to the
530/// /// `lastName` attribute of this object.
531/// const bsl::string& lastName() const;
532///
533/// /// Return the value of the `id` attribute of this object.
534/// int id() const;
535/// };
536/// @endcode
537/// Next, we declare the free operators for `Employee`:
538/// @code
539/// /// Return `true` if the specified `lhs` and `rhs` objects have the same
540/// /// value, and `false` otherwise. Two `Employee` objects have the
541/// /// same value if all of their corresponding values of their
542/// /// `firstName`, `lastName`, and `id` attributes are the same.
543/// inline
544/// bool operator==(const Employee& lhs, const Employee& rhs);
545///
546/// /// Return `true` if the specified `lhs` and `rhs` objects do not have
547/// /// the same value, and `false` otherwise. Two `Employee` objects do
548/// /// not have the same value if any of the corresponding values of their
549/// /// `firstName`, `lastName`, or `id` attributes are not the same.
550/// inline
551/// bool operator!=(const Employee& lhs, const Employee& rhs);
552/// @endcode
553/// Then, we implement the various methods of the `Employee` class:
554/// @code
555/// // CREATORS
556/// inline
557/// Employee::Employee(bslma::Allocator *basicAllocator)
558/// : d_firstName(basicAllocator)
559/// , d_lastName(basicAllocator)
560/// , d_id(0)
561/// {
562/// }
563///
564/// inline
565/// Employee::Employee(const bsl::string_view& firstName,
566/// const bsl::string_view& lastName,
567/// int id,
568/// bslma::Allocator *basicAllocator)
569/// : d_firstName(firstName.begin(), firstName.end(), basicAllocator)
570/// , d_lastName(lastName.begin(), lastName.end(), basicAllocator)
571/// , d_id(id)
572/// {
573/// BSLS_ASSERT_SAFE(!firstName.empty());
574/// BSLS_ASSERT_SAFE(!lastName.empty());
575/// }
576///
577/// inline
578/// Employee::Employee(const Employee& original,
579/// bslma::Allocator *basicAllocator)
580/// : d_firstName(original.d_firstName, basicAllocator)
581/// , d_lastName(original.d_lastName, basicAllocator)
582/// , d_id(original.d_id)
583/// {
584/// }
585/// @endcode
586/// Notice that the `basicAllocator` parameter can simply be passed as an
587/// argument to the constructor of `bsl::string`.
588///
589/// Now, we implement the remaining manipulators of the `Employee` class:
590/// @code
591/// // MANIPULATORS
592/// inline
593/// Employee& Employee::operator=(const Employee& rhs)
594/// {
595/// d_firstName = rhs.d_firstName;
596/// d_lastName = rhs.d_lastName;
597/// d_id = rhs.d_id;
598/// return *this;
599/// }
600///
601/// inline
602/// void Employee::setFirstName(const bsl::string_view& value)
603/// {
604/// BSLS_ASSERT_SAFE(!value.empty());
605///
606/// d_firstName.assign(value.begin(), value.end());
607/// }
608///
609/// inline
610/// void Employee::setLastName(const bsl::string_view& value)
611/// {
612/// BSLS_ASSERT_SAFE(!value.empty());
613///
614/// d_lastName.assign(value.begin(), value.end());
615/// }
616///
617/// inline
618/// void Employee::setId(int value)
619/// {
620/// d_id = value;
621/// }
622///
623/// // ACCESSORS
624/// inline
625/// const bsl::string& Employee::firstName() const
626/// {
627/// return d_firstName;
628/// }
629///
630/// inline
631/// const bsl::string& Employee::lastName() const
632/// {
633/// return d_lastName;
634/// }
635///
636/// inline
637/// int Employee::id() const
638/// {
639/// return d_id;
640/// }
641/// @endcode
642/// Finally, we implement the free operators for `Employee` class:
643/// @code
644/// inline
645/// bool operator==(const Employee& lhs, const Employee& rhs)
646/// {
647/// return lhs.firstName() == rhs.firstName()
648/// && lhs.lastName() == rhs.lastName()
649/// && lhs.id() == rhs.id();
650/// }
651///
652/// inline
653/// bool operator!=(const Employee& lhs, const Employee& rhs)
654/// {
655/// return lhs.firstName() != rhs.firstName()
656/// || lhs.lastName() != rhs.lastName()
657/// || lhs.id() != rhs.id();
658/// }
659/// @endcode
660///
661/// ### Example 3: A stream text replacement filter {#bslstl_string-example-3-a-stream-text-replacement-filter}
662///
663///
664/// In this example, we will utilize the `string` type and its associated
665/// utility functions to define a function that reads data from an input stream,
666/// replaces all occurrences of a specified text fragment with another text
667/// fragment, and writes the resulting text to an output stream.
668///
669/// First, we define the signature of the function, `replace`:
670/// @code
671/// /// Read data from the specified `inputStream` and replace all
672/// /// occurrences of the text contained in the specified `oldString` in
673/// /// the stream with the text contained in the specified `newString`.
674/// /// Write the modified data to the specified `outputStream`.
675/// void replace(bsl::ostream& outputStream,
676/// bsl::istream& inputStream,
677/// const bsl::string& oldString,
678/// const bsl::string& newString)
679/// @endcode
680/// Then, we provide the implementation for `replace`:
681/// @code
682/// {
683/// const bsl::string::size_type oldStringSize = oldString.size();
684/// const bsl::string::size_type newStringSize = newString.size();
685/// bsl::string line;
686///
687/// bsl::getline(inputStream, line);
688/// @endcode
689/// Notice that we can use the `getline` free function defined in this component
690/// to read a single line of data from an input stream into a `bsl::string`.
691/// @code
692/// if (!inputStream) {
693/// return; // RETURN
694/// }
695///
696/// do {
697/// @endcode
698/// Next, we use the `find` function to search the contents of `line` for
699/// characters matching the contents of `oldString`:
700/// @code
701/// int pos = line.find(oldString);
702/// while (bsl::string::npos != pos) {
703/// @endcode
704/// Now, we use the `replace` method to modify the contents of `line` matching
705/// `oldString` to `newString`:
706/// @code
707/// line.replace(pos, oldStringSize, newString);
708/// pos = line.find(oldString, pos + newStringSize);
709/// @endcode
710/// Notice that we provide `find` with the starting position from which to start
711/// searching.
712/// @code
713/// }
714/// @endcode
715/// Finally, we write the updated contents of `line` to the output stream:
716/// @code
717/// outputStream << line;
718///
719/// bsl::getline(inputStream, line);
720/// } while (inputStream);
721/// }
722/// @endcode
723/// @}
724/** @} */
725/** @} */
726
727/** @addtogroup bsl
728 * @{
729 */
730/** @addtogroup bslstl
731 * @{
732 */
733/** @addtogroup bslstl_string
734 * @{
735 */
736
737#include <bslscm_version.h>
738
739#include <bslstl_algorithm.h>
740#include <bslstl_compare.h>
741#include <bslstl_concepts.h>
742#include <bslstl_hash.h>
745#include <bslstl_iterator.h>
746#include <bslstl_iteratorutil.h>
747#include <bslstl_ranges.h>
748#include <bslstl_stdexceptutil.h>
749#include <bslstl_stringrefdata.h>
750#include <bslstl_stringview.h>
752
753#include <bslalg_containerbase.h>
756
757#include <bslh_hash.h>
758
759#include <bslma_allocator.h>
761#include <bslma_allocatorutil.h>
762#include <bslma_isstdallocator.h>
763#include <bslma_bslallocator.h>
765
766#include <bslmf_assert.h>
768#include <bslmf_enableif.h>
772#include <bslmf_isconvertible.h>
773#include <bslmf_issame.h>
774#include <bslmf_matchanytype.h>
776#include <bslmf_movableref.h>
778#include <bslmf_nil.h>
779#include <bslmf_util.h> // 'forward(V)' for C++03
780#include <bslmf_voidtype.h>
781
782#include <bsls_alignedbuffer.h>
783#include <bsls_alignment.h>
785#include <bsls_assert.h>
787#include <bsls_keyword.h>
788#include <bsls_libraryfeatures.h>
789#include <bsls_nullptr.h>
790#include <bsls_performancehint.h>
791#include <bsls_platform.h>
792#include <bsls_util.h> // 'forward<T>(V)' for C++11
793
794#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
795 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
796# define BSLSTL_STRING_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T) \
797 requires ::BloombergLP::bslmf::ContainerCompatibleRange<R, T>
798#else
799# define BSLSTL_STRING_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T)
800#endif
801
802#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
803# include <initializer_list>
804#endif
805
806#include <istream> // for 'std::basic_istream', 'sentry'
807#include <limits> // for 'std::numeric_limits'
808#include <locale> // for 'std::ctype', 'locale'
809#include <ostream> // for 'std::basic_ostream', 'sentry'
810#include <string> // for 'std::char_traits'
811
812#ifndef BDE_OMIT_INTERNAL_DEPRECATED
813#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
814
815#include <bsls_nativestd.h>
816
817#include <exception>
818#include <stdexcept>
819
820#if defined(BDE_BUILD_TARGET_STLPORT)
821// Code in Robo depends on these headers included transitively with <string>
822// and it fails to build otherwise in the stlport4 mode on Sun.
823
824# include <stdio.h>
825# include <stdlib.h>
826# include <string.h>
827#endif
828
829#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
830#endif // BDE_OMIT_INTERNAL_DEPRECATED
831
832namespace bsl {
833
834// Import @ref char_traits into the `bsl` namespace so that @ref basic_string and
835// @ref char_traits are always in the same namespace.
836using std::char_traits;
837
838template <class CHAR_TYPE,
839 class CHAR_TRAITS = char_traits<CHAR_TYPE>,
840 class ALLOCATOR = allocator<CHAR_TYPE> >
841class basic_string;
842
843// TYPEDEFS
846
847#if defined(BSLS_COMPILERFEATURES_SUPPORT_UTF8_CHAR_TYPE)
848typedef basic_string<char8_t> u8string;
849#endif
850
851#if defined(BSLS_COMPILERFEATURES_SUPPORT_UNICODE_CHAR_TYPES)
852typedef basic_string<char16_t> u16string;
853typedef basic_string<char32_t> u32string;
854#endif
855
856#if defined(BSLS_LIBRARYFEATURES_STDCPP_LIBCSTD)
857/// This `class` provides an implementation of the `find` function for the
858/// (template parameter) type `ORIGINAL_TRAITS`. This is an alternate
859/// representation for Sun's `char_traits::find` that returns an incorrect
860/// result for character types other than `char` (such as `wchar`).
861///
862/// See @ref bslstl_string
863template <class ORIGINAL_TRAITS>
864class String_Traits {
865
866 // PRIVATE TYPES
867 typedef typename ORIGINAL_TRAITS::char_type char_type;
868 typedef std::size_t size_type;
869
870 public:
871 // CLASS METHODS
872
873 /// Return an address providing non-modifiable access to the first
874 /// character that matches the specified character `a` in the specified
875 /// `n` characters of the specified `s` string.
876 ///
877 /// \pre The behavior is undefined unless `s` holds at least `n` characters.
878 static const char_type *find(const char_type *s,
879 size_type n,
880 const char_type& a);
881};
882
883/// Sun implemented `find` for `char` properly, so this specialization
884/// simply forwards the call to Sun.
885template <>
886class String_Traits<std::char_traits<char> > {
887
888 // PRIVATE TYPES
889 typedef std::size_t size_type;
890
891 public:
892 // CLASS METHODS
893
894 /// Return an address providing non-modifiable access to the first
895 /// character that matches the specified character `a` in the specified
896 /// `n` characters of the specified `s` string.
897 ///
898 /// \pre The behavior is undefined unless `s` holds at least `n` characters.
899 static const char *find(const char *s, size_type n, const char& a);
900};
901
902// CLASS METHODS
903template <class ORIGINAL_TRAITS>
904const typename ORIGINAL_TRAITS::char_type *
905String_Traits<ORIGINAL_TRAITS>::find(const char_type *s,
906 size_type n,
907 const char_type& a)
908{
909 while (n > 0 && !ORIGINAL_TRAITS::eq(*s, a)) {
910 --n;
911 ++s;
912 }
913 return n > 0 ? s : 0;
914}
915
916inline
917const char *
918String_Traits<std::char_traits<char> >::find(const char *s,
919 size_type n,
920 const char& a)
921{
922 return std::char_traits<char>::find(s, n, a);
923}
924
925#define BSLSTL_CHAR_TRAITS String_Traits<CHAR_TRAITS>
926
927#else
928
929#define BSLSTL_CHAR_TRAITS CHAR_TRAITS
930
931#endif
932
933#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
934// The usual practice of using a 'bslmf::MovableRef<>' cannot be applied, since
935// compilers on Solaris cannot compile such heavy code. Therefore, it was
936// decided to add 'operator+' accepting rvalue references only for platforms
937// and compilers that support them.
938
939#define BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
940#endif
941
942#ifdef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
943template <class CHAR_TRAITS, class = void>
944struct String_ComparisonCategory
945{
946 using type = weak_ordering;
947};
948template <class CHAR_TRAITS>
949struct String_ComparisonCategory<CHAR_TRAITS,
950 bsl::void_t<typename CHAR_TRAITS::comparison_category>>
951{
952 using type = typename CHAR_TRAITS::comparison_category;
953};
954
955template <class CHAR_TRAITS>
956using String_ComparisonCategoryType =
957 typename String_ComparisonCategory<CHAR_TRAITS>::type;
958#endif
959
960/// SFINAE enable_if type alias for types convertible to string_view but NOT
961/// convertible to C-string and NOT an accessible base of `bsl::basic_string`
962/// or `std::basic_string`. The result type is the macro argument if enabled.
963/// This is a variadic macro to support result types containing commas (e.g.,
964/// `basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>`).
965#define BSLSTL_STRING_ONLY_STRINGVIEW_ENABLE_IF_T(...) \
966 typename bsl::enable_if< \
967 BloombergLP::bslstl::IsConvertibleToStringView< \
968 CHAR_TYPE, \
969 CHAR_TRAITS, \
970 BSLSTL_STRINGVIEWLIKEPARAM_TYPE_IF_COMPLETE>::value \
971 && !BloombergLP::bslstl::IsConvertibleToCString< \
972 CHAR_TYPE, \
973 BSLSTL_STRINGVIEWLIKEPARAM_TYPE_IF_COMPLETE>::value \
974 && !BloombergLP::bslmf::IsAccessibleBaseOf< \
975 bsl::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>, \
976 STRING_VIEW_LIKE_TYPE>::value \
977 && !BloombergLP::bslmf::IsAccessibleBaseOf< \
978 std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>, \
979 STRING_VIEW_LIKE_TYPE>::value, \
980 __VA_ARGS__>::type
981
982 // ================
983 // class String_Imp
984 // ================
985
986/// This component private `class` describes the basic data layout for a
987/// string class and provides methods to help encapsulate internal string
988/// implementation details. It is parameterized by `CHAR_TYPE` and
989/// `SIZE_TYPE` only, and implements the portion of @ref basic_string that does
990/// not need to know about its (template parameter) types `CHAR_TRAITS` or
991/// `ALLOCATOR`. It contains the following data fields: pointer to string,
992/// short string buffer, length, and capacity. The purpose of the short
993/// string buffer is to implement a "short string optimization" such that
994/// strings with lengths shorter than a certain number of characters are
995/// stored directly inside the string object (inside the short string
996/// buffer), and thereby avoid memory allocations/deallocations.
997///
998/// See @ref bslstl_string
999template <class CHAR_TYPE, class SIZE_TYPE>
1001
1002 public:
1003 // TYPES
1004
1005 /// This `enum` contains values necessary to calculate the size of the
1006 /// short string buffer. The starting value is
1007 /// `SHORT_BUFFER_MIN_BYTES`, which defines the minimal number of bytes
1008 /// (or `char` values) that the short string buffer should be able to
1009 /// contain. Then this value is aligned to a word boundary. Then we
1010 /// make sure that it fits at least one `CHAR_TYPE` character (because
1011 /// the default state of the string object requires that the first
1012 /// character is initialized with a NULL-terminator). The final output
1013 /// of this enum used by `String_Imp` is the `SHORT_BUFFER_CAPACITY`
1014 /// value. It defines the capacity of the short string buffer and also
1015 /// the capacity of the default-constructed empty string object.
1017
1018 SHORT_BUFFER_MIN_BYTES = 20, // minimum required size of the short
1019 // string buffer in bytes
1020
1022 (SHORT_BUFFER_MIN_BYTES + sizeof(SIZE_TYPE) - 1)
1023 & ~(sizeof(SIZE_TYPE) - 1),
1024 // round it to a word boundary
1025
1026 SHORT_BUFFER_BYTES = sizeof(CHAR_TYPE) < SHORT_BUFFER_NEED_BYTES
1028 : sizeof(CHAR_TYPE),
1029 // in case 'CHAR_TYPE' is very large
1030
1031 SHORT_BUFFER_LENGTH = SHORT_BUFFER_BYTES / sizeof(CHAR_TYPE),
1032
1033 SHORT_BUFFER_CAPACITY = SHORT_BUFFER_LENGTH - 1
1034 // short string buffer capacity (not
1035 // including the null-terminator)
1036 };
1037
1038 // Make sure the buffer is large enough to fit a pointer.
1039 BSLMF_ASSERT(SHORT_BUFFER_BYTES >= sizeof(CHAR_TYPE *));
1040
1042 // These configurable parameters define various aspects of the string
1043 // behavior when it's not strictly defined by the Standard.
1044
1048
1049 // DATA
1050
1051 /// This is the union of the string storage options: it can either be
1052 /// stored inside the short string buffer, `d_short`, or in the
1053 /// externally allocated memory, pointed to by `d_start_p`.
1054 union {
1055
1056 BloombergLP::bsls::AlignedBuffer<
1057 SHORT_BUFFER_BYTES,
1058 BloombergLP::bsls::AlignmentFromType<CHAR_TYPE>::VALUE>
1059 d_short; // short string buffer
1060 CHAR_TYPE *d_start_p; // pointer to the data on heap
1061 };
1062
1063 SIZE_TYPE d_length; // length of the string
1064 SIZE_TYPE d_capacity; // capacity to which the string can grow
1065 // without reallocation
1066
1067 // TRAITS
1068
1069 // `CHAR_TYPE` is required to be a POD as per the Standard, which makes
1070 // `CHAR_TYPE` bitwise-movable, so `String_Imp` is also bitwise-movable.
1072 BloombergLP::bslmf::IsBitwiseMoveable);
1073
1074 // CLASS METHODS
1075
1076 /// Compute and return the capacity required for a string having the
1077 /// specified `newLength` and using the specified `oldCapacity` to
1078 /// exercise an exponential capacity growth necessary to ensure the
1079 /// amortized linear complexity of `push_back` and other operations and
1080 /// ensuring that the new capacity does not exceed the specified `maxSize`.
1081 ///
1082 /// \note Note that the behavior is undefined unless
1083 /// `newLength > oldCapacity`, `newLength < maxSize`, and
1084 /// `oldCapacity < maxSize`.
1085 static SIZE_TYPE computeNewCapacity(SIZE_TYPE newLength,
1086 SIZE_TYPE oldCapacity,
1087 SIZE_TYPE maxSize);
1088
1089 // CREATORS
1090
1091 /// Create a `String_Imp` object having (default) attribute values
1092 /// except that the `d_capacity` attribute is initialized with
1093 /// `SHORT_BUFFER_CAPACITY`.
1095
1096 /// Create a `String_Imp` object and initialize the `d_length` and
1097 /// `d_capacity` attributes with the specified `length` and specified
1098 /// `capacity`, respectively. If `capacity` is less than
1099 /// `SHORT_BUFFER_CAPACITY`, then d_capacity is set to
1100 /// `SHORT_BUFFER_CAPACITY`. The value of the `d_short` and `d_start_p`
1101 /// fields are left uninitialized. @ref basic_string is required to assign
1102 /// either d_short or d_start_p to a proper value before using any
1103 /// methods of this class.
1104 String_Imp(SIZE_TYPE length, SIZE_TYPE capacity);
1105
1106 /// Create a `String_Imp` object having the same value as the specified `original` object.
1107 ///
1108 /// \note Note that this copy constructor is generated by
1109 /// the compiler.
1110 String_Imp(const String_Imp& original) = default;
1111
1112 /// Destroy this object.
1113 /// \note Note that this destructor is generated by the
1114 /// compiler.
1115 ~String_Imp() = default;
1116
1117 /// Assign to this object the value of the specified `rhs` object, and
1118 /// return a reference providing modifiable access to this object.
1119 ///
1120 /// \note Note that this assignment operator is generated by the compiler.
1122
1123 // MANIPULATORS
1124
1125 /// Efficiently exchange the value of this object with the value of the
1126 /// specified `other` object. This method provides the no-throw
1127 /// exception-safety guarantee.
1128 void swap(String_Imp& other);
1129
1130 /// Reset all fields of this object to their default-constructed state.
1132
1133 /// Return an address providing modifiable access to the NULL-terminated C-string stored by this string object.
1134 ///
1135 /// \note Note that the returned
1136 /// address can point to either the internal short string buffer or the
1137 /// externally allocated memory depending on the type of the string
1138 /// defined by the return value of `isShortString`.
1139 CHAR_TYPE *dataPtr();
1140
1141 // ACCESSORS
1142
1143 /// Return `true` if this object contains a short string and the string
1144 /// data is stored in the short string buffer, and `false` if the object
1145 /// contains a long string (and the short string buffer contains a
1146 /// pointer to the string data allocated externally).
1147 bool isShortString() const;
1148
1149 /// Return an address providing non-modifiable access to the
1150 /// NULL-terminated C-string stored by this string object.
1151 ///
1152 /// \note Note that the returned address can point to either the internal short string
1153 /// buffer or the externally allocated memory depending on the type of
1154 /// the string defined by the return value of `isShortString`.
1155 const CHAR_TYPE *dataPtr() const;
1156};
1157
1158 // =========================
1159 // class String_ClearProctor
1160 // =========================
1161
1162/// This component private `class` implements a proctor that sets the length
1163/// of a string to zero, and, if `release` is not called, will restore that
1164/// string upon it's destruction. The intended usage is to implement
1165/// `assign` methods in terms of `append` (by clearing the string before
1166/// appending to it), while maintaining the strong exceptions guarantee.
1167///
1168/// \note Note that after constructing this proctor for a string `s`, the
1169/// invariant `s[s.length()] == CHAR_TYPE()` is violated for non-empty `s`.
1170/// This invariant will be restored by either a successful `append` or by the proctor's destructor if an exception is thrown.
1171///
1172/// \note Note that the
1173/// template parameter was renamed from STRING_TYPE to FULL_STRING_TYPE due
1174/// to a name clash with a define elsewhere in the code base (see DRQS
1175/// 112049582).
1176///
1177/// See @ref bslstl_string
1178template <class FULL_STRING_TYPE>
1180
1181 // PRIVATE TYPES
1182 typedef typename FULL_STRING_TYPE::size_type size_type;
1183
1184 // DATA
1185 FULL_STRING_TYPE *d_string_p; // pointer to the string supplied at
1186 // construction (held, not owned)
1187
1188 size_type d_originalLength; // original length of the string
1189 // supplied at construction
1190
1191 public:
1192 // CREATORS
1193
1194 /// Create a `String_ClearProctor` for the specified `stringPtr`, and
1195 /// set both the length of `stringPtr` to 0 and the first character of
1196 /// `stringPtr` to `CHAR_TYPE()`.
1197 explicit String_ClearProctor(FULL_STRING_TYPE *stringPtr);
1198
1199 /// Destroy this object, and if `release` has not been called, restore
1200 /// the original state of the string supplied at construction.
1202
1203 // MANIPULATORS
1204
1205 /// Release the proctor indicating that the string state need not to be
1206 /// restored.
1207 void release();
1208};
1209
1210 // =======================
1211 // class bsl::basic_string
1212 // =======================
1213
1214/// This class template provides an STL-compliant `string` that conforms to
1215/// the `bslma::Allocator` model. For the requirements of a string class,
1216/// consult the second revision of the ISO/IEC 14882 Programming Language C++ (2003).
1217///
1218/// \note Note that the (template parameter) `CHAR_TYPE` must be
1219/// *equal* to `ALLOCATOR::value_type`. In addition, this implementation
1220/// offers strong exception guarantees (see below), with the general rules
1221/// that:
1222///
1223/// 1. any method that would result in a string of length larger than the
1224/// size returned by @ref max_size throws `std::length_error`, and
1225/// 2. any method that attempts to access a position outside the valid range
1226/// of a string throws `std::out_of_range`.
1227///
1228/// Circumstances where a method throws `bsl::length_error` (1) are clear
1229/// and not repeated in the individual function-level documentations below.
1230///
1231/// More generally, this class supports an almost complete set of *in-core*
1232/// *value* *semantic* operations, including copy construction, assignment,
1233/// equality comparison (but excluding `ostream` printing since this
1234/// component is below STL). A precise operational definition of when two
1235/// objects have the same value can be found in the description of
1236/// `operator==` for the class. This class is *exception* *neutral* with
1237/// full guarantee of rollback: if an exception is thrown during the
1238/// invocation of a method on a pre-existing object, the object is left
1239/// unchanged. In no event is memory leaked.
1240///
1241///
1242/// \note Note that *aliasing* (e.g., using all or part of an object as both
1243/// source and destination) is supported in all cases in the public
1244/// interface of @ref basic_string . However, the private interface (`...Raw`
1245/// methods) should be assumed to be not alias-safe unless specifically
1246/// noted otherwise.
1247template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1249 : private String_Imp<CHAR_TYPE,
1250 typename allocator_traits<ALLOCATOR>::size_type>
1251 , private BloombergLP::bslalg::ContainerBase<ALLOCATOR>
1252{
1253
1254 // PRIVATE TYPES
1255
1256 /// This `typedef` is a convenient alias for the utility associated with
1257 /// movable references.
1258 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
1259
1260 /// This `typedef` is an alias for a utility class that provides many
1261 /// useful functions that operate on allocators.
1262 typedef BloombergLP::bslma::AllocatorUtil AllocatorUtil;
1263
1264 /// This `typedef` is an alias for the allocator traits type associated
1265 /// with this container.
1267
1268 public:
1269 // PUBLIC TYPES
1271 typedef typename CHAR_TRAITS::char_type value_type;
1272
1273 typedef ALLOCATOR allocator_type;
1274 typedef typename AllocatorTraits::size_type size_type;
1278
1281 typedef CHAR_TYPE *iterator;
1282 typedef const CHAR_TYPE *const_iterator;
1283 typedef bsl::reverse_iterator<iterator> reverse_iterator;
1284
1285 /// These types satisfy the `ReversibleSequence` requirements.
1286 typedef bsl::reverse_iterator<const_iterator> const_reverse_iterator;
1287
1288 // TRAITS
1289
1290 /// `CHAR_TYPE` is required to be a POD as per the Standard, which makes
1291 /// `CHAR_TYPE` bitwise-movable, so @ref basic_string is bitwise-movable as
1292 /// long as the (template parameter) type `ALLOCATOR` is also
1293 /// bitwise-movable.
1296 BloombergLP::bslmf::IsBitwiseMoveable,
1297 BloombergLP::bslmf::IsBitwiseMoveable<ALLOCATOR>::value);
1298
1299 private:
1300 // PRIVATE TYPES
1302
1303 typedef BloombergLP::bslalg::ContainerBase<ALLOCATOR> ContainerBase;
1304
1305 // FRIENDS
1306
1307 /// `to_string` functions are made friends to allow access to the
1308 /// internal short string buffer.
1309 friend string to_string(int);
1310 friend string to_string(long);
1311 friend string to_string(long long);
1312 friend string to_string(unsigned);
1313 friend string to_string(unsigned long);
1314 friend string to_string(unsigned long long);
1315
1316 /// `String_ClearProctor` is made friend to allow access to internal
1317 /// buffer and length.
1318 friend class String_ClearProctor<basic_string>;
1319
1320 // PRIVATE CLASS METHODS
1321
1322 /// Throw `length_error` with the specified `message` if the specified
1323 /// `maxLengthExceeded` is `true`. Otherwise, this method has no
1324 /// effect.
1325 static void privateThrowLengthError(bool maxLengthExceeded,
1326 const char *message);
1327
1328 /// Throw @ref out_of_range with the specified `message` if the specified
1329 /// `outOfRange` is `true`. Otherwise, this method has no effect.
1330 static void privateThrowOutOfRange(bool outOfRange, const char *message);
1331
1332 // PRIVATE MANIPULATORS
1333
1334 // Note: '...Raw' functions are low level private manipulators and they do
1335 // not perform checks for exceptions. '...Dispatch' functions perform
1336 // overload selection for iterator types in order to resolve ambiguities
1337 // between template and non-template method overloads.
1338
1339 /// Allocate and return a buffer capable of holding the specified
1340 /// `numChars` number of characters.
1341 CHAR_TYPE *privateAllocate(size_type numChars);
1342
1343 /// Deallocate the internal string buffer, which was allocated with
1344 /// `privateAllocate` and stored in `String_Imp::d_start_p` without
1345 /// modifying any data members.
1346 void privateDeallocate();
1347
1348 /// Copy the specified `original` string content into this string
1349 /// object, assuming that the default copy constructor of the
1350 /// `String_Imp` base class and the appropriate copy constructor of the
1351 /// `ContainerBase` base class have just been run.
1352 ///
1353 /// \pre The behavior is undefined unless `original` holds an out-of-place representation of a string.
1354 ///
1355 /// \note Note that the out-of-place representation may be short
1356 /// enough to fit into the small buffer storage.
1357 void privateCopyFromOutOfPlaceBuffer(const basic_string& original);
1358
1359 /// Append to this string the specified initial `numChars` characters
1360 /// from the specified `characterString`, and return a reference
1361 /// providing modifiable access to this string. Throw `length_error`
1362 /// with the specified `message` if `numChars > max_size() - length()`.
1363 ///
1364 /// \pre The behavior is undefined unless `characterString` is at least
1365 /// `numChars` long.
1366 basic_string& privateAppend(const CHAR_TYPE *characterString,
1367 size_type numChars,
1368 const char *message);
1369
1370 /// Append the specified `numChars` copies of the specified `character`
1371 /// to this string. Return a reference providing modifiable access to
1372 /// this string. Throw `length_error` with the specified `message` if
1373 /// `numChars > max_size() - length()`.
1374 basic_string& privateAppend(size_type numChars,
1375 CHAR_TYPE character,
1376 const char *message);
1377
1378 /// Append the characters from the string represented by the specified
1379 /// `first` and `last` iterators. Throw `length_error` with the
1380 /// specified `message` if `length() > max_size() - (last - first)`.
1381 ///
1382 /// \pre The behavior is undefined unless `first` and `last` refer to a
1383 /// sequence of valid values where `first` is at a position at or before
1384 /// `last`.
1385 basic_string& privateAppend(iterator first,
1386 iterator last,
1387 const char *message,
1388 std::forward_iterator_tag);
1389 basic_string& privateAppend(const_iterator first,
1390 const_iterator last,
1391 const char *message,
1392 std::forward_iterator_tag);
1393
1394 /// Specialized append for input iterators, using repeated `push_back`
1395 /// operations. Throw `length_error` with the specified `message` if
1396 /// `length() > max_size() - distance(first, last)`. The optionally supplied `numChars` is ignored.
1397 ///
1398 /// \note Note that, for the "basic"
1399 /// `std::input_iterator`, one must assume that stepping the iterator, to
1400 /// determine the number of characters, invalidates that iterator for
1401 /// using that iterator to obtain characters to append. Also note that the
1402 /// implementation passes `npos` for `numChars` for these iterators.
1403 template <class INPUT_ITER, class SENTINEL>
1404 basic_string& privateAppend(INPUT_ITER first,
1405 SENTINEL last,
1406 const char *message,
1407 std::input_iterator_tag tag);
1408
1409 template <class INPUT_ITER, class SENTINEL>
1410 basic_string& privateAppend(INPUT_ITER first,
1411 SENTINEL last,
1412 size_type numChars,
1413 const char *message,
1414 std::input_iterator_tag );
1415
1416 /// Specialized append for forward, bidirectional, and random-access
1417 /// iterators. Throw `length_error` with the specified `message` if
1418 /// `length() > max_size() - distance(first, last)`. Optionally, specify
1419 /// `numChars` if that value can be precalculated.
1420 ///
1421 /// \pre The behavior is undefined if the iterators support the calculation of distance,
1422 /// `numchars` is provided, and `numchars` is not the distance from `first`
1423 /// to `last`.
1424 template <class INPUT_ITER, class SENTINEL>
1425 basic_string& privateAppend(INPUT_ITER first,
1426 SENTINEL last,
1427 const char *message,
1428 std::forward_iterator_tag tag);
1429 template <class INPUT_ITER, class SENTINEL>
1430 basic_string& privateAppend(INPUT_ITER first,
1431 SENTINEL last,
1432 size_type numChars,
1433 const char *message,
1434 std::forward_iterator_tag );
1435
1436 /// Dispatch the append operation to the correct `privateAppend`
1437 /// overload using `privateAppendDispatch`.
1438 template <class INPUT_ITER>
1439 basic_string& privateAppend(INPUT_ITER first,
1440 INPUT_ITER last,
1441 const char *message);
1442
1443 /// Dispatch the append operation to the correct `privateAppendRange`
1444 /// overload.
1445 template <class INPUT_ITER, class SENTINEL>
1446 basic_string& privateAppendRange(INPUT_ITER first,
1447 SENTINEL last,
1448 size_type numberChars,
1449 const char *message);
1450
1451 /// Match integral type for `INPUT_ITER`.
1452 template <class INPUT_ITER>
1453 basic_string& privateAppendDispatch(
1454 INPUT_ITER first,
1455 INPUT_ITER last,
1456 const char *message,
1457 BloombergLP::bslmf::MatchArithmeticType ,
1458 BloombergLP::bslmf::Nil );
1459
1460 /// Match non-integral type for `INPUT_ITER`.
1461 template <class INPUT_ITER>
1462 basic_string& privateAppendDispatch(
1463 INPUT_ITER first,
1464 INPUT_ITER last,
1465 const char *message,
1466 BloombergLP::bslmf::MatchAnyType ,
1467 BloombergLP::bslmf::MatchAnyType );
1468
1469 /// Assign to this string the value of the string described by the
1470 /// specified `first` and `second` values, and return a reference
1471 /// providing modifiable access to this string. The (template
1472 /// parameter) types `FIRST_TYPE` and `SECOND_TYPE` may resolve to
1473 /// `const CHAR_TYPE *` and `size_type`, `size_type` and `CHAR_TYPE`, or
1474 /// a pair of iterators. This method clears the string and then
1475 /// dispatches to the corresponding `privateAppend` function. Throw
1476 /// `length_error` with the specified `message` if the length of the
1477 /// string described by `first` and `second` is greater than
1478 /// `max_size()`. Provides the strong exception guarantee.
1479 template <class FIRST_TYPE, class SECOND_TYPE>
1480 basic_string& privateAssignDispatch(FIRST_TYPE first,
1481 SECOND_TYPE second,
1482 const char *message);
1483
1484 /// Assign to this string the value of the string described by the
1485 /// specified `first` and `second` values, and return a reference
1486 /// providing modifiable access to this string. This method clears the
1487 /// string and then dispatches to the corresponding `privateAppendRange`
1488 /// function. Provides the strong exception guarantee.
1489 template <class INPUT_ITER, class SENTINEL>
1490 basic_string& privateAssignRangeDispatch(INPUT_ITER first,
1491 SENTINEL second,
1492 size_type numChars,
1493 const char *message);
1494
1495 /// Return a reference providing modifiable access to the base object
1496 /// of this string.
1497 Imp& privateBase();
1498
1499 /// Reset this string object to its default-constructed value and
1500 /// deallocate its string buffer if the specified `deallocateBufferFlag`
1501 /// is `true`.
1502 void privateClear(bool deallocateBufferFlag);
1503
1504 /// Insert into this object at the specified `position` a string
1505 /// represented by the specified `first` and `last` iterators using the
1506 /// `privateInsertRaw` method for insertion.
1507 ///
1508 /// \pre The behavior is undefined unless `first` and `last` refer to a sequence of valid values where
1509 /// `first` is at a position at or before `last`.
1510 void privateInsertDispatch(const_iterator position,
1511 iterator first,
1512 iterator last);
1513 void privateInsertDispatch(const_iterator position,
1514 const_iterator first,
1515 const_iterator last);
1516
1517 /// Insert into this object at the specified `position` a string
1518 /// represented by the specified `first` and `last` iterators.
1519 ///
1520 /// \pre The behavior is undefined unless `first` and `last` refer to a sequence
1521 /// of valid values where `first` is at a position at or before `last`.
1522 ///
1523 /// \note Note that since the (template parameter) type `INPUT_ITER` can also
1524 /// resolve to an integral type, use the `privateReplaceDispatch` to
1525 /// disambiguate between the integral type and iterator types.
1526 template <class INPUT_ITER>
1527 void privateInsertDispatch(const_iterator position,
1528 INPUT_ITER first,
1529 INPUT_ITER last);
1530
1531 /// Dispatch the @ref insert_range call to the appropriate `privateReplace`
1532 /// specialization. The specified `inNumChars` is the number of characters
1533 /// between the specified `first` and `last`. If that value cannot be
1534 /// pre-calculated (e.g., the category of (template parameter)
1535 /// `INPUT_ITERATOR` is`std::input_iterator`), `numChars` is ignored by the resulting specialization.
1536 ///
1537 /// \note Note that the implementation set
1538 /// `numChars` to `npos` when the iterator category is
1539 /// `std::input_iterator`.
1540 template <class INPUT_ITER, class SENTINEL>
1541 void privateInsertRange(const_iterator position,
1542 size_type inNumChars,
1543 INPUT_ITER first,
1544 SENTINEL last);
1545
1546 /// Insert into this object at the specified `outPosition` the specified
1547 /// initial `numChars` from the specified `characterString`.
1548 ///
1549 /// \pre The behavior is undefined unless `numChars <= max_size() - length()` and `characterString` is at least `numChars` long.
1550 ///
1551 /// \note Note that this
1552 /// method is alias-safe, i.e., it works correctly even if
1553 /// `characterString` points into this string object.
1554 basic_string& privateInsertRaw(size_type outPosition,
1555 const CHAR_TYPE *characterString,
1556 size_type numChars);
1557
1558 /// Move-construct this object so that it is a substring of the specified
1559 /// `numChars` length starting at the specified `position` in the specified
1560 /// `original` string. If `original` uses a heap-allocated buffer and an
1561 /// equal allocator, the buffer is "stolen". When this function is called,
1562 /// the `String_Imp` subobject contains a copy of the corresponding
1563 /// `original` subobject.
1564 void privateMoveConstruct(basic_string& original,
1565 size_type position,
1566 size_type numChars = npos);
1567
1568 /// Replace the specified `outNumChars` characters of this string
1569 /// starting at the specified `outPosition` with the specified initial
1570 /// `numChars` from the specified `characterString`, and return a
1571 /// reference providing modifiable access to this string.
1572 ///
1573 /// \pre The behavior is undefined unless `outPosition <= length()`,
1574 /// `outNumChars <= length()`, `outPosition <= length() - outNumChars`,
1575 /// `numChars <= max_size()`,
1576 /// `length() - outNumChars <= max_size() - numChars`, and `characterString` is at least `numChars` long.
1577 ///
1578 /// \note Note that this
1579 /// method is alias-safe, i.e., it works correctly even if
1580 /// `characterString` points into this string object.
1581 basic_string& privateReplaceRaw(size_type outPosition,
1582 size_type outNumChars,
1583 const CHAR_TYPE *characterString,
1584 size_type numChars);
1585
1586 /// Replace the specified `outNumChars` characters of this string
1587 /// starting at the specified `outPosition` with the specified
1588 /// `numChars` copies of the specified `character`, and return a
1589 /// reference providing modifiable access to this string.
1590 ///
1591 /// \pre The behavior is undefined unless `outPosition <= length()`,
1592 /// `outNumChars <= length()`, `outPosition <= length() - outNumChars`,
1593 /// and `length() <= max_size() - numChars`.
1594 basic_string& privateReplaceRaw(size_type outPosition,
1595 size_type outNumChars,
1596 size_type numChars,
1597 CHAR_TYPE character);
1598
1599 /// Match integral type for `INPUT_ITER`.
1600 template <class INPUT_ITER>
1601 basic_string& privateReplaceDispatch(
1602 size_type position,
1603 size_type outNumChars,
1604 INPUT_ITER first,
1605 INPUT_ITER last,
1606 BloombergLP::bslmf::MatchArithmeticType ,
1607 BloombergLP::bslmf::Nil );
1608
1609 /// Match non-integral type for `INPUT_ITER`.
1610 template <class INPUT_ITER>
1611 basic_string& privateReplaceDispatch(
1612 size_type position,
1613 size_type outNumChars,
1614 INPUT_ITER first,
1615 INPUT_ITER last,
1616 BloombergLP::bslmf::MatchAnyType ,
1617 BloombergLP::bslmf::MatchAnyType );
1618
1619 /// Specialized replacement for input iterators using repeated `push_back`
1620 /// operations. The optionally supplied `inNumChars` is ignored for this specialization.
1621 ///
1622 /// \note Note that the implementation sets `inNumChars` to
1623 /// `npos`.
1624 template <class INPUT_ITER>
1625 basic_string& privateReplace(size_type position,
1626 size_type outNumChars,
1627 INPUT_ITER first,
1628 INPUT_ITER last,
1629 std::input_iterator_tag tag);
1630 template <class INPUT_ITER, class SENTINEL>
1631 basic_string& privateReplace(size_type position,
1632 size_type outNumChars,
1633 size_type inNumChars,
1634 INPUT_ITER first,
1635 SENTINEL last,
1636 std::input_iterator_tag );
1637
1638 /// Specialized replacement for forward, bidirectional, and
1639 /// random-access iterators. Throw `length_error` if
1640 /// `length() - numChars > max_size() - distance(first, last)`.
1641 /// Optionally supply the pre-calculated `numChars`.
1642 ///
1643 /// \pre The behavior is undefined if the iterators support the calculation of distance,
1644 /// `numchars` is provided, and `numchars` is not the distance from `first`
1645 /// to `last`.
1646 template <class INPUT_ITER>
1647 basic_string& privateReplace(size_type position,
1648 size_type numChars,
1649 INPUT_ITER first,
1650 INPUT_ITER last,
1651 std::forward_iterator_tag tag);
1652 template <class INPUT_ITER, class SENTINEL>
1653 basic_string& privateReplace(size_type position,
1654 size_type numChars,
1655 size_type inNumChars,
1656 INPUT_ITER first,
1657 SENTINEL last,
1658 std::forward_iterator_tag );
1659
1660 /// Replace the specified `numChars` characters of this object starting
1661 /// at the specified `position` of this string with the characters found
1662 /// between the specified `first` and `last` iterators.
1663 ///
1664 /// \pre The behavior is undefined unless `first` and `last` refer to a sequence of valid values
1665 /// where `first` is at a position at or before `last`.
1666 basic_string& privateReplace(size_type position,
1667 size_type numChars,
1668 iterator first,
1669 iterator last,
1670 std::forward_iterator_tag );
1671 basic_string& privateReplace(size_type position,
1672 size_type numChars,
1673 const_iterator first,
1674 const_iterator last,
1675 std::forward_iterator_tag );
1676
1677 /// Dispatch the @ref replace_with_range operation to the correct
1678 /// `privateReplace` overload.
1679 template <class INPUT_ITER, class SENTINEL>
1680 basic_string& privateReplaceRange(size_type position,
1681 size_type outNumChars,
1682 size_type inNumChars,
1683 INPUT_ITER first,
1684 SENTINEL last);
1685
1686 /// Update the capacity of this object to be a value greater than or
1687 /// equal to the specified `newCapacity`.
1688 ///
1689 /// \pre The behavior is undefined unless `newCapacity <= max_size()`.
1690 /// \note Note that a null-terminating
1691 /// character is not counted in `newCapacity`, and that this method has
1692 /// no effect unless `newCapacity > capacity()`.
1693 void privateReserveRaw(size_type newCapacity);
1694
1695 /// Update the capacity of this object and load into the specified
1696 /// `storage` to be a value greater than or equal to the specified
1697 /// `newCapacity`. Upon reallocation, copy the first specified
1698 /// `numChars` from the previous buffer to the new buffer, and load
1699 /// `storage` with the new capacity. If `*storage >= newCapacity`, this
1700 /// method has no effect. Return the new buffer if reallocation, and 0 otherwise.
1701 ///
1702 /// \pre The behavior is undefined unless `numChars <= length()` and `newCapacity <= max_size()`.
1703 ///
1704 /// \note Note that a null-terminating
1705 /// character is not counted in `*storage` nor `newCapacity`. Also note
1706 /// that the previous buffer is *not* deallocated, nor is the string
1707 /// representation changed (in case the previous buffer may contain data
1708 /// that must be copied): it is the responsibility of the caller to do
1709 /// so upon reallocation.
1710 CHAR_TYPE *privateReserveRaw(size_type *storage,
1711 size_type newCapacity,
1712 size_type numChars);
1713
1714 /// Change the length of this string to the specified `newLength`. If
1715 /// `newLength > length()`, fill in the new positions by copies of the
1716 /// specified `character`. Do not change the capacity unless
1717 /// `newLength` exceeds the current capacity.
1718 ///
1719 /// \pre The behavior is undefined unless `newLength <= max_size()`.
1720 basic_string& privateResizeRaw(size_type newLength, CHAR_TYPE character);
1721
1722 /// Efficiently exchange the value and allocator of this object with the
1723 /// value and allocator of the specified `other` object. This method provides the no-throw exception-safety guarantee.
1724 ///
1725 /// \note Note that this
1726 /// method should not be called unless the allocators compare equal or
1727 /// the allocator traits support allocator propagation (`ALLOC_PROP` is
1728 /// `true`).
1729 template <bool ALLOC_PROP>
1730 void quickSwapExchangeAllocators(basic_string& other,
1732
1733 /// Efficiently exchange the value of this object with the value of the
1734 /// specified `other` object. This method provides the no-throw exception-safety guarantee.
1735 ///
1736 /// \pre The behavior is undefined unless
1737 /// `*this` and `other` allocators compare equal.
1738 void quickSwapRetainAllocators(basic_string& other);
1739
1740 // PRIVATE ACCESSORS
1741
1742 /// Lexicographically compare the substring of this string starting at
1743 /// the specified `lhsPosition` of length `lhsNumChars` with the
1744 /// specified initial `otherNumChars` characters in the specified
1745 /// `other` string, and return a negative value if the indicated
1746 /// substring of this string is less than `other`, a positive value if
1747 /// it is greater than `other`, and 0 in case of equality.
1748 ///
1749 /// \pre The behavior is undefined unless `lhsPosition <= length()`,
1750 /// `lhsNumChars <= length()`, and
1751 /// `lhsPosition <= length() - lhsNumChars`.
1752 int privateCompareRaw(size_type lhsPosition,
1753 size_type lhsNumChars,
1754 const CHAR_TYPE *other,
1755 size_type otherNumChars) const;
1756
1757 /// Return the number of characters in the specified `range`. If the
1758 /// `range` iterator category is `std::input_iterator_tag`, `npos' is
1759 /// returned without invalidating the iterator. When possible, the number
1760 /// of characters is calculated in constant time.
1761 template <class RANGE>
1763 size_type privateNumCharsInRange(
1764 BSLS_COMPILERFEATURES_FORWARD_REF(RANGE) range) const;
1765
1766 /// Return the number of characters in the range from the specified `first`
1767 /// to `last`. If the `INPUT_ITER` iterator category is
1768 /// `std::input_iterator_tag`, `npos' is returned without invalidating the
1769 /// iterator.
1770 template <class INPUT_ITER, class SENTINEL>
1771 size_type privateNumCharsInRange(INPUT_ITER first, SENTINEL last) const;
1772
1773 private:
1774 // NOT IMPLEMENTED
1775
1776 /// This method signature is defined as private, unimplemented, and (if
1777 /// that is supported) deleted to avoid calls like `string.insert(0, 'x')`
1778 /// to be picked up by the wrong insert function because the 0 converts
1779 /// into a null pointer that is then treated as an iterator. If the intent
1780 /// is to insert at the beginning, use `s.insert(s.begin(), 'x')`.
1781 void insert(size_type zero, CHAR_TYPE) BSLS_KEYWORD_DELETED;
1782
1783 // INVARIANTS
1784 BSLMF_ASSERT((bsl::is_same<CHAR_TYPE,
1785 typename ALLOCATOR::value_type>::value));
1786 // This is required by the C++ standard (23.1, clause 1).
1787
1788 public:
1789 // PUBLIC CLASS DATA
1790
1791 /// Value used to denote "not-a-position", guaranteed to be outside the
1792 /// range `[0 .. max_size()]`.
1793 static const size_type npos = ~size_type(0);
1794
1795 // CREATORS
1796
1797 // *** 21.3.2 construct/copy/destroy: ***
1798
1800
1801 /// Create an empty string. Optionally specify the `basicAllocator`
1802 /// used to supply memory. If `basicAllocator` is not specified, a
1803 /// default-constructed allocator is used.
1804 explicit basic_string(const ALLOCATOR& basicAllocator)
1806
1807 /// Create a string that has the same value as the specified `original`
1808 /// string. Use the allocator returned by
1809 /// 'bsl::allocator_traits<ALLOCATOR>::
1810 /// select_on_container_copy_construction(original.get_allocator())' to
1811 /// supply memory.
1812 basic_string(const basic_string& original);
1813
1814 /// Create a string that has the same value as the specified `original`
1815 /// string and uses the specified `basicAllocator` to supply memory.
1816 ///
1817 ///
1818 /// \note Note that it is important to have two copy constructors instead of a
1819 /// single:
1820 /// @code
1821 /// basic_string(const basic_string& original,
1822 /// const ALLOCATOR& basicAllocator = ALLOCATOR());
1823 /// @endcode
1824 /// When the copy constructor with the default allocator is used, xlC10
1825 /// gets confused and refuses to use the return value optimization,
1826 /// which then causes extra allocations when returning by value in
1827 /// `operator+`.
1829 const ALLOCATOR& basicAllocator);
1830
1831 /// Create a string that has the same value as the specified `original`
1832 /// string by moving (in constant time) the contents of `original` to
1833 /// the new string. The allocator associated with `original` is
1834 /// propagated for use in the newly-created string. `original` is left
1835 /// in a valid but unspecified state.
1836 basic_string(BloombergLP::bslmf::MovableRef<basic_string> original)
1838
1839 /// Create a string that has the same value as the specified `original`
1840 /// string that uses the specified `basicAllocator` to supply memory.
1841 /// The contents of `original` are moved (in constant time) to the new
1842 /// string if `basicAllocator == original.get_allocator()`, and are
1843 /// copied (in linear time) using `basicAllocator` otherwise.
1844 /// `original` is left in a valid but unspecified state.
1845 basic_string(BloombergLP::bslmf::MovableRef<basic_string> original,
1846 const ALLOCATOR& basicAllocator);
1847
1848 /// Create a string that has the same value as the substring starting at
1849 /// the specified `position` in the specified `original` string.
1850 /// Optionally specify the `basicAllocator` used to supply memory. If
1851 /// `basicAllocator` is not specified, a default-constructed allocator is
1852 /// used. The contents of `original` are moved (in constant time) to the
1853 /// new string if `basicAllocator == original.get_allocator()`, and are
1854 /// copied (in linear time) using `basicAllocator` otherwise. `original`
1855 /// is left in a valid but unspecified state. Throw @ref out_of_range if
1856 /// `position > original.length()`.
1857 basic_string(BloombergLP::bslmf::MovableRef<basic_string> original,
1858 size_type position,
1859 const ALLOCATOR& basicAllocator =
1860 ALLOCATOR());
1861
1862 /// Create a string that has the same value as the substring of the
1863 /// specified `numChars` length starting at the specified `position` in
1864 /// the specified `original` string. If `numChars` is more than the
1865 /// available string length, then the remaining length of the string is
1866 /// used (i.e., `numChars` is set to `original.length() - position`).
1867 /// Optionally specify the `basicAllocator` used to supply memory. If
1868 /// `basicAllocator` is not specified, a default-constructed allocator is
1869 /// used. The contents of `original` are moved (in constant time) to the
1870 /// new string if `basicAllocator == original.get_allocator()`, and are
1871 /// copied (in linear time) using `basicAllocator` otherwise. `original`
1872 /// is left in a valid but unspecified state. Throw @ref out_of_range if
1873 /// `position > original.length()`.
1874 basic_string(BloombergLP::bslmf::MovableRef<basic_string> original,
1875 size_type position,
1876 size_type numChars,
1877 const ALLOCATOR& basicAllocator =
1878 ALLOCATOR());
1879
1880 /// Create a string that has the same value as the substring of the
1881 /// specified `numChars` length starting at the specified `position` in the
1882 /// specified `original` string. Optionally specify the `basicAllocator`
1883 /// used to supply memory. If `basicAllocator` is not specified, a
1884 /// default-constructed allocator is used. Throw @ref out_of_range if
1885 /// `position > original.length()`.
1887 size_type position,
1888 const ALLOCATOR& basicAllocator = ALLOCATOR());
1889
1890 /// Create a string that has the same value as the substring of the
1891 /// specified `numChars` length starting at the specified `position` in
1892 /// the specified `original` string. If `numChars` equals `npos`, then
1893 /// the remaining length of the string is used (i.e., `numChars` is set
1894 /// to `original.length() - position`). Optionally specify the
1895 /// `basicAllocator` used to supply memory. If `basicAllocator` is not
1896 /// specified, a default-constructed allocator is used. Throw
1897 /// @ref out_of_range if `position > original.length()`.
1899 size_type position,
1900 size_type numChars,
1901 const ALLOCATOR& basicAllocator = ALLOCATOR());
1902
1903 /// Create a string having the same value as the specified
1904 /// null-terminated `characterString` (of length
1905 /// `CHAR_TRAITS::length(characterString)`). Optionally specify a
1906 /// `basicAllocator` used to supply memory. If `basicAllocator` is not
1907 /// specified, a default-constructed allocator is used.
1908#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
1909 template <class = bsl::enable_if_t<bsl::IsStdAllocator<ALLOCATOR>::value>>
1910#endif
1911 basic_string(const CHAR_TYPE *characterString,
1912 const ALLOCATOR& basicAllocator = ALLOCATOR()); // IMPLICIT
1913
1914#ifdef BSLS_COMPILERFEATURES_FULL_CPP11
1915 /// A string cannot be constructed from a `nullptr` or from a literal `0`.
1916 basic_string(bsl::nullptr_t ) = delete;
1917#endif
1918
1919 /// Create a string that has the same value as the substring of the
1920 /// optionally specified `numChars` length starting at the beginning of
1921 /// the specified `characterString`. If `numChars` is not specified,
1922 /// `CHAR_TRAITS::length(characterString)` is used. Optionally specify
1923 /// the `basicAllocator` used to supply memory. If `basicAllocator` is
1924 /// not specified, a default-constructed allocator is used. Throw
1925 /// @ref out_of_range if `numChars >= npos`.
1926 basic_string(const CHAR_TYPE *characterString,
1927 size_type numChars,
1928 const ALLOCATOR& basicAllocator = ALLOCATOR());
1929
1930 /// Create a string of the specified `numChars` length whose every
1931 /// position contains the specified `character`. Optionally specify a
1932 /// `basicAllocator` used to supply memory. If `basicAllocator` is not
1933 /// specified, a default-constructed allocator is used.
1934#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
1935 template <class = bsl::enable_if_t<bsl::IsStdAllocator<ALLOCATOR>::value>>
1936#endif
1938 CHAR_TYPE character,
1939 const ALLOCATOR& basicAllocator = ALLOCATOR());
1940
1941 /// Create a string from the characters in the range starting at the
1942 /// specified `first` iterator and ending right before the specified
1943 /// `last` iterator of the (template parameter) type `INPUT_ITER`.
1944 /// Optionally specify a `basicAllocator` used to supply memory. If
1945 /// `basicAllocator` is not specified, a default-constructed allocator is used.
1946 ///
1947 /// \pre The behavior is undefined unless `first` and `last` refer
1948 /// to a sequence of valid values where `first` is at a position at or
1949 /// before `last`.
1950 template <class INPUT_ITER>
1951 basic_string(INPUT_ITER first,
1952 INPUT_ITER last,
1953 const ALLOCATOR& basicAllocator = ALLOCATOR());
1954
1955 /// Create a string that containing the characters from the specified
1956 /// `range`. Optionally specify a `basicAllocator` used to supply memory.
1957 /// If `basicAllocator` is not specified, a default-constructed allocator is used.
1958 ///
1959 /// \note Note that `range` must meet the requirements of an input
1960 /// range and the values from `range` must have a type matching or
1961 /// convertible to (template parameter) `CHAR_TYPE`.
1962 template <class RANGE>
1966 const ALLOCATOR& basicAllocator =
1967 ALLOCATOR());
1968
1969 /// Create a string that has the same value as the specified `original`
1970 /// string, where the type `original` is the string type native to the
1971 /// compiler's library, instantiated with the same character type and
1972 /// traits type, but not necessarily the same allocator type. The
1973 /// resulting string will contain the same sequence of characters as
1974 /// `original`. Optionally specify a `basicAllocator` used to supply
1975 /// memory. If `basicAllocator` is not specified, then a
1976 /// default-constructed allocator is used.
1977 template <class ALLOC2>
1979 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& original,
1980 const ALLOCATOR& basicAllocator = ALLOCATOR()); // IMPLICIT
1981
1982 /// Create a string that has the same value as the specified `strRef`
1983 /// string. The resulting string will contain the same sequence of
1984 /// characters as `strRef`. Optionally specify a `basicAllocator` used
1985 /// to supply memory. If `basicAllocator` is not specified, then a
1986 /// default-constructed allocator is used.
1987 basic_string(const BloombergLP::bslstl::StringRefData<CHAR_TYPE>& strRef,
1988 const ALLOCATOR& basicAllocator = ALLOCATOR()); // IMPLICIT
1989
1990 /// Create a string that has the same value as the specified `object`.
1991 /// Optionally specify a `basicAllocator` used to supply memory. If
1992 /// `basicAllocator` is not specified, then a default-constructed
1993 /// allocator is used.
1994 template <class STRING_VIEW_LIKE_TYPE>
1996 const STRING_VIEW_LIKE_TYPE& object,
1998 basicAllocator = ALLOCATOR());
1999
2000 /// Create a string that has the same value as the substring of the
2001 /// specified `numChars` length starting at the specified `position` in
2002 /// the specified `object`. Optionally specify a `basicAllocator` used
2003 /// to supply memory. If the `basicAllocator` is not specified, a
2004 /// default-constructed allocator is used. Throw @ref out_of_range if
2005 /// `position > original.object()`.
2006 template <class STRING_VIEW_LIKE_TYPE>
2007 basic_string(const STRING_VIEW_LIKE_TYPE& object,
2008 size_type position,
2009 size_type numChars,
2010 const ALLOCATOR& basicAllocator = ALLOCATOR(),
2012
2013#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2014 /// Create a string and insert (in order) each `CHAR_TYPE` object in the
2015 /// specified `values` initializer list. Optionally specify a
2016 /// `basicAllocator` used to supply memory. If `basicAllocator` is not
2017 /// specified, then a default-constructed allocator is used.
2018 basic_string(std::initializer_list<CHAR_TYPE> values,
2019 const ALLOCATOR& basicAllocator =
2020 ALLOCATOR());
2021#endif
2022
2023 /// Destroy this string object.
2025
2026 // MANIPULATORS
2027
2028 // *** 21.3.2 construct/copy/destroy: ***
2029
2030 /// Assign to this string the value of the specified `rhs` string,
2031 /// propagate to this object the allocator of `rhs` if the `ALLOCATOR`
2032 /// type has trait @ref propagate_on_container_copy_assignment , and return
2033 /// a reference providing modifiable access to this string.
2035
2036 /// Assign to this string the value of the specified `rhs` string,
2037 /// propagate to this object the allocator of `rhs` if the `ALLOCATOR`
2038 /// type has trait @ref propagate_on_container_move_assignment , and return
2039 /// a reference providing modifiable access to this string. The content
2040 /// of `rhs` is moved (in constant time) to this string if
2041 /// `get_allocator() == rhs.get_allocator()` (after accounting for the
2042 /// aforementioned trait). `rhs` is left in a valid but unspecified
2043 /// state.
2044#ifndef DOXYGEN_SKIP
2045 basic_string& operator=(BloombergLP::bslmf::MovableRef<basic_string> rhs)
2047 AllocatorTraits::propagate_on_container_move_assignment::value ||
2048 AllocatorTraits::is_always_equal::value);
2049#else
2050 basic_string& operator=(BloombergLP::bslmf::MovableRef<basic_string> rhs);
2051#endif
2052
2053 /// Assign to this string the value of the specified `rhs` object, and
2054 /// return a reference providing modifiable access to this string.
2055 template <class STRING_VIEW_LIKE_TYPE>
2057 operator=(const STRING_VIEW_LIKE_TYPE& rhs);
2058
2059 /// Assign to this string the value of the specified null-terminated
2060 /// `rhs` string (of length `CHAR_TRAITS::length(characterString)`), and
2061 /// return a reference providing modifiable access to this string.
2062 basic_string& operator=(const CHAR_TYPE *rhs);
2063
2064 /// Assign to this string the value of the string of length one
2065 /// consisting of the specified `character`, and return a reference
2066 /// providing modifiable access to this string.
2067 basic_string& operator=(CHAR_TYPE character);
2068
2069 /// Assign to this string the value of the specified `rhs` string, and
2070 /// return a reference providing modifiable access to this string.
2071 template <class ALLOC2>
2072 basic_string& operator=(
2073 const std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC2>& rhs);
2074
2075#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2076 /// Assign to this string the value resulting from first clearing this
2077 /// string and then inserting (in order) each `CHAR_TYPE` object in the
2078 /// specified `values` initializer list.
2079 basic_string& operator=(std::initializer_list<CHAR_TYPE> values);
2080#endif
2081
2082 // *** 21.3.4 capacity: ***
2083
2084 /// Change the length of this string to the specified `newLength`,
2085 /// erasing characters at the end if `newLength < length()` or appending
2086 /// the appropriate number of copies of the specified `character` at the
2087 /// end if `length() < newLength`.
2088 void resize(size_type newLength, CHAR_TYPE character);
2089
2090 /// Change the length of this string to the specified `newLength`,
2091 /// erasing characters at the end if `newLength < length()` or appending
2092 /// the appropriate number of copies of `CHAR_TYPE()` at the end if
2093 /// `length() < newLength`.
2094 void resize(size_type newLength);
2095
2096 /// Change the length of this string to the specified `newLength`,
2097 /// erasing characters at the end if `newLength < length()` or appending
2098 /// the appropriate number of characters at the end if
2099 /// `length() < newLength`. Subsequently, invoke the specified
2100 /// `operation` passing the address of the null-terminated buffer and
2101 /// the adjusted length of this string as parameters. Finally, change
2102 /// the length of this string to the value returned by the `operation`.
2103 /// Throw `length_error` if `newLength > max_size()`.
2104 ///
2105 /// \pre The behavior is undefined unless the value returned by the `operation` is less than
2106 /// or equal to `newLength`.
2107 template <class OPERATION>
2108 void resize_and_overwrite(size_type newLength, OPERATION operation);
2109
2110 /// Change the capacity of this string to the specified `newCapacity`.
2111 ///
2112 /// \note Note that the capacity of a string is the maximum length it can
2113 /// accommodate without reallocation. The actual storage allocated may
2114 /// be higher.
2115 void reserve(size_type newCapacity);
2116
2117 /// Request the removal of unused capacity by causing reallocation.
2118 ///
2119 /// \note Note that this method has no effect if the capacity is equal to the
2120 /// size. Also note that if (and only if) reallocation occurs, all
2121 /// iterators, including the past the end iterator, and all references
2122 /// to the elements are invalidated.
2124
2125 /// Reset this string to an empty value.
2126 /// \note Note that the capacity may
2127 /// change (or not if `BASIC_STRING_DEALLOCATE_IN_CLEAR` is `false`).
2128 ///
2129 /// \note Note that the Standard doesn't allow to reduce capacity on `clear`.
2131
2132 // *** 21.3.3 iterators: ***
2133
2134 /// Return an iterator referring to the first character in this
2135 /// modifiable string (or the past-the-end iterator if this string is
2136 /// empty).
2138
2139 /// Return the past-the-end iterator for this modifiable string.
2141
2142 /// Return a reverse iterator referring to the last character in this
2143 /// modifiable string (or the past-the-end reverse iterator if this
2144 /// string is empty).
2146
2147 /// Return the past-the-end reverse iterator for this modifiable string.
2149
2150 // *** 21.3.5 element access: ***
2151
2152 /// Return a reference providing modifiable access to the character at
2153 /// the specified `position` in this string if `position < length()`, or
2154 /// a reference providing non-modifiable access to the null-terminating
2155 /// character if `position == length()`.
2156 ///
2157 /// \pre The behavior is undefined unless `position <= length()`, and, in the case of
2158 /// `position == length()`, the null-terminating character is not
2159 /// modified through the returned reference.
2160 reference operator[](size_type position);
2161
2162 /// Return a reference providing modifiable access to the character at
2163 /// the specified `position` in this string. Throw @ref out_of_range if
2164 /// `position >= length()`.
2165 reference at(size_type position);
2166
2167 /// Return a reference providing modifiable access to the character at the first position in this string.
2168 ///
2169 /// \pre The behavior is undefined if
2170 /// this string is empty.
2171 CHAR_TYPE& front();
2172
2173 /// Return a reference providing modifiable access to the character at the last position in this string.
2174 ///
2175 /// \pre The behavior is undefined if this string is empty.
2176 ///
2177 /// \note Note that the last position is `length() - 1`.
2178 CHAR_TYPE& back();
2179
2180 // *** 21.3.6 modifiers: ***
2181
2182 /// Append the specified `rhs` string to this string, and return a
2183 /// reference providing modifiable access to this string.
2184 basic_string& operator+=(const basic_string& rhs);
2185
2186 /// Append the specified null-terminated `rhs` string (of length
2187 /// `CHAR_TRAITS::length(rhs)`) to this string, and return a reference
2188 /// providing modifiable access to this string.
2189 basic_string& operator+=(const CHAR_TYPE *rhs);
2190
2191 /// Append the specified `character` to this string, and return a
2192 /// reference providing modifiable access to this string.
2193 basic_string& operator+=(CHAR_TYPE character);
2194
2195 /// Append the specified `rhs` to this string, and return a reference
2196 /// providing modifiable access to this string.
2197 template <class STRING_VIEW_LIKE_TYPE>
2199 operator+=(const STRING_VIEW_LIKE_TYPE& rhs);
2200
2201 /// Append the specified `rhs` string to this string, and return a
2202 /// reference providing modifiable access to this string.
2203 template <class ALLOC2>
2204 basic_string& operator+=(
2205 const std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC2>& rhs);
2206
2207 /// Append to this string the specified `suffix`, and return a reference
2208 /// providing modifiable access to this string.
2209 basic_string& append(const basic_string& suffix);
2210
2211 /// Append to this string the optionally specified `numChars` characters
2212 /// starting at the specified `position` in the specified `suffix`, or
2213 /// the tail of `suffix` starting at `position` if
2214 /// `position + numChars > suffix.length()`. If `numChars` is not
2215 /// specified, `npos` is used. Return a reference providing modifiable
2216 /// access to this string. Throw @ref out_of_range if
2217 /// `position > suffix.length()`.
2218 basic_string& append(const basic_string& suffix,
2219 size_type position,
2220 size_type numChars = npos);
2221
2222 /// Append to this string the specified initial `numChars` characters
2223 /// from the specified `characterString`, and return a reference
2224 /// providing modifiable access to this string.
2225 ///
2226 /// \pre The behavior is undefined unless `characterString` is at least `numChars` long.
2227 basic_string& append(const CHAR_TYPE *characterString,
2228 size_type numChars);
2229
2230 /// Append the specified null-terminated `characterString` (of length
2231 /// `CHAR_TRAITS::length(characterString)`) to this string, and return a
2232 /// reference providing modifiable access to this string.
2233 basic_string& append(const CHAR_TYPE *characterString);
2234
2235 /// Append the specified `numChars` copies of the specified `character`
2236 /// to this string, and return a reference providing modifiable access
2237 /// to this string.
2238 basic_string& append(size_type numChars, CHAR_TYPE character);
2239
2240 /// Append to this string the `bsl::string_view` object, obtained from
2241 /// the specified `suffix`, and return a reference providing modifiable
2242 /// access to this string. Throw `length_error` if the length of the
2243 /// resulting string exceeds `max_size()`.
2244 template <class STRING_VIEW_LIKE_TYPE>
2246 append(const STRING_VIEW_LIKE_TYPE& suffix);
2247
2248 /// Append to this string the optionally specified `numChars` characters
2249 /// starting at the specified `position` in the `bsl::string_view`
2250 /// object, obtained from the specified `suffix`, or its tail starting
2251 /// at `position` if `numChars` exceeds the length of this tail. If
2252 /// `numChars` is not specified, `npos` is used. Return a reference
2253 /// providing modifiable access to this string. Throw @ref out_of_range if
2254 /// `position > strView.length()`. Throw `length_error` if the length
2255 /// of the resulting string exceeds `max_size()`.
2256 template <class STRING_VIEW_LIKE_TYPE>
2258 append(const STRING_VIEW_LIKE_TYPE& suffix,
2259 size_type position,
2260 size_type numChars = npos);
2261
2262 /// Append to this string the characters in the range starting at the
2263 /// specified `first` iterator and ending right before the specified
2264 /// `last` iterator of the (template parameter) type `INPUT_ITER`.
2265 /// Return a reference providing modifiable access to this string.
2266 ///
2267 /// \pre The behavior is undefined unless `first` and `last` refer to a sequence
2268 /// of valid values where `first` is at a position at or before `last`.
2269 template <class INPUT_ITER>
2270 basic_string& append(INPUT_ITER first, INPUT_ITER last);
2271
2272#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2273 /// Append to this string each `CHAR_TYPE` object in the specified
2274 /// `values` initializer list, and return a reference providing
2275 /// modifiable access to this string.
2276 basic_string& append(std::initializer_list<CHAR_TYPE> values);
2277#endif
2278
2279 /// Append to this string the characters from the specified `range`.
2280 /// Return a reference providing modifiable access to this string.
2281 ///
2282 /// \note Note that `range` must meet the requirements of an input range and the
2283 /// values from `range` must have a type matching or convertible to
2284 /// (template parameter) `CHAR_TYPE`.
2285 template <class RANGE>
2288
2289 /// Append the specified `character` to this string.
2290 void push_back(CHAR_TYPE character);
2291
2292 /// Assign to this string the value of the specified `replacement`
2293 /// string, propagate to this object the allocator of `replacement` if
2294 /// the `ALLOCATOR` type has trait
2295 /// @ref propagate_on_container_copy_assignment , and return a reference providing modifiable access to this string.
2296 ///
2297 /// \note Note that this method
2298 /// has exactly the same behavior as the corresponding `operator=`.
2299 basic_string& assign(const basic_string& replacement);
2300
2301 /// Assign to this string the value of the specified `replacement`
2302 /// string, propagate to this object the allocator of `replacement` if
2303 /// the `ALLOCATOR` type has trait
2304 /// @ref propagate_on_container_move_assignment , and return a reference
2305 /// providing modifiable access to this string. The content of
2306 /// `replacement` is moved (in constant time) to this string if
2307 /// `get_allocator() == rhs.get_allocator()` (after accounting for the
2308 /// aforementioned trait). `replacement` is left in a valid but unspecified state.
2309 ///
2310 /// \note Note that this method has exactly the same
2311 /// behavior as the corresponding `operator=`.
2313 BloombergLP::bslmf::MovableRef<basic_string> replacement)
2315
2316 /// Assign to this string the value of the optionally specified
2317 /// `numChars` characters starting at the specified `position` in the
2318 /// specified `replacement` string, or the suffix of `replacement`
2319 /// starting at `position` if
2320 /// `position + numChars > replacement.length()`. If `numChars` is not
2321 /// specified, `npos` is used. Return a reference providing modifiable
2322 /// access to this string. Throw @ref out_of_range if
2323 /// `position > replacement.length()`.
2324 basic_string& assign(const basic_string& replacement,
2325 size_type position,
2326 size_type numChars = npos);
2327
2328 /// Assign to this string the value of the specified null-terminated
2329 /// `characterString` (of length
2330 /// `CHAR_TRAITS::length(characterString)`), and return a reference
2331 /// providing modifiable access to this string.
2332 basic_string& assign(const CHAR_TYPE *characterString);
2333
2334 /// Assign to this string the specified initial `numChars` characters in
2335 /// the specified `characterString`, and return a reference providing modifiable access to this string.
2336 ///
2337 /// \pre The behavior is undefined unless
2338 /// `characterString` is at least `numChars` long.
2339 basic_string& assign(const CHAR_TYPE *characterString,
2340 size_type numChars);
2341
2342 /// Assign to this string the value of the specified `replacement`, and
2343 /// return a reference providing modifiable access to this string.
2344 ///
2345 /// \note Note that this method has exactly the same behavior as the corresponding
2346 /// `operator=`.
2347 template <class STRING_VIEW_LIKE_TYPE>
2349 assign(const STRING_VIEW_LIKE_TYPE& replacement);
2350
2351 /// Assign to this string the value of the optionally specified
2352 /// `numChars` characters starting at the specified `position` in the
2353 /// specified `replacement`, or the suffix of the `replacement` starting
2354 /// at `position` if `position + numChars > replacement.length()`. If
2355 /// `numChars` is not specified, `npos` is used. Return a reference
2356 /// providing modifiable access to this string. Throw @ref out_of_range if
2357 /// `position > replacement.length()`.
2358 template <class STRING_VIEW_LIKE_TYPE>
2360 assign(const STRING_VIEW_LIKE_TYPE& replacement,
2361 size_type position,
2362 size_type numChars = npos);
2363
2364 /// Assign to this string the value of the specified `string`, and
2365 /// return a reference providing modifiable access to this string.
2366 template <class ALLOC2>
2368 const std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC2>& string);
2369
2370 /// Assign to this string the value of a string of the specified
2371 /// `numChars` length whose every character is equal to the specified
2372 /// `character`, and return a reference providing modifiable access to
2373 /// this string.
2374 basic_string& assign(size_type numChars, CHAR_TYPE character);
2375
2376 /// Assign to this string the characters in the range starting at the
2377 /// specified `first` iterator and ending right before the specified
2378 /// `last` iterator of the (template parameter) type `INPUT_ITER`.
2379 /// Return a reference providing modifiable access to this string.
2380 ///
2381 /// \pre The behavior is undefined unless `first` and `last` refer to a sequence
2382 /// of valid values where `first` is at a position at or before `last`.
2383 template <class INPUT_ITER>
2384 basic_string& assign(INPUT_ITER first, INPUT_ITER last);
2385
2386#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2387 /// Assign to this string the value resulting from first clearing this
2388 /// string and then inserting (in order) each `CHAR_TYPE` object in the
2389 /// specified `values` initializer list. Return a reference providing
2390 /// modifiable access to this string.
2391 basic_string& assign(std::initializer_list<CHAR_TYPE> values);
2392#endif
2393
2394 /// Assign to this string the characters from the specified `range`.
2395 /// Return a reference providing modifiable access to this string.
2396 ///
2397 /// \note Note that `range` must meet the requirements of an input range and the
2398 /// values from `range` must have a type matching or convertible to
2399 /// (template parameter) `CHAR_TYPE`.
2400 template <class RANGE>
2403
2404 /// Insert at the specified `position` in this string a copy of the
2405 /// specified `other` string, and return a reference providing
2406 /// modifiable access to this string. Throw @ref out_of_range if
2407 /// `position > length()`.
2408 basic_string& insert(size_type position, const basic_string& other);
2409
2410 /// Insert at the specified `position` in this string the optionally
2411 /// specified `numChars` characters starting at the specified
2412 /// `sourcePosition` in the specified `other` string, or the suffix of
2413 /// `other` starting at `sourcePosition` if
2414 /// `sourcePosition + numChars > other.length()`. If `numChars` is not
2415 /// specified, `npos` is used. Return a reference providing modifiable
2416 /// access to this string. Throw @ref out_of_range if
2417 /// `position > length()` or `sourcePosition > other.length()`.
2418 basic_string& insert(size_type position,
2419 const basic_string& other,
2420 size_type sourcePosition,
2421 size_type numChars = npos);
2422
2423 /// Insert at the specified `position` in this string the specified
2424 /// initial `numChars` characters in the specified `characterString`,
2425 /// and return a reference providing modifiable access to this string.
2426 /// Throw @ref out_of_range if `position > length()`.
2427 ///
2428 /// \pre The behavior is undefined unless `characterString` is at least `numChars` long.
2429 basic_string& insert(size_type position,
2430 const CHAR_TYPE *characterString,
2431 size_type numChars);
2432
2433 /// Insert at the specified `position` in this string the specified
2434 /// null-terminated `characterString` (of length
2435 /// `CHAR_TRAITS::length(characterString)`), and return a reference
2436 /// providing modifiable access to this string. Throw @ref out_of_range if
2437 /// `position > length()`.
2438 basic_string& insert(size_type position,
2439 const CHAR_TYPE *characterString);
2440
2441 /// Insert at the specified `position` in this string the specified
2442 /// `numChars` copies of the specified `character`, and return a
2443 /// reference providing modifiable access to this string. Throw
2444 /// @ref out_of_range if `position > length()`.
2445 basic_string& insert(size_type position,
2446 size_type numChars,
2447 CHAR_TYPE character);
2448
2449 /// Insert the specified `character` at the specified `position` in this
2450 /// string, and return an iterator providing modifiable access to the inserted character.
2451 ///
2452 /// \pre The behavior is undefined unless `position` is
2453 /// a valid iterator on this string.
2454 iterator insert(const_iterator position, CHAR_TYPE character);
2455
2456 /// Insert at the specified `position` in this string the characters in
2457 /// the range starting at the specified `first` iterator and ending
2458 /// right before the specified `last` iterator of the (template
2459 /// parameter) type `INPUT_ITER`, and return an iterator providing
2460 /// modifiable access to the first inserted character, or a non-`const`
2461 /// copy of `position` if `first == last`.
2462 ///
2463 /// \pre The behavior is undefined unless `position` is a valid iterator on this string, and `first`
2464 /// and `last` refer to a sequence of valid values where `first` is at a
2465 /// position at or before `last`.
2466 template <class INPUT_ITER>
2467 iterator insert(const_iterator position,
2468 INPUT_ITER first,
2469 INPUT_ITER last);
2470
2471 /// Insert at the specified `position` in this string the specified
2472 /// `numChars` copies of the specified `character`, and return an
2473 /// iterator providing modifiable access to the first inserted
2474 /// character, or a non-`const` copy of `position` if `0 == numChars`.
2475 ///
2476 /// \pre The behavior is undefined unless `position` is a valid iterator on
2477 /// this string.
2478 iterator insert(const_iterator position,
2479 size_type numChars,
2480 CHAR_TYPE character);
2481
2482 /// Insert at the specified `position` in this string the
2483 /// `bsl::string_view` object, obtained from the specified `other`, and
2484 /// return a reference providing modifiable access to this string.
2485 /// Throw @ref out_of_range if `position > length()`. Throw `length_error`
2486 /// if the length of the resulting string exceeds `max_size()`.
2487 template <class STRING_VIEW_LIKE_TYPE>
2489 insert(size_type position, const STRING_VIEW_LIKE_TYPE& other);
2490
2491 /// Insert at the specified `position` in this string the optionally
2492 /// specified `numChars` characters starting at the specified
2493 /// `sourcePosition` in the `bsl::string_view` object, obtained from the
2494 /// specified `other`, or the suffix of this object starting at
2495 /// `sourcePosition` if `sourcePosition + numChars > other.length()`.
2496 /// If `numChars` is not specified, `npos` is used. Return a reference
2497 /// providing modifiable access to this string. Throw @ref out_of_range if
2498 /// `position > length()` or `sourcePosition > other.length()`. Throw
2499 /// `length_error` if the length of the resulting string exceeds
2500 /// `max_size()`.
2501 template <class STRING_VIEW_LIKE_TYPE>
2503 insert(size_type position,
2504 const STRING_VIEW_LIKE_TYPE& other,
2505 size_type sourcePosition,
2506 size_type numChars = npos);
2507
2508#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2509 /// Insert at the specified `position` in this string each `CHAR_TYPE`
2510 /// object in the specified `values` initializer list, and return an
2511 /// iterator to the first newly-inserted character. If an exception is
2512 /// thrown (other than by the copy constructor, move constructor,
2513 /// assignment operator, and move assignment operator of `CHAR_TYPE`), `*this` is unaffected.
2514 ///
2515 /// \pre The behavior is undefined unless `position`
2516 /// is an iterator in the range `[begin() .. end()]` (both endpoints
2517 /// included).
2518 iterator insert(const_iterator position,
2519 std::initializer_list<CHAR_TYPE> values);
2520#endif
2521
2522 /// Insert at the specified `position` in this string the characters
2523 /// from the specified `range` and return an iterator providing
2524 /// non-modifiable access to the first inserted character, or a non-`const`
2525 /// copy of `position` if `true == bsl::ranges.empty()`.
2526 ///
2527 /// \pre The behavior is undefined unless `position` is an iterator in the range `[begin() .. end()]` (both endpoints included).
2528 ///
2529 /// \note Note that `range` must
2530 /// meet the requirements of an input range and the values from `range`
2531 /// must have a type matching or convertible to (template parameter)
2532 /// `CHAR_TYPE`>
2533 template <class RANGE>
2535 iterator insert_range(const_iterator position,
2537
2538 /// Erase from this string the substring of length the optionally
2539 /// specified `numChars` or `original.length() - position`, whichever is
2540 /// smaller, starting at the optionally specified `position`. If
2541 /// `position` is not specified, the first position is used (i.e.,
2542 /// `position` is set to 0). Return a reference providing modifiable
2543 /// access to this string. If `numChars` equals `npos`, then the
2544 /// remaining length of the string is erased (i.e., `numChars` is set to
2545 /// `length() - position`). Throw @ref out_of_range if
2546 /// `position > length()`.
2547 basic_string& erase(size_type position = 0, size_type numChars = npos);
2548
2549 /// Erase a character at the specified `position` from this string, and
2550 /// return an iterator providing modifiable access to the character at
2551 /// `position` prior to erasing. If no such character exists, return `end()`.
2552 ///
2553 /// \pre The behavior is undefined unless `position` is within the
2554 /// half-open range `[cbegin() .. cend())`.
2555 iterator erase(const_iterator position);
2556
2557 /// Erase from this string a substring defined by the specified pair of
2558 /// `first` and `last` iterators within this string. Return an iterator
2559 /// providing modifiable access to the character at the `last` position
2560 /// prior to erasing. If no such character exists, return `end()`.
2561 /// This method invalidates existing iterators pointing to `first` or a subsequent position.
2562 ///
2563 /// \pre The behavior is undefined unless `first` and
2564 /// `last` are both within the range `[cbegin() .. cend()]` and `first
2565 /// <= last`.
2567
2568 /// Erase the last character from this string.
2569 ///
2570 /// \pre The behavior is undefined if this string is empty.
2571 void pop_back();
2572
2573 /// Replace the specified `outNumChars` characters starting at the
2574 /// specified `outPosition` in this string (or the suffix of this string
2575 /// starting at `outPosition` if `outPosition + outNumChars > length()`)
2576 /// with the specified `replacement` string, and return a reference
2577 /// providing modifiable access to this string. Throw @ref out_of_range if
2578 /// `outPosition > length()`.
2579 basic_string& replace(size_type outPosition,
2580 size_type outNumChars,
2581 const basic_string& replacement);
2582
2583 /// Replace the specified `outNumChars` characters starting at the
2584 /// specified `outPosition` in this string (or the suffix of this string
2585 /// starting at `outPosition` if `outPosition + outNumChars > length()`)
2586 /// with the optionally specified `numChars` characters starting at the
2587 /// specified `position` in the specified `replacement` string (or the
2588 /// suffix of `replacement` starting at `position` if
2589 /// `position + numChars > replacement.length()`). If `numChars` is not
2590 /// specified, `npos` is used. Return a reference providing modifiable
2591 /// access to this string. Throw @ref out_of_range if
2592 /// `outPosition > length()` or `position > replacement.length()`.
2593 basic_string& replace(size_type outPosition,
2594 size_type outNumChars,
2595 const basic_string& replacement,
2596 size_type position,
2597 size_type numChars = npos);
2598
2599 /// Replace the specified `outNumChars` characters starting at the
2600 /// specified `outPosition` in this string (or the suffix of this string
2601 /// starting at `outPosition` if `outPosition + outNumChars > length()`)
2602 /// with the specified initial `numChars` characters in the specified
2603 /// `characterString`. Return a reference providing modifiable access
2604 /// to this string. Throw @ref out_of_range if `outPosition > length()`.
2605 ///
2606 /// \pre The behavior is undefined unless `characterString` is at least
2607 /// `numChars` long.
2608 basic_string& replace(size_type outPosition,
2609 size_type outNumChars,
2610 const CHAR_TYPE *characterString,
2611 size_type numChars);
2612
2613 /// Replace the specified `outNumChars` characters starting at the
2614 /// specified `outPosition` in this string (or the suffix of this string
2615 /// starting at `outPosition` if `outPosition + outNumChars > length()`)
2616 /// with the specified null-terminated `characterString` (of length
2617 /// `CHAR_TRAITS::length(characterString)`). Return a reference
2618 /// providing modifiable access to this string. Throw @ref out_of_range if
2619 /// `outPosition > length()`.
2620 basic_string& replace(size_type outPosition,
2621 size_type outNumChars,
2622 const CHAR_TYPE *characterString);
2623
2624 /// Replace the specified `outNumChars` characters starting at the
2625 /// specified `outPosition` in this string (or the suffix of this string
2626 /// starting at `outPosition` if `outPosition + outNumChars > length()`)
2627 /// with the specified `numChars` copies of the specified `character`.
2628 /// Return a reference providing modifiable access to this string.
2629 /// Throw @ref out_of_range if `outPosition > length()`.
2630 basic_string& replace(size_type outPosition,
2631 size_type outNumChars,
2632 size_type numChars,
2633 CHAR_TYPE character);
2634
2635 /// Replace the specified `outNumChars` characters starting at the
2636 /// specified `outPosition` in this string (or the suffix of this string
2637 /// starting at `outPosition` if `outPosition + outNumChars > length()`)
2638 /// with the specified `replacement`, and return a reference providing
2639 /// modifiable access to this string. Throw @ref out_of_range if
2640 /// `outPosition > length()`.
2641 template <class STRING_VIEW_LIKE_TYPE>
2643 replace(size_type outPosition,
2644 size_type outNumChars,
2645 const STRING_VIEW_LIKE_TYPE& replacement);
2646
2647 /// Replace the specified `outNumChars` characters starting at the
2648 /// specified `outPosition` in this string (or the suffix of this string
2649 /// starting at `outPosition` if `outPosition + outNumChars > length()`)
2650 /// with the optionally specified `numChars` characters starting at the
2651 /// specified `position` in the specified `replacement` (or the suffix
2652 /// of `replacement` starting at `position` if
2653 /// `position + numChars > replacement.length()`). If `numChars` is not
2654 /// specified, `npos` is used. Return a reference providing modifiable
2655 /// access to this string. Throw @ref out_of_range if
2656 /// `outPosition > length()` or `position > replacement.length()`.
2657 template <class STRING_VIEW_LIKE_TYPE>
2659 replace(size_type outPosition,
2660 size_type outNumChars,
2661 const STRING_VIEW_LIKE_TYPE& replacement,
2662 size_type position,
2663 size_type numChars = npos);
2664
2665 /// Replace the substring in the range starting at the specified `first`
2666 /// position and ending right before the specified `last` position with
2667 /// the specified `replacement` string. Return a reference providing modifiable access to this string.
2668 ///
2669 /// \pre The behavior is undefined unless
2670 /// `first` and `last` are both within the range `[cbegin() .. cend()]`
2671 /// and `first <= last`.
2673 const_iterator last,
2674 const basic_string& replacement);
2675
2676 /// Replace the substring in the range starting at the specified `first`
2677 /// position and ending right before the specified `last` position with
2678 /// the specified `replacement`. Return a reference providing modifiable access to this string.
2679 ///
2680 /// \pre The behavior is undefined unless
2681 /// `first` and `last` are both within the range `[cbegin() .. cend()]`
2682 /// and `first <= last`.
2683 template <class STRING_VIEW_LIKE_TYPE>
2685 replace(const_iterator first,
2686 const_iterator last,
2687 const STRING_VIEW_LIKE_TYPE& replacement);
2688
2689 /// Replace the substring in the range starting at the specified `first`
2690 /// position and ending right before the specified `last` position with
2691 /// the specified initial `numChars` characters in the specified
2692 /// `characterString`. Return a reference providing modifiable access to this string.
2693 ///
2694 /// \pre The behavior is undefined unless `first` and `last`
2695 /// are both within the range `[cbegin() .. cend()]`, `first <= last`,
2696 /// and `characterString` is at least `numChars` long.
2698 const_iterator last,
2699 const CHAR_TYPE *characterString,
2700 size_type numChars);
2701
2702 /// Replace the substring in the range starting at the specified `first`
2703 /// position and ending right before the specified `last` position with
2704 /// the specified null-terminated `characterString` (of length
2705 /// `CHAR_TRAITS::length(characterString)`). Return a reference
2706 /// providing modifiable access to this string.
2707 ///
2708 /// \pre The behavior is undefined unless `first` and `last` are both within the range
2709 /// `[cbegin() .. cend()]` and `first <= last`.
2711 const_iterator last,
2712 const CHAR_TYPE *characterString);
2713
2714 /// Replace the substring in the range starting at the specified `first`
2715 /// position and ending right before the specified `last` position with
2716 /// the specified `numChars` copies of the specified `character`.
2717 /// Return a reference providing modifiable access to this string.
2718 ///
2719 /// \pre The behavior is undefined unless `first` and `last` are both within the
2720 /// range `[cbegin() .. cend()]` and `first <= last`.
2722 const_iterator last,
2723 size_type numChars,
2724 CHAR_TYPE character);
2725
2726 /// Replace the substring in the range starting at the specified `first`
2727 /// position and ending right before the specified `last` position with
2728 /// the characters in the range starting at the specified `stringFirst`
2729 /// and ending right before the specified `stringLast` iterator, both of
2730 /// the (template parameter) type `INPUT_ITER`. Return a reference
2731 /// providing modifiable access to this string.
2732 ///
2733 /// \pre The behavior is undefined unless `first` and `last` are both within the range
2734 /// `[cbegin() .. cend()]`, `first <= last`, and `stringFirst` and
2735 /// `stringLast` refer to a sequence of valid values where `stringFirst` is
2736 /// at a position at or before `stringLast`.
2737 template <class INPUT_ITER>
2739 const_iterator last,
2740 INPUT_ITER stringFirst,
2741 INPUT_ITER stringLast);
2742
2743 /// Replace the substring in the range starting at the specified `first`
2744 /// position and ending right before the specified `last` position with
2745 /// the characters from the specified `range`. Return a reference providing modifiable access to this string.
2746 ///
2747 /// \pre The behavior is undefined unless
2748 /// `first` and `last` are both within the range `[cbegin() .. cend()]`.
2749 ///
2750 /// \note Note that `range` must meet the requirements of an input range and the
2751 /// values from `range` must have a type matching or convertible to
2752 /// template parameter) `CHAR_TYPE`.
2753 template <class RANGE>
2755 basic_string& replace_with_range(
2756 const_iterator first,
2757 const_iterator last,
2759
2760 // *** 21.3.7 string operations: ***
2761
2762 /// Return an address providing modifiable access to the null-terminated
2763 /// buffer of `length() + 1` characters whose contents are identical to the value of this string.
2764 ///
2765 /// \note Note that any call to the string
2766 /// destructor or any of its manipulators invalidates the returned
2767 /// pointer.
2768 CHAR_TYPE *data() BSLS_KEYWORD_NOEXCEPT;
2769
2770 /// Exchange the value of this object with that of the specified `other`
2771 /// object; also exchange the allocator of this object with that of
2772 /// `other` if the (template parameter) type `ALLOCATOR` has the
2773 /// @ref propagate_on_container_swap trait, and do not modify either
2774 /// allocator otherwise. This method provides the no-throw
2775 /// exception-safety guarantee. This operation has `O[1]` complexity if
2776 /// either this object was created with the same allocator as `other` or
2777 /// `ALLOCATOR` has the @ref propagate_on_container_swap trait; otherwise,
2778 /// it has `O[n + m]` complexity, where `n` and `m` are the lengths of this object and `other`, respectively.
2779 ///
2780 /// \note Note that this method`s
2781 /// support for swapping objects created with different allocators when
2782 /// `ALLOCATOR` does not have the @ref propagate_on_container_swap trait is
2783 /// a departure from the C++ Standard.
2785 AllocatorTraits::propagate_on_container_swap::value ||
2786 AllocatorTraits::is_always_equal::value);
2787
2788 // ACCESSORS
2789
2790 // *** 21.3.3 iterators: ***
2791
2793
2794 /// Return an iterator providing non-modifiable access to the first
2795 /// character of this string (or the past-the-end iterator if this
2796 /// string is empty).
2798
2800
2801 /// Return the past-the-end iterator for this string.
2803
2805
2806 /// Return a reverse iterator providing non-modifiable access to the
2807 /// last character of this string (or the past-the-end reverse iterator
2808 /// if this string is empty).
2810
2812
2813 /// Return the past-the-end reverse iterator for this string.
2815
2816 // *** 21.3.4 capacity: ***
2817
2818 /// Return the length of this string.
2819 /// \note Note that this number may differ
2820 /// from `CHAR_TRAITS::length(c_str())` in case the string contains null
2821 /// characters. Also note that a null-terminating character added by
2822 /// the `c_str` method is *not* counted in this length.
2824
2825 /// Return the length of this string.
2826 /// \note Note that this number may differ
2827 /// from `CHAR_TRAITS::length(c_str())` in case the string contains null
2828 /// characters. Also note that a null-terminating character added by
2829 /// the `c_str` method is *not* counted in this length.
2831
2832 /// Return the maximal possible length of this string.
2833 ///
2834 /// \note Note that requests to create a string longer than this number of characters
2835 /// are guaranteed to raise a `length_error` exception.
2837
2838 /// Return the capacity of this string, i.e., the maximum length for
2839 /// which resizing is guaranteed not to trigger a reallocation.
2841
2842 /// Return `true` if this string has length 0, and `false` otherwise.
2843 bool empty() const BSLS_KEYWORD_NOEXCEPT;
2844
2845 // *** 21.3.5 element access: ***
2846
2847 /// Return a reference providing non-modifiable access to the character
2848 /// at the specified `position` in this string.
2849 ///
2850 /// \pre The behavior is undefined unless `position <= length()`.
2851 /// \note Note that if
2852 /// `position == length()`, a reference to the null-terminating
2853 /// character is returned.
2854 const_reference operator[](size_type position) const;
2855
2856 /// Return a reference providing non-modifiable access to the character
2857 /// at the specified `position` in this string. Throw @ref out_of_range if
2858 /// `position >= length()`.
2859 const_reference at(size_type position) const;
2860
2861 /// Return a reference providing non-modifiable access to the character at the first position in this string.
2862 ///
2863 /// \pre The behavior is undefined if
2864 /// this string is empty.
2865 const CHAR_TYPE& front() const;
2866
2867 /// Return a reference providing non-modifiable access to the character at the last position in this string.
2868 ///
2869 /// \pre The behavior is undefined if this string is empty.
2870 ///
2871 /// \note Note that the last position is
2872 /// `length() - 1`.
2873 const CHAR_TYPE& back() const;
2874
2875 /// Copy from this string, starting from the optionally specified
2876 /// `position`, the specified `numChars` or `length() - position`
2877 /// characters, whichever is smaller, into the specified
2878 /// `characterString` buffer, and return the number of characters
2879 /// copied. If `position` is not specified, 0 is used. Throw
2880 /// @ref out_of_range if `position > length()`.
2881 ///
2882 /// \pre The behavior is undefined unless `characterString` is at least `numChars` long.
2883 /// \note Note that the
2884 /// output `characterString` is *not* null-terminated.
2885 size_type copy(CHAR_TYPE *characterString,
2886 size_type numChars,
2887 size_type position = 0) const;
2888
2889 // *** 21.3.7 string operations: ***
2890
2891 /// Return an address providing non-modifiable access to the
2892 /// null-terminated buffer of `length() + 1` characters whose contents are identical to the value of this string.
2893 ///
2894 /// \note Note that any call to
2895 /// the string destructor or any of its manipulators invalidates the
2896 /// returned pointer.
2897 const CHAR_TYPE *c_str() const BSLS_KEYWORD_NOEXCEPT;
2898
2899 /// Return an address providing non-modifiable access to the
2900 /// null-terminated buffer of `length() + 1` characters whose contents are identical to the value of this string.
2901 ///
2902 /// \note Note that any call to
2903 /// the string destructor or any of its manipulators invalidates the
2904 /// returned pointer.
2905 const CHAR_TYPE *data() const BSLS_KEYWORD_NOEXCEPT;
2906
2907 /// Return the allocator used by this string to supply memory.
2909
2910 /// Return the starting position of the *first* occurrence of the
2911 /// specified `substring`, if such a substring can be found in this
2912 /// string (on or *after* the optionally specified `position` if such a
2913 /// `position` is specified) using `CHAR_TRAITS::eq` to compare
2914 /// characters, and return `npos` otherwise.
2915 size_type find(const basic_string& substring,
2916 size_type position = 0) const
2918
2919 /// Return the starting position of the *first* occurrence of the
2920 /// specified `substring`, if such a substring can be found in this
2921 /// string (on or *after* the optionally specified `position` if such a
2922 /// `position` is specified) using `CHAR_TRAITS::eq` to compare
2923 /// characters, and return `npos` otherwise.
2924 ///
2925 /// \pre The behavior is undefined unless the conversion from `STRING_VIEW_LIKE_TYPE` to
2926 /// `bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS>` does not throw any exception.
2927 ///
2928 /// \note Note that this behavior differs from the behavior
2929 /// implemented in the standard container, where the following noexcept
2930 /// specification is used:
2931 /// @code
2932 /// noexcept(
2933 /// std::is_nothrow_convertible_v<const T&,
2934 /// std::basic_string_view<CharT,
2935 /// Traits> >)
2936 /// @endcode
2937 template <class STRING_VIEW_LIKE_TYPE>
2939 const STRING_VIEW_LIKE_TYPE& substring,
2940 size_type position = 0,
2943
2944 /// Return the starting position of the *first* occurrence of the
2945 /// specified `substring` of the optionally specified `numChars` length,
2946 /// if such a substring can be found in this string (on or *after* the
2947 /// optionally specified `position` if such a `position` is specified)
2948 /// using `CHAR_TRAITS::eq` to compare characters, and return `npos`
2949 /// otherwise. If `numChars` is not specified,
2950 /// `CHAR_TRAITS::length(substring)` is used.
2951 size_type find(const CHAR_TYPE *substring,
2952 size_type position,
2953 size_type numChars) const;
2954 size_type find(const CHAR_TYPE *substring,
2955 size_type position = 0) const;
2956
2957 /// Return the position of the *first* occurrence of the specified
2958 /// `character`, if such an occurrence can be found in this string (on
2959 /// or *after* the optionally specified `position` if such a `position`
2960 /// is specified), and return `npos` otherwise.
2961 size_type find(CHAR_TYPE character, size_type position = 0) const;
2962
2963 /// Return the starting position of the *last* occurrence of the
2964 /// specified `substring` within this string, if such a sequence can be
2965 /// found in this string (on or *before* the optionally specified
2966 /// `position` if such a `position` is specified) using
2967 /// `CHAR_TRAITS::eq` to compare characters, and return `npos`
2968 /// otherwise.
2969 size_type rfind(const basic_string& substring,
2970 size_type position = npos) const
2972
2973 /// Return the starting position of the *last* occurrence of the
2974 /// specified `substring` within this string, if such a sequence can be
2975 /// found in this string (on or *before* the optionally specified
2976 /// `position` if such a `position` is specified) using
2977 /// `CHAR_TRAITS::eq` to compare characters, and return `npos` otherwise.
2978 ///
2979 /// \pre The behavior is undefined unless the conversion from
2980 /// `STRING_VIEW_LIKE_TYPE` to
2981 /// `bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS>` does not throw any exception.
2982 ///
2983 /// \note Note that this behavior differs from the behavior
2984 /// implemented in the standard container, where the following noexcept
2985 /// specification is used:
2986 /// @code
2987 /// noexcept(
2988 /// std::is_nothrow_convertible_v<const T&,
2989 /// std::basic_string_view<CharT,
2990 /// Traits> >)
2991 /// @endcode
2992 template <class STRING_VIEW_LIKE_TYPE>
2994 const STRING_VIEW_LIKE_TYPE& substring,
2995 size_type position = npos,
2998
2999 /// Return the starting position of the *last* occurrence of a substring
3000 /// whose value equals that of the specified `characterString` of the
3001 /// optionally specified `numChars` length, if such a substring can be
3002 /// found in this string (on or *before* the optionally specified
3003 /// `position` if such a `position` is specified), and return `npos`
3004 /// otherwise. If `numChars` is not specified,
3005 /// `CHAR_TRAITS::length(characterString)` is used.
3006 size_type rfind(const CHAR_TYPE *characterString,
3007 size_type position,
3008 size_type numChars) const;
3009 size_type rfind(const CHAR_TYPE *characterString,
3010 size_type position = npos) const;
3011
3012 /// Return the position of the *last* occurrence of the specified
3013 /// `character`, if such an occurrence can be found in this string (on
3014 /// or *before* the optionally specified `position` if such a `position`
3015 /// is specified), and return `npos` otherwise.
3016 size_type rfind(CHAR_TYPE character, size_type position = npos) const;
3017
3018 /// Return the position of the *first* occurrence of a character
3019 /// belonging to the specified `characterString`, if such an occurrence
3020 /// can be found in this string (on or *after* the optionally specified
3021 /// `position` if such a `position` is specified), and return `npos`
3022 /// otherwise.
3023 size_type find_first_of(const basic_string& characterString,
3024 size_type position = 0) const
3026
3027 /// Return the position of the *first* occurrence of a character
3028 /// belonging to the specified `characterString`, if such an occurrence
3029 /// can be found in this string (on or *after* the optionally specified
3030 /// `position` if such a `position` is specified), and return `npos` otherwise.
3031 ///
3032 /// \pre The behavior is undefined unless the conversion from
3033 /// `STRING_VIEW_LIKE_TYPE` to
3034 /// `bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS>` does not throw any exception.
3035 ///
3036 /// \note Note that this behavior differs from the behavior
3037 /// implemented in the standard container, where the following noexcept
3038 /// specification is used:
3039 /// @code
3040 /// noexcept(
3041 /// std::is_nothrow_convertible_v<const T&,
3042 /// std::basic_string_view<CharT,
3043 /// Traits> >)
3044 /// @endcode
3045 template <class STRING_VIEW_LIKE_TYPE>
3046 size_type find_first_of(
3047 const STRING_VIEW_LIKE_TYPE& characterString,
3048 size_type position = 0,
3051
3052 /// Return the position of the *first* occurrence of a character
3053 /// belonging to the specified `characterString` of the optionally
3054 /// specified `numChars` length, if such an occurrence can be found in
3055 /// this string (on or *after* the optionally specified `position` if
3056 /// such a `position` is specified), and return `npos` otherwise. If
3057 /// `numChars` is not specified, `CHAR_TRAITS::length(characterString)`
3058 /// is used.
3059 size_type find_first_of(const CHAR_TYPE *characterString,
3060 size_type position,
3061 size_type numChars) const;
3062 size_type find_first_of(const CHAR_TYPE *characterString,
3063 size_type position = 0) const;
3064
3065 /// Return the position of the *first* occurrence of the specified
3066 /// `character`, if such an occurrence can be found in this string (on
3067 /// or *after* the optionally specified `position` if such a `position`
3068 /// is specified), and return `npos` otherwise.
3069 size_type find_first_of(CHAR_TYPE character,
3070 size_type position = 0) const;
3071
3072 /// Return the position of the *last* occurrence of a character
3073 /// belonging to the specified `characterString`, if such an occurrence
3074 /// can be found in this string (on or *before* the optionally specified
3075 /// `position` if such a `position` is specified), and return `npos`
3076 /// otherwise.
3077 size_type find_last_of(const basic_string& characterString,
3078 size_type position = npos) const
3080
3081 /// Return the position of the *last* occurrence of a character
3082 /// belonging to the specified `characterString`, if such an occurrence
3083 /// can be found in this string (on or *before* the optionally specified
3084 /// `position` if such a `position` is specified), and return `npos` otherwise.
3085 ///
3086 /// \pre The behavior is undefined unless the conversion from
3087 /// `STRING_VIEW_LIKE_TYPE` to
3088 /// `bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS>` does not throw any exception.
3089 ///
3090 /// \note Note that this behavior differs from the behavior
3091 /// implemented in the standard container, where the following noexcept
3092 /// specification is used:
3093 /// @code
3094 /// noexcept(
3095 /// std::is_nothrow_convertible_v<const T&,
3096 /// std::basic_string_view<CharT,
3097 /// Traits> >)
3098 /// @endcode
3099 template <class STRING_VIEW_LIKE_TYPE>
3100 size_type find_last_of(
3101 const STRING_VIEW_LIKE_TYPE& characterString,
3102 size_type position = npos,
3105
3106 /// Return the position of the *last* occurrence of a character
3107 /// belonging to the specified `characterString` of the optionally
3108 /// specified `numChars` length, if such an occurrence can be found in
3109 /// this string (on or *before* the optionally specified `position` if
3110 /// such a `position` is specified), and return `npos` otherwise. If
3111 /// `numChars` is not specified, `CHAR_TRAITS::length(characterString)`
3112 /// is used.
3113 size_type find_last_of(const CHAR_TYPE *characterString,
3114 size_type position,
3115 size_type numChars) const;
3116 size_type find_last_of(const CHAR_TYPE *characterString,
3117 size_type position = npos) const;
3118
3119 /// Return the position of the *last* occurrence of the specified
3120 /// `character`, if such an occurrence can be found in this string (on
3121 /// or *before* the optionally specified `position` if such a `position`
3122 /// is specified), and return `npos` otherwise.
3123 size_type find_last_of(CHAR_TYPE character,
3124 size_type position = npos) const;
3125
3126 /// Return the position of the *first* occurrence of a character *not*
3127 /// belonging to the specified `characterString`, if such an occurrence
3128 /// can be found in this string (on or *after* the optionally specified
3129 /// `position` if such a `position` is specified), and return `npos`
3130 /// otherwise.
3131 size_type find_first_not_of(const basic_string& characterString,
3132 size_type position = 0) const
3134
3135 /// Return the position of the *first* occurrence of a character *not*
3136 /// belonging to the specified `characterString`, if such an occurrence
3137 /// can be found in this string (on or *after* the optionally specified
3138 /// `position` if such a `position` is specified), and return `npos` otherwise.
3139 ///
3140 /// \pre The behavior is undefined unless the conversion from
3141 /// `STRING_VIEW_LIKE_TYPE` to
3142 /// `bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS>` does not throw any exception.
3143 ///
3144 /// \note Note that this behavior differs from the behavior
3145 /// implemented in the standard container, where the following noexcept
3146 /// specification is used:
3147 /// @code
3148 /// noexcept(
3149 /// std::is_nothrow_convertible_v<const T&,
3150 /// std::basic_string_view<CharT,
3151 /// Traits> >)
3152 /// @endcode
3153 template <class STRING_VIEW_LIKE_TYPE>
3154 size_type find_first_not_of(
3155 const STRING_VIEW_LIKE_TYPE& characterString,
3156 size_type position = 0,
3159
3160 /// Return the position of the *first* occurrence of a character *not*
3161 /// belonging to the specified `characterString` of the optionally
3162 /// specified `numChars` length, if such an occurrence can be found in
3163 /// this string (on or *after* the optionally specified `position` if
3164 /// such a `position` is specified), and return `npos` otherwise. If
3165 /// `numChars` is not specified, `CHAR_TRAITS::length(characterString)`
3166 /// is used.
3167 size_type find_first_not_of(const CHAR_TYPE *characterString,
3168 size_type position,
3169 size_type numChars) const;
3170 size_type find_first_not_of(const CHAR_TYPE *characterString,
3171 size_type position = 0) const;
3172
3173 /// Return the position of the *first* occurrence of a character
3174 /// *different* from the specified `character`, if such an occurrence
3175 /// can be found in this string (on or *after* the optionally specified
3176 /// `position` if such a `position` is specified), and return `npos`
3177 /// otherwise.
3178 size_type find_first_not_of(CHAR_TYPE character,
3179 size_type position = 0) const;
3180
3181 /// Return the position of the *last* occurrence of a character *not*
3182 /// belonging to the specified `characterString`, if such an occurrence
3183 /// can be found in this string (on or *before* the optionally specified
3184 /// `position` if such a `position` is specified), and return `npos`
3185 /// otherwise.
3186 size_type find_last_not_of(const basic_string& characterString,
3187 size_type position = npos) const
3189
3190 /// Return the position of the *last* occurrence of a character *not*
3191 /// belonging to the specified `characterString`, if such an occurrence
3192 /// can be found in this string (on or *before* the optionally specified
3193 /// `position` if such a `position` is specified), and return `npos` otherwise.
3194 ///
3195 /// \pre The behavior is undefined unless the conversion from
3196 /// `STRING_VIEW_LIKE_TYPE` to
3197 /// `bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS>` does not throw any exception.
3198 ///
3199 /// \note Note that this behavior differs from the behavior
3200 /// implemented in the standard container, where the following noexcept
3201 /// specification is used:
3202 /// @code
3203 /// noexcept(
3204 /// std::is_nothrow_convertible_v<const T&,
3205 /// std::basic_string_view<CharT,
3206 /// Traits> >)
3207 /// @endcode
3208 template <class STRING_VIEW_LIKE_TYPE>
3209 size_type find_last_not_of(
3210 const STRING_VIEW_LIKE_TYPE& characterString,
3211 size_type position = npos,
3214
3215 /// Return the position of the *last* occurrence of a character *not*
3216 /// belonging to the specified `characterString` of the optionally
3217 /// specified `numChars` length, if such an occurrence can be found in
3218 /// this string (on or *before* the optionally specified `position` if
3219 /// such a `position` is specified), and return `npos` otherwise. If
3220 /// `numChars` is not specified, `CHAR_TRAITS::length(characterString)`
3221 /// is used.
3222 size_type find_last_not_of(const CHAR_TYPE *characterString,
3223 size_type position,
3224 size_type numChars) const;
3225 size_type find_last_not_of(const CHAR_TYPE *characterString,
3226 size_type position = npos) const;
3227
3228 /// Return the position of the *last* occurrence of a character
3229 /// *different* from the specified `character`, if such an occurrence
3230 /// can be found in this string (on or *before* the optionally specified
3231 /// `position` if such a `position` is specified), and return `npos`
3232 /// otherwise.
3233 size_type find_last_not_of(CHAR_TYPE character,
3234 size_type position = npos) const;
3235
3236 /// Return `true` if this view contains with the specified `subview`, and
3237 /// `false` otherwise. See {Lexicographical Comparisons}.
3238 bool contains(basic_string_view<CHAR_TYPE, CHAR_TRAITS> subview)
3240
3241 /// Return `true` if this view contains with the specified `character`,
3242 /// and `false` otherwise.
3243 bool contains(CHAR_TYPE character) const BSLS_KEYWORD_NOEXCEPT;
3244
3245 /// Return `true` if this view contains with the specified
3246 /// `characterString`, and `false` otherwise.
3247 bool contains(const CHAR_TYPE* characterString) const;
3248
3249 /// Return `true` if the length of this string is equal to or greater
3250 /// than the length of the specified `characterString` and the first
3251 /// `characterString.length()` characters of this string are equal to
3252 /// the characters of the `characterString`, and `false` otherwise.
3253 /// `CHAR_TRAITS::compare` is used to compare characters. See
3254 /// {Lexicographical Comparisons}.
3255 bool starts_with(basic_string_view<CHAR_TYPE, CHAR_TRAITS> characterString)
3257
3258 /// Return `true` if this string contains at least one symbol and the
3259 /// last symbol of this string is equal to the specified `character`,
3260 /// and `false` otherwise. `CHAR_TRAITS::eq` is used to compare
3261 /// characters. See {Lexicographical Comparisons}.
3262 bool starts_with(CHAR_TYPE character) const BSLS_KEYWORD_NOEXCEPT;
3263
3264 /// Return `true` if the length of this string is equal to or greater
3265 /// than the length of the specified `characterString` and the first
3266 /// `CHAR_TRAITS::length(characterString)` characters of this string are
3267 /// equal to the characters of the `characterString`, and `false`
3268 /// otherwise. `CHAR_TRAITS::compare` is used to compare characters.
3269 /// See {Lexicographical Comparisons}.
3270 bool starts_with(const CHAR_TYPE *characterString) const;
3271
3272 /// Return `true` if the length of this string is equal to or greater
3273 /// than the length of the specified `characterString` and the last
3274 /// `characterString.length()` characters of this string are equal to
3275 /// the characters of the `characterString`, and `false` otherwise.
3276 /// `CHAR_TRAITS::compare` is used to compare characters. See
3277 /// {Lexicographical Comparisons}.
3278 bool ends_with(basic_string_view<CHAR_TYPE, CHAR_TRAITS> characterString)
3280
3281 /// Return `true` if this string contains at least one symbol and the
3282 /// last symbol of this string is equal to the specified `character`,
3283 /// and `false` otherwise. `CHAR_TRAITS::eq` is used to compare
3284 /// characters. See {Lexicographical Comparisons}.
3285 bool ends_with(CHAR_TYPE character) const BSLS_KEYWORD_NOEXCEPT;
3286
3287 /// Return `true` if the length of this string is equal to or greater
3288 /// than the length of the specified `characterString` and the last
3289 /// `CHAR_TRAITS::length(characterString)` characters of this string are
3290 /// equal to the characters of the `characterString`, and `false`
3291 /// otherwise. `CHAR_TRAITS::compare` is used to compare characters.
3292 /// See {Lexicographical Comparisons}.
3293 bool ends_with(const CHAR_TYPE *characterString) const;
3294
3295 /// Return a string whose value is the substring starting at the
3296 /// optionally specified `position` in this string, of length the
3297 /// optionally specified `numChars` or `length() - position`, whichever
3298 /// is smaller. If `position` is not specified, 0 is used (i.e., the
3299 /// substring is from the beginning of this string). If `numChars` is
3300 /// not specified, `npos` is used (i.e., the entire suffix from
3301 /// `position` to the end of the string is returned).
3302#ifdef BSLS_COMPILERFEATURES_SUPPORT_REF_QUALIFIERS
3303 basic_string substr(size_type position = 0,
3304 size_type numChars = npos) const &;
3305 basic_string substr(size_type position = 0,
3306 size_type numChars = npos) &&;
3307#else
3309 size_type numChars = npos) const;
3310#endif
3311
3312 /// Lexicographically compare this string with the specified `other`
3313 /// string, and return a negative value if this string is less than
3314 /// `other`, a positive value if it is greater than `other`, and 0 in
3315 /// case of equality. `CHAR_TRAITS::lt` is used to compare characters.
3316 /// See {Lexicographical Comparisons}.
3318
3319 /// Lexicographically compare the substring of this string of the
3320 /// specified `numChars` length starting at the specified `position` (or
3321 /// the suffix of this string starting at `position` if
3322 /// `position + numChars > length()`) with the specified `other` string,
3323 /// and return a negative value if the indicated substring of this
3324 /// string is less than `other`, a positive value if it is greater than
3325 /// `other`, and 0 in case of equality. `CHAR_TRAITS::lt` is used to
3326 /// compare characters. See {Lexicographical Comparisons}. Throw
3327 /// @ref out_of_range if `position > length()`.
3328 int compare(size_type position,
3329 size_type numChars,
3330 const basic_string& other) const;
3331
3332 /// Lexicographically compare the substring of this string of the
3333 /// specified `lhsNumChars` length starting at the specified
3334 /// `lhsPosition` (or the suffix of this string starting at
3335 /// `lhsPosition` if `lhsPosition + lhsNumChars > length()`) with the
3336 /// substring of the specified `other` string of the optionally
3337 /// specified `otherNumChars` length starting at the specified
3338 /// `otherPosition` (or the suffix of `other` starting at
3339 /// `otherPosition` if
3340 /// `otherPosition + otherNumChars > other.length()`). If `numChars` is
3341 /// not specified, `npos` is used. Return a negative value if the
3342 /// indicated substring of this string is less than the indicated
3343 /// substring of `other`, a positive value if it is greater than the
3344 /// indicated substring of `other`, and 0 in case of equality.
3345 /// `CHAR_TRAITS::lt` is used to compare characters. Throw
3346 /// @ref out_of_range if `lhsPosition > length()` or
3347 /// `otherPosition > other.length()`. See {Lexicographical
3348 /// Comparisons}.
3349 int compare(size_type lhsPosition,
3350 size_type lhsNumChars,
3351 const basic_string& other,
3352 size_type otherPosition,
3353 size_type otherNumChars = npos) const;
3354
3355 /// Lexicographically compare this string with the specified
3356 /// null-terminated `other` string (of length
3357 /// `CHAR_TRAITS::length(other)`), and return a negative value if this
3358 /// string is less than `other`, a positive value if it is greater than
3359 /// `other`, and 0 in case of equality. `CHAR_TRAITS::lt` is used to
3360 /// compare characters. See {Lexicographical Comparisons}.
3361 int compare(const CHAR_TYPE *other) const;
3362
3363 /// Lexicographically compare the substring of this string of the
3364 /// specified `lhsNumChars` length starting at the specified
3365 /// `lhsPosition` (or the suffix of this string starting at
3366 /// `lhsPosition` if `lhsPosition + lhsNumChars > length()`) with the
3367 /// specified `other` string of the specified `otherNumChars` length,
3368 /// and return a negative value if the indicated substring of this
3369 /// string is less than `other`, a positive value if it is greater than
3370 /// `other`, and 0 in case of equality. `CHAR_TRAITS::lt` is used to
3371 /// compare characters. Throw @ref out_of_range if
3372 /// `lhsPosition > length()`. See {Lexicographical Comparisons}.
3373 int compare(size_type lhsPosition,
3374 size_type lhsNumChars,
3375 const CHAR_TYPE *other,
3376 size_type otherNumChars) const;
3377
3378 /// Lexicographically compare the substring of this string of the
3379 /// specified `lhsNumChars` length starting at the specified
3380 /// `lhsPosition` (or the suffix of this string starting at
3381 /// `lhsPosition` if `lhsPosition + lhsNumChars > length()`) with the
3382 /// specified null-terminated `other` string (of length
3383 /// `CHAR_TRAITS::length(other)`), and return a negative value if the
3384 /// indicated substring of this string is less than `other`, a positive
3385 /// value if it is greater than `other`, and 0 in case of equality.
3386 /// `CHAR_TRAITS::lt` is used to compare characters. Throw
3387 /// @ref out_of_range if `lhsPosition > length()`. See {Lexicographical
3388 /// Comparisons}.
3389 int compare(size_type lhsPosition,
3390 size_type lhsNumChars,
3391 const CHAR_TYPE *other) const;
3392
3393 /// Lexicographically compare this string with the specified `other`,
3394 /// and return a negative value if this string is less than `other`, a
3395 /// positive value if it is greater than `other`, and 0 in case of
3396 /// equality. `CHAR_TRAITS::lt` is used to compare characters. See {Lexicographical Comparisons}.
3397 ///
3398 /// \pre The behavior is undefined unless the
3399 /// conversion from `STRING_VIEW_LIKE_TYPE` to
3400 /// `bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS>` does not throw any exception.
3401 ///
3402 /// \note Note that this behavior differs from the behavior
3403 /// implemented in the standard container, where the following noexcept
3404 /// specification is used:
3405 /// @code
3406 /// noexcept(
3407 /// std::is_nothrow_convertible_v<const T&,
3408 /// std::basic_string_view<CharT,
3409 /// Traits> >)
3410 /// @endcode
3411 template <class STRING_VIEW_LIKE_TYPE>
3413 const STRING_VIEW_LIKE_TYPE& other,
3416
3417 /// Lexicographically compare the substring of this string of the
3418 /// specified `numChars` length starting at the specified `position` (or
3419 /// the suffix of this string starting at `position` if
3420 /// `position + numChars > length()`) with the specified `other`, and
3421 /// return a negative value if the indicated substring of this string is
3422 /// less than `other`, a positive value if it is greater than `other`,
3423 /// and 0 in case of equality. `CHAR_TRAITS::lt` is used to compare
3424 /// characters. See {Lexicographical Comparisons}. Throw
3425 /// @ref out_of_range if `position > length()`.
3426 template <class STRING_VIEW_LIKE_TYPE>
3427 int compare(
3428 size_type position,
3429 size_type numChars,
3430 const STRING_VIEW_LIKE_TYPE& other,
3432
3433 /// Lexicographically compare the substring of this string of the
3434 /// specified `lhsNumChars` length starting at the specified
3435 /// `lhsPosition` (or the suffix of this string starting at
3436 /// `lhsPosition` if `lhsPosition + lhsNumChars > length()`) with the
3437 /// substring of the specified `other` of the optionally specified
3438 /// `otherNumChars` length starting at the specified `otherPosition` (or
3439 /// the suffix of `other` starting at `otherPosition` if
3440 /// `otherPosition + otherNumChars > other.length()`). If `numChars` is
3441 /// not specified, `npos` is used. Return a negative value if the
3442 /// indicated substring of this string is less than the indicated
3443 /// substring of `other`, a positive value if it is greater than the
3444 /// indicated substring of `other`, and 0 in case of equality.
3445 /// `CHAR_TRAITS::lt` is used to compare characters. See
3446 /// {Lexicographical Comparisons}. Throw @ref out_of_range if
3447 /// `lhsPosition > length()` or `otherPosition > other.length()`.
3448 template <class STRING_VIEW_LIKE_TYPE>
3449 int compare(
3450 size_type lhsPosition,
3451 size_type lhsNumChars,
3452 const STRING_VIEW_LIKE_TYPE& other,
3453 size_type otherPosition,
3454 size_type otherNumChars = npos,
3456
3457 // *** BDE compatibility with platform libraries: ***
3458
3459 /// Convert this object to a string type native to the compiler's
3460 /// library, instantiated with the same character type and traits type,
3461 /// but not necessarily the same allocator type. The return string will
3462 /// contain the same sequence of characters as `orig` and will have a default-constructed allocator.
3463 ///
3464 /// \note Note that this conversion operator
3465 /// can be invoked implicitly (e.g., during argument passing).
3466 template <class ALLOC2>
3467 operator std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>() const
3468 {
3469 // See {DRQS 131792157} for why this is inline.
3470 std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2> result;
3471 result.assign(data(), length());
3472 return result;
3473 }
3474
3475 /// Convert this object to a @ref string_view type instantiated with the
3476 /// same character type and traits type. The return view will contain the same sequence of characters as this object.
3477 ///
3478 /// \note Note that this
3479 /// conversion operator can be invoked implicitly (e.g., during argument
3480 /// passing).
3482
3483#ifdef BSLSTL_STRING_VIEW_AND_STD_STRING_VIEW_COEXIST
3484 /// Convert this object to a `std::basic_string_view`.
3485 operator std::basic_string_view<CHAR_TYPE, CHAR_TRAITS>() const;
3486#endif
3487};
3488
3489#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
3490// CLASS TEMPLATE DEDUCTION GUIDES
3491
3492/// Deduce the template parameters `CHAR_TYPE`, `TRAITS`, and `ALLOCATOR`
3493/// from the corresponding template parameters of the `bsl::basic_string`
3494/// passed to the constructor of @ref basic_string . This deduction guide does
3495/// not participate unless the specified `ALLOC` is convertible to
3496/// `ALLOCATOR`.
3497template <
3498 class CHAR_TYPE,
3499 class CHAR_TRAITS,
3500 class ALLOCATOR,
3501 class ALLOC,
3502 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC, ALLOCATOR>>
3503 >
3506
3507/// Deduce the template parameter `CHAR_TYPE` from the parameters passed to
3508/// the constructor of @ref basic_string . This deduction guide does not
3509/// participate unless the specified `ALLOC` is convertible to
3510/// `bsl::allocator<CHAR_TYPE>`.
3511template <
3512 class CHAR_TYPE,
3513 class ALLOC,
3514 class DEFAULT_ALLOCATOR = bsl::allocator<CHAR_TYPE>,
3515 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
3516 >
3517basic_string(const CHAR_TYPE *, ALLOC *)
3519
3520/// Deduce the template parameter `CHAR_TYPE` from the parameters passed to
3521/// the constructor of @ref basic_string . This deduction guide does not
3522/// participate unless the specified `ALLOC` is convertible to
3523/// `bsl::allocator<CHAR_TYPE>`.
3524template <
3525 class CHAR_TYPE,
3526 class ALLOC,
3527 class SZ,
3528 class DEFAULT_ALLOCATOR = bsl::allocator<CHAR_TYPE>,
3529 class = bsl::enable_if_t<
3530 bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>,
3531 class = bsl::enable_if_t<!bsl::is_pointer_v<SZ>>
3532 // this last check eliminates an ambiguity for the case
3533 // basic_string(const char *, const char *, Allocator *)
3534 >
3535basic_string(const CHAR_TYPE *, SZ, ALLOC *)
3537
3538/// Deduce the template parameter `CHAR_TYPE` from the parameters passed to
3539/// the constructor of @ref basic_string . This deduction guide does not
3540/// participate unless the specified `ALLOC` is convertible to
3541/// `bsl::allocator<CHAR_TYPE>`.
3542template <
3543 class CHAR_TYPE,
3544 class ALLOC,
3545 class DEFAULT_ALLOCATOR = bsl::allocator<CHAR_TYPE>,
3547 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
3548 >
3549basic_string(SZ, CHAR_TYPE, ALLOC *)
3551
3552/// Deduce the template parameters `CHAR_TYPE`, `TRAITS`, and `ALLOCATOR`
3553/// from the corresponding template parameters of the `bsl::basic_string`
3554/// passed to the constructor of @ref basic_string . This deduction guide does
3555/// not participate unless the specified `ALLOC` is convertible to
3556/// `ALLOCATOR`.
3557template <
3558 class CHAR_TYPE,
3559 class CHAR_TRAITS,
3560 class ALLOCATOR,
3561 class ALLOC,
3562 class SZ = typename allocator_traits<ALLOCATOR>::size_type,
3563 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, ALLOCATOR>>
3564 >
3567
3568/// Deduce the template parameter `CHAR_TYPE` from the `value_type` of the
3569/// iterators passed to passed to the constructor of @ref basic_string . Deduce
3570/// the template parameter `ALLOCATOR` from the optional argument passed to
3571/// the constructor. This deduction guide does not participate unless the
3572/// specified `ALLOCATOR` meets the requirements of a standard allocator.
3573template <
3574 class INPUT_ITER,
3575 class CHAR_TYPE =
3576 typename BloombergLP::bslstl::IteratorUtil::IterVal_t<INPUT_ITER>,
3577 class ALLOCATOR = bsl::allocator<CHAR_TYPE>,
3578 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
3579 >
3580basic_string(INPUT_ITER, INPUT_ITER, ALLOCATOR = ALLOCATOR())
3582
3583/// Deduce the template parameter `CHAR_TYPE` from the `value_type` of the
3584/// iterators passed to passed to the constructor of @ref basic_string . This
3585/// deduction guide does not participate unless the specified `ALLOC` is
3586/// convertible to `bsl::allocator<CHAR_TYPE>`.
3587template <
3588 class INPUT_ITER,
3589 class CHAR_TYPE =
3590 typename BloombergLP::bslstl::IteratorUtil::IterVal_t<INPUT_ITER>,
3591 class ALLOC,
3592 class DEFAULT_ALLOCATOR = bsl::allocator<CHAR_TYPE>,
3593 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
3594 >
3595basic_string(INPUT_ITER, INPUT_ITER, ALLOC *)
3597
3598/// Deduce the template parameters `CHAR_TYPE` and `TRAITS` from the
3599/// corresponding template parameters of the `bsl::basic_string_view` passed
3600/// to the constructor of @ref basic_string . Deduce the template parameter
3601/// `ALLOCATOR` from the optional argument passed to the constructor. This
3602/// deduction guide does not participate unless the specified `ALLOCATOR`
3603/// meets the requirements of a standard allocator.
3604template <
3605 class CHAR_TYPE,
3606 class CHAR_TRAITS,
3607 class ALLOCATOR = allocator<CHAR_TYPE>,
3608 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
3609 >
3611 ALLOCATOR = ALLOCATOR())
3613
3614/// Deduce the template parameters `CHAR_TYPE` and `TRAITS` from the
3615/// corresponding template parameters of the `bsl::basic_string_view` passed
3616/// to the constructor of @ref basic_string . This deduction guide does not
3617/// participate unless the specified `ALLOC` is convertible to
3618/// `bsl::allocator<CHAR_TYPE>`.
3619template <
3620 class CHAR_TYPE,
3621 class CHAR_TRAITS,
3622 class ALLOC,
3623 class DEFAULT_ALLOCATOR = bsl::allocator<CHAR_TYPE>,
3624 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
3625 >
3628
3629/// Deduce the template parameter `CHAR_TYPE` from the `value_type` of the
3630/// @ref initializer_list passed to the constructor of @ref basic_string . This
3631/// deduction guide does not participate unless the specified `ALLOC` is
3632/// convertible to `bsl::allocator<CHAR_TYPE>`.
3633template <
3634 class CHAR_TYPE,
3635 class ALLOC,
3636 class DEFAULT_ALLOCATOR = bsl::allocator<CHAR_TYPE>,
3637 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
3638 >
3639basic_string(std::initializer_list<CHAR_TYPE>, ALLOC *)
3641
3642#endif
3643
3644// FREE OPERATORS
3645template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3649template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3650bool
3652 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
3654
3655/// Return `true` if the specified `lhs` string has the same value as the
3656/// specified `rhs` string, and `false` otherwise. Two strings have the
3657/// same value if they have the same length, and the characters at each
3658/// respective position have the same value according to `CHAR_TRAITS::eq`.
3659template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3661 const CHAR_TYPE *rhs);
3662
3663#ifdef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
3664
3665template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3666String_ComparisonCategoryType<CHAR_TRAITS>
3670
3671/// Perform a lexicographic three-way comparison of the specified `lhs` and
3672/// the specified `rhs` strings by using `CHAR_TRAITS::eq` on each
3673/// character; return the result of that comparison.
3674template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3675String_ComparisonCategoryType<CHAR_TRAITS>
3677 const CHAR_TYPE *rhs);
3678template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3679String_ComparisonCategoryType<CHAR_TRAITS>
3681 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
3683
3684#else
3685
3686/// Return `true` if the specified `lhs` string has the same value as the
3687/// specified `rhs` string, and `false` otherwise. Two strings have the
3688/// same value if they have the same length, and the characters at each
3689/// respective position have the same value according to `CHAR_TRAITS::eq`.
3690template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3691bool
3692operator==(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3695template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3696bool operator==(const CHAR_TYPE *lhs,
3698
3699/// Return `true` if the specified `lhs` string has a different value from
3700/// the specified `rhs` string, and `false` otherwise. Two strings have the
3701/// same value if they have the same length, and the characters at each
3702/// respective position have the same value according to `CHAR_TRAITS::eq`.
3703template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3707template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3708bool
3709operator!=(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3712template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3713bool
3715 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
3717
3718template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3719bool operator!=(const CHAR_TYPE *lhs,
3721template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3723 const CHAR_TYPE *rhs);
3724
3725/// Return `true` if the specified `lhs` string has a lexicographically
3726/// smaller value than the specified `rhs` string, and `false` otherwise.
3727/// See {Lexicographical Comparisons}.
3728template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3732template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3733bool
3734operator<(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3737template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3738bool
3740 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
3742template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3743
3744bool operator<(const CHAR_TYPE *lhs,
3746template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3748 const CHAR_TYPE *rhs);
3749
3750template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3754template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3755bool
3756operator>(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3759template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3760bool
3762 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
3764
3765/// Return `true` if the specified `lhs` string has a lexicographically
3766/// larger value than the specified `rhs` string, and `false` otherwise.
3767/// See {Lexicographical Comparisons}.
3768template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3769bool operator>(const CHAR_TYPE *lhs,
3771template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3773 const CHAR_TYPE *rhs);
3774
3775/// Return `true` if the specified `lhs` string has a value
3776/// lexicographically smaller than or equal to the specified `rhs`
3777/// string, and `false` otherwise. See {Lexicographical Comparisons}.
3778template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3782template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3783bool
3784operator<=(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3787template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3788bool
3790 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
3792
3793template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3794bool operator<=(const CHAR_TYPE *lhs,
3796template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3798 const CHAR_TYPE *rhs);
3799
3800/// Return `true` if the specified `lhs` string has a value
3801/// lexicographically larger than or equal to the specified `rhs` string,
3802/// and `false` otherwise. See {Lexicographical Comparisons}.
3803template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3807template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3808bool
3809operator>=(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3812template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3813bool
3815 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
3817
3818template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3819bool operator>=(const CHAR_TYPE *lhs,
3821template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3823 const CHAR_TYPE *rhs);
3824#endif
3825
3826/// Return the concatenation of strings constructed from the specified `lhs`
3827/// and `rhs` arguments, i.e., `basic_string(lhs).append(rhs)`. The
3828/// allocator of the returned string is determined per the rules in P1165
3829/// (https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1165r1.html).
3830///
3831/// \note Note that overloads that accept rvalue references are implemented for
3832/// C++11 and later only.
3833template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3837#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3838template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3842template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3846template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3850#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3851template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3853operator+(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3855#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3856template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3858operator+(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3860#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3861template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3864 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs);
3865#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3866template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3869 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs);
3870#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3871template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3873operator+(const CHAR_TYPE *lhs,
3875#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3876template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3878operator+(const CHAR_TYPE *lhs,
3880#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3881template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3883operator+(CHAR_TYPE lhs,
3885#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3886template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3888operator+(CHAR_TYPE lhs,
3890#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3891template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3894 const CHAR_TYPE *rhs);
3895#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3896template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3899 const CHAR_TYPE *rhs);
3900#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3901template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3904 CHAR_TYPE rhs);
3905#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3906template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3909 CHAR_TYPE rhs);
3910#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3911template <class CHAR_TYPE,
3912 class CHAR_TRAITS,
3913 class ALLOCATOR,
3914 class STRING_VIEW_LIKE_TYPE>
3917operator+(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR> & lhs,
3918 const STRING_VIEW_LIKE_TYPE & rhs);
3919#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3920template <class CHAR_TYPE,
3921 class CHAR_TRAITS,
3922 class ALLOCATOR,
3923 class STRING_VIEW_LIKE_TYPE>
3927 const STRING_VIEW_LIKE_TYPE & rhs);
3928#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3929template <class CHAR_TYPE,
3930 class CHAR_TRAITS,
3931 class ALLOCATOR,
3932 class STRING_VIEW_LIKE_TYPE>
3935operator+(const STRING_VIEW_LIKE_TYPE & lhs,
3937#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3938template <class CHAR_TYPE,
3939 class CHAR_TRAITS,
3940 class ALLOCATOR,
3941 class STRING_VIEW_LIKE_TYPE>
3944operator+(const STRING_VIEW_LIKE_TYPE & lhs,
3946#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3947
3948/// Write the string specified by `str` into the output stream specified by
3949/// `os`, and return `os`. If the string is shorter than `os.width()`, then
3950/// it is padded to `os.width()` with the current `os.fill()` character.
3951/// The padding, if any, is output after the string (on the right) if
3952/// `os.flags() | ios::left` is non-zero and before the string otherwise.
3953/// This function will do nothing unless `os.good()` is true on entry.
3954template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3955std::basic_ostream<CHAR_TYPE, CHAR_TRAITS>&
3956operator<<(std::basic_ostream<CHAR_TYPE, CHAR_TRAITS>& os,
3958
3959/// Replace the contents of the specified `str` string with a word read from
3960/// the specified `is` input stream, and return `is`. The word begins at
3961/// the first non-whitespace character on the input stream and ends when
3962/// another whitespace character (or eof) is found. The trailing whitespace
3963/// character is left on the input stream. If `is.good()` is not true on
3964/// entry or if eof is found before any non-whitespace characters, then
3965/// `str` is unchanged and `is.fail()` is becomes true. If eof is detected
3966/// after some characters have been read into `str`, then `is.eof()` becomes
3967/// true, but `is.fail()` does not.
3968template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3969std::basic_istream<CHAR_TYPE, CHAR_TRAITS>&
3970operator>>(std::basic_istream<CHAR_TYPE, CHAR_TRAITS>& is,
3972
3973#if defined (BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY) && \
3974 defined (BSLS_COMPILERFEATURES_SUPPORT_INLINE_NAMESPACE)
3975inline namespace literals {
3976inline namespace string_literals {
3977/// Convert a character sequence of the specified `length` excluding the
3978/// terminating null character starting at the beginning of the specified
3979/// `characterString` to a string object of the indicated return type. Use
3980/// the `bslma::Default::defaultAllocator()` to supply memory. (See the
3981/// "User-Defined Literals" section in the component-level documentation.)
3982///
3983/// Example:
3984/// @code
3985/// using namespace bsl::string_literals;
3986/// bsl::string str1 = "123\0abc";
3987/// bsl::string str2 = "123\0abc"_s;
3988/// assert(3 == str1.size());
3989/// assert(7 == str2.size());
3990///
3991/// bsl::wstring str3 = L"123\0abc"_s;
3992/// assert(7 == str3.size());
3993/// @endcode
3994 string operator ""_s(const char *characterString, std::size_t length);
3995wstring operator ""_s(const wchar_t *characterString, std::size_t length);
3996
3997#if !defined(BSLS_PLATFORM_OS_SOLARIS) || \
3998 (defined(BSLS_PLATFORM_CMP_GNU) && BSLS_PLATFORM_CMP_VERSION >= 80000)
3999/// Convert a character sequence of the specified `length` excluding the
4000/// terminating null character starting at the beginning of the specified
4001/// `characterString` to a string object of the indicated return type. Use
4002/// the `bslma::Default::globalAllocator()` to supply memory. (See the
4003/// "Memory Allocation For a File-Scope Strings" section in the
4004/// component-level documentation.)
4005///
4006/// Example:
4007/// @code
4008/// using namespace bsl::string_literals;
4009/// static const bsl::string g_str1 = "123\0abc"_S;
4010/// static const bsl::wstring g_str2 = L"123\0abc"_S;
4011/// @endcode
4012 string operator ""_S(const char *characterString, std::size_t length);
4013wstring operator ""_S(const wchar_t *characterString, std::size_t length);
4014#endif
4015}
4016}
4017
4018#endif // BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY &&
4019 // BSLS_COMPILERFEATURES_SUPPORT_INLINE_NAMESPACE
4020
4021// FREE FUNCTIONS
4022
4023/// Exchange the value of the specified `a` object with that of the
4024/// specified `b` object; also exchange the allocator of `a` with that of
4025/// `b` if the (template parameter) type `ALLOCATOR` has the
4026/// @ref propagate_on_container_swap trait, and do not modify either allocator
4027/// otherwise. This function provides the no-throw exception-safety
4028/// guarantee. This operation has `O[1]` complexity if either `a` was
4029/// created with the same allocator as `b` or `ALLOCATOR` has the
4030/// @ref propagate_on_container_swap trait; otherwise, it has `O[n + m]`
4031/// complexity, where `n` and `m` are the lengths of `a` and `b`, respectively.
4032///
4033/// \note Note that this function`s support for swapping objects
4034/// created with different allocators when `ALLOCATOR` does not have the
4035/// @ref propagate_on_container_swap trait is a departure from the C++
4036/// Standard.
4037template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4042
4043/// Replace the contents of the specified `str` string by extracting
4044/// characters from the specified `is` stream until the specified `delim`
4045/// character is extracted, and return `is`. The `delim` character is
4046/// removed from the input stream but is not appended to `str`. If an `eof`
4047/// is detected before `delim`, then the characters up to the `eof` are put
4048/// into `str` and `is.eof()` becomes true. If `is.good()` is false on
4049/// entry, then do nothing, otherwise if no characters are extracted (e.g.,
4050/// because because the stream is at eof), `str` will become empty and
4051/// `is.fail()` will become true.
4052template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4053std::basic_istream<CHAR_TYPE, CHAR_TRAITS>&
4054getline(std::basic_istream<CHAR_TYPE, CHAR_TRAITS>& is,
4056 CHAR_TYPE delim);
4057
4058/// Replace the contents of the specified `str` string by extracting
4059/// characters from the specified `is` stream until a newline character
4060/// (`is.widen('\n')`) is extracted, and return `is`. The newline character is
4061/// removed from the input stream but is not appended to `str`. If an `eof`
4062/// is detected before the newline, then the characters up to the `eof` are
4063/// put into `str` and `is.eof()` becomes true. If `is.good()` is false on
4064/// entry, then do nothing, otherwise if no characters are extracted (e.g.,
4065/// because because the stream is at eof), `str` will become empty and
4066/// `is.fail()` will become true.
4067template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4068std::basic_istream<CHAR_TYPE, CHAR_TRAITS>&
4069getline(std::basic_istream<CHAR_TYPE, CHAR_TRAITS>& is,
4071
4072int stoi(const string& str, std::size_t *pos = 0, int base = 10);
4073int stoi(const wstring& str, std::size_t *pos = 0, int base = 10);
4074long stol(const string& str, std::size_t *pos = 0, int base = 10);
4075long stol(const wstring& str, std::size_t *pos = 0, int base = 10);
4076unsigned long stoul(const string& str, std::size_t *pos = 0, int base = 10);
4077unsigned long stoul(const wstring& str, std::size_t *pos = 0, int base = 10);
4078long long stoll(const string& str, std::size_t *pos = 0, int base = 10);
4079long long stoll(const wstring& str, std::size_t *pos = 0, int base = 10);
4080
4081/// Return the value of the specified `str` by parsing the string and
4082/// interpreting its content as an integral number. Optionally specify
4083/// `pos` whose value is set to the position of the next character in `str`
4084/// after the numerical value. Optionally specify `base` used to change the
4085/// interpretation of `str` to a integral number written in the given
4086/// `base`. Valid bases are bases in the range of [2,36] and base 0, where
4087/// base 0 automatically determines the base while parsing the string: the
4088/// base will be 16 if the number is prefixed with `0x` or `0X`, base 8 if
4089/// the number is prefixed with a `0`, and base 10 otherwise. The function
4090/// ignores leading white space characters and interprets as many characters
4091/// possible to form a valid integral number in the chosen base. If no
4092/// conversion could be performed, then an @ref invalid_argument exception is
4093/// thrown. If the value read is out of range of the return type, then an `out_of_range` exception is thrown.
4094///
4095/// \pre The behavior is undefined unless `base` is valid.
4096///
4097/// \note Note that negative numbers are parsed by interpreting
4098/// the numeric sequence following the `-` character, and then negating the
4099/// result, so that `stoul` and `stoull` have defined results for negative
4100/// numbers where the absolute value falls in the valid range for the
4101/// corresponding signed conversion.
4102unsigned long long stoull(const string& str,
4103 std::size_t *pos = 0,
4104 int base = 10);
4105unsigned long long stoull(const wstring& str,
4106 std::size_t *pos = 0,
4107 int base = 10);
4108
4109float stof(const string& str, std::size_t *pos =0);
4110float stof(const wstring& str, std::size_t *pos =0);
4111double stod(const string& str, std::size_t *pos =0);
4112double stod(const wstring& str, std::size_t *pos =0);
4113
4114/// Parses `str` interpreting its contents as a floating point number. In
4115/// C++11 if the number in `str` is prefixed with `0x` or `0X` the string
4116/// will be interpreted as a hex number. If there is no leading 0x or 0X
4117/// the string will be interpreted as a decimal number. Optionally specify
4118/// `pos` whose value is set to the position of the next character after the
4119/// numerical value. The function ignores leading white space characters
4120/// and interprets as many characters possible to form a valid floating
4121/// point number. If no conversion could be performed, then an
4122/// @ref invalid_argument exception is thrown. If the value read is out of
4123/// range of the return type, then an @ref out_of_range exception is thrown.
4124long double stold(const string& str, std::size_t *pos =0);
4125long double stold(const wstring& str, std::size_t *pos =0);
4126
4127/// Constructs a string with contents equal to the specified `value`. The
4128/// contents of the string will be the same as what
4129/// `std::sprintf(buf, "%d", value)` would produce with a sufficiently large
4130/// buffer.
4131string to_string(int value);
4132
4133/// Constructs a string with contents equal to the specified `value`. The
4134/// contents of the string will be the same as what
4135/// `std::sprintf(buf, "%ld", value)` would produce with a sufficiently
4136/// large buffer.
4137string to_string(long value);
4138
4139/// Constructs a string with contents equal to the specified `value`. The
4140/// contents of the string will be the same as what
4141/// `std::sprintf(buf, "%lld", value)` would produce with a sufficiently
4142/// large buffer.
4143string to_string(long long value);
4144
4145/// Constructs a string with contents equal to the specified `value`. The
4146/// contents of the string will be the same as what
4147/// `std::sprintf(buf, "%u", value)` would produce with a sufficiently large
4148/// buffer.
4149string to_string(unsigned value);
4150
4151/// Constructs a string with contents equal to the specified `value`. The
4152/// contents of the string will be the same as what
4153/// `std::sprintf(buf, "%lu", value)` would produce with a sufficiently
4154/// large buffer.
4155string to_string(unsigned long value);
4156
4157/// Constructs a string with contents equal to the specified `value`. The
4158/// contents of the string will be the same as what
4159/// `std::sprintf(buf, "%llu", value)` would produce with a sufficiently
4160/// large buffer.
4161string to_string(unsigned long long value);
4162
4163/// converts a floating point value to a string with the same contents as
4164/// what `std::sprintf(buf, "%f", value)` would produce for a sufficiently
4165/// large buffer.
4166string to_string(float value);
4167string to_string(double value);
4168
4169/// converts a floating point value to a string with the same contents as
4170/// what `std::sprintf(buf, "%Lf", value)` would produce for a sufficiently
4171/// large buffer.
4172string to_string(long double value);
4173
4174/// Constructs a string with contents equal to the specified `value`. The
4175/// contents of the string will be the same as what
4176/// `std::swprintf(buf, L"%d", value)` would produce with a sufficiently
4177/// large buffer.
4179
4180/// Constructs a string with contents equal to the specified `value`. The
4181/// contents of the string will be the same as what
4182/// `std::swprintf(buf, L"%ld", value)` would produce with a sufficiently
4183/// large buffer.
4185
4186/// Constructs a string with contents equal to the specified `value`. The
4187/// contents of the string will be the same as what
4188/// `std::swprintf(buf, L"%lld", value)` would produce with a sufficiently
4189/// large buffer.
4190wstring to_wstring(long long value);
4191
4192/// Constructs a string with contents equal to the specified `value`. The
4193/// contents of the string will be the same as what
4194/// `std::swprintf(buf, L"%u", value)` would produce with a sufficiently
4195/// large buffer.
4196wstring to_wstring(unsigned value);
4197
4198/// Constructs a string with contents equal to the specified `value`. The
4199/// contents of the string will be the same as what
4200/// `std::swprintf(buf, L"%lu", value)` would produce with a sufficiently
4201/// large buffer.
4202wstring to_wstring(unsigned long value);
4203
4204/// Constructs a string with contents equal to the specified `value`. The
4205/// contents of the string will be the same as what
4206/// `std::swprintf(buf, L"%llu", value)` would produce with a sufficiently
4207/// large buffer.
4208wstring to_wstring(unsigned long long value);
4209
4210/// converts a floating point value to a string with the same contents as
4211/// what `std::sprintf(buf, sz, L"%f", value)` would produce for a
4212/// sufficiently large buffer.
4213wstring to_wstring(float value);
4214wstring to_wstring(double value);
4215
4216/// converts a floating point value to a string with the same contents as
4217/// `what std::sprintf(buf, sz, L"%Lf", value)` would produce for a
4218/// sufficiently large buffer.
4219wstring to_wstring(long double value);
4220
4221/// Erase (in-place) all the elements from the specified `str` that compare
4222/// equal to the specified `c`, and return the number of erased elements.
4223template <class CHAR_TYPE,
4224 class CHAR_TRAITS,
4225 class ALLOCATOR,
4226 class OTHER_CHAR_TYPE>
4229 const OTHER_CHAR_TYPE& c);
4230
4231/// Erase (in-place) all the elements from the specified `str` where the
4232/// specified `pred` returns `true`, and return the number of erased
4233/// elements.
4234template <class CHAR_TYPE,
4235 class CHAR_TRAITS,
4236 class ALLOCATOR,
4237 class UNARY_PREDICATE>
4240 const UNARY_PREDICATE& pred);
4241
4242/// This `enum` give upper bounds on the maximum string lengths storing each
4243/// scalar numerical type, and the starting value for `long double` that can
4244/// get way too long for stack storage when printed. It is safe to use
4245/// stack-allocated buffers of these sizes for generating decimal
4246/// representations of the corresponding type, including sign and terminating
4247/// null character, using the default precision of 6 significant digits for
4248/// floating point types.
4250
4251 e_MAX_SHORT_STRLEN10 = 2 + sizeof(short) * 3,
4252 e_MAX_INT_STRLEN10 = 2 + sizeof(int) * 3,
4258
4259 e_STARTING_LONGDOUBLE_STRLEN10 = 318 // Try to print into this with
4260 // `snprintf`, if too long print into
4261 // a dynamically allocated buffer.
4263
4264// HASH SPECIALIZATIONS
4265
4266/// Pass the specified `input` string to the specified `hashAlg` hashing
4267/// algorithm of the (template parameter) type `HASHALG`.
4268template <class HASHALG, class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4269void hashAppend(HASHALG& hashAlg,
4271
4272/// Return a hash value for the specified `str`.
4273template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4274std::size_t
4276
4277/// Return a hash value for the specified `str`.
4278std::size_t hashBasicString(const string& str);
4279
4280/// Return a hash value for the specified `str`.
4281std::size_t hashBasicString(const wstring& str);
4282
4283/// Specialize `bsl::hash` for strings, including an overload for pointers
4284/// to allow character arrays to be hashed without converting them first.
4285template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4286struct hash<basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR> >
4287 : ::BloombergLP::bslh::Hash<>
4288{
4289 // PUBLIC ACCESSORS
4290
4291 /// Compute and return the hash value of the specified `input`.
4292 std::size_t operator()(
4294
4295 /// Compute and return the hash value of the contents of the specified
4296 /// null-terminated `input`. This value will be the same as the hash
4297 /// value of a @ref basic_string constructed from `input`.
4298 std::size_t operator()(const CHAR_TYPE *input) const;
4299};
4300
4301#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
4302// DRQS 132030795
4303
4304// Sun CC 12.3 has trouble with the partial specializations above in certain
4305// circumstances (see DRQS 132030795). Adding these explicit specializations
4306// for `string` and `wstring` makes the problematic cases work.
4307
4308template <>
4309struct hash<string> : ::BloombergLP::bslh::Hash<>
4310{
4311 // PUBLIC ACCESSORS
4312
4313 /// Compute and return the hash value of the specified `input`.
4314 std::size_t operator()(const string& input) const;
4315
4316 /// Compute and return the hash value of the contents of the specified
4317 /// null-terminated `input`. This value will be the same as the hash
4318 /// value of a @ref basic_string constructed from `input`.
4319 std::size_t operator()(const char *input) const;
4320};
4321
4322template <>
4323struct hash<wstring> : ::BloombergLP::bslh::Hash<>
4324{
4325 // PUBLIC ACCESSORS
4326
4327 /// Compute and return the hash value of the specified `input`.
4328 std::size_t operator()(const wstring& input) const;
4329
4330 /// Compute and return the hash value of the contents of the specified
4331 /// null-terminated `input`. This value will be the same as the hash
4332 /// value of a @ref basic_string constructed from `input`.
4333 std::size_t operator()(const wchar_t *input) const;
4334};
4335
4336#endif
4337
4338} // close namespace bsl
4339
4340
4341namespace bslh {
4342
4343/// Pass the specified `input` string to the specified `hashAlg` hashing algorithm of the (template parameter) type `HASHALG`.
4344///
4345/// \note Note that this
4346/// function violates the BDE coding standard, adding a function for a
4347/// namespace for a different package, and none of the function parameters
4348/// are from this package either. This is necessary in order to provide an
4349/// implementation of `bslh::hashAppend` for the (native) standard library
4350/// `string` type as we are not allowed to add overloads directly into
4351/// namespace `std`, and this component essentially provides the interface
4352/// between `bsl` and `std` string types.
4353template <class HASHALG, class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4355void hashAppend(
4356 HASHALG& hashAlg,
4357 const std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& input);
4358
4359} // close namespace bslh
4360
4361
4362// ============================================================================
4363// FUNCTION TEMPLATE DEFINITIONS
4364// ============================================================================
4365// See IMPLEMENTATION NOTES in the '.cpp' before modifying anything below.
4366
4367namespace bsl {
4368 // ----------------
4369 // class String_Imp
4370 // ----------------
4371
4372// CLASS METHODS
4373template <class CHAR_TYPE, class SIZE_TYPE>
4374SIZE_TYPE
4376 SIZE_TYPE oldCapacity,
4377 SIZE_TYPE maxSize)
4378{
4379 BSLS_ASSERT_SAFE(newLength >= oldCapacity);
4380
4381 // We must exercise an exponential growth, otherwise we cannot
4382 // guarantee amortized time for `append`, `insert`, `push_back`,
4383 // `replace`, etc. 1.5 growth factor helps to reuse previously
4384 // allocated and freed memory blocks on frequent re-allocations due to
4385 // a continuous string growth (for example, when calling `push_back` in
4386 // a loop).
4387 //
4388 // TBD: consider bounding the exponential growth when `newCapacity` is
4389 // about several megabytes.
4390 SIZE_TYPE newCapacity = oldCapacity + (oldCapacity >> 1);
4391
4392 if (newLength > newCapacity) {
4393 newCapacity = newLength;
4394 }
4395
4396 if (newCapacity < oldCapacity || newCapacity > maxSize) { // overflow
4397 newCapacity = maxSize;
4398 }
4399
4400 return newCapacity;
4401}
4402
4403// CREATORS
4404template <class CHAR_TYPE, class SIZE_TYPE>
4407: d_start_p(0)
4408, d_length(0)
4409, d_capacity(this->SHORT_BUFFER_CAPACITY) // See {DRQS 131792157} for 'this'.
4410{
4411}
4412
4413template <class CHAR_TYPE, class SIZE_TYPE>
4416 SIZE_TYPE capacity)
4417: d_start_p(0)
4418, d_length(length)
4419, d_capacity(capacity <= static_cast<SIZE_TYPE>(this->SHORT_BUFFER_CAPACITY)
4420 ? static_cast<SIZE_TYPE>(this->SHORT_BUFFER_CAPACITY)
4421 : capacity) // See {DRQS 131792157} for 'this'.
4422{
4423}
4424
4425// MANIPULATORS
4426template <class CHAR_TYPE, class SIZE_TYPE>
4428{
4429 if (!isShortString() && !other.isShortString()) {
4430 // If both strings are long, swap the individual fields.
4431 BloombergLP::bslalg::ScalarPrimitives::swap(d_length, other.d_length);
4432 BloombergLP::bslalg::ScalarPrimitives::swap(d_capacity,
4433 other.d_capacity);
4434 BloombergLP::bslalg::ScalarPrimitives::swap(d_start_p,
4435 other.d_start_p);
4436 }
4437 else {
4438 // Otherwise bitwise-swap the whole objects (relies on the
4439 // BitwiseMoveable type trait).
4440 BloombergLP::bslalg::ScalarPrimitives::swap(*this, other);
4441 }
4442}
4443
4444// PRIVATE MANIPULATORS
4445template <class CHAR_TYPE, class SIZE_TYPE>
4446inline
4448{
4449 d_start_p = 0;
4450 d_length = 0;
4451 d_capacity = this->SHORT_BUFFER_CAPACITY;
4452 // See {DRQS 131792157} for 'this'.
4453}
4454
4455template <class CHAR_TYPE, class SIZE_TYPE>
4456inline
4458{
4459 return isShortString()
4460 ? reinterpret_cast<CHAR_TYPE *>((void *)d_short.buffer())
4461 : d_start_p;
4462}
4463
4464// PRIVATE ACCESSORS
4465template <class CHAR_TYPE, class SIZE_TYPE>
4466inline
4468{
4469 // suppress buggy warning in GCC 12 and later {DRQS 176453450}
4470#ifdef BSLS_PLATFORM_PRAGMA_GCC_DIAGNOSTIC_GCC
4471#pragma GCC diagnostic push
4472#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
4473#endif
4474 return d_capacity == this->SHORT_BUFFER_CAPACITY;
4475 // See {DRQS 131792157} for `this`.
4476#ifdef BSLS_PLATFORM_PRAGMA_GCC_DIAGNOSTIC_GCC
4477#pragma GCC diagnostic pop
4478#endif
4479}
4480
4481template <class CHAR_TYPE, class SIZE_TYPE>
4482inline
4484{
4485 return isShortString()
4486 ? reinterpret_cast<const CHAR_TYPE *>((const void *)d_short.buffer())
4487 : d_start_p;
4488}
4489
4490 // ------------------------------
4491 // class bsl::String_ClearProctor
4492 // ------------------------------
4493
4494// CREATORS
4495template <class FULL_STRING_TYPE>
4497 FULL_STRING_TYPE *stringPtr)
4498: d_string_p(stringPtr)
4499, d_originalLength(stringPtr->d_length)
4500{
4501 d_string_p->d_length = 0;
4502}
4503
4504template <class FULL_STRING_TYPE>
4506{
4507 if (d_string_p) {
4508 d_string_p->d_length = d_originalLength;
4509 }
4510}
4511
4512// MANIPULATORS
4513template <class FULL_STRING_TYPE>
4515{
4516 d_string_p = 0;
4517}
4518
4519 // -----------------------
4520 // class bsl::basic_string
4521 // -----------------------
4522
4523// CLASS DATA
4524template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4527
4528// PRIVATE CLASS METHODS
4529template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4530inline
4531void
4533 bool maxLengthExceeded,
4534 const char *message)
4535{
4536 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(maxLengthExceeded)) {
4538 BloombergLP::bslstl::StdExceptUtil::throwLengthError(message);
4539 }
4540}
4541
4542template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4543inline
4544void
4545basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::privateThrowOutOfRange(
4546 bool outOfRange,
4547 const char *message)
4548{
4549 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(outOfRange)) {
4551 BloombergLP::bslstl::StdExceptUtil::throwOutOfRange(message);
4552 }
4553}
4554
4555// PRIVATE MANIPULATORS
4556template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4557inline
4558CHAR_TYPE *
4559basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateAllocate(
4560 size_type numChars)
4561{
4562 return AllocatorUtil::allocateObject<CHAR_TYPE>(this->allocatorRef(),
4563 numChars + 1);
4564}
4565
4566template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4567inline
4568void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateDeallocate()
4569{
4570 if (!this->isShortString()) {
4571 AllocatorUtil::deallocateObject(this->allocatorRef(),
4572 this->d_start_p, this->d_capacity + 1);
4573 }
4574}
4575
4576template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4577inline
4578void
4579basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateCopyFromOutOfPlaceBuffer(
4580 const basic_string& original)
4581{
4582 BSLS_ASSERT_SAFE(!this->isShortString());
4583 BSLS_ASSERT_SAFE(!original.isShortString());
4584
4585 // Note that it is possible that 'original' is not a short-string, but its
4586 // length has been updated to fit in the short-string buffer (so 'this'
4587 // copy should be a short-string).
4588
4589 static_cast<Imp &>(*this) = Imp(original.length(), original.length());
4590
4591 if (!this->isShortString()) {
4592 this->d_start_p = privateAllocate(this->d_capacity);
4593 }
4594
4595 CHAR_TRAITS::copy(this->dataPtr(), original.data(), this->d_length + 1);
4596}
4597
4598template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4599basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4600basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateAppend(
4601 const CHAR_TYPE *characterString,
4602 size_type numChars,
4603 const char *message)
4604{
4605 privateThrowLengthError(numChars > max_size() - length(), message);
4606
4607 size_type newLength = this->d_length + numChars;
4608 size_type newStorage = this->d_capacity;
4609 CHAR_TYPE *newBuffer = privateReserveRaw(&newStorage,
4610 newLength,
4611 this->d_length);
4612
4613 if (newBuffer) {
4614 CHAR_TRAITS::copy(newBuffer + this->d_length,
4615 characterString,
4616 numChars);
4617 CHAR_TRAITS::assign(*(newBuffer + newLength), CHAR_TYPE());
4618
4619 privateDeallocate();
4620
4621 this->d_start_p = newBuffer;
4622 this->d_capacity = newStorage;
4623 }
4624 else {
4625 CHAR_TRAITS::move(this->dataPtr() + length(),
4626 characterString,
4627 numChars);
4628 CHAR_TRAITS::assign(*(this->dataPtr() + newLength), CHAR_TYPE());
4629 }
4630
4631 this->d_length = newLength;
4632 return *this;
4633}
4634
4635template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4636basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4637basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateAppend(
4638 size_type numChars,
4639 CHAR_TYPE character,
4640 const char *message)
4641{
4642 privateThrowLengthError(numChars > max_size() - length(), message);
4643
4644 size_type newLength = this->d_length + numChars;
4645 privateReserveRaw(newLength);
4646 CHAR_TRAITS::assign(this->dataPtr() + this->d_length, numChars, character);
4647 this->d_length = newLength;
4648 CHAR_TRAITS::assign(*(this->dataPtr() + newLength), CHAR_TYPE());
4649 return *this;
4650}
4651
4652template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4653inline
4654basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4655basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateAppend(
4656 iterator first,
4657 iterator last,
4658 const char *message,
4659 std::forward_iterator_tag)
4660{
4661 BSLS_ASSERT_SAFE(first <= last);
4662
4663 return privateAppend(const_iterator(first),
4664 const_iterator(last),
4665 message,
4666 std::forward_iterator_tag());
4667}
4668
4669template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4670inline
4671basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4672basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateAppend(
4673 const_iterator first,
4674 const_iterator last,
4675 const char *message,
4676 std::forward_iterator_tag)
4677{
4678 BSLS_ASSERT_SAFE(first <= last);
4679 return privateAppend(&*first, last - first, message);
4680}
4681
4682template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4683template <class INPUT_ITER, class SENTINEL>
4684inline
4685basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4687 INPUT_ITER first,
4688 SENTINEL last,
4689 const char *message,
4690 std::input_iterator_tag tag)
4691{
4692 return privateAppend(first, last, npos, message, tag);
4693}
4694
4695template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4696template <class INPUT_ITER, class SENTINEL>
4697inline
4700 INPUT_ITER first,
4701 SENTINEL last,
4702 size_type numChars,
4703 const char *message,
4704 std::input_iterator_tag )
4705{
4706 BSLS_ASSERT_SAFE(npos == numChars); (void) numChars;
4707
4708 basic_string temp(get_allocator());
4709 for (; first != last; ++first) {
4710 temp.push_back(*first);
4711 }
4712 if (length() == 0 && capacity() <= temp.capacity()) {
4713 quickSwapRetainAllocators(temp);
4714
4715 // This object may not have been null-terminated because of
4716 // String_ClearProctor, so force null termination in the swapped-into
4717 // temporary.
4718 CHAR_TRAITS::assign(*(temp.dataPtr()), CHAR_TYPE());
4719 return *this; // RETURN
4720 }
4721 return privateAppend(temp.data(), temp.length(), message);
4722}
4723
4724template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4725template <class INPUT_ITER, class SENTINEL>
4726inline
4729 INPUT_ITER first,
4730 SENTINEL last,
4731 const char *message,
4732 std::forward_iterator_tag tag)
4733{
4734 size_type numChars = privateNumCharsInRange(first, last);
4735 return privateAppend(first, last, numChars, message, tag);
4736}
4737
4738template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4739template <class INPUT_ITER, class SENTINEL>
4740inline
4743 INPUT_ITER first,
4744 SENTINEL last,
4745 size_type numChars,
4746 const char *message,
4747 std::forward_iterator_tag )
4748{
4749 BSLS_ASSERT_SAFE(numChars == static_cast<size_type>(
4750 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last)));
4751
4752 privateThrowLengthError(numChars > max_size() - length(), message);
4753
4754 size_type newLength = this->d_length + numChars;
4755 size_type newStorage = this->d_capacity;
4756 CHAR_TYPE *newBuffer = privateReserveRaw(&newStorage,
4757 newLength,
4758 this->d_length);
4759
4760 if (newBuffer) {
4761 for (size_type pos = this->d_length; first != last; ++first, ++pos) {
4762 CHAR_TRAITS::assign(*(newBuffer + pos), *first);
4763 }
4764
4765 privateDeallocate();
4766
4767 this->d_start_p = newBuffer;
4768 this->d_capacity = newStorage;
4769 }
4770 else {
4771 for (size_type pos = this->d_length; first != last; ++first, ++pos) {
4772 CHAR_TRAITS::assign(*(this->dataPtr() + pos), *first);
4773 }
4774 }
4775
4776 CHAR_TRAITS::assign(*(this->dataPtr() + newLength), CHAR_TYPE());
4777 this->d_length = newLength;
4778 return *this;
4779}
4780
4781template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4782template <class INPUT_ITER>
4783inline
4786 INPUT_ITER first,
4787 INPUT_ITER last,
4788 const char *message)
4789{
4790 return privateAppendDispatch(first,
4791 last,
4792 message,
4793 first,
4794 BloombergLP::bslmf::Nil());
4795}
4796
4797template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4798template <class INPUT_ITER, class SENTINEL>
4799inline
4802 INPUT_ITER first,
4803 SENTINEL last,
4804 size_type numChars,
4805 const char *message)
4806{
4807 typename iterator_traits<INPUT_ITER>::iterator_category tag;
4808 return privateAppend(first, last, numChars, message, tag);
4809}
4810
4811template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4812template <class INPUT_ITER>
4813inline
4816 INPUT_ITER first,
4817 INPUT_ITER last,
4818 const char *message,
4819 BloombergLP::bslmf::MatchArithmeticType ,
4820 BloombergLP::bslmf::Nil )
4821{
4822 return privateAppend((size_type)first, (CHAR_TYPE)last, message);
4823}
4824
4825template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4826template <class INPUT_ITER>
4827inline
4830 INPUT_ITER first,
4831 INPUT_ITER last,
4832 const char *message,
4833 BloombergLP::bslmf::MatchAnyType ,
4834 BloombergLP::bslmf::MatchAnyType )
4835{
4836 typename iterator_traits<INPUT_ITER>::iterator_category tag;
4837 return privateAppend(first, last, message, tag);
4838}
4839
4840template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4841template <class FIRST_TYPE, class SECOND_TYPE>
4842inline
4845 FIRST_TYPE first,
4846 SECOND_TYPE second,
4847 const char *message)
4848{
4849 {
4851 privateAppend(first, second, message);
4852 guard.release();
4853 }
4854
4855 return *this;
4856}
4857
4858template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4859template <class INPUT_ITER, class SENTINEL>
4860inline
4863 INPUT_ITER first,
4864 SENTINEL last,
4865 size_type numChars,
4866 const char *message)
4867{
4868 {
4870 privateAppendRange(first, last, numChars, message);
4871 guard.release();
4872 }
4873
4874 return *this;
4875}
4876
4877template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4878inline
4879typename basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::Imp&
4881{
4882 return *static_cast<Imp *>(this);
4883}
4884
4885template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4886void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateClear(
4887 bool deallocateBufferFlag)
4888{
4889 if (deallocateBufferFlag) {
4890 privateDeallocate();
4891 this->resetFields();
4892 }
4893 else {
4894 this->d_length = 0;
4895 }
4896
4897 CHAR_TRAITS::assign(*begin(), CHAR_TYPE());
4898}
4899
4900template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4901inline
4902void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateInsertDispatch(
4903 const_iterator position,
4904 iterator first,
4905 iterator last)
4906{
4907 BSLS_ASSERT_SAFE(first <= last);
4908
4909 privateInsertDispatch(position,
4910 const_iterator(first),
4911 const_iterator(last));
4912}
4913
4914template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4915void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateInsertDispatch(
4916 const_iterator position,
4917 const_iterator first,
4918 const_iterator last)
4919{
4920 BSLS_ASSERT_SAFE(first <= last);
4921
4922 size_type pos = position - cbegin();
4923 privateThrowOutOfRange(
4924 pos > length(),
4925 "string<...>::insert<Iter>(pos,i,j): invalid position");
4926
4927 size_type numChars = last - first;
4928 privateThrowLengthError(
4929 numChars > max_size() - length(),
4930 "string<...>::insert<Iter>(pos,i,j): string too long");
4931
4932 privateInsertRaw(pos, &*first, numChars);
4933}
4934
4935template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4936template <class INPUT_ITER>
4937inline
4938void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateInsertDispatch(
4939 const_iterator position,
4940 INPUT_ITER first,
4941 INPUT_ITER last)
4942{
4943 size_type pos = position - cbegin();
4944 privateReplaceDispatch(pos,
4945 size_type(0),
4946 first,
4947 last,
4948 first,
4949 BloombergLP::bslmf::Nil());
4950}
4951
4952template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4953template <class INPUT_ITER, class SENTINEL>
4954inline
4955void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateInsertRange(
4956 const_iterator position,
4957 size_type inNumChars,
4958 INPUT_ITER first,
4959 SENTINEL last)
4960{
4961 size_type outPosition = position - cbegin();
4962 privateReplaceRange(outPosition, size_type(0), inNumChars, first, last);
4963}
4964
4965template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4966basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4967basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateInsertRaw(
4968 size_type outPosition,
4969 const CHAR_TYPE *characterString,
4970 size_type numChars)
4971{
4972 BSLS_ASSERT_SAFE(outPosition <= length());
4973 BSLS_ASSERT_SAFE(numChars <= max_size() - length());
4974 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
4975
4976 size_type newLength = this->d_length + numChars;
4977 size_type newStorage = this->d_capacity;
4978 CHAR_TYPE *newBuffer = privateReserveRaw(&newStorage,
4979 newLength,
4980 outPosition);
4981
4982 if (newBuffer) {
4983 // Source and destination cannot overlap, order of next two copies is
4984 // arbitrary. Do it left to right to maintain cache consistency.
4985
4986 const CHAR_TYPE *tail = this->dataPtr() + outPosition;
4987 size_type tailLen = this->d_length - outPosition;
4988
4989 CHAR_TRAITS::copy(newBuffer + outPosition, characterString, numChars);
4990 CHAR_TRAITS::copy(newBuffer + outPosition + numChars, tail, tailLen);
4991 CHAR_TRAITS::assign(*(newBuffer + newLength), CHAR_TYPE());
4992
4993 privateDeallocate();
4994
4995 this->d_start_p = newBuffer;
4996 this->d_capacity = newStorage;
4997 }
4998 else {
4999 // Because of possible aliasing, we have to be very careful in which
5000 // order to move blocks. If 'characterString' overlaps with tail, or
5001 // is entirely contained: in the former case, 'characterString' is
5002 // shifted by 'numChars' (takes 'first' onto 'last'); in the latter,
5003 // the tail moves in by 'numChars', so cannot overwrite
5004 // 'characterString'!
5005
5006 const CHAR_TYPE *first = characterString;
5007 const CHAR_TYPE *last = characterString + numChars;
5008 CHAR_TYPE *tail = this->dataPtr() + outPosition;
5009 size_type tailLen = this->d_length - outPosition;
5010 const CHAR_TYPE *shifted = (tail < first && last <= tail + tailLen)
5011 ? last // 'first' shifted by 'numChars'
5012 : first; // 'no shift
5013
5014 CHAR_TRAITS::move(tail + numChars, tail, tailLen);
5015 CHAR_TRAITS::move(tail, shifted, numChars);
5016 CHAR_TRAITS::assign(*(this->dataPtr() + newLength), CHAR_TYPE());
5017 }
5018
5019 this->d_length = newLength;
5020 return *this;
5021}
5022
5023template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5024void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateMoveConstruct(
5025 basic_string& original,
5026 size_type position,
5027 size_type numChars)
5028{
5029 privateThrowOutOfRange(position > original.length(),
5030 "string(string&&,pos,n): invalid position");
5031
5032 size_type len = length() - position;
5033 if (numChars < len) {
5034 len = numChars;
5035 }
5036 this->d_length = len;
5037
5038 CHAR_TYPE *data = this->dataPtr();
5039
5040 if (original.isShortString()) { // short -> short
5041 CHAR_TRAITS::move(data, data + position, len);
5042 }
5043 else if (this->get_allocator() == original.get_allocator()) {
5044 // long `original`, steal the buffer
5045 original.resetFields();
5046 CHAR_TRAITS::move(data, data + position, len);
5047 }
5048 else if (len <= this->SHORT_BUFFER_CAPACITY) { // long -> short
5049 this->d_capacity = this->SHORT_BUFFER_CAPACITY;
5050 data = this->dataPtr();
5051 CHAR_TRAITS::copy(data, original.data() + position, len);
5052 }
5053 else {
5054 // long -> long, own buffer
5055 this->d_start_p = data = privateAllocate(len);
5056 this->d_capacity = len;
5057 CHAR_TRAITS::copy(data, original.data() + position, len);
5058 }
5059 CHAR_TRAITS::assign(data[len], CHAR_TYPE());
5060}
5061
5062template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5063basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
5064basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateReplaceRaw(
5065 size_type outPosition,
5066 size_type outNumChars,
5067 const CHAR_TYPE *characterString,
5068 size_type numChars)
5069{
5070 BSLS_ASSERT_SAFE(outPosition <= length());
5071 BSLS_ASSERT_SAFE(outNumChars <= length());
5072 BSLS_ASSERT_SAFE(outPosition <= length() - outNumChars);
5073 BSLS_ASSERT_SAFE(length() - outNumChars <= max_size() - numChars);
5074 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
5075
5076 const difference_type displacement =
5077 static_cast<difference_type>(numChars - outNumChars);
5078
5079 size_type newLength = this->d_length + displacement;
5080 size_type newStorage = this->d_capacity;
5081 CHAR_TYPE *newBuffer = privateReserveRaw(&newStorage,
5082 newLength,
5083 outPosition);
5084
5085 const CHAR_TYPE *tail = this->dataPtr() + outPosition + outNumChars;
5086 size_type tailLen = this->d_length - outPosition - outNumChars;
5087
5088 if (newBuffer) {
5089 // Source and destination cannot overlap, order of next two copies is
5090 // arbitrary. Do it left to right to maintain cache consistency.
5091
5092 CHAR_TRAITS::copy(newBuffer + outPosition, characterString, numChars);
5093 CHAR_TRAITS::copy(newBuffer + outPosition + numChars, tail, tailLen);
5094 CHAR_TRAITS::assign(*(newBuffer + newLength), CHAR_TYPE());
5095
5096 privateDeallocate();
5097
5098 this->d_start_p = newBuffer;
5099 this->d_capacity = newStorage;
5100 this->d_length = newLength;
5101 return *this; // RETURN
5102 }
5103
5104 // Because of possible aliasing, we have to be very careful in which order
5105 // to move blocks. There are up to three blocks if 'characterString'
5106 // overlaps with the tail.
5107
5108 CHAR_TYPE *dest = this->dataPtr() + outPosition;
5109 const CHAR_TYPE *first = characterString;
5110 const CHAR_TYPE *last = characterString + numChars;
5111
5112 if (tail < last && last <= tail + tailLen) {
5113 // Either 'characterString' overlaps with tail, or is entirely
5114 // contained.
5115
5116 if (first < tail) {
5117 // Not entirely contained: break '[first .. last)' at 'tail', and
5118 // move it in two steps, the second shifted but not the first.
5119
5120 size_type prefix = tail - first, suffix = last - tail;
5121 if (outNumChars < numChars) {
5122 CHAR_TRAITS::move(dest + numChars, tail, tailLen);
5123 CHAR_TRAITS::move(dest, first, prefix);
5124 }
5125 else {
5126 CHAR_TRAITS::move(dest, first, prefix);
5127 CHAR_TRAITS::move(dest + numChars, tail, tailLen);
5128 }
5129 CHAR_TRAITS::move(dest + prefix,
5130 last - suffix + displacement,
5131 suffix);
5132 }
5133 else {
5134 // Entirely contained: copy 'tail' first, and copy
5135 // '[first .. last)' shifted by 'displacement'.
5136
5137 CHAR_TRAITS::move(dest + numChars, tail, tailLen);
5138 CHAR_TRAITS::copy(dest, first + displacement, numChars);
5139 }
5140 }
5141 else {
5142 // Note: no aliasing in tail.
5143
5144 if (outNumChars < numChars) {
5145 CHAR_TRAITS::move(dest + numChars, tail, tailLen);
5146 CHAR_TRAITS::move(dest, characterString, numChars);
5147 }
5148 else {
5149 CHAR_TRAITS::move(dest, characterString, numChars);
5150 CHAR_TRAITS::move(dest + numChars, tail, tailLen);
5151 }
5152 }
5153 CHAR_TRAITS::assign(*(this->dataPtr() + newLength), CHAR_TYPE());
5154 this->d_length = newLength;
5155 return *this;
5156}
5157
5158template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5159basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
5160basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateReplaceRaw(
5161 size_type outPosition,
5162 size_type outNumChars,
5163 size_type numChars,
5164 CHAR_TYPE character)
5165{
5166 BSLS_ASSERT_SAFE(outPosition <= length());
5167 BSLS_ASSERT_SAFE(outNumChars <= length());
5168 BSLS_ASSERT_SAFE(outPosition <= length() - outNumChars);
5169 BSLS_ASSERT_SAFE(length() <= max_size() - numChars);
5170
5171 size_type newLength = this->d_length - outNumChars + numChars;
5172 size_type newStorage = this->d_capacity;
5173 CHAR_TYPE *newBuffer = privateReserveRaw(&newStorage,
5174 newLength,
5175 outPosition);
5176
5177 const CHAR_TYPE *tail = this->dataPtr() + outPosition + outNumChars;
5178 size_type tailLen = this->d_length - outPosition - outNumChars;
5179
5180 if (newBuffer) {
5181 CHAR_TYPE *dest = newBuffer + outPosition;
5182
5183 CHAR_TRAITS::assign(dest, numChars, character);
5184 CHAR_TRAITS::copy(dest + numChars, tail, tailLen);
5185 CHAR_TRAITS::assign(*(newBuffer + newLength), CHAR_TYPE());
5186
5187 privateDeallocate();
5188
5189 this->d_start_p = newBuffer;
5190 this->d_capacity = newStorage;
5191 }
5192 else {
5193 CHAR_TYPE *dest = this->dataPtr() + outPosition;
5194
5195 CHAR_TRAITS::move(dest + numChars, tail, tailLen);
5196 CHAR_TRAITS::assign(dest, numChars, character);
5197 CHAR_TRAITS::assign(*(this->dataPtr() + newLength), CHAR_TYPE());
5198 }
5199
5200 this->d_length = newLength;
5201 return *this;
5202}
5203
5204template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5205template <class INPUT_ITER>
5206inline
5207basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
5209 size_type position,
5210 size_type numChars,
5211 INPUT_ITER first,
5212 INPUT_ITER last,
5213 BloombergLP::bslmf::MatchArithmeticType ,
5214 BloombergLP::bslmf::Nil )
5215{
5216 return replace(position, numChars, (size_type)first, (CHAR_TYPE)last);
5217}
5218
5219template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5220template <class INPUT_ITER>
5221inline
5224 size_type position,
5225 size_type numChars,
5226 INPUT_ITER first,
5227 INPUT_ITER last,
5228 BloombergLP::bslmf::MatchAnyType ,
5229 BloombergLP::bslmf::MatchAnyType )
5230{
5231 typename iterator_traits<INPUT_ITER>::iterator_category tag;
5232 return privateReplace(position, numChars, first, last, tag);
5233}
5234
5235template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5236template <class INPUT_ITER>
5239 size_type outPosition,
5240 size_type outNumChars,
5241 INPUT_ITER first,
5242 INPUT_ITER last,
5243 std::input_iterator_tag tag)
5244{
5245 return privateReplace(outPosition, outNumChars, npos, first, last, tag);
5246}
5247
5248template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5249template <class INPUT_ITER, class SENTINEL>
5252 size_type outPosition,
5253 size_type outNumChars,
5254 size_type inNumChars,
5255 INPUT_ITER first,
5256 SENTINEL last,
5257 std::input_iterator_tag )
5258{
5259 BSLS_ASSERT_SAFE(npos == inNumChars); (void) inNumChars;
5260
5261 privateThrowOutOfRange(
5262 length() < outPosition,
5263 "string<...>::replace<InputIter>(pos,n,i,j): invalid position");
5264
5265 basic_string temp(get_allocator());
5266 for (; first != last; ++first) {
5267 temp.push_back(*first);
5268 }
5269 if (outPosition == 0 && length() <= outNumChars) {
5270 // Note: can potentially shrink the capacity, hence the reserve.
5271
5272 temp.privateReserveRaw(capacity());
5273 quickSwapRetainAllocators(temp);
5274 return *this; // RETURN
5275 }
5276 return privateReplaceRaw(outPosition,
5277 outNumChars,
5278 temp.data(),
5279 temp.length());
5280}
5281
5282template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5283template <class INPUT_ITER>
5286 size_type outPosition,
5287 size_type outNumChars,
5288 INPUT_ITER first,
5289 INPUT_ITER last,
5290 std::forward_iterator_tag tag)
5291{
5292 size_type inNumChars = privateNumCharsInRange(first, last);
5293 return privateReplace(outPosition, outNumChars,
5294 inNumChars,
5295 first,
5296 last,
5297 tag);
5298}
5299
5300template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5301template <class INPUT_ITER, class SENTINEL>
5304 size_type outPosition,
5305 size_type outNumChars,
5306 size_type inNumChars,
5307 INPUT_ITER first,
5308 SENTINEL last,
5309 std::forward_iterator_tag )
5310{
5311 BSLS_ASSERT_SAFE(inNumChars == static_cast<size_type>(
5312 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last)));
5313 (void) last;
5314
5315 privateThrowOutOfRange(
5316 length() < outPosition,
5317 "string<...>::replace<Iter>(pos,n,i,j): invalid position");
5318
5319 privateThrowLengthError(
5320 max_size() - (length() - outPosition) < inNumChars,
5321 "string<...>::replace<Iter>(pos,n,i,j): string too long");
5322
5323 // Create a temp string because the 'first'/'last' iterator pair can alias
5324 // the current string; not using the constructor with two iterators because
5325 // it recurses back here.
5326 basic_string temp(inNumChars, CHAR_TYPE());
5327
5328 for (size_type pos = 0; pos != inNumChars; ++first, ++pos) {
5329 temp[pos] = *first;
5330 }
5331
5332 return privateReplaceRaw(outPosition,
5333 outNumChars,
5334 temp.data(),
5335 temp.length());
5336}
5337
5338template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5341 size_type position,
5342 size_type numChars,
5343 const_iterator first,
5344 const_iterator last,
5345 std::forward_iterator_tag)
5346{
5347 BSLS_ASSERT_SAFE(first <= last);
5348
5349 privateThrowOutOfRange(
5350 length() < position,
5351 "string<...>::replace<Iter>(pos,n,i,j): invalid position");
5352
5353 size_type numNewChars = bsl::distance(first, last);
5354 privateThrowLengthError(
5355 max_size() - (length() - position) < numNewChars,
5356 "string<...>::replace<Iter>(pos,n,i,j): string too long");
5357
5358 return privateReplaceRaw(position, numChars, &*first, numNewChars);
5359}
5360
5361template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5363basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
5364basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateReplace(
5365 size_type position,
5366 size_type numChars,
5367 iterator first,
5368 iterator last,
5369 std::forward_iterator_tag)
5370{
5371 BSLS_ASSERT_SAFE(first <= last);
5372
5373 return privateReplace(position,
5374 numChars,
5375 const_iterator(first),
5376 const_iterator(last),
5377 std::forward_iterator_tag());
5378}
5379
5380template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5381template <class INPUT_ITER, class SENTINEL>
5383basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
5385 size_type position,
5386 size_type outNumChars,
5387 size_type inNumChars,
5388 INPUT_ITER first,
5389 SENTINEL last)
5390{
5391 typename iterator_traits<INPUT_ITER>::iterator_category tag;
5392 return privateReplace(position,
5393 outNumChars,
5394 inNumChars,
5395 first,
5396 last,
5397 tag);
5398}
5399
5400template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5402 size_type newCapacity)
5403{
5404 BSLS_ASSERT_SAFE(newCapacity <= max_size());
5405
5406 if (this->d_capacity < newCapacity) {
5407 size_type newStorage = this->computeNewCapacity(newCapacity,
5408 this->d_capacity,
5409 max_size());
5410 CHAR_TYPE *newBuffer = privateAllocate(newStorage);
5411
5412 CHAR_TRAITS::copy(newBuffer, this->dataPtr(), this->d_length + 1);
5413
5414 privateDeallocate();
5415
5416 this->d_start_p = newBuffer;
5417 this->d_capacity = newStorage;
5418 }
5419}
5420
5421template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5422CHAR_TYPE *
5423basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateReserveRaw(
5424 size_type *storage,
5425 size_type newCapacity,
5426 size_type numChars)
5427{
5428 BSLS_ASSERT_SAFE(numChars <= length());
5429 BSLS_ASSERT_SAFE(newCapacity <= max_size());
5430 BSLS_ASSERT_SAFE(storage != 0);
5431
5432 if (*storage >= newCapacity) {
5433 return 0; // RETURN
5434 }
5435
5436 *storage = this->computeNewCapacity(newCapacity,
5437 *storage,
5438 max_size());
5439
5440 CHAR_TYPE *newBuffer = privateAllocate(*storage);
5441
5442 CHAR_TRAITS::copy(newBuffer, this->dataPtr(), numChars);
5443 return newBuffer;
5444}
5445
5446template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5447basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
5448basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateResizeRaw(
5449 size_type newLength,
5450 CHAR_TYPE character)
5451{
5452 BSLS_ASSERT_SAFE(newLength <= max_size());
5453
5454 privateReserveRaw(newLength);
5455
5456 if (newLength > this->d_length) {
5457 CHAR_TRAITS::assign(this->dataPtr() + this->d_length,
5458 newLength - this->d_length,
5459 character);
5460 }
5461 this->d_length = newLength;
5462 CHAR_TRAITS::assign(*(this->dataPtr() + this->d_length), CHAR_TYPE());
5463 return *this;
5464}
5465
5466template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5467template <bool ALLOC_PROP>
5468inline
5469void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::
5470quickSwapExchangeAllocators(basic_string& other,
5472{
5473 privateBase().swap(other.privateBase());
5474 AllocatorUtil::swap(&this->allocatorRef(), &other.allocatorRef(),
5475 Propagate);
5476}
5477
5478template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5479inline
5480void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::
5481 quickSwapRetainAllocators(basic_string& other)
5482{
5483 privateBase().swap(other.privateBase());
5484}
5485
5486// PRIVATE ACCESSORS
5487template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5488int basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateCompareRaw(
5489 size_type lhsPosition,
5490 size_type lhsNumChars,
5491 const CHAR_TYPE *other,
5492 size_type otherNumChars) const
5493{
5494 BSLS_ASSERT_SAFE(lhsPosition <= length());
5495 BSLS_ASSERT_SAFE(lhsNumChars <= length());
5496 BSLS_ASSERT_SAFE(lhsPosition <= length() - lhsNumChars);
5497 BSLS_ASSERT_SAFE(other);
5498
5499 size_type numChars = lhsNumChars < otherNumChars ? lhsNumChars
5500 : otherNumChars;
5501 int cmpResult = CHAR_TRAITS::compare(this->dataPtr() + lhsPosition,
5502 other,
5503 numChars);
5504 if (cmpResult) {
5505 return cmpResult; // RETURN
5506 }
5507 if (lhsNumChars < otherNumChars) {
5508 return -1; // RETURN
5509 }
5510 if (lhsNumChars > otherNumChars) {
5511 return 1; // RETURN
5512 }
5513 return 0;
5514}
5515
5516template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5517template <class RANGE>
5519typename
5521basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateNumCharsInRange(
5522 BSLS_COMPILERFEATURES_FORWARD_REF(RANGE) range) const
5523{
5524
5525#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
5526 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
5527
5528 if constexpr (ranges::sized_range<RANGE>) {
5529 return ranges::size(range); // RETURN
5530 }
5531
5532#endif
5533
5534 return privateNumCharsInRange(ranges::begin(range),
5535 ranges::end (range));
5536}
5537
5538template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5539template <class INPUT_ITERATOR, class SENTINEL>
5540typename
5543 INPUT_ITERATOR first,
5544 SENTINEL last) const
5545{
5546 typedef typename iterator_traits<INPUT_ITERATOR>::iterator_category
5547 category;
5549 ? npos
5550 : BloombergLP::bslstl::IteratorUtil::insertDistance(first,last);
5551}
5552
5553// CREATORS
5554
5555 // *** 21.3.2 construct/copy/destroy: ***
5556
5557template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5558inline
5561: Imp()
5562, BloombergLP::bslalg::ContainerBase<allocator_type>(ALLOCATOR())
5563{
5564 CHAR_TRAITS::assign(*begin(), CHAR_TYPE());
5565}
5566
5567template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5568inline
5570 const ALLOCATOR& basicAllocator)
5572: Imp()
5573, ContainerBase(basicAllocator)
5574{
5575 CHAR_TRAITS::assign(*begin(), CHAR_TYPE());
5576}
5577
5578template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5581 const basic_string& original)
5582: Imp(original)
5583, ContainerBase(AllocatorTraits::select_on_container_copy_construction(
5584 original.get_allocator()))
5585{
5586 if (!this->isShortString()) {
5587 // Copy out-of-place string into either short buffer or new long
5588 // buffer, according to size.
5589
5590 privateCopyFromOutOfPlaceBuffer(original);
5591 }
5592}
5593
5594template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5597 const basic_string& original,
5598 const ALLOCATOR& basicAllocator)
5599: Imp(original)
5600, ContainerBase(basicAllocator)
5601{
5602 if (!this->isShortString()) {
5603 // Copy out-of-place string into either short buffer or new long
5604 // buffer, according to size.
5605
5606 privateCopyFromOutOfPlaceBuffer(original);
5607 }
5608}
5609
5610template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5611inline
5613 BloombergLP::bslmf::MovableRef<basic_string> original)
5615: Imp(original)
5616, ContainerBase(MoveUtil::access(original).get_allocator())
5617{
5618 if (!this->isShortString()) { // nothing to fix up if string is short
5619 basic_string& originalRef = MoveUtil::access(original);
5620 originalRef.resetFields();
5621 }
5622}
5623
5624template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5625inline
5627 BloombergLP::bslmf::MovableRef<basic_string> original,
5628 const ALLOCATOR& basicAllocator)
5629: Imp(original)
5630, ContainerBase(basicAllocator)
5631{
5632 if (!this->isShortString()) { // nothing to fix up if string is short
5633 basic_string& originalRef = MoveUtil::access(original);
5634
5635 if (this->get_allocator() == originalRef.get_allocator()) {
5636 originalRef.resetFields();
5637 }
5638 else {
5639 privateCopyFromOutOfPlaceBuffer(originalRef);
5640 }
5641 }
5642}
5643
5644template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5645inline
5647 BloombergLP::bslmf::MovableRef<basic_string> original,
5648 size_type position,
5649 const ALLOCATOR& basicAllocator)
5650: Imp(original)
5651, ContainerBase(basicAllocator)
5652{
5653 privateMoveConstruct(MoveUtil::access(original), position);
5654}
5655
5656template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5657inline
5659 BloombergLP::bslmf::MovableRef<basic_string> original,
5660 size_type position,
5661 size_type numChars,
5662 const ALLOCATOR& basicAllocator)
5663: Imp(original)
5664, ContainerBase(basicAllocator)
5665{
5666 privateMoveConstruct(MoveUtil::access(original), position, numChars);
5667}
5668
5669template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5672 const basic_string& original,
5673 size_type position,
5674 const ALLOCATOR& basicAllocator)
5675: Imp()
5676, ContainerBase(basicAllocator)
5677{
5678 assign(original, position, npos);
5679}
5680
5681template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5684 const basic_string& original,
5685 size_type position,
5686 size_type numChars,
5687 const ALLOCATOR& basicAllocator)
5688: Imp()
5689, ContainerBase(basicAllocator)
5690{
5691 assign(original, position, numChars);
5692}
5693
5694template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5695#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
5696template <class>
5697#endif
5700 const CHAR_TYPE *characterString,
5701 const ALLOCATOR& basicAllocator)
5702: Imp()
5703, ContainerBase(basicAllocator)
5704{
5705 BSLS_ASSERT_SAFE(characterString);
5706
5707 assign(characterString);
5708}
5709
5710template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5713 const CHAR_TYPE *characterString,
5714 size_type numChars,
5715 const ALLOCATOR& basicAllocator)
5716: Imp()
5717, ContainerBase(basicAllocator)
5718{
5719 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
5720
5721 assign(characterString, numChars);
5722}
5723
5724template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5725#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
5726template <class>
5727#endif
5730 size_type numChars,
5731 CHAR_TYPE character,
5732 const ALLOCATOR& basicAllocator)
5733: Imp()
5734, ContainerBase(basicAllocator)
5735{
5736 assign(numChars, character);
5737}
5738
5739template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5740template <class INPUT_ITER>
5741inline
5743 INPUT_ITER first,
5744 INPUT_ITER last,
5745 const ALLOCATOR& basicAllocator)
5746: Imp()
5747, ContainerBase(basicAllocator)
5748{
5749 append(first, last);
5750}
5751
5752template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5753template <class RANGE>
5755inline
5757 from_range_t ,
5759 const ALLOCATOR& basicAllocator)
5760: Imp()
5761, ContainerBase(basicAllocator)
5762{
5763 append_range(range);
5764}
5765
5766template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5767template <class ALLOC2>
5770 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& original,
5771 const ALLOCATOR& basicAllocator)
5772: Imp()
5773, ContainerBase(basicAllocator)
5774{
5775 this->assign(original.data(), original.length());
5776}
5777
5778template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5779inline
5781 const BloombergLP::bslstl::StringRefData<CHAR_TYPE>& strRef,
5782 const ALLOCATOR& basicAllocator)
5783: Imp()
5784, ContainerBase(basicAllocator)
5785{
5786 assign(strRef.data(), strRef.length());
5787}
5788
5789template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5790template <class STRING_VIEW_LIKE_TYPE>
5791inline
5793 const STRING_VIEW_LIKE_TYPE& object,
5795 basicAllocator)
5796: Imp()
5797, ContainerBase(basicAllocator)
5798{
5800 assign(strView.data(), strView.length());
5801}
5802
5803template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5804template <class STRING_VIEW_LIKE_TYPE>
5805inline
5807 const STRING_VIEW_LIKE_TYPE& object,
5808 size_type position,
5809 size_type numChars,
5810 const ALLOCATOR& basicAllocator,
5812: Imp()
5813, ContainerBase(basicAllocator)
5814{
5816 privateThrowOutOfRange(
5817 position > strView.length(),
5818 "string<...>::assign(const string_view&,pos,n): invalid position");
5819
5820 if (numChars > strView.length() - position) {
5821 numChars = strView.length() - position;
5822 }
5823
5824 assign(strView.data() + position, numChars);
5825}
5826
5827#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
5828template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5829inline
5831 std::initializer_list<CHAR_TYPE> values,
5832 const ALLOCATOR& basicAllocator)
5833: Imp()
5834, ContainerBase(basicAllocator)
5835{
5836 append(values.begin(), values.end());
5837}
5838#endif
5839
5840template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5843{
5844 // perform a validity check
5845 BSLS_ASSERT_SAFE((*this)[this->d_length] == CHAR_TYPE());
5846 BSLS_ASSERT_SAFE(capacity() >= length());
5847
5848 privateDeallocate();
5849 this->d_length = npos; // invalid length
5850}
5851
5852// MANIPULATORS
5853
5854 // *** 21.3.2 construct/copy/destroy: ***
5855
5856template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5860 const basic_string& rhs)
5861{
5862 typedef typename
5864
5866 if (Propagate::value) {
5867 basic_string other(rhs, rhs.get_allocator());
5868 quickSwapExchangeAllocators(other, Propagate());
5869 }
5870 else {
5871 privateAssignDispatch(
5872 rhs.data(),
5873 rhs.size(),
5874 "string<...>::operator=(const string&...): string too long");
5875 }
5876 }
5877 return *this;
5878}
5879
5880template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5881inline
5884 BloombergLP::bslmf::MovableRef<basic_string> rhs)
5886 AllocatorTraits::propagate_on_container_move_assignment::value ||
5887 AllocatorTraits::is_always_equal::value)
5888{
5889 typedef typename
5891
5892 basic_string& lvalue = rhs;
5893
5894 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(this != &lvalue)) {
5895 if (Propagate::value) {
5896 basic_string other(MoveUtil::move(lvalue));
5897 quickSwapExchangeAllocators(other, Propagate());
5898 }
5899 else if (get_allocator() == lvalue.get_allocator()) {
5900 basic_string other(MoveUtil::move(lvalue));
5901 quickSwapRetainAllocators(other);
5902 }
5903 else {
5904 privateAssignDispatch(
5905 lvalue.data(),
5906 lvalue.size(),
5907 "string<...>::operator=(MovableRef<...>): string too long");
5908 }
5909 }
5910 return *this;
5911}
5912
5913template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5914template <class STRING_VIEW_LIKE_TYPE>
5915inline
5919 const STRING_VIEW_LIKE_TYPE& rhs)
5920{
5922 return privateAssignDispatch(
5923 strView.data(),
5924 strView.size(),
5925 "string<>::operator=(basic_string_view&): string too long");
5926}
5927
5928template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5930basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
5932{
5934
5935 return assign(rhs);
5936}
5937
5938template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5942{
5943 return assign(1, character);
5944}
5945
5946template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5947template <class ALLOC2>
5951 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
5952{
5953 return privateAssignDispatch(
5954 rhs.data(),
5955 rhs.size(),
5956 "string<...>::operator=(std::string&...): string too long");
5957}
5958
5959#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
5960template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5964 std::initializer_list<CHAR_TYPE> values)
5965{
5966 return privateAssignDispatch(
5967 values.begin(),
5968 values.end(),
5969 "string<...>::operator=(initializer_list): string too long");
5970}
5971#endif
5972
5973 // *** 21.3.4 capacity: ***
5974
5975template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5978 CHAR_TYPE character)
5979{
5980 privateThrowLengthError(newLength > max_size(),
5981 "string<...>::resize(n,c): string too long");
5982 privateResizeRaw(newLength, character);
5983}
5984
5985template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5988{
5989 privateThrowLengthError(newLength > max_size(),
5990 "string<...>::resize(n): string too long");
5991 privateResizeRaw(newLength, CHAR_TYPE());
5992}
5993
5994template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5995template <class OPERATION>
5997 size_type newLength,
5998 OPERATION operation)
5999{
6000 privateThrowLengthError(newLength > max_size(),
6001 "string<...>::resize_and_overwrite(n, op): string too long");
6002
6003 privateReserveRaw(newLength);
6004 this->d_length = newLength;
6005
6006#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
6007 size_type finalLength = static_cast<size_type>(
6008 MoveUtil::move(operation)(this->dataPtr(), newLength));
6009#else
6010 size_type finalLength = static_cast<size_type>(
6011 operation(this->dataPtr(), newLength));
6012#endif
6013 BSLS_ASSERT(finalLength <= newLength);
6014 this->d_length = finalLength;
6015 CHAR_TRAITS::assign(*(this->dataPtr() + this->d_length), CHAR_TYPE());
6016}
6017
6018template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6021 size_type newCapacity)
6022{
6023 privateThrowLengthError(newCapacity > max_size(),
6024 "string<...>::reserve(n): string too long");
6025 privateReserveRaw(newCapacity);
6026}
6027
6028template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6031{
6032 if (this->size() < this->d_capacity) {
6033 basic_string temp(this->get_allocator());
6034 temp.privateAppend(this->data(),
6035 this->length(),
6036 "string<...>::shrink_to_fit(): string too long");
6037 quickSwapRetainAllocators(temp);
6038 }
6039}
6040
6041template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6045{
6046 // Note: Stlport and Dinkumware do not deallocate the allocated buffer in
6047 // long string representation, ApacheSTL does.
6048
6049 privateClear(Imp::BASIC_STRING_DEALLOCATE_IN_CLEAR);
6050}
6051
6052 // *** 21.3.3 iterators: ***
6053
6054template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6055inline
6058{
6059 return this->dataPtr();
6060}
6061
6062template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6063inline
6069
6070template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6071inline
6077
6078template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6079inline
6085
6086 // *** 21.3.5 element access: ***
6087
6088template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6089inline
6092{
6093 BSLS_ASSERT_SAFE(position <= length());
6094
6095 return *(begin() + position);
6096}
6097
6098template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6101{
6102 // Note: deliberately not inline, because 1) this is not a very widely used
6103 // function, and 2) it is very convenient to have at least one non-inlined
6104 // element accessor for debugging.
6105
6106 privateThrowOutOfRange(position >= length(),
6107 "string<...>::at(n): invalid position");
6108
6109 return *(begin() + position);
6110}
6111
6112template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6113inline
6114CHAR_TYPE&
6121
6122template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6123inline
6124CHAR_TYPE&
6126{
6128
6129 return *(begin() + length() - 1);
6130}
6131
6132 // *** 21.3.6 modifiers: ***
6133
6134template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6142
6143template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6147 const CHAR_TYPE *rhs)
6148{
6150
6151 return append(rhs);
6152}
6153
6154template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6158{
6159 push_back(character);
6160 return *this;
6161}
6162
6163template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6164template <class STRING_VIEW_LIKE_TYPE>
6169 const STRING_VIEW_LIKE_TYPE& rhs)
6170{
6172 return append(strView.data(),strView.length());
6173}
6174
6175template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6176template <class ALLOC2>
6178basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
6180 const std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC2>& rhs)
6181{
6182 return append(rhs.begin(),rhs.end());
6183}
6184
6185template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6189 const basic_string& suffix)
6190{
6191 return append(suffix, size_type(0), npos);
6192}
6193
6194template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6197 const basic_string& suffix,
6198 size_type position,
6199 size_type numChars)
6200{
6201 privateThrowOutOfRange(
6202 position > suffix.length(),
6203 "string<...>::append(const string&,pos,n): invalid position");
6204
6205 if (numChars > suffix.length() - position) {
6206 numChars = suffix.length() - position;
6207 }
6208 return privateAppend(
6209 suffix.data() + position,
6210 numChars,
6211 "string<...>::append(const string&,pos,n): string too long");
6212}
6213
6214template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6218 const CHAR_TYPE *characterString,
6219 size_type numChars)
6220{
6221 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
6222
6223 return privateAppend(characterString,
6224 numChars,
6225 "string<...>::append(char*...): string too long");
6226}
6227
6228template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6232 const CHAR_TYPE *characterString)
6233{
6234 BSLS_ASSERT_SAFE(characterString);
6235
6236 return append(characterString, CHAR_TRAITS::length(characterString));
6237}
6238
6239template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6243 CHAR_TYPE character)
6244{
6245 return privateAppend(numChars,
6246 character,
6247 "string<...>::append(n,c): string too long");
6248}
6249
6250template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6251template <class STRING_VIEW_LIKE_TYPE>
6256 const STRING_VIEW_LIKE_TYPE& suffix)
6257{
6259 return privateAppend(
6260 strView.data(),
6261 strView.length(),
6262 "string<...>::append(basic_string_view): string too long");
6263}
6264
6265template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6266template <class STRING_VIEW_LIKE_TYPE>
6268 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>&)
6270 const STRING_VIEW_LIKE_TYPE& suffix,
6271 size_type position,
6272 size_type numChars)
6273{
6275 privateThrowOutOfRange(
6276 position > strView.length(),
6277 "string<...>::append(basic_string_view,pos,n): invalid position");
6278
6279 if (numChars > strView.length() - position) {
6280 numChars = strView.length() - position;
6281 }
6282 return privateAppend(
6283 strView.data() + position,
6284 numChars,
6285 "string<...>::append(basic_string_view,pos,n): string too long");
6286}
6287
6288template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6289template <class INPUT_ITER>
6291basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
6293 INPUT_ITER last)
6294{
6295 return privateAppend(first,
6296 last,
6297 "string<...>::append<Iter>(i,j): string too long");
6298}
6299
6300#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
6301template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6305 std::initializer_list<CHAR_TYPE> values)
6306{
6307 return privateAppend(
6308 values.begin(),
6309 values.end(),
6310 "string<...>::append(initializer_list): string too long");
6311}
6312#endif
6313
6314template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6315template <class RANGE>
6318basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
6321{
6322 size_type numChars = privateNumCharsInRange(range);
6323 return privateAppendRange(ranges::begin(range),
6324 ranges::end (range),
6325 numChars,
6326 "string<...>::append_range(r): string too long");
6327}
6328
6329template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6331 CHAR_TYPE character)
6332{
6333 privateThrowLengthError(length() >= max_size(),
6334 "string<...>::push_back(char): string too long");
6335
6336 if (length() + 1 > capacity()) {
6337 privateReserveRaw(length() + 1);
6338 }
6339 CHAR_TRAITS::assign(*(begin() + length()), character);
6340 ++this->d_length;
6341 CHAR_TRAITS::assign(*(begin() + length()), CHAR_TYPE());
6342}
6343
6344template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6348 const basic_string& replacement)
6349{
6350 return this->operator=(replacement);
6351}
6352
6353template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6354inline
6357 BloombergLP::bslmf::MovableRef<basic_string> replacement)
6359{
6360 basic_string& other = replacement;
6361 return this->operator=(MoveUtil::move(other));
6362}
6363
6364template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6367 const basic_string& replacement,
6368 size_type position,
6369 size_type numChars)
6370{
6371 privateThrowOutOfRange(
6372 position > replacement.length(),
6373 "string<...>::assign(const string&,pos,n): invalid position");
6374
6375 if (numChars > replacement.length() - position) {
6376 numChars = replacement.length() - position;
6377 }
6378 return privateAssignDispatch(
6379 replacement.data() + position,
6380 numChars,
6381 "string<...>::assign(const string&,pos,n): invalid position");
6382}
6383
6384template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6388 const CHAR_TYPE *characterString)
6389{
6390 BSLS_ASSERT_SAFE(characterString);
6391
6392 return assign(characterString, CHAR_TRAITS::length(characterString));
6393}
6394
6395template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6399 const CHAR_TYPE *characterString,
6400 size_type numChars)
6401{
6402 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
6403
6404 return privateAssignDispatch(
6405 characterString,
6406 numChars,
6407 "string<...>::assign(char*...): string too long");
6408}
6409
6410template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6411template <class STRING_VIEW_LIKE_TYPE>
6416 const STRING_VIEW_LIKE_TYPE& replacement)
6417{
6418 const bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS> strView = replacement;
6419
6420 return this->operator=(strView);
6421}
6422
6423template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6424template <class STRING_VIEW_LIKE_TYPE>
6427 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>&)
6429 const STRING_VIEW_LIKE_TYPE& replacement,
6430 size_type position,
6431 size_type numChars)
6432{
6433 const bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS> strView = replacement;
6434
6435 privateThrowOutOfRange(
6436 position > strView.length(),
6437 "string<...>::assign(const StrViewLike&,pos,n): invalid position");
6438
6439 if (numChars > strView.length() - position) {
6440 numChars = strView.length() - position;
6441 }
6442 return privateAssignDispatch(
6443 strView.data() + position,
6444 numChars,
6445 "string<...>::assign(const StrViewLike&,pos,n): invalid position");
6446}
6447
6448template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6449template <class ALLOC2>
6451basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>&
6453 const std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC2>& string)
6454{
6455 return this->operator=(string);
6456}
6457
6458template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6462 CHAR_TYPE character)
6463{
6464 return privateAssignDispatch(numChars,
6465 character,
6466 "string<...>::assign(n,c): string too long");
6467}
6468
6469template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6470template <class INPUT_ITER>
6474 INPUT_ITER last)
6475{
6476 return privateAssignDispatch(
6477 first,
6478 last,
6479 "string<...>::assign<Iter>(i,j): string too long");
6480}
6481
6482#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
6483template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6487 std::initializer_list<CHAR_TYPE> values)
6488{
6489 return privateAssignDispatch(
6490 values.begin(),
6491 values.end(),
6492 "string<...>::assign(initializer_list): string too long");
6493}
6494#endif
6495
6496template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6497template <class RANGE>
6500basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
6503{
6504 size_type numChars = privateNumCharsInRange(range);
6505 return privateAssignRangeDispatch(
6506 ranges::begin(range),
6507 ranges::end (range),
6508 numChars,
6509 "string<...>::assign<Range>(r): string too long");
6510}
6511
6512template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6516 size_type position,
6517 const basic_string& other)
6518{
6519 return insert(position, other, size_type(0), npos);
6520}
6521
6522template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6525 size_type position,
6526 const basic_string& other,
6527 size_type sourcePosition,
6528 size_type numChars)
6529{
6530 privateThrowOutOfRange(
6531 position > length(),
6532 "string<...>::insert(pos,const string&...): invalid position");
6533 privateThrowOutOfRange(
6534 sourcePosition > other.length(),
6535 "string<...>::insert(pos,const string&...): invalid source position");
6536
6537 if (numChars > other.length() - sourcePosition) {
6538 numChars = other.length() - sourcePosition;
6539 }
6540 privateThrowLengthError(
6541 numChars > max_size() - length(),
6542 "string<...>::insert(pos,const string&...): string too long");
6543 return privateInsertRaw(position, other.data() + sourcePosition, numChars);
6544}
6545
6546template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6549 size_type position,
6550 const CHAR_TYPE *characterString,
6551 size_type numChars)
6552{
6553 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
6554
6555 privateThrowOutOfRange(
6556 position > length(),
6557 "string<...>::insert(pos,char*...): invalid position");
6558
6559 privateThrowLengthError(
6560 numChars > max_size() - length(),
6561 "string<...>::insert(pos,char*...): string too long");
6562 return privateInsertRaw(position, characterString, numChars);
6563}
6564
6565template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6569 size_type position,
6570 const CHAR_TYPE *characterString)
6571{
6572 BSLS_ASSERT_SAFE(characterString);
6573
6574 return insert(position,
6575 characterString,
6576 CHAR_TRAITS::length(characterString));
6577}
6578
6579template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6582 size_type numChars,
6583 CHAR_TYPE character)
6584{
6585 privateThrowOutOfRange(position > length(),
6586 "string<...>::insert(pos,n,c): invalid position");
6587
6588 privateThrowLengthError(numChars > max_size() - length(),
6589 "string<...>::insert(pos,n,c): string too long");
6590 return privateReplaceRaw(position, size_type(0), numChars, character);
6591}
6592
6593template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6596 CHAR_TYPE character)
6597{
6598 BSLS_ASSERT_SAFE(position >= cbegin());
6599 BSLS_ASSERT_SAFE(position <= cend());
6600
6601 size_type pos = position - cbegin();
6602 insert(pos, size_type(1), character);
6603 return begin() + pos;
6604}
6605
6606#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
6607 // Sun CC compiler doesn't like that 'iterator' return type of 'insert'
6608 // method with an additional 'INPUT_ITER' template parameter depends on
6609 // template parameters of the primary template class @ref basic_string .
6610 // However, it happily accepts 'CHAR_TYPE *', which is how 'iterator' is
6611 // currently defined. It will also accept an inline definition of this
6612 // method (this workaround should be used when 'iterator' becomes a real
6613 // class and the current workaround stops working).
6614# define BSLSTL_INSERT_RETURN_TYPE CHAR_TYPE *
6615#else
6616# define BSLSTL_INSERT_RETURN_TYPE \
6617 typename basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::iterator
6618#endif
6619
6620template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6621template <class INPUT_ITER>
6622inline
6625 INPUT_ITER first,
6626 INPUT_ITER last)
6627{
6628 BSLS_ASSERT_SAFE(position >= cbegin());
6629 BSLS_ASSERT_SAFE(position <= cend());
6630
6631 size_type pos = position - cbegin();
6632 privateInsertDispatch(position, first, last);
6633 return begin() + pos;
6634}
6635
6636template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6637inline
6640 size_type numChars,
6641 CHAR_TYPE character)
6642{
6643 BSLS_ASSERT_SAFE(position >= cbegin());
6644 BSLS_ASSERT_SAFE(position <= cend());
6645
6646 size_type pos = position - cbegin();
6647 insert(pos, numChars, character);
6648 return begin() + pos;
6649}
6650
6651template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6652template <class STRING_VIEW_LIKE_TYPE>
6656 size_type position,
6657 const STRING_VIEW_LIKE_TYPE& other)
6658{
6660 privateThrowOutOfRange(
6661 position > length(),
6662 "string<...>::insert(pos,const string_view&): invalid position");
6663 privateThrowLengthError(
6664 strView.length() > max_size() - length(),
6665 "string<...>::insert(pos,const string_view&): string too long");
6666 return privateInsertRaw(position, strView.data(), strView.length());
6667}
6668
6669template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6670template <class STRING_VIEW_LIKE_TYPE>
6672 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>&)
6673basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::insert(
6674 size_type position,
6675 const STRING_VIEW_LIKE_TYPE& other,
6676 size_type sourcePosition,
6677 size_type numChars)
6678{
6680 privateThrowOutOfRange(
6681 position > length(),
6682 "string<...>::insert(pos,const string_view&...): invalid position");
6683 privateThrowOutOfRange(sourcePosition > strView.length(),
6684 "string<...>::insert(pos,const string_view&...): "
6685 "invalid source position");
6686
6687 if (numChars > strView.length() - sourcePosition) {
6688 numChars = strView.length() - sourcePosition;
6689 }
6690 privateThrowLengthError(
6691 numChars > max_size() - length(),
6692 "string<...>::insert(pos,const string&...): string too long");
6693 return privateInsertRaw(position,
6694 strView.data() + sourcePosition,
6695 numChars);
6696}
6697
6698#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
6699template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6700inline
6702basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::insert(
6703 const_iterator position,
6704 std::initializer_list<CHAR_TYPE> values)
6705{
6706 BSLS_ASSERT_SAFE(position >= cbegin());
6707 BSLS_ASSERT_SAFE(position <= cend());
6708
6709 size_type pos = position - cbegin();
6710 privateInsertDispatch(position, values.begin(), values.end());
6711 return begin() + pos;
6712}
6713#endif
6714
6715template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6716template <class RANGE>
6718inline
6721 const_iterator position,
6723{
6724 BSLS_ASSERT_SAFE(position >= cbegin());
6725 BSLS_ASSERT_SAFE(position <= cend());
6726
6727 size_type pos = position - cbegin();
6728 size_type inNumChars = privateNumCharsInRange(range);
6729 privateInsertRange(position,
6730 inNumChars,
6731 ranges::begin(range),
6732 ranges:: end(range));
6733 return begin() + pos;
6734}
6735
6736#undef BSLSTL_INSERT_RETURN_TYPE
6737
6738template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6741 size_type numChars)
6742{
6743 privateThrowOutOfRange(position > length(),
6744 "string<...>::erase(pos,n): invalid position");
6745
6746 if (numChars > length() - position) {
6747 numChars = length() - position;
6748 }
6749 if (numChars) {
6750 this->d_length -= numChars;
6751 CHAR_TRAITS::move(this->dataPtr() + position,
6752 this->dataPtr() + position + numChars,
6753 this->d_length - position);
6754 CHAR_TRAITS::assign(*(begin() + length()), CHAR_TYPE());
6755 }
6756 return *this;
6757}
6758
6759template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6762{
6763 BSLS_ASSERT_SAFE(position >= cbegin());
6764 BSLS_ASSERT_SAFE(position < cend());
6765
6766 const_iterator postPosition = position;
6767 iterator dstPosition = begin() + (position - cbegin());
6768
6769 ++postPosition;
6770 CHAR_TRAITS::move(&*dstPosition, &*postPosition, cend() - postPosition);
6771
6772 --this->d_length;
6773 CHAR_TRAITS::assign(*(this->dataPtr() + length()), CHAR_TYPE());
6774
6775 return dstPosition;
6776}
6777
6778template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6781 const_iterator last)
6782{
6783 BSLS_ASSERT_SAFE(first >= cbegin());
6784 BSLS_ASSERT_SAFE(first <= cend());
6785 BSLS_ASSERT_SAFE(last >= cbegin());
6786 BSLS_ASSERT_SAFE(last <= cend());
6787 BSLS_ASSERT_SAFE(last - first >= 0);
6788
6789 iterator dstFirst = begin() + (first - cbegin());
6790
6791 if (first != last) {
6792 CHAR_TRAITS::move(&*dstFirst, &*last, cend() - last);
6793
6794 this->d_length -= last - first;
6795 CHAR_TRAITS::assign(*(this->dataPtr() + length()), CHAR_TYPE());
6796 }
6797
6798 return dstFirst;
6799}
6800
6801template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6802inline
6804{
6806
6807 --this->d_length;
6808 CHAR_TRAITS::assign(*(begin() + length()), CHAR_TYPE());
6809}
6810
6811template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6814 size_type outPosition,
6815 size_type outNumChars,
6816 const basic_string& replacement)
6817{
6818 privateThrowOutOfRange(
6819 length() < outPosition,
6820 "string<...>::replace(pos,const string&...): invalid position");
6821 if (outNumChars > length() - outPosition) {
6822 outNumChars = length() - outPosition;
6823 }
6824 privateThrowLengthError(
6825 replacement.length() > outNumChars &&
6826 replacement.length() - outNumChars > max_size() - length(),
6827 "string<...>::replace(pos,const string&...): string too long");
6828 return privateReplaceRaw(outPosition,
6829 outNumChars,
6830 replacement.data(),
6831 replacement.length());
6832}
6833
6834template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6837 size_type outPosition,
6838 size_type outNumChars,
6839 const basic_string& replacement,
6840 size_type position,
6841 size_type numChars)
6842{
6843 privateThrowOutOfRange(
6844 length() < outPosition,
6845 "string<...>::replace(pos,const string&...): invalid position");
6846
6847 if (outNumChars > length() - outPosition) {
6848 outNumChars = length() - outPosition;
6849 }
6850 privateThrowOutOfRange(
6851 position > replacement.length(),
6852 "string<...>::replace(pos,const string&...): invalid position");
6853
6854 if (numChars > replacement.length() - position) {
6855 numChars = replacement.length() - position;
6856 }
6857 privateThrowLengthError(
6858 numChars > outNumChars &&
6859 numChars - outNumChars > max_size() - length(),
6860 "string<...>::replace(pos,const string&...): string too long");
6861 return privateReplaceRaw(outPosition,
6862 outNumChars,
6863 replacement.data() + position,
6864 numChars);
6865}
6866
6867template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6870 size_type outPosition,
6871 size_type outNumChars,
6872 const CHAR_TYPE *characterString,
6873 size_type numChars)
6874{
6875 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
6876
6877 privateThrowOutOfRange(
6878 length() < outPosition,
6879 "string<...>::replace(pos,char*...): invalid position");
6880
6881 if (outNumChars > length() - outPosition) {
6882 outNumChars = length() - outPosition;
6883 }
6884
6885 privateThrowLengthError(
6886 numChars > outNumChars &&
6887 numChars - outNumChars > max_size() - length(),
6888 "string<...>::replace(pos,char*...): string too long");
6889 return privateReplaceRaw(outPosition,
6890 outNumChars,
6891 characterString,
6892 numChars);
6893}
6894
6895template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6899 size_type outPosition,
6900 size_type outNumChars,
6901 const CHAR_TYPE *characterString)
6902{
6903 BSLS_ASSERT_SAFE(characterString);
6904
6905 return replace(outPosition,
6906 outNumChars,
6907 characterString,
6908 CHAR_TRAITS::length(characterString));
6909}
6910
6911template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6914 size_type outNumChars,
6915 size_type numChars,
6916 CHAR_TYPE character)
6917{
6918 privateThrowOutOfRange(
6919 length() < outPosition,
6920 "string<...>::replace(pos,n,c): invalid position");
6921 if (outNumChars > length() - outPosition) {
6922 outNumChars = length() - outPosition;
6923 }
6924 privateThrowLengthError(
6925 numChars > outNumChars &&
6926 numChars - outNumChars > max_size() - length(),
6927 "string<...>::replace(pos,n,c): string too long");
6928 return privateReplaceRaw(outPosition,
6929 outNumChars,
6930 numChars,
6931 character);
6932}
6933
6934template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6935template <class STRING_VIEW_LIKE_TYPE>
6939 size_type outPosition,
6940 size_type outNumChars,
6941 const STRING_VIEW_LIKE_TYPE& replacement)
6942{
6943 privateThrowOutOfRange(
6944 length() < outPosition,
6945 "string<...>::replace(pos,const strView&...): invalid position");
6946 if (outNumChars > length() - outPosition) {
6947 outNumChars = length() - outPosition;
6948 }
6949
6951 privateThrowLengthError(
6952 strView.length() > outNumChars &&
6953 strView.length() - outNumChars > max_size() - length(),
6954 "string<...>::replace(pos,const strView&...): string too long");
6955 return privateReplaceRaw(outPosition,
6956 outNumChars,
6957 strView.data(),
6958 strView.length());
6959}
6960
6961template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6962template <class STRING_VIEW_LIKE_TYPE>
6964 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>&)
6966 size_type outPosition,
6967 size_type outNumChars,
6968 const STRING_VIEW_LIKE_TYPE& replacement,
6969 size_type position,
6970 size_type numChars)
6971{
6972 privateThrowOutOfRange(
6973 length() < outPosition,
6974 "string<...>::replace(pos,const strView&...): invalid position");
6975
6976 if (outNumChars > length() - outPosition) {
6977 outNumChars = length() - outPosition;
6978 }
6979
6981 privateThrowOutOfRange(
6982 position > strView.length(),
6983 "string<...>::replace(pos,const strView&...): invalid position");
6984
6985 if (numChars > strView.length() - position) {
6986 numChars = strView.length() - position;
6987 }
6988 privateThrowLengthError(
6989 numChars > outNumChars &&
6990 numChars - outNumChars > max_size() - length(),
6991 "string<...>::replace(pos,const strView&...): string too long");
6992 return privateReplaceRaw(outPosition,
6993 outNumChars,
6994 strView.data() + position,
6995 numChars);
6996}
6997
6998template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6999basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
7001 const_iterator first,
7002 const_iterator last,
7003 const basic_string& replacement)
7004{
7005 BSLS_ASSERT_SAFE(first >= cbegin());
7006 BSLS_ASSERT_SAFE(first <= cend());
7007 BSLS_ASSERT_SAFE(first <= last);
7008 BSLS_ASSERT_SAFE(last <= cend());
7009
7010 size_type outPosition = first - cbegin();
7011 size_type outNumChars = last - first;
7012
7013 privateThrowLengthError(
7014 replacement.length() > outNumChars &&
7015 replacement.length() - outNumChars > max_size() - length(),
7016 "string<...>::replace(const string&...): string too long");
7017
7018 return privateReplaceRaw(outPosition,
7019 outNumChars,
7020 replacement.data(),
7021 replacement.length());
7022}
7023
7024template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7025template <class STRING_VIEW_LIKE_TYPE>
7029 const_iterator first,
7030 const_iterator last,
7031 const STRING_VIEW_LIKE_TYPE& replacement)
7032{
7033 BSLS_ASSERT_SAFE(first >= cbegin());
7034 BSLS_ASSERT_SAFE(first <= cend());
7035 BSLS_ASSERT_SAFE(first <= last);
7036 BSLS_ASSERT_SAFE(last <= cend());
7037
7038 size_type outPosition = first - cbegin();
7039 size_type outNumChars = last - first;
7040
7042 privateThrowLengthError(
7043 strView.length() > outNumChars &&
7044 strView.length() - outNumChars > max_size() - length(),
7045 "string<...>::replace(const strView&...): string too long");
7046
7047 return privateReplaceRaw(outPosition,
7048 outNumChars,
7049 strView.data(),
7050 strView.length());
7051}
7052
7053template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7054basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
7056 const_iterator first,
7057 const_iterator last,
7058 const CHAR_TYPE *characterString,
7059 size_type numChars)
7060{
7061 BSLS_ASSERT_SAFE(first >= cbegin());
7062 BSLS_ASSERT_SAFE(first <= cend());
7063 BSLS_ASSERT_SAFE(first <= last);
7064 BSLS_ASSERT_SAFE(last <= cend());
7065 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
7066
7067 size_type outPosition = first - cbegin();
7068 size_type outNumChars = last - first;
7069 privateThrowLengthError(
7070 numChars > outNumChars &&
7071 numChars - outNumChars > max_size() - length(),
7072 "string<...>::replace(char*...): string too long");
7073 return privateReplaceRaw(outPosition,
7074 outNumChars,
7075 characterString,
7076 numChars);
7077}
7078
7079template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7083 const_iterator first,
7084 const_iterator last,
7085 const CHAR_TYPE *characterString)
7086{
7087 BSLS_ASSERT_SAFE(first >= cbegin());
7088 BSLS_ASSERT_SAFE(first <= cend());
7089 BSLS_ASSERT_SAFE(first <= last);
7090 BSLS_ASSERT_SAFE(last <= cend());
7091 BSLS_ASSERT_SAFE(characterString);
7092
7093 return replace(first,
7094 last,
7095 characterString,
7096 CHAR_TRAITS::length(characterString));
7097}
7098
7099template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7102 const_iterator first,
7103 const_iterator last,
7104 size_type numChars,
7105 CHAR_TYPE character)
7106{
7107 BSLS_ASSERT_SAFE(first >= cbegin());
7108 BSLS_ASSERT_SAFE(first <= cend());
7109 BSLS_ASSERT_SAFE(first <= last);
7110 BSLS_ASSERT_SAFE(last <= cend());
7111
7112 size_type outPosition = first - cbegin();
7113 size_type outNumChars = last - first;
7114 privateThrowLengthError(numChars > outNumChars &&
7115 numChars - outNumChars > max_size() - length(),
7116 "string<...>::replace(n,c): string too long");
7117 return privateReplaceRaw(outPosition, outNumChars, numChars, character);
7118}
7119
7120template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7121template <class INPUT_ITER>
7122inline
7125 const_iterator first,
7126 const_iterator last,
7127 INPUT_ITER stringFirst,
7128 INPUT_ITER stringLast)
7129{
7130 BSLS_ASSERT_SAFE(first >= cbegin());
7131 BSLS_ASSERT_SAFE(first <= cend());
7132 BSLS_ASSERT_SAFE(first <= last);
7133 BSLS_ASSERT_SAFE(last <= cend());
7134
7135 size_type outPosition = first - cbegin();
7136 size_type outNumChars = last - first;
7137 return privateReplaceDispatch(outPosition,
7138 outNumChars,
7139 stringFirst,
7140 stringLast,
7141 stringFirst,
7142 BloombergLP::bslmf::Nil());
7143}
7144
7145template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7146template <class RANGE>
7148inline
7151 const_iterator first,
7152 const_iterator last,
7154{
7155 BSLS_ASSERT_SAFE(first >= cbegin());
7156 BSLS_ASSERT_SAFE(first <= cend());
7157 BSLS_ASSERT_SAFE(first <= last);
7158 BSLS_ASSERT_SAFE(last <= cend());
7159
7160 size_type outPosition = first - cbegin();
7161 size_type outNumChars = last - first;
7162 size_type inNumChars = privateNumCharsInRange(range);
7163
7164 return privateReplaceRange(outPosition,
7165 outNumChars,
7166 inNumChars,
7167 ranges::begin(range),
7168 ranges:: end(range));
7169 return *this;
7170}
7171
7172 // *** 21.3.7 string operations: ***
7173
7174template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7175inline
7176CHAR_TYPE *
7181
7182template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7183void
7186 AllocatorTraits::propagate_on_container_swap::value ||
7187 AllocatorTraits::is_always_equal::value)
7188{
7189 typedef typename
7190 AllocatorTraits::propagate_on_container_swap Propagate;
7191
7192 if (Propagate::value) {
7193 quickSwapExchangeAllocators(other, Propagate());
7194 }
7196 get_allocator() == other.get_allocator())) {
7197 quickSwapRetainAllocators(other);
7198 }
7199 else {
7201
7202 basic_string toThisCopy(MoveUtil::move(other), get_allocator());
7203 basic_string toOtherCopy(MoveUtil::move(*this),
7204 other.get_allocator());
7205
7206 this->quickSwapRetainAllocators(toThisCopy);
7207 other.quickSwapRetainAllocators(toOtherCopy);
7208 }
7209}
7210
7211// ACCESSORS
7212
7213 // *** 21.3.3 iterators: ***
7214
7215template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7216inline
7220{
7221 return this->dataPtr();
7222}
7223
7224template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7225inline
7232
7233template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7234inline
7238{
7239 return begin() + this->d_length;
7240}
7241
7242template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7243inline
7250
7251template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7252inline
7259
7260template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7261inline
7268
7269template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7277
7278template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7286
7287 // *** 21.3.4 capacity: ***
7288
7289template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7290inline
7294{
7295 return this->d_length;
7296}
7297
7298template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7299inline
7303{
7304 return this->d_length;
7305}
7306
7307template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7308inline
7312{
7313 // Must take into account the null-terminating character.
7314
7315 size_type stringMaxSize = ~size_type(0) / sizeof(CHAR_TYPE) - 1;
7316 size_type allocMaxSize = AllocatorTraits::max_size(get_allocator()) - 1;
7317 return allocMaxSize < stringMaxSize ? allocMaxSize : stringMaxSize;
7318}
7319
7320template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7321inline
7325{
7326 return this->d_capacity;
7327}
7328
7329template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7330inline
7333{
7334 return this->d_length == 0;
7335}
7336
7337 // *** 21.3.5 element access: ***
7338
7339template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7340inline
7343 size_type position) const
7344{
7345 BSLS_ASSERT_SAFE(position <= length());
7346
7347 return *(begin() + position);
7348}
7349
7350template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7354{
7355 // Note: deliberately not inlined (see comment in non-'const' version).
7356
7357 privateThrowOutOfRange(position >= length(),
7358 "const string<...>::at(n): invalid position");
7359 return *(begin() + position);
7360}
7361
7362template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7363inline
7364const CHAR_TYPE&
7371
7372template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7373inline
7374const CHAR_TYPE&
7376{
7378
7379 return *(end() - 1);
7380}
7381
7382template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7385 size_type numChars,
7386 size_type position) const
7387{
7388 BSLS_ASSERT_SAFE(characterString);
7389
7390 privateThrowOutOfRange(
7391 length() < position,
7392 "const string<...>::copy(str,pos,n): invalid position");
7393 if (numChars > length() - position) {
7394 numChars = length() - position;
7395 }
7396 CHAR_TRAITS::move(characterString, this->dataPtr() + position, numChars);
7397 return numChars;
7398}
7399
7400 // *** 21.3.7 string operations: ***
7401
7402template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7403inline
7404const CHAR_TYPE *
7407{
7408 return this->dataPtr();
7409}
7410
7411template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7412inline
7413const CHAR_TYPE *
7416{
7417 return this->dataPtr();
7418}
7419
7420template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7421inline
7425{
7426 return this->allocatorRef();
7427}
7428
7429template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7433 const basic_string& substring,
7434 size_type position) const
7436{
7437 return find(substring.data(), position, substring.length());
7438}
7439
7440template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7441template <class STRING_VIEW_LIKE_TYPE>
7445 const STRING_VIEW_LIKE_TYPE& substring,
7446 size_type position,
7449{
7451 return find(strView.data(), position, strView.length());
7452}
7453
7454template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7457 const CHAR_TYPE *substring,
7458 size_type position,
7459 size_type numChars) const
7460{
7461 BSLS_ASSERT_SAFE(substring);
7462
7463 size_type remChars = length() - position;
7464 if (position > length() || numChars > remChars) {
7465 return npos; // RETURN
7466 }
7467 if (0 == numChars) {
7468 return position; // RETURN
7469 }
7470 const CHAR_TYPE *thisString = this->dataPtr() + position;
7471 const CHAR_TYPE *nextString;
7472 for (remChars -= numChars - 1;
7473 0 != (nextString = BSLSTL_CHAR_TRAITS::find(thisString,
7474 remChars,
7475 *substring));
7476 remChars -= ++nextString - thisString, thisString = nextString)
7477 {
7478 if (0 == CHAR_TRAITS::compare(nextString, substring, numChars)) {
7479 return nextString - this->dataPtr(); // RETURN
7480 }
7481 }
7482 return npos;
7483}
7484
7485template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7489 const CHAR_TYPE *substring,
7490 size_type position) const
7491{
7492 BSLS_ASSERT_SAFE(substring);
7493
7494 return find(substring, position, CHAR_TRAITS::length(substring));
7495}
7496
7497template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7500 size_type position) const
7501{
7502 if (position >= length()) {
7503 return npos; // RETURN
7504 }
7505 const CHAR_TYPE *result =
7506 BSLSTL_CHAR_TRAITS::find(this->dataPtr() + position,
7507 length() - position,
7508 character);
7509 return result ? result - this->dataPtr() : npos;
7510}
7511
7512template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7516 const basic_string& substring,
7517 size_type position) const
7519{
7520 return rfind(substring.data(), position, substring.length());
7521}
7522
7523template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7524template <class STRING_VIEW_LIKE_TYPE>
7528 const STRING_VIEW_LIKE_TYPE& substring,
7529 size_type position,
7532{
7534 return rfind(strView.data(), position, strView.length());
7535}
7536
7537template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7540 const CHAR_TYPE *characterString,
7541 size_type position,
7542 size_type numChars) const
7543{
7544 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
7545
7546 if (0 == numChars) {
7547 return position > length() ? length() : position; // RETURN
7548 }
7549 if (numChars <= length()) {
7550 if (position > length() - numChars) {
7551 position = length() - numChars;
7552 }
7553 const CHAR_TYPE *thisString = this->dataPtr() + position;
7554 for (; position != npos; --thisString, --position) {
7555 if (0 == CHAR_TRAITS::compare(thisString,
7556 characterString,
7557 numChars)) {
7558 return position; // RETURN
7559 }
7560 }
7561 }
7562 return npos;
7563}
7564
7565template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7569 const CHAR_TYPE *characterString,
7570 size_type position) const
7571{
7572 BSLS_ASSERT_SAFE(characterString);
7573
7574 return rfind(characterString,
7575 position,
7576 CHAR_TRAITS::length(characterString));
7577}
7578
7579template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7583 size_type position) const
7584{
7585 return rfind(&character, position, size_type(1));
7586}
7587
7588template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7592 const basic_string& characterString,
7593 size_type position) const
7595{
7596 return find_first_of(characterString.data(),
7597 position,
7598 characterString.length());
7599}
7600
7601template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7602template <class STRING_VIEW_LIKE_TYPE>
7606 const STRING_VIEW_LIKE_TYPE& characterString,
7607 size_type position,
7610{
7611 bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS> strView = characterString;
7612 return find_first_of(strView.data(), position, strView.length());
7613}
7614
7615template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7618 const CHAR_TYPE *characterString,
7619 size_type position,
7620 size_type numChars) const
7621{
7622 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
7623
7624 if (0 < numChars && position < length()) {
7625 for (const CHAR_TYPE *current = this->dataPtr() + position;
7626 current != this->dataPtr() + length();
7627 ++current)
7628 {
7629 if (BSLSTL_CHAR_TRAITS::find(characterString, numChars, *current)
7630 != 0) {
7631 return current - this->dataPtr(); // RETURN
7632 }
7633 }
7634 }
7635 return npos;
7636}
7637
7638template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7642 const CHAR_TYPE *characterString,
7643 size_type position) const
7644{
7645 BSLS_ASSERT_SAFE(characterString);
7646
7647 return find_first_of(characterString,
7648 position,
7649 CHAR_TRAITS::length(characterString));
7650}
7651
7652template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7656 CHAR_TYPE character,
7657 size_type position) const
7658{
7659 return find_first_of(&character, position, size_type(1));
7660}
7661
7662template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7666 const basic_string& characterString,
7667 size_type position) const
7669{
7670 return find_last_of(characterString.data(),
7671 position,
7672 characterString.length());
7673}
7674
7675template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7676template <class STRING_VIEW_LIKE_TYPE>
7680 const STRING_VIEW_LIKE_TYPE& characterString,
7681 size_type position,
7684{
7685 bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS> strView = characterString;
7686 return find_last_of(strView.data(), position, strView.length());
7687}
7688
7689template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7692 const CHAR_TYPE *characterString,
7693 size_type position,
7694 size_type numChars) const
7695{
7696 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
7697
7698 if (0 < numChars && 0 < length()) {
7699 size_type remChars = position < length() ? position : length() - 1;
7700 for (const CHAR_TYPE *current = this->dataPtr() + remChars;
7701 ;
7702 --current)
7703 {
7704 if (BSLSTL_CHAR_TRAITS::find(
7705 characterString, numChars, *current)) {
7706 return current - this->dataPtr(); // RETURN
7707 }
7708 if (current == this->dataPtr()) {
7709 break;
7710 }
7711 }
7712 }
7713 return npos;
7714}
7715
7716template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7720 const CHAR_TYPE *characterString,
7721 size_type position) const
7722{
7723 BSLS_ASSERT_SAFE(characterString);
7724
7725 return find_last_of(characterString,
7726 position,
7727 CHAR_TRAITS::length(characterString));
7728}
7729
7730template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7734 CHAR_TYPE character,
7735 size_type position) const
7736{
7737 return find_last_of(&character, position, size_type(1));
7738}
7739
7740template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7744 const basic_string& characterString,
7745 size_type position) const
7747{
7748 return find_first_not_of(characterString.data(),
7749 position,
7750 characterString.length());
7751}
7752
7753template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7754template <class STRING_VIEW_LIKE_TYPE>
7758 const STRING_VIEW_LIKE_TYPE& characterString,
7759 size_type position,
7762{
7763 bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS> strView = characterString;
7764 return find_first_not_of(strView.data(), position, strView.length());
7765}
7766
7767template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7770 const CHAR_TYPE *characterString,
7771 size_type position,
7772 size_type numChars) const
7773{
7774 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
7775
7776 if (position < length()) {
7777 const CHAR_TYPE *last = this->dataPtr() + length();
7778 for (const CHAR_TYPE *current = this->dataPtr() + position;
7779 current != last;
7780 ++current)
7781 {
7782 if (!BSLSTL_CHAR_TRAITS::find(
7783 characterString, numChars, *current)) {
7784 return current - this->dataPtr(); // RETURN
7785 }
7786 }
7787 }
7788 return npos;
7789}
7790
7791template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7795 const CHAR_TYPE *characterString,
7796 size_type position) const
7797{
7798 BSLS_ASSERT_SAFE(characterString);
7799
7800 return find_first_not_of(characterString,
7801 position,
7802 CHAR_TRAITS::length(characterString));
7803}
7804
7805template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7809 CHAR_TYPE character,
7810 size_type position) const
7811{
7812 return find_first_not_of(&character, position, size_type(1));
7813}
7814
7815template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7819 const basic_string& characterString,
7820 size_type position) const
7822{
7823 return find_last_not_of(characterString.data(),
7824 position,
7825 characterString.length());
7826}
7827
7828template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7829template <class STRING_VIEW_LIKE_TYPE>
7833 const STRING_VIEW_LIKE_TYPE& characterString,
7834 size_type position,
7837{
7838 bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS> strView = characterString;
7839 return find_last_not_of(strView.data(), position, strView.length());
7840}
7841
7842template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7845 const CHAR_TYPE *characterString,
7846 size_type position,
7847 size_type numChars) const
7848{
7849 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
7850
7851 if (0 < length()) {
7852 size_type remChars = position < length() ? position : length() - 1;
7853 for (const CHAR_TYPE *current = this->dataPtr() + remChars;
7854 remChars != npos;
7855 --current, --remChars)
7856 {
7857 if (!BSLSTL_CHAR_TRAITS::find(
7858 characterString, numChars, *current)) {
7859 return current - this->dataPtr(); // RETURN
7860 }
7861 }
7862 }
7863 return npos;
7864}
7865
7866template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7870 const CHAR_TYPE *characterString,
7871 size_type position) const
7872{
7873 BSLS_ASSERT_SAFE(characterString);
7874
7875 return find_last_not_of(characterString,
7876 position,
7877 CHAR_TRAITS::length(characterString));
7878}
7879
7880template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7884 CHAR_TYPE character,
7885 size_type position) const
7886{
7887 return find_last_not_of(&character, position, size_type(1));
7888}
7889
7890template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7898
7899template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7902 CHAR_TYPE character) const BSLS_KEYWORD_NOEXCEPT
7903{
7904 return npos != find(character);
7905}
7906
7907template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7910 const CHAR_TYPE* characterString) const
7911{
7912 BSLS_ASSERT_SAFE(characterString);
7913 return npos != find(characterString);
7914}
7915
7916template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7921{
7922 return (length() >= characterString.length() &&
7923 0 == CHAR_TRAITS::compare(data(),
7924 characterString.data(),
7925 characterString.size()));
7926}
7927
7928template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7931 CHAR_TYPE character) const BSLS_KEYWORD_NOEXCEPT
7932{
7933 return (0 < length() && CHAR_TRAITS::eq(*data(), character));
7934}
7935
7936template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7939 const CHAR_TYPE *characterString) const
7940{
7941 BSLS_ASSERT_SAFE(characterString);
7942
7943 std::size_t strLength = CHAR_TRAITS::length(characterString);
7944 return (length() >= strLength &&
7945 0 == CHAR_TRAITS::compare(data(),
7946 characterString,
7947 strLength));
7948}
7949
7950template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7955{
7956 return (length() >= characterString.length() &&
7957 0 == CHAR_TRAITS::compare(
7958 data() + length() - characterString.length(),
7959 characterString.data(),
7960 characterString.size()));
7961}
7962
7963template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7966 CHAR_TYPE character) const BSLS_KEYWORD_NOEXCEPT
7967{
7968 return (0 < length() &&
7969 CHAR_TRAITS::eq(*(data()+ length() - 1), character));
7970}
7971
7972template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7975 const CHAR_TYPE *characterString) const
7976{
7977 BSLS_ASSERT_SAFE(characterString);
7978
7979 std::size_t strLength = CHAR_TRAITS::length(characterString);
7980 return (length() >= strLength &&
7981 0 == CHAR_TRAITS::compare(data() + length() - strLength,
7982 characterString,
7983 strLength));
7984}
7985
7986#ifdef BSLS_COMPILERFEATURES_SUPPORT_REF_QUALIFIERS
7987template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7988inline
7991 size_type position,
7992 size_type numChars) const &
7993{
7994 return basic_string<CHAR_TYPE,
7996 ALLOCATOR>(*this, position, numChars);
7997}
7998
7999template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8000inline
8001basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>
8003 size_type numChars) &&
8004{
8005 return basic_string<CHAR_TYPE,
8007 ALLOCATOR>(MoveUtil::move(*this), position, numChars);
8008}
8009#else
8010template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8012basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>
8014 size_type numChars) const
8015{
8016 return basic_string<CHAR_TYPE,
8018 ALLOCATOR>(*this, position, numChars);
8019}
8020#endif
8021
8022template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8025 const basic_string& other) const
8027{
8028 return privateCompareRaw(size_type(0),
8029 length(),
8030 other.data(),
8031 other.length());
8032}
8033
8034template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8036 size_type position,
8037 size_type numChars,
8038 const basic_string& other) const
8039{
8040 privateThrowOutOfRange(
8041 length() < position,
8042 "const string<...>::compare(pos,n,...): invalid position");
8043 if (numChars > length() - position) {
8044 numChars = length() - position;
8045 }
8046 return privateCompareRaw(position, numChars, other.data(), other.length());
8047}
8048
8049template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8051 size_type lhsPosition,
8052 size_type lhsNumChars,
8053 const basic_string& other,
8054 size_type otherPosition,
8055 size_type otherNumChars) const
8056{
8057 privateThrowOutOfRange(
8058 length() < lhsPosition,
8059 "const string<...>::compare(pos,n,...): invalid position");
8060 if (lhsNumChars > length() - lhsPosition) {
8061 lhsNumChars = length() - lhsPosition;
8062 }
8063 privateThrowOutOfRange(
8064 other.length() < otherPosition,
8065 "const string<...>::compare(pos,n,...): invalid position");
8066 if (otherNumChars > other.length() - otherPosition) {
8067 otherNumChars = other.length() - otherPosition;
8068 }
8069 return privateCompareRaw(lhsPosition,
8070 lhsNumChars,
8071 other.dataPtr() + otherPosition,
8072 otherNumChars);
8073}
8074
8075template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8078 const CHAR_TYPE *other) const
8079{
8080 BSLS_ASSERT_SAFE(other);
8081
8082 return privateCompareRaw(size_type(0),
8083 length(),
8084 other,
8085 CHAR_TRAITS::length(other));
8086}
8087
8088template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8090 size_type lhsPosition,
8091 size_type lhsNumChars,
8092 const CHAR_TYPE *other,
8093 size_type otherNumChars) const
8094{
8095 BSLS_ASSERT_SAFE(other);
8096
8097 privateThrowOutOfRange(
8098 length() < lhsPosition,
8099 "const string<...>::compare(pos,n,...): invalid position");
8100 if (lhsNumChars > length() - lhsPosition) {
8101 lhsNumChars = length() - lhsPosition;
8102 }
8103 return privateCompareRaw(lhsPosition,
8104 lhsNumChars,
8105 other,
8106 otherNumChars);
8107}
8108
8109template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8112 size_type lhsPosition,
8113 size_type lhsNumChars,
8114 const CHAR_TYPE *other) const
8115{
8116 BSLS_ASSERT_SAFE(other);
8117
8118 return compare(lhsPosition,
8119 lhsNumChars,
8120 other,
8121 CHAR_TRAITS::length(other));
8122}
8123
8124template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8125template <class STRING_VIEW_LIKE_TYPE>
8128 const STRING_VIEW_LIKE_TYPE& other,
8131{
8133
8134 return privateCompareRaw(size_type(0),
8135 length(),
8136 strView.data(),
8137 strView.length());
8138}
8139
8140template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8141template <class STRING_VIEW_LIKE_TYPE>
8143 size_type position,
8144 size_type numChars,
8145 const STRING_VIEW_LIKE_TYPE& other,
8147{
8148 privateThrowOutOfRange(
8149 length() < position,
8150 "string<...>::compare(pos,n,StrViewLike): invalid position");
8151
8153
8154 if (numChars > length() - position) {
8155 numChars = length() - position;
8156 }
8157 return privateCompareRaw(position,
8158 numChars,
8159 strView.data(),
8160 strView.length());
8161}
8162
8163template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8164template <class STRING_VIEW_LIKE_TYPE>
8166 size_type lhsPosition,
8167 size_type lhsNumChars,
8168 const STRING_VIEW_LIKE_TYPE& other,
8169 size_type otherPosition,
8170 size_type otherNumChars,
8172{
8173 privateThrowOutOfRange(
8174 length() < lhsPosition,
8175 "string<...>::compare(pos,n, StrViewLike,...): invalid lhs position");
8176
8178
8179 privateThrowOutOfRange(
8180 strView.length() < otherPosition,
8181 "string<...>::compare(pos,n, StrViewLike,...): invalid rhs position");
8182
8183 if (lhsNumChars > length() - lhsPosition) {
8184 lhsNumChars = length() - lhsPosition;
8185 }
8186 if (otherNumChars > other.length() - otherPosition) {
8187 otherNumChars = other.length() - otherPosition;
8188 }
8189 return privateCompareRaw(lhsPosition,
8190 lhsNumChars,
8191 strView.data() + otherPosition,
8192 otherNumChars);
8193}
8194
8195template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8202
8203#ifdef BSLSTL_STRING_VIEW_AND_STD_STRING_VIEW_COEXIST
8204template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8205inline
8207operator std::basic_string_view<CHAR_TYPE, CHAR_TRAITS>() const
8208{
8209 return {data(), size()};
8210}
8211#endif // BSLSTL_STRING_VIEW_AND_STD_STRING_VIEW_COEXIST
8212
8213// PUBLIC ACCESSORS
8214template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8217operator()(const basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& input) const
8218{
8219 using ::BloombergLP::bslh::hashAppend;
8220 ::BloombergLP::bslh::Hash<>::HashAlgorithm hashAlg;
8221 hashAlg(input.data(), sizeof(CHAR_TYPE) * input.size());
8222 hashAppend(hashAlg, input.size());
8223 return static_cast<std::size_t>(hashAlg.computeHash());
8224}
8225
8226template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8229operator()(const CHAR_TYPE *input) const
8230{
8231 BSLS_ASSERT_SAFE(input);
8232 using ::BloombergLP::bslh::hashAppend;
8233 std::size_t length = CHAR_TRAITS::length(input);
8234 ::BloombergLP::bslh::Hash<>::HashAlgorithm hashAlg;
8235 hashAlg(input, sizeof(CHAR_TYPE) * length);
8236 hashAppend(hashAlg, length);
8237 return static_cast<std::size_t>(hashAlg.computeHash());
8238}
8239
8240#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
8241// DRQS 132030795
8242inline
8243std::size_t hash<string>::operator()(const string& input) const
8244{
8245 using ::BloombergLP::bslh::hashAppend;
8246 ::BloombergLP::bslh::Hash<>::HashAlgorithm hashAlg;
8247 hashAlg(input.data(), input.size());
8248 hashAppend(hashAlg, input.size());
8249 return static_cast<std::size_t>(hashAlg.computeHash());
8250}
8251
8252inline
8253std::size_t hash<string>::operator()(const char *input) const
8254{
8255 BSLS_ASSERT_SAFE(input);
8256 using ::BloombergLP::bslh::hashAppend;
8257 std::size_t length = char_traits<char>::length(input);
8258 ::BloombergLP::bslh::Hash<>::HashAlgorithm hashAlg;
8259 hashAlg(input, length);
8260 hashAppend(hashAlg, length);
8261 return static_cast<std::size_t>(hashAlg.computeHash());
8262}
8263
8264inline
8265std::size_t hash<wstring>::operator()(const wstring& input) const
8266{
8267 using ::BloombergLP::bslh::hashAppend;
8268 ::BloombergLP::bslh::Hash<>::HashAlgorithm hashAlg;
8269 hashAlg(input.data(), sizeof(wchar_t) * input.size());
8270 hashAppend(hashAlg, input.size());
8271 return static_cast<std::size_t>(hashAlg.computeHash());
8272}
8273
8274inline
8275std::size_t hash<wstring>::operator()(const wchar_t *input) const
8276{
8277 BSLS_ASSERT_SAFE(input);
8278 using ::BloombergLP::bslh::hashAppend;
8279 std::size_t length = char_traits<wchar_t>::length(input);
8280 ::BloombergLP::bslh::Hash<>::HashAlgorithm hashAlg;
8281 hashAlg(input, sizeof(wchar_t) * length);
8282 hashAppend(hashAlg, length);
8283 return static_cast<std::size_t>(hashAlg.computeHash());
8284}
8285
8286#endif
8287
8288} // close namespace bsl
8289
8290// FREE FUNCTIONS
8291template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8292inline
8293void bsl::swap(basic_string<CHAR_TYPE,CHAR_TRAITS, ALLOCATOR>& a,
8294 basic_string<CHAR_TYPE,CHAR_TRAITS, ALLOCATOR>& b)
8297{
8298 a.swap(b);
8299}
8300
8301template <class CHAR_TYPE,
8302 class CHAR_TRAITS,
8303 class ALLOCATOR,
8304 class OTHER_CHAR_TYPE>
8305inline
8307bsl::erase(basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& str,
8308 const OTHER_CHAR_TYPE& c)
8309{
8310 typename basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::iterator it =
8311 bsl::remove(str.begin(), str.end(), c);
8312
8313 typename basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::size_type
8314 result = bsl::distance(it, str.end());
8315
8316 str.erase(it, str.end());
8317
8318 return result;
8319}
8320
8321template <class CHAR_TYPE,
8322 class CHAR_TRAITS,
8323 class ALLOCATOR,
8324 class UNARY_PREDICATE>
8325inline
8327bsl::erase_if(basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& str,
8328 const UNARY_PREDICATE& pred)
8329{
8330 typename basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::iterator it =
8331 bsl::remove_if(str.begin(), str.end(), pred);
8332
8333 typename basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::size_type
8334 result = bsl::distance(it, str.end());
8335
8336 str.erase(it, str.end());
8337
8338 return result;
8339}
8340
8341// FREE OPERATORS
8342template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8343inline
8344bool bsl::operator==(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
8345 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
8347{
8348 return lhs.size() == rhs.size()
8349 && 0 == CHAR_TRAITS::compare(lhs.data(), rhs.data(), lhs.size());
8350}
8351
8352template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8353inline
8354bool
8356 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
8358{
8359 return lhs.size() == rhs.size()
8360 && 0 == CHAR_TRAITS::compare(lhs.data(), rhs.data(), lhs.size());
8361}
8362
8363template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8364inline
8365bool bsl::operator==(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
8366 const CHAR_TYPE *rhs)
8367{
8368 BSLS_ASSERT_SAFE(rhs);
8369
8370 std::size_t len = CHAR_TRAITS::length(rhs);
8371 return lhs.size() == len
8372 && 0 == CHAR_TRAITS::compare(lhs.data(), rhs, len);
8373}
8374
8375#ifdef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
8376
8377template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8378inline bsl::String_ComparisonCategoryType<CHAR_TRAITS>
8379bsl::operator<=>(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
8380 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
8382{
8383 return static_cast<String_ComparisonCategoryType<CHAR_TRAITS>>(
8384 lhs.compare(rhs) <=> 0);
8385}
8386
8387template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8388inline bsl::String_ComparisonCategoryType<CHAR_TRAITS>
8389bsl::operator<=>(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
8390 const CHAR_TYPE *rhs)
8391{
8392 BSLS_ASSERT_SAFE(rhs);
8393 return static_cast<String_ComparisonCategoryType<CHAR_TRAITS>>(
8394 lhs.compare(rhs) <=> 0);
8395}
8396
8397template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8398inline bsl::String_ComparisonCategoryType<CHAR_TRAITS>
8399bsl::operator<=>(const bsl::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
8400 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
8402{
8403 return static_cast<String_ComparisonCategoryType<CHAR_TRAITS>>(
8404 lhs.compare(rhs) <=> 0);
8405}
8406
8407#else
8408
8409template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8410inline
8411bool
8412bsl::operator==(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
8415{
8416 return lhs.size() == rhs.size()
8417 && 0 == CHAR_TRAITS::compare(lhs.data(), rhs.data(), lhs.size());
8418}
8419
8420template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8421inline
8422bool bsl::operator==(const CHAR_TYPE *lhs,
8423 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
8424{
8425 BSLS_ASSERT_SAFE(lhs);
8426
8427 std::size_t len = CHAR_TRAITS::length(lhs);
8428 return len == rhs.size()
8429 && 0 == CHAR_TRAITS::compare(lhs, rhs.data(), len);
8430}
8431
8432template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8433inline
8434bool bsl::operator!=(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
8435 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
8437{
8438 return !(lhs == rhs);
8439}
8440
8441template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8442inline
8443bool
8444bsl::operator!=(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
8447{
8448 return !(lhs == rhs);
8449}
8450
8451template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8452inline
8453bool
8455 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
8457{
8458 return !(lhs == rhs);
8459}
8460
8461template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8462inline
8463bool bsl::operator!=(const CHAR_TYPE *lhs,
8464 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
8465{
8466 BSLS_ASSERT_SAFE(lhs);
8467
8468 return !(lhs == rhs);
8469}
8470
8471template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8472inline
8473bool bsl::operator!=(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
8474 const CHAR_TYPE *rhs)
8475{
8476 BSLS_ASSERT_SAFE(rhs);
8477
8478 return !(lhs == rhs);
8479}
8480
8481template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8482bool bsl::operator<(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
8483 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
8485{
8486 const std::size_t minLen = lhs.length() < rhs.length()
8487 ? lhs.length() : rhs.length();
8488
8489 int ret = CHAR_TRAITS::compare(lhs.data(), rhs.data(), minLen);
8490 if (0 == ret) {
8491 return lhs.length() < rhs.length(); // RETURN
8492 }
8493 return ret < 0;
8494}
8495
8496template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8497bool
8498bsl::operator<(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
8501{
8502 const std::size_t minLen = lhs.length() < rhs.length()
8503 ? lhs.length() : rhs.length();
8504
8505 int ret = CHAR_TRAITS::compare(lhs.data(), rhs.data(), minLen);
8506 if (0 == ret) {
8507 return lhs.length() < rhs.length(); // RETURN
8508 }
8509 return ret < 0;
8510}
8511
8512template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8513bool
8515 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
8517{
8518 const std::size_t minLen = lhs.length() < rhs.length()
8519 ? lhs.length() : rhs.length();
8520
8521 int ret = CHAR_TRAITS::compare(lhs.data(), rhs.data(), minLen);
8522 if (0 == ret) {
8523 return lhs.length() < rhs.length(); // RETURN
8524 }
8525 return ret < 0;
8526}
8527
8528template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8529bool bsl::operator<(const CHAR_TYPE *lhs,
8530 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
8531{
8532 BSLS_ASSERT_SAFE(lhs);
8533
8534 const std::size_t lhsLen = CHAR_TRAITS::length(lhs);
8535 const std::size_t minLen = lhsLen < rhs.length() ? lhsLen : rhs.length();
8536
8537 int ret = CHAR_TRAITS::compare(lhs, rhs.data(), minLen);
8538 if (0 == ret) {
8539 return lhsLen < rhs.length(); // RETURN
8540 }
8541 return ret < 0;
8542}
8543
8544template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8545bool bsl::operator<(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
8546 const CHAR_TYPE *rhs)
8547{
8548 BSLS_ASSERT_SAFE(rhs);
8549
8550 const std::size_t rhsLen = CHAR_TRAITS::length(rhs);
8551 const std::size_t minLen = rhsLen < lhs.length() ? rhsLen : lhs.length();
8552
8553 int ret = CHAR_TRAITS::compare(lhs.data(), rhs, minLen);
8554 if (0 == ret) {
8555 return lhs.length() < rhsLen; // RETURN
8556 }
8557 return ret < 0;
8558}
8559
8560template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8561inline
8562bool bsl::operator>(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
8563 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
8565{
8566 return rhs < lhs;
8567}
8568
8569template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8570inline
8571bool
8572bsl::operator>(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
8575{
8576 return rhs < lhs;
8577}
8578
8579template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8580inline
8581bool
8583 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
8585{
8586 return rhs < lhs;
8587}
8588
8589template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8590inline
8591bool bsl::operator>(const CHAR_TYPE *lhs,
8592 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
8593{
8594 BSLS_ASSERT_SAFE(lhs);
8595
8596 return rhs < lhs;
8597}
8598
8599template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8600inline
8601bool bsl::operator>(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
8602 const CHAR_TYPE *rhs)
8603{
8604 BSLS_ASSERT_SAFE(rhs);
8605
8606 return rhs < lhs;
8607}
8608
8609template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8610inline
8611bool bsl::operator<=(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
8612 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
8614{
8615 return !(rhs < lhs);
8616}
8617
8618template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8619inline
8620bool
8621bsl::operator<=(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
8624{
8625 return !(rhs < lhs);
8626}
8627
8628template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8629inline
8630bool
8632 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
8634{
8635 return !(rhs < lhs);
8636}
8637
8638template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8639inline
8640bool bsl::operator<=(const CHAR_TYPE *lhs,
8641 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
8642{
8643 BSLS_ASSERT_SAFE(lhs);
8644
8645 return !(rhs < lhs);
8646}
8647
8648template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8649inline
8650bool bsl::operator<=(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
8651 const CHAR_TYPE *rhs)
8652{
8653 BSLS_ASSERT_SAFE(rhs);
8654
8655 return !(rhs < lhs);
8656}
8657
8658template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8659inline
8660bool bsl::operator>=(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
8661 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
8663{
8664 return !(lhs < rhs);
8665}
8666
8667template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8668inline
8669bool
8670bsl::operator>=(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
8673{
8674 return !(lhs < rhs);
8675}
8676
8677template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8678inline
8679bool
8681 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
8683{
8684 return !(lhs < rhs);
8685}
8686
8687template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8688inline
8689bool bsl::operator>=(const CHAR_TYPE *lhs,
8690 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
8691{
8692 BSLS_ASSERT_SAFE(lhs);
8693
8694 return !(lhs < rhs);
8695}
8696
8697template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8698inline
8699bool bsl::operator>=(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
8700 const CHAR_TYPE *rhs)
8701{
8702 BSLS_ASSERT_SAFE(rhs);
8703
8704 return !(lhs < rhs);
8705}
8706
8707#endif // BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
8708
8709template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8711bsl::operator+(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& lhs,
8712 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& rhs)
8713{
8714 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR> result(
8716 select_on_container_copy_construction(lhs.get_allocator()));
8717 result.reserve(lhs.length() + rhs.length());
8718 result += lhs;
8719 result += rhs;
8720 return result;
8721}
8722
8723#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8724template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8727 const basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& rhs)
8728{
8729 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lvalue = lhs;
8730 lvalue.append(rhs);
8731 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>(
8732 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8733}
8734
8735template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8737bsl::operator+(const basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lhs,
8739{
8740 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lvalue = rhs;
8741 lvalue.insert(0, lhs);
8742 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>(
8743 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8744}
8745
8746template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8750{
8751 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lvalue = lhs;
8752 lvalue.append(rhs);
8753 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>(
8754 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8755}
8756#endif
8757
8758template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8760bsl::operator+(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
8762{
8765 select_on_container_copy_construction(rhs.get_allocator()));
8766 result.reserve(lhs.length() + rhs.length());
8767 result.append(lhs.c_str(), lhs.length());
8768 result += rhs;
8769 return result;
8770}
8771
8772#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8773template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8775bsl::operator+(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
8777{
8778 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC2>& lvalue = rhs;
8779 lvalue.insert(0, lhs.c_str(), lhs.size());
8780 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC2>(
8781 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8782}
8783#endif
8784
8785template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8788 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
8789{
8792 select_on_container_copy_construction(lhs.get_allocator()));
8793 result.reserve(lhs.length() + rhs.length());
8794 result += lhs;
8795 result.append(rhs.c_str(), rhs.length());
8796 return result;
8797}
8798
8799#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8800template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8803 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
8804{
8805 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC1>& lvalue = lhs;
8806 lvalue.append(rhs.c_str(), rhs.length());
8807 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC1>(
8808 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8809}
8810#endif
8811
8812template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8814bsl::operator+(const CHAR_TYPE *lhs,
8815 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& rhs)
8816{
8817 BSLS_ASSERT_SAFE(lhs);
8818
8819 typename basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::size_type
8820 lhsLength = CHAR_TRAITS::length(lhs);
8821
8822 basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR> result(
8824 select_on_container_copy_construction(rhs.get_allocator()));
8825 result.reserve(lhsLength + rhs.length());
8826 result.append(lhs, lhsLength);
8827 result += rhs;
8828 return result;
8829}
8830
8831#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8832template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8834bsl::operator+(const CHAR_TYPE *lhs,
8836{
8837 BSLS_ASSERT_SAFE(lhs);
8838
8839 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lvalue = rhs;
8840 lvalue.insert(0, lhs);
8841 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>(
8842 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8843}
8844#endif
8845
8846template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8848bsl::operator+(CHAR_TYPE lhs,
8849 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& rhs)
8850{
8851 basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR> result(
8853 select_on_container_copy_construction(rhs.get_allocator()));
8854 result.reserve(1 + rhs.length());
8855 result.push_back(lhs);
8856 result += rhs;
8857 return result;
8858}
8859
8860#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8861template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8863bsl::operator+(CHAR_TYPE lhs,
8865{
8866 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lvalue = rhs;
8867 lvalue.insert(lvalue.begin(), lhs);
8868 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>(
8869 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8870}
8871#endif
8872
8873template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8875bsl::operator+(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& lhs,
8876 const CHAR_TYPE *rhs)
8877{
8878 BSLS_ASSERT_SAFE(rhs);
8879 typename basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::size_type
8880 rhsLength = CHAR_TRAITS::length(rhs);
8881
8882 basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR> result(
8884 select_on_container_copy_construction(lhs.get_allocator()));
8885 result.reserve(lhs.length() + rhsLength);
8886 result += lhs;
8887 result.append(rhs, rhsLength);
8888 return result;
8889}
8890
8891#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8892template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8895 const CHAR_TYPE *rhs)
8896{
8897 BSLS_ASSERT_SAFE(rhs);
8898
8899 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lvalue = lhs;
8900 lvalue.append(rhs);
8901 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>(
8902 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8903}
8904#endif
8905
8906template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8908bsl::operator+(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& lhs,
8909 CHAR_TYPE rhs)
8910{
8911 basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR> result(
8913 select_on_container_copy_construction(lhs.get_allocator()));
8914 result.reserve(lhs.length() + 1);
8915 result += lhs;
8916 result.push_back(rhs);
8917 return result;
8918}
8919
8920#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8921template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8924 CHAR_TYPE rhs)
8925{
8926 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lvalue = lhs;
8927 lvalue.push_back(rhs);
8928 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>(
8929 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8930}
8931#endif
8932
8933template <class CHAR_TYPE,
8934 class CHAR_TRAITS,
8935 class ALLOCATOR,
8936 class STRING_VIEW_LIKE_TYPE>
8940 const STRING_VIEW_LIKE_TYPE & rhs)
8941{
8942 basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR> result(
8943 allocator_traits<ALLOCATOR>::
8944 select_on_container_copy_construction(lhs.get_allocator()));
8945 result.reserve(lhs.length() + rhs.length());
8946 result.append(lhs);
8947 result.append(rhs);
8948 return result;
8949}
8950
8951#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8952template <class CHAR_TYPE,
8953 class CHAR_TRAITS,
8954 class ALLOCATOR,
8955 class STRING_VIEW_LIKE_TYPE>
8959 const STRING_VIEW_LIKE_TYPE & rhs)
8960{
8961 lhs.append(rhs);
8962 return std::move(lhs);
8963}
8964#endif
8965
8966template <class CHAR_TYPE,
8967 class CHAR_TRAITS,
8968 class ALLOCATOR,
8969 class STRING_VIEW_LIKE_TYPE>
8972bsl::operator+(const STRING_VIEW_LIKE_TYPE & lhs,
8974{
8975 basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR> result(
8977 select_on_container_copy_construction(rhs.get_allocator()));
8978 result.reserve(lhs.length() + rhs.length());
8979 result.append(lhs);
8980 result.append(rhs);
8981 return result;
8982}
8983
8984#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8985template <class CHAR_TYPE,
8986 class CHAR_TRAITS,
8987 class ALLOCATOR,
8988 class STRING_VIEW_LIKE_TYPE>
8991bsl::operator+(const STRING_VIEW_LIKE_TYPE & lhs,
8993{
8994 rhs.insert(0, lhs);
8995 return std::move(rhs);
8996}
8997#endif
8998
8999/// Do not use, for internal use by `operator<<` only.
9000template <class CHAR_TYPE, class CHAR_TRAITS>
9001bool bslstl_string_fill(std::basic_ostream<CHAR_TYPE, CHAR_TRAITS>& os,
9002 std::basic_streambuf<CHAR_TYPE, CHAR_TRAITS> *buf,
9003 std::size_t n)
9004{
9005 BSLS_ASSERT_SAFE(buf);
9006
9007 CHAR_TYPE fillChar = os.fill();
9008
9009 for (std::size_t i = 0; i < n; ++i) {
9010 if (CHAR_TRAITS::eq_int_type(buf->sputc(fillChar), CHAR_TRAITS::eof()))
9011 {
9012 return false; // RETURN
9013 }
9014 }
9015
9016 return true;
9017}
9018
9019template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
9020std::basic_ostream<CHAR_TYPE, CHAR_TRAITS>&
9021bsl::operator<<(std::basic_ostream<CHAR_TYPE, CHAR_TRAITS>& os,
9022 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& str)
9023{
9024 typedef std::basic_ostream<CHAR_TYPE, CHAR_TRAITS> Ostrm;
9025 typename Ostrm::sentry sentry(os);
9026 bool ok = false;
9027
9028 if (sentry) {
9029 ok = true;
9030 std::size_t n = str.size();
9031 std::size_t padLen = 0;
9032 bool left = (os.flags() & Ostrm::left) != 0;
9033 std::streamsize w = os.width(0);
9034
9035 std::basic_streambuf<CHAR_TYPE, CHAR_TRAITS> *buf = os.rdbuf();
9036
9037 if (w > 0 && std::size_t(w) > n) {
9038 padLen = std::size_t(w) - n;
9039 }
9040
9041 if (!left) {
9042 ok = bslstl_string_fill(os, buf, padLen);
9043 }
9044
9045 ok = ok && (buf->sputn(str.data(), std::streamsize(n)) ==
9046 std::streamsize(n));
9047
9048 if (left) {
9049 ok = ok && bslstl_string_fill(os, buf, padLen);
9050 }
9051 }
9052
9053 if (!ok) {
9054 os.setstate(Ostrm::failbit);
9055 }
9056
9057 return os;
9058}
9059
9060template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
9061std::basic_istream<CHAR_TYPE, CHAR_TRAITS>&
9062bsl::operator>>(std::basic_istream<CHAR_TYPE, CHAR_TRAITS>& is,
9063 basic_string<CHAR_TYPE,CHAR_TRAITS, ALLOCATOR>& str)
9064{
9065 typedef std::basic_istream<CHAR_TYPE, CHAR_TRAITS> Istrm;
9066 typename Istrm::sentry sentry(is);
9067
9068 if (sentry) {
9069 std::basic_streambuf<CHAR_TYPE, CHAR_TRAITS> *buf = is.rdbuf();
9070 typedef std::ctype<CHAR_TYPE> CType;
9071
9072 const std::locale& loc = is.getloc();
9073 const CType& ctype = std::use_facet<CType>(loc);
9074
9075 str.clear();
9076 std::streamsize n = is.width(0);
9077 if (n <= 0) {
9078 n = std::numeric_limits<std::streamsize>::max();
9079 }
9080 else {
9081 str.reserve(n);
9082 }
9083
9084 while (n-- > 0) {
9085 typename CHAR_TRAITS::int_type c1 = buf->sbumpc();
9086 if (CHAR_TRAITS::eq_int_type(c1, CHAR_TRAITS::eof())) {
9087 is.setstate(Istrm::eofbit);
9088 break;
9089 }
9090 else {
9091 CHAR_TYPE c = CHAR_TRAITS::to_char_type(c1);
9092
9093 if (ctype.is(CType::space, c)) {
9094 if (CHAR_TRAITS::eq_int_type(buf->sputbackc(c),
9095 CHAR_TRAITS::eof())) {
9096 is.setstate(Istrm::failbit);
9097 }
9098 break;
9099 }
9100 else {
9101 str.push_back(c);
9102 }
9103 }
9104 }
9105
9106 // If we have read no characters, then set failbit.
9107
9108 if (str.size() == 0) {
9109 is.setstate(Istrm::failbit);
9110 }
9111 }
9112 else {
9113 is.setstate(Istrm::failbit);
9114 }
9115
9116 return is;
9117}
9118
9119template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
9120std::basic_istream<CHAR_TYPE, CHAR_TRAITS>&
9121bsl::getline(std::basic_istream<CHAR_TYPE, CHAR_TRAITS>& is,
9122 basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& str,
9123 CHAR_TYPE delim)
9124{
9125 typedef std::basic_istream<CHAR_TYPE, CHAR_TRAITS> Istrm;
9126 std::size_t nread = 0;
9127 typename Istrm::sentry sentry(is, true);
9128 if (sentry) {
9129 std::basic_streambuf<CHAR_TYPE, CHAR_TRAITS> *buf = is.rdbuf();
9130 str.clear();
9131
9132 while (nread < str.max_size()) {
9133 int c1 = buf->sbumpc();
9134 if (CHAR_TRAITS::eq_int_type(c1, CHAR_TRAITS::eof())) {
9135 is.setstate(Istrm::eofbit);
9136 break;
9137 }
9138
9139 ++nread;
9140 CHAR_TYPE c = CHAR_TRAITS::to_char_type(c1);
9141 if (!CHAR_TRAITS::eq(c, delim)) {
9142 str.push_back(c);
9143 }
9144 else {
9145 break; // character is extracted but not appended
9146 }
9147 }
9148 }
9149 if (nread == 0 || nread >= str.max_size()) {
9150 is.setstate(Istrm::failbit);
9151 }
9152
9153 return is;
9154}
9155
9156template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
9157inline
9158std::basic_istream<CHAR_TYPE, CHAR_TRAITS>&
9159bsl::getline(std::basic_istream<CHAR_TYPE, CHAR_TRAITS>& is,
9160 basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& str)
9161{
9162 return getline(is, str, is.widen('\n'));
9163}
9164
9165// HASH SPECIALIZATIONS
9166template <class HASHALG, class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
9167inline
9168void bsl::hashAppend(
9169 HASHALG& hashAlg,
9170 const basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& input)
9171{
9172 using ::BloombergLP::bslh::hashAppend;
9173 hashAlg(input.data(), sizeof(CHAR_TYPE)*input.size());
9174 hashAppend(hashAlg, input.size());
9175}
9176
9177template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
9179std::size_t bsl::hashBasicString(
9180 const basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& str)
9181{
9182 return ::BloombergLP::bslh::Hash<>()(str);
9183}
9184
9185
9186
9187template <class HASHALG, class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
9189void bslh::hashAppend(
9190 HASHALG& hashAlg,
9191 const std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& input)
9192{
9193 hashAlg(input.data(), sizeof(CHAR_TYPE)*input.size());
9194 hashAppend(hashAlg, input.size());
9195}
9196
9197
9198
9199// ============================================================================
9200// TYPE TRAITS
9201// ============================================================================
9202
9203// Type traits for STL *sequence* containers:
9204// o A sequence container defines STL iterators.
9205// o A sequence container is bitwise movable if the allocator is bitwise
9206// movable.
9207// o A sequence container uses 'bslma' allocators if the (template parameter)
9208// type 'ALLOCATOR' is convertible from 'bslma::Allocator *'.
9209
9210
9211
9212namespace bslalg {
9213
9214template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
9215struct HasStlIterators<bsl::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC> >
9217{};
9218
9219} // close namespace bslalg
9220
9221namespace bslma {
9222
9223template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
9224struct UsesBslmaAllocator<bsl::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC> >
9225 : bsl::is_convertible<Allocator *, ALLOC>
9226{};
9227
9228} // close namespace bslma
9229
9230
9231
9232#undef BSLSTL_CHAR_TRAITS
9233
9234#ifdef BSLS_COMPILERFEATURES_SUPPORT_EXTERN_TEMPLATE
9237extern template class bsl::basic_string<char>;
9238extern template class bsl::basic_string<wchar_t>;
9239
9240# if defined(BSLS_COMPILERFEATURES_SUPPORT_UTF8_CHAR_TYPE)
9242extern template class bsl::basic_string<char8_t>;
9243# endif
9244
9245# if defined(BSLS_COMPILERFEATURES_SUPPORT_UNICODE_CHAR_TYPES)
9248extern template class bsl::basic_string<char16_t>;
9249extern template class bsl::basic_string<char32_t>;
9250# endif
9251
9252#endif
9253
9254#undef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
9255
9256#undef BSLSTL_STRING_ONLY_STRINGVIEW_ENABLE_IF_T
9257
9258#undef BSLSTL_STRING_DEDUCE_RVREF
9259#undef BSLSTL_STRING_DEDUCE_RVREF_1
9260#undef BSLSTL_STRING_DEDUCE_RVREF_2
9261
9262#endif
9263
9264// ----------------------------------------------------------------------------
9265// Copyright 2013 Bloomberg Finance L.P.
9266//
9267// Licensed under the Apache License, Version 2.0 (the "License");
9268// you may not use this file except in compliance with the License.
9269// You may obtain a copy of the License at
9270//
9271// http://www.apache.org/licenses/LICENSE-2.0
9272//
9273// Unless required by applicable law or agreed to in writing, software
9274// distributed under the License is distributed on an "AS IS" BASIS,
9275// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9276// See the License for the specific language governing permissions and
9277// limitations under the License.
9278// ----------------------------- END-OF-FILE ----------------------------------
9279
9280/** @} */
9281/** @} */
9282/** @} */
#define BSLSTL_INSERT_RETURN_TYPE
Definition bslstl_string.h:6616
#define BSLSTL_STRING_ONLY_STRINGVIEW_ENABLE_IF_T(...)
Definition bslstl_string.h:965
Definition bslstl_string.h:1179
String_ClearProctor(FULL_STRING_TYPE *stringPtr)
Definition bslstl_string.h:4496
void release()
Definition bslstl_string.h:4514
~String_ClearProctor()
Definition bslstl_string.h:4505
Definition bslstl_string.h:1000
bool isShortString() const
Definition bslstl_string.h:4467
String_Imp()
Definition bslstl_string.h:4406
~String_Imp()=default
SIZE_TYPE d_length
Definition bslstl_string.h:1063
String_Imp(const String_Imp &original)=default
BSLMF_NESTED_TRAIT_DECLARATION(String_Imp, BloombergLP::bslmf::IsBitwiseMoveable)
static SIZE_TYPE computeNewCapacity(SIZE_TYPE newLength, SIZE_TYPE oldCapacity, SIZE_TYPE maxSize)
Definition bslstl_string.h:4375
ShortBufferConstraints
Definition bslstl_string.h:1016
@ SHORT_BUFFER_MIN_BYTES
Definition bslstl_string.h:1018
@ SHORT_BUFFER_NEED_BYTES
Definition bslstl_string.h:1021
String_Imp(SIZE_TYPE length, SIZE_TYPE capacity)
Definition bslstl_string.h:4415
BSLMF_ASSERT(SHORT_BUFFER_BYTES >=sizeof(CHAR_TYPE *))
ConfigurableParameters
Definition bslstl_string.h:1041
@ BASIC_STRING_DEALLOCATE_IN_CLEAR
Definition bslstl_string.h:1045
@ BASIC_STRING_HONOR_SHRINK_REQUEST
Definition bslstl_string.h:1046
void swap(String_Imp &other)
Definition bslstl_string.h:4427
SIZE_TYPE d_capacity
Definition bslstl_string.h:1064
BloombergLP::bsls::AlignedBuffer< SHORT_BUFFER_BYTES, BloombergLP::bsls::AlignmentFromType< CHAR_TYPE >::VALUE > d_short
Definition bslstl_string.h:1059
CHAR_TYPE * dataPtr()
Definition bslstl_string.h:4457
const CHAR_TYPE * dataPtr() const
Definition bslstl_string.h:4483
void resetFields()
Reset all fields of this object to their default-constructed state.
Definition bslstl_string.h:4447
CHAR_TYPE * d_start_p
Definition bslstl_string.h:1060
String_Imp & operator=(const String_Imp &rhs)=default
Definition bslma_bslallocator.h:588
Definition bslstl_stringview.h:471
BSLS_KEYWORD_CONSTEXPR size_type length() const BSLS_KEYWORD_NOEXCEPT
Return the length of this view.
Definition bslstl_stringview.h:1913
BSLS_KEYWORD_CONSTEXPR const_pointer data() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stringview.h:1988
BSLS_KEYWORD_CONSTEXPR size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the length of this view.
Definition bslstl_stringview.h:1904
Definition bslstl_string.h:1252
bsl::reverse_iterator< iterator > reverse_iterator
Definition bslstl_string.h:1283
friend string to_string(long)
basic_string & assign_range(BSLS_COMPILERFEATURES_FORWARD_REF(RANGE) range)
size_type length() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7301
const_reverse_iterator crbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7263
reference operator[](size_type position)
Definition bslstl_string.h:6091
size_type find_last_of(const basic_string &characterString, size_type position=npos) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7665
size_type find_first_of(const basic_string &characterString, size_type position=0) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7591
basic_string substr(size_type position=0, size_type numChars=npos) const
Definition bslstl_string.h:8013
basic_string() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:5559
basic_string & replace_with_range(const_iterator first, const_iterator last, BSLS_COMPILERFEATURES_FORWARD_REF(RANGE) range)
int compare(const basic_string &other) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:8024
basic_string & operator+=(const basic_string &rhs)
Definition bslstl_string.h:6137
basic_string(const CHAR_TYPE *characterString, size_type numChars, const ALLOCATOR &basicAllocator=ALLOCATOR())
Definition bslstl_string.h:5712
int compare(size_type lhsPosition, size_type lhsNumChars, const CHAR_TYPE *other) const
Definition bslstl_string.h:8111
int compare(const STRING_VIEW_LIKE_TYPE &other, BSLSTL_STRINGVIEWLIKEPARAM_ONLY_ENABLE_IF_T(void) *=0) const BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(true)
basic_string & append_range(BSLS_COMPILERFEATURES_FORWARD_REF(RANGE) range)
const CHAR_TYPE * c_str() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7405
basic_string & assign(const basic_string &replacement)
Definition bslstl_string.h:6347
size_type size() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7292
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Return the allocator used by this string to supply memory.
Definition bslstl_string.h:7423
CHAR_TYPE & front()
Definition bslstl_string.h:6115
BSLMF_NESTED_TRAIT_DECLARATION_IF(basic_string, BloombergLP::bslmf::IsBitwiseMoveable, BloombergLP::bslmf::IsBitwiseMoveable< ALLOCATOR >::value)
basic_string & replace(size_type outPosition, size_type outNumChars, const basic_string &replacement)
Definition bslstl_string.h:6813
int compare(size_type lhsPosition, size_type lhsNumChars, const CHAR_TYPE *other, size_type otherNumChars) const
Definition bslstl_string.h:8089
AllocatorTraits::size_type size_type
Definition bslstl_string.h:1274
size_type find(const basic_string &substring, size_type position=0) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7432
iterator insert_range(const_iterator position, BSLS_COMPILERFEATURES_FORWARD_REF(RANGE) range)
void shrink_to_fit()
Definition bslstl_string.h:6030
void push_back(CHAR_TYPE character)
Append the specified character to this string.
Definition bslstl_string.h:6330
const_reverse_iterator crend() const BSLS_KEYWORD_NOEXCEPT
Return the past-the-end reverse iterator for this string.
Definition bslstl_string.h:7281
AllocatorTraits::pointer pointer
Definition bslstl_string.h:1276
static const size_type npos
Definition bslstl_string.h:1793
~basic_string()
Destroy this string object.
Definition bslstl_string.h:5842
basic_string(size_type numChars, CHAR_TYPE character, const ALLOCATOR &basicAllocator=ALLOCATOR())
Definition bslstl_string.h:5729
CHAR_TYPE & back()
Definition bslstl_string.h:6125
bool empty() const BSLS_KEYWORD_NOEXCEPT
Return true if this string has length 0, and false otherwise.
Definition bslstl_string.h:7331
CHAR_TYPE * iterator
Definition bslstl_string.h:1281
friend string to_string(long long)
CHAR_TRAITS traits_type
Definition bslstl_string.h:1270
basic_string(const CHAR_TYPE *characterString, const ALLOCATOR &basicAllocator=ALLOCATOR())
Definition bslstl_string.h:5699
const_iterator cbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7227
basic_string(INPUT_ITER first, INPUT_ITER last, const ALLOCATOR &basicAllocator=ALLOCATOR())
Definition bslstl_string.h:5742
iterator end() BSLS_KEYWORD_NOEXCEPT
Return the past-the-end iterator for this modifiable string.
Definition bslstl_string.h:6065
CHAR_TYPE * data() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7177
bool starts_with(basic_string_view< CHAR_TYPE, CHAR_TRAITS > characterString) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7918
int compare(size_type lhsPosition, size_type lhsNumChars, const basic_string &other, size_type otherPosition, size_type otherNumChars=npos) const
Definition bslstl_string.h:8050
size_type find_last_not_of(const basic_string &characterString, size_type position=npos) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7818
AllocatorTraits::difference_type difference_type
Definition bslstl_string.h:1275
reference at(size_type position)
Definition bslstl_string.h:6100
void resize(size_type newLength, CHAR_TYPE character)
Definition bslstl_string.h:5977
void swap(basic_string &other) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:2792
size_type max_size() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7310
basic_string & operator=(const basic_string &rhs)
Definition bslstl_string.h:5859
void pop_back()
Definition bslstl_string.h:6803
friend string to_string(unsigned long)
friend string to_string(unsigned)
friend string to_string(int)
size_type find_first_not_of(const basic_string &characterString, size_type position=0) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7743
value_type & reference
Definition bslstl_string.h:1279
ALLOCATOR allocator_type
Definition bslstl_string.h:1273
basic_string & operator=(BloombergLP::bslmf::MovableRef< basic_string > rhs)
Definition bslstl_string.h:5883
size_type rfind(const basic_string &substring, size_type position=npos) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7515
AllocatorTraits::const_pointer const_pointer
Definition bslstl_string.h:1277
int compare(size_type position, size_type numChars, const basic_string &other) const
Definition bslstl_string.h:8035
const CHAR_TYPE * const_iterator
Definition bslstl_string.h:1282
bsl::reverse_iterator< const_iterator > const_reverse_iterator
These types satisfy the ReversibleSequence requirements.
Definition bslstl_string.h:1286
void resize(size_type newLength)
Definition bslstl_string.h:5987
reverse_iterator rend() BSLS_KEYWORD_NOEXCEPT
Return the past-the-end reverse iterator for this modifiable string.
Definition bslstl_string.h:6081
void reserve(size_type newCapacity)
Definition bslstl_string.h:6020
void resize_and_overwrite(size_type newLength, OPERATION operation)
Definition bslstl_string.h:5996
const_iterator cend() const BSLS_KEYWORD_NOEXCEPT
Return the past-the-end iterator for this string.
Definition bslstl_string.h:7245
int compare(const CHAR_TYPE *other) const
Definition bslstl_string.h:8077
size_type copy(CHAR_TYPE *characterString, size_type numChars, size_type position=0) const
Definition bslstl_string.h:7384
reverse_iterator rbegin() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6073
bool ends_with(basic_string_view< CHAR_TYPE, CHAR_TRAITS > characterString) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7952
void clear() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6043
bool contains(basic_string_view< CHAR_TYPE, CHAR_TRAITS > subview) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7892
CHAR_TRAITS::char_type value_type
Definition bslstl_string.h:1271
basic_string & erase(size_type position=0, size_type numChars=npos)
Definition bslstl_string.h:6740
const value_type & const_reference
Definition bslstl_string.h:1280
size_type capacity() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7323
basic_string & append(const basic_string &suffix)
Definition bslstl_string.h:6188
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2343
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_NOEXCEPT_OPERATOR(...)
Definition bsls_keyword.h:677
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:651
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
#define BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(...)
Definition bsls_keyword.h:676
#define BSLS_PERFORMANCEHINT_PREDICT_LIKELY(expr)
Definition bsls_performancehint.h:451
#define BSLS_PERFORMANCEHINT_UNLIKELY_HINT
Definition bsls_performancehint.h:484
#define BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(expr)
Definition bsls_performancehint.h:452
#define BSLS_PLATFORM_AGGRESSIVE_INLINE
Definition bsls_platform.h:737
bool bslstl_string_fill(std::basic_ostream< CHAR_TYPE, CHAR_TRAITS > &os, std::basic_streambuf< CHAR_TYPE, CHAR_TRAITS > *buf, std::size_t n)
Do not use, for internal use by operator<< only.
Definition bslstl_string.h:9001
#define BSLSTL_STRING_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T)
Definition bslstl_string.h:799
#define BSLSTL_STRINGVIEWLIKEPARAM_ONLY_ENABLE_IF_T(...)
Definition bslstl_stringviewlikeparam.h:159
#define BSLSTL_STRINGVIEWLIKEPARAM_ENABLE_IF_T(...)
Definition bslstl_stringviewlikeparam.h:143
void hashAppend(HASH_ALGORITHM &hashAlgorithm, const BigEndianInt16 &object)
Definition bdlat_valuetypefunctions.h:939
unsigned long stoul(const string &str, std::size_t *pos=0, int base=10)
BloombergLP::bsls::Nullptr_Impl::Type nullptr_t
Definition bsls_nullptr.h:283
unsigned long long stoull(const string &str, std::size_t *pos=0, int base=10)
long stol(const string &str, std::size_t *pos=0, int base=10)
void swap(array< VALUE_TYPE, SIZE > &lhs, array< VALUE_TYPE, SIZE > &rhs)
int stoi(const string &str, std::size_t *pos=0, int base=10)
float stof(const string &str, std::size_t *pos=0)
T::const_iterator cend(const T &container)
Definition bslstl_iterator.h:1709
long long stoll(const string &str, std::size_t *pos=0, int base=10)
bool operator<(const array< VALUE_TYPE, SIZE > &lhs, const array< VALUE_TYPE, SIZE > &rhs)
void hashAppend(HASH_ALGORITHM &hashAlgorithm, const array< TYPE, SIZE > &input)
Pass the specified input to the specified hashAlgorithm
Definition bslstl_array.h:959
bool operator>(const array< VALUE_TYPE, SIZE > &lhs, const array< VALUE_TYPE, SIZE > &rhs)
std::basic_istream< CHAR_TYPE, TRAITS > & operator>>(std::basic_istream< CHAR_TYPE, TRAITS > &is, bitset< N > &x)
Definition bslstl_bitset.h:1373
bool operator>=(const array< VALUE_TYPE, SIZE > &lhs, const array< VALUE_TYPE, SIZE > &rhs)
bool operator<=(const array< VALUE_TYPE, SIZE > &lhs, const array< VALUE_TYPE, SIZE > &rhs)
wstring to_wstring(int value)
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
deque< VALUE_TYPE, ALLOCATOR >::size_type erase(deque< VALUE_TYPE, ALLOCATOR > &deq, const BDE_OTHER_TYPE &value)
Definition bslstl_deque.h:4424
std::size_t hashBasicString(const basic_string< CHAR_TYPE, CHAR_TRAITS, ALLOCATOR > &str)
Return a hash value for the specified str.
std::basic_istream< CHAR_TYPE, CHAR_TRAITS > & getline(std::basic_istream< CHAR_TYPE, CHAR_TRAITS > &is, basic_string< CHAR_TYPE, CHAR_TRAITS, ALLOCATOR > &str, CHAR_TYPE delim)
T::iterator begin(T &container)
Definition bslstl_iterator.h:1593
bool operator==(const memory_resource &a, const memory_resource &b)
T::const_iterator cbegin(const T &container)
Definition bslstl_iterator.h:1651
std::basic_ostream< CHAR_TYPE, TRAITS > & operator<<(std::basic_ostream< CHAR_TYPE, TRAITS > &os, const bitset< N > &x)
Definition bslstl_bitset.h:1417
basic_string< CHAR_TYPE, CHAR_TRAITS, ALLOCATOR > operator+(const basic_string< CHAR_TYPE, CHAR_TRAITS, ALLOCATOR > &lhs, const basic_string< CHAR_TYPE, CHAR_TRAITS, ALLOCATOR > &rhs)
double stod(const string &str, std::size_t *pos=0)
string to_string(int value)
ALLOCATOR & lhs
Definition bslstl_string.h:3917
CHAR_TRAITS
Definition bslstl_string.h:3917
basic_string< wchar_t > wstring
Definition bslstl_string.h:845
T::iterator end(T &container)
Definition bslstl_iterator.h:1621
basic_string< char > string
Definition bslstl_string.h:844
deque< VALUE_TYPE, ALLOCATOR >::size_type erase_if(deque< VALUE_TYPE, ALLOCATOR > &deq, PREDICATE predicate)
Definition bslstl_deque.h:4433
long double stold(const string &str, std::size_t *pos=0)
BSLS_KEYWORD_CONSTEXPR CONTAINER::value_type * data(CONTAINER &container)
Definition bslstl_iterator.h:1325
bool operator!=(const memory_resource &a, const memory_resource &b)
BSLS_KEYWORD_CONSTEXPR bool empty(const CONTAINER &container)
Definition bslstl_iterator.h:1377
MaxDecimalStringLengths
Definition bslstl_string.h:4249
@ e_MAX_LONGDOUBLE_STRLEN10
Definition bslstl_string.h:4256
@ e_MAX_INT_STRLEN10
Definition bslstl_string.h:4252
@ e_MAX_SHORT_STRLEN10
Definition bslstl_string.h:4251
@ e_MAX_INT64_STRLEN10
Definition bslstl_string.h:4253
@ e_MAX_FLOAT_STRLEN10
Definition bslstl_string.h:4254
@ e_STARTING_LONGDOUBLE_STRLEN10
Definition bslstl_string.h:4259
@ e_MAX_DOUBLE_STRLEN10
Definition bslstl_string.h:4255
@ e_MAX_SCALAR_STRLEN10
Definition bslstl_string.h:4257
Definition bdlc_flathashmap.h:2218
Definition bslh_defaulthashalgorithm.h:339
bsl::enable_if<(bsl::is_integral< TYPE >::value||bsl::is_pointer< TYPE >::value||bsl::is_enum< TYPE >::value)&&!bsl::is_same< TYPE, bool >::value >::type hashAppend(HASH_ALGORITHM &hashAlg, TYPE input)
Definition bslh_hash.h:643
Definition baljsn_encoder_testtypes.h:76
Definition bdlbb_blob.h:579
Definition bslstl_algorithm.h:84
Definition bdldfp_decimal.h:5549
Definition bslma_allocatortraits.h:1089
BloombergLP::bslma::AllocatorTraits_ConstPointerType< ALLOCATOR >::type const_pointer
Definition bslma_allocatortraits.h:1183
BloombergLP::bslma::AllocatorTraits_PropOnCopyAssign< ALLOCATOR >::type propagate_on_container_copy_assignment
Definition bslma_allocatortraits.h:1332
BloombergLP::bslma::AllocatorTraits_PropOnMoveAssign< ALLOCATOR >::type propagate_on_container_move_assignment
Definition bslma_allocatortraits.h:1341
BloombergLP::bslma::AllocatorTraits_SizeType< ALLOCATOR_TYPE >::type size_type
Definition bslma_allocatortraits.h:1196
BloombergLP::bslma::AllocatorTraits_PointerType< ALLOCATOR >::type pointer
Definition bslma_allocatortraits.h:1180
BloombergLP::bslma::AllocatorTraits_DifferenceType< ALLOCATOR >::type difference_type
Definition bslma_allocatortraits.h:1193
Definition bslstl_ranges.h:301
Definition bslstl_hash.h:495
std::size_t operator()(const TYPE &value) const
Definition bslstl_hash.h:1067
Definition bslmf_integralconstant.h:261
Definition bslmf_isconvertible.h:875
Definition bslmf_issame.h:146
Definition bslalg_hasstliterators.h:99
Definition bslma_usesbslmaallocator.h:344