BDE 4.14.0 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#ifndef INCLUDED_BSLSTL_STRING
9#define INCLUDED_BSLSTL_STRING
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_string bslstl_string
15/// @brief Provide a standard-compliant `basic_string` class template.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_string
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_string-purpose"> Purpose</a>
25/// * <a href="#bslstl_string-classes"> Classes </a>
26/// * <a href="#bslstl_string-description"> Description </a>
27/// * <a href="#bslstl_string-memory-allocation"> Memory Allocation </a>
28/// * <a href="#bslstl_string-bslma-style-allocators"> bslma-Style Allocators </a>
29/// * <a href="#bslstl_string-lexicographical-comparisons"> Lexicographical Comparisons </a>
30/// * <a href="#bslstl_string-operations"> Operations </a>
31/// * <a href="#bslstl_string-user-defined-literals"> User-defined literals </a>
32/// * <a href="#bslstl_string-memory-allocation-for-a-file-scope-strings"> Memory Allocation For a File-Scope Strings </a>
33/// * <a href="#bslstl_string-usage"> Usage </a>
34/// * <a href="#bslstl_string-example-1-basic-syntax"> Example 1: Basic Syntax </a>
35/// * <a href="#bslstl_string-example-2-string-as-a-data-member"> Example 2: string as a data member </a>
36/// * <a href="#bslstl_string-example-3-a-stream-text-replacement-filter"> Example 3: A stream text replacement filter </a>
37///
38/// # Purpose {#bslstl_string-purpose}
39/// Provide a standard-compliant @ref basic_string class template.
40///
41/// # Classes {#bslstl_string-classes}
42///
43/// - bsl::basic_string: C++ standard compliant @ref basic_string implementation
44/// - bsl::string: `typedef` for `bsl::basic_string<char>`
45/// - bsl::wstring: `typedef` for `bsl::basic_string<wchar_t>`/
46///
47/// **Canonical header:** bsl_string.h
48///
49/// @see ISO C++ Standard, Section 21 [strings]
50///
51/// # Description {#bslstl_string-description}
52/// This component defines a single class template @ref basic_string ,
53/// implementing standard containers, `std::string` and `std::wstring`, that
54/// hold a sequence of characters.
55///
56/// An instantiation of @ref basic_string is an allocator-aware, value-semantic
57/// type whose salient attributes are its size (number of characters) and the
58/// sequence of characters that the string contains. The @ref basic_string `class`
59/// is parameterized by the character type, `CHAR_TYPE`, that character type's
60/// traits, `CHAR_TRAITS`, and an allocator, `ALLOCATOR`. The traits for each
61/// character type provide functions that assign, compare, and copy a sequence
62/// of those characters.
63///
64/// A @ref basic_string meets the requirements of a sequential container with
65/// random access iterators as specified in the [basic.string] section of the
66/// C++ standard [21.4]. The @ref basic_string implemented here adheres to the
67/// C++11 standard, except that it does not have template specializations
68/// `std::u16string` and `std::u32string`. Note that excluded C++11 features
69/// are those that require (or are greatly simplified by) C++11 compiler
70/// support.
71///
72/// ## Memory Allocation {#bslstl_string-memory-allocation}
73///
74///
75/// The type supplied as a @ref basic_string s `ALLOCATOR` template parameter
76/// determines how that @ref basic_string will allocate memory. The @ref basic_string
77/// template supports allocators meeting the requirements of the C++11 standard,
78/// in addition it supports scoped-allocators derived from the
79/// `bslma::Allocator` memory allocation protocol. Clients intending to use
80/// `bslma` style allocators should use the template's default `ALLOCATOR` type:
81/// The default type for the `ALLOCATOR` template parameter, `bsl::allocator`,
82/// provides a C++11 standard-compatible adapter for a `bslma::Allocator`
83/// object.
84///
85/// ### bslma-Style Allocators {#bslstl_string-bslma-style-allocators}
86///
87///
88/// If the (template parameter) type `ALLOCATOR` of an @ref basic_string
89/// instantiation is `bsl::allocator`, then objects of that @ref basic_string type
90/// will conform to the standard behavior of a `bslma`-allocator-enabled type.
91/// Such a @ref basic_string accepts an optional `bslma::Allocator` argument at
92/// construction. If the address of a `bslma::Allocator` object is explicitly
93/// supplied at construction, it is used to supply memory for the @ref basic_string
94/// throughout its lifetime; otherwise, the @ref basic_string will use the default
95/// allocator installed at the time of the @ref basic_string 's construction (see
96/// @ref bslma_default ).
97///
98/// ## Lexicographical Comparisons {#bslstl_string-lexicographical-comparisons}
99///
100///
101/// Two @ref basic_string s `lhs` and `rhs` are lexicographically compared by first
102/// determining `N`, the smaller of the lengths of `lhs` and `rhs`, and
103/// comparing characters at each position between 0 and `N - 1`, using
104/// `CHAR_TRAITS::lt` in lexicographical fashion. If `CHAR_TRAITS::lt`
105/// determines that strings are non-equal (smaller or larger), then this is the
106/// result. Otherwise, the lengths of the strings are compared and the shorter
107/// string is declared the smaller. Lexicographical comparison returns equality
108/// only when both strings have the same length and the same character value in
109/// each respective position.
110///
111/// ## Operations {#bslstl_string-operations}
112///
113///
114/// This section describes the run-time complexity of operations on instances of
115/// @ref basic_string :
116/// @code
117/// Legend
118/// ------
119/// 'V' - the 'CHAR_TYPE' template parameter type of the
120/// 'basic_string'
121/// 'a', 'b' - two distinct objects of type 'basic_string<V>'
122/// 'k' - an integral number
123/// 'al' - an STL-style memory allocator
124/// 'i1', 'i2' - two iterators defining a sequence of 'CHAR_TYPE'
125/// characters
126/// 'v' - an object of type 'V'
127/// 'p1', 'p2' - two iterators belonging to 'a'
128/// distance(i1,i2) - the number of values in the range [i1, i2)
129///
130/// +-----------------------------------------+-------------------------------+
131/// | Operation | Complexity |
132/// |=========================================+===============================|
133/// | basic_string<V> a (default construction)| O[1] |
134/// | basic_string<V> a(al) | |
135/// |-----------------------------------------+-------------------------------|
136/// | basic_string<V> a(b) (copy construction)| O[n] |
137/// | basic_string<V> a(b, al) | |
138/// |-----------------------------------------+-------------------------------|
139/// | basic_string<V> a(std::move(b)) | O[1] |
140/// | (move construction) | |
141/// |-----------------------------------------+-------------------------------|
142/// | basic_string<V> a(std::move(b), a1) | O[n] |
143/// | (extended move construction) | |
144/// |-----------------------------------------+-------------------------------|
145/// | basic_string<V> a(k) | O[n] |
146/// | basic_string<V> a(k, al) | |
147/// |-----------------------------------------+-------------------------------|
148/// | basic_string<V> a(i1, i2) | O[distance(i1,i2)] |
149/// | basic_string<V> a(i1, i2, al) | |
150/// |-----------------------------------------+-------------------------------|
151/// | a.~basic_string<V>() (destruction) | O[1] |
152/// |-----------------------------------------+-------------------------------|
153/// | get_allocator() | O[1] |
154/// |-----------------------------------------+-------------------------------|
155/// | a.begin(), a.end(), | O[1] |
156/// | a.cbegin(), a.cend(), | |
157/// | a.rbegin(), a.rend(), | |
158/// | a.crbegin(), a.crend() | |
159/// |-----------------------------------------+-------------------------------|
160/// | a.size() | O[1] |
161/// |-----------------------------------------+-------------------------------|
162/// | a.max_size() | O[1] |
163/// |-----------------------------------------+-------------------------------|
164/// | a.resize(k) | O[k] |
165/// | a.resize(k, v) | |
166/// |-----------------------------------------+-------------------------------|
167/// | a.resize_and_overwrite(k, op) | O[k] |
168/// |-----------------------------------------+-------------------------------|
169/// | a.empty() | O[1] |
170/// |-----------------------------------------+-------------------------------|
171/// | a.reserve(k) | O[1] |
172/// |-----------------------------------------+-------------------------------|
173/// | a.shrink_to_fit() | O[n] |
174/// |-----------------------------------------+-------------------------------|
175/// | a[k] | O[1] |
176/// |-----------------------------------------+-------------------------------|
177/// | a.at(k) | O[1] |
178/// |-----------------------------------------+-------------------------------|
179/// | a.front() | O[1] |
180/// |-----------------------------------------+-------------------------------|
181/// | a.back() | O[1] |
182/// |-----------------------------------------+-------------------------------|
183/// | a.push_back() | O[1] |
184/// |-----------------------------------------+-------------------------------|
185/// | a.pop_back() | O[1] |
186/// |-----------------------------------------+-------------------------------|
187/// | a += b; | O[n] |
188/// |-----------------------------------------+-------------------------------|
189/// | a.append(b); | O[n] |
190/// |-----------------------------------------+-------------------------------|
191/// | a.assign(b); | O[n] |
192/// |-----------------------------------------+-------------------------------|
193/// | a.assign(std::move(b)); | O[1] if the allocator can be |
194/// | | propagated on container move |
195/// | | assignment or 'a' and 'b' use |
196/// | | the same allocator; O[n] |
197/// | | otherwise |
198/// |-----------------------------------------+-------------------------------|
199/// | a.assign(k, v) | O[k] |
200/// |-----------------------------------------+-------------------------------|
201/// | a.assign(i1, i2) | O[distance(i1,i2)] |
202/// |-----------------------------------------+-------------------------------|
203/// | a.insert(p1, v) | O[1 + distance(p1, a.end())] |
204/// |-----------------------------------------+-------------------------------|
205/// | a.insert(p1, k, v) | O[k + distance(p1, a.end())] |
206/// |-----------------------------------------+-------------------------------|
207/// | a.insert(p1, i1, i2) | O[distance(i1, i2) |
208/// | | + distance(p1, a.end())] |
209/// |-----------------------------------------+-------------------------------|
210/// | a.erase(p1) | O[1 + distance(p1, a.end())] |
211/// |-----------------------------------------+-------------------------------|
212/// | a.erase(p1, p2) | O[1 + distance(p1, a.end())] |
213/// |-----------------------------------------+-------------------------------|
214/// | a.swap(b), swap(a, b) | O[1] if 'a' and 'b' allocators|
215/// | | compare equal, O[n + m] |
216/// | | otherwise |
217/// |-----------------------------------------+-------------------------------|
218/// | a.clear() | O[1] |
219/// |-----------------------------------------+-------------------------------|
220/// | a = b; (assignment) | O[n] |
221/// |-----------------------------------------+-------------------------------|
222/// | a = std::move(b); (move assignment) | O[1] if the allocator can be |
223/// | | propagated on container move |
224/// | | assignment or 'a' and 'b' use |
225/// | | the same allocator; O[n] |
226/// | | otherwise |
227/// |-----------------------------------------+-------------------------------|
228/// | a == b, a != b | O[n] |
229/// |-----------------------------------------+-------------------------------|
230/// | a < b, a <= b, a > b, a >= b | O[n] |
231/// +-----------------------------------------+-------------------------------+
232/// @endcode
233///
234/// ## User-defined literals {#bslstl_string-user-defined-literals}
235///
236///
237/// The user-defined literal operators are declared for the `bsl::string` and
238/// `bsl::wstring` types. The ud-suffix `_s` is chosen to distinguish between
239/// the `bsl`-string's user-defined literal operators and the `std`-string's
240/// user-defined literal `operator ""s` introduced in the C++14 standard and
241/// implemented in the standard library provided by the compiler vendor. Note
242/// that the `bsl`-string's `operator "" _s`, unlike the `std`-string's
243/// `operator ""s`, can be used in a client's code if the compiler supports the
244/// C++11 standard. Also note that if the compiler supports the C++14 standard
245/// then the `std`-string's `operator ""s` can be used to initialize a
246/// `bsl`-string as follows:
247/// @code
248/// using namespace std::string_literals;
249/// bsl::string str = "test"s;
250/// @endcode
251/// however such initialization introduces significant performance overhead due
252/// to extra `std`-string object creation/destruction.
253///
254/// Also note that `bsl`-string's user-defined literal operators are declared in
255/// the `bsl::literals::string_literals` namespace, where `literals` and
256/// @ref string_literals are inline namespaces. Access to these operators can be
257/// gained with either `using namespace bsl::literals`,
258/// `using namespace bsl::string_literals` or
259/// `using namespace bsl::literals::string_literals`. But we recommend
260/// `using namespace bsl::string_literals` to minimize the scope of the using
261/// declaration:
262/// @code
263/// using namespace bsl::string_literals;
264/// bsl::string str = "test"_s;
265/// @endcode
266///
267/// ### Memory Allocation For a File-Scope Strings {#bslstl_string-memory-allocation-for-a-file-scope-strings}
268///
269///
270/// The `operator "" _s` uses the currently installed default allocator to
271/// supply memory. Note that the default allocator can become locked prior to
272/// entering `main` as a side-effect of initializing a file-scope static string
273/// object using `operator "" _s`. To avoid the default allocator locking an
274/// `operator "" _S` can be used instead. This operator uses the global
275/// allocator to supply memory and has no side-effects. (See the "Default
276/// Allocator" section in the `bslma::Default` component-level documentation for
277/// details.) For Example:
278/// @code
279/// using namespace bsl::string_literals;
280/// static const bsl::string s = "Use '_S' to initialize a file-scope string"_S;
281/// @endcode
282///
283/// ## Usage {#bslstl_string-usage}
284///
285///
286/// In this section we show intended use of this component.
287///
288/// ### Example 1: Basic Syntax {#bslstl_string-example-1-basic-syntax}
289///
290///
291/// In this example, we will show how to create and use the `string` typedef.
292///
293/// First, we will default-construct a `string` object:
294/// @code
295/// bsl::string s;
296/// assert(s.empty());
297/// assert(0 == s.size());
298/// assert("" == s);
299/// @endcode
300/// Then, we will construct a `string` object from a string literal:
301/// @code
302/// bsl::string t = "Hello World";
303/// assert(!t.empty());
304/// assert(11 == t.size());
305/// assert("Hello World" == t);
306/// @endcode
307/// Next, we will clear the contents of `t` and assign it a couple of values:
308/// first from a string literal; and second from another `string` object:
309/// @code
310/// t.clear();
311/// assert(t.empty());
312/// assert("" == t);
313///
314/// t = "Good Morning";
315/// assert(!t.empty());
316/// assert("Good Morning" == t);
317///
318/// t = s;
319/// assert(t.empty());
320/// assert("" == t);
321/// assert(t == s);
322/// @endcode
323/// Then, we will create three `string` objects: the first representing a street
324/// name, the second a state, and the third a ZIP code. We will then
325/// concatenate them into a single address `string` and print the contents of
326/// that `string` on standard output:
327/// @code
328/// const bsl::string street = "731 Lexington Avenue";
329/// const bsl::string state = "NY";
330/// const bsl::string zipCode = "10022";
331///
332/// const bsl::string fullAddress = street + " " + state + " " + zipCode;
333///
334/// bsl::cout << fullAddress << bsl::endl;
335/// @endcode
336/// The above print statement should produce a single line of output:
337/// @code
338/// 731 Lexington Avenue NY 10022
339/// @endcode
340/// Then, we search the contents of `address` (using the `find` function) to
341/// determine if it lies on a specified street:
342/// @code
343/// const bsl::string streetName = "Lexington";
344///
345/// if (bsl::string::npos != fullAddress.find(streetName, 0)) {
346/// bsl::cout << "The address " << fullAddress << " is located on "
347/// << streetName << "." << bsl::endl;
348/// }
349/// @endcode
350/// Next, we show how to get a reference providing modifiable access to the
351/// null-terminated string literal stored by a `string` object using the `c_str`
352/// function. Note that the returned string literal can be passed to various
353/// standard functions expecting a null-terminated string:
354/// @code
355/// const bsl::string v = "Another string";
356/// const char *cs = v.c_str();
357/// assert(bsl::strlen(cs) == v.size());
358/// @endcode
359/// Then, we construct two `string` objects, `x` and `y`, using a user-specified
360/// allocator:
361/// @code
362/// bslma::TestAllocator allocator1, allocator2;
363///
364/// const char *SHORT_STRING = "A small string";
365/// const char *LONG_STRING = "This long string would definitely cause "
366/// "memory to be allocated on creation";
367///
368/// const bsl::string x(SHORT_STRING, &allocator1);
369/// const bsl::string y(LONG_STRING, &allocator2);
370///
371/// assert(SHORT_STRING == x);
372/// assert(LONG_STRING == y);
373/// @endcode
374/// Notice that, no memory was allocated from the allocator for object `x`
375/// because of the short-string optimization used in the `string` type.
376///
377/// Finally, we can track memory usage of `x` and `y` using `allocator1` and
378/// `allocator2` and check that memory was allocated only by `allocator2`:
379/// @code
380/// assert(0 == allocator1.numBlocksInUse());
381/// assert(1 == allocator2.numBlocksInUse());
382/// @endcode
383///
384/// ### Example 2: string as a data member {#bslstl_string-example-2-string-as-a-data-member}
385///
386///
387/// The most common use of `string` objects are as data members in user-defined
388/// classes. In this example, we will show how `string` objects can be used as
389/// data members.
390///
391/// First, we begin to define a `class`, `Employee`, that represents the data
392/// corresponding to an employee of a company:
393/// @code
394/// /// This simply constrained (value-semantic) attribute class represents
395/// /// the information about an employee. An employee's first and last
396/// /// name are represented as `string` objects and their employee
397/// /// identification number is represented by an `int`. Note that the
398/// /// class invariants are identically the constraints on the individual
399/// /// attributes.
400/// ///
401/// /// This class:
402/// /// * supports a complete set of *value-semantic* operations
403/// /// - except for BDEX serialization
404/// /// * is **exception-neutral** (agnostic)
405/// /// * is **alias-safe**
406/// /// * is `const` **thread-safe**
407/// class Employee {
408///
409/// // DATA
410/// bsl::string d_firstName; // first name
411/// bsl::string d_lastName; // last name
412/// int d_id; // identification number
413/// @endcode
414/// Next, we define the creators for this class:
415/// @code
416/// public:
417/// // CREATORS
418///
419/// /// Create a `Employee` object having the (default) attribute
420/// /// values:
421/// /// ```
422/// /// firstName() == ""
423/// /// lastName() == ""
424/// /// id() == 0
425/// /// ```
426/// /// Optionally specify a `basicAllocator` used to supply memory. If
427/// /// `basicAllocator` is 0, the currently installed default
428/// /// allocator is used.
429/// Employee(bslma::Allocator *basicAllocator = 0);
430///
431/// /// Create a `Employee` object having the specified `firstName`,
432/// /// `lastName`, and `id` attribute values. Optionally specify a
433/// /// `basicAllocator` used to supply memory. If `basicAllocator` is
434/// /// 0, the currently installed default allocator is used.
435/// Employee(const bsl::string_view& firstName,
436/// const bsl::string_view& lastName,
437/// int id,
438/// bslma::Allocator *basicAllocator = 0);
439///
440/// /// Create a `Employee` object having the same value as the
441/// /// specified `original` object. Optionally specify a
442/// /// `basicAllocator` used to supply memory. If `basicAllocator` is
443/// /// 0, the currently installed default allocator is used.
444/// Employee(const Employee& original,
445/// bslma::Allocator *basicAllocator = 0);
446///
447/// /// Destroy this object.
448/// //! ~Employee() = default;
449/// @endcode
450/// Notice that all constructors of the `Employee` class are optionally provided
451/// an allocator that is then passed through to the `string` data members of
452/// `Employee`. This allows the user to control how memory is allocated by
453/// `Employee` objects. Also note that the type of the `firstName` and
454/// `lastName` arguments of the value constructor is `bsl::string_view`. The
455/// `bsl::string_view` allows specifying a `string` or a `const char *` to
456/// represent a string value. For the sake of brevity its implementation is
457/// not explored here.
458///
459/// Then, declare the remaining methods of the class:
460/// @code
461/// // MANIPULATORS
462///
463/// /// Assign to this object the value of the specified `rhs` object,
464/// /// and return a reference providing modifiable access to this
465/// /// object.
466/// Employee& operator=(const Employee& rhs);
467///
468/// /// Set the `firstName` attribute of this object to the specified
469/// /// `value`.
470/// void setFirstName(const bsl::string_view& value);
471///
472/// /// Set the `lastName` attribute of this object to the specified
473/// /// `value`.
474/// void setLastName(const bsl::string_view& value);
475///
476/// /// Set the `id` attribute of this object to the specified `value`.
477/// void setId(int value);
478///
479/// // ACCESSORS
480///
481/// /// Return a reference providing non-modifiable access to the
482/// /// `firstName` attribute of this object.
483/// const bsl::string& firstName() const;
484///
485/// /// Return a reference providing non-modifiable access to the
486/// /// `lastName` attribute of this object.
487/// const bsl::string& lastName() const;
488///
489/// /// Return the value of the `id` attribute of this object.
490/// int id() const;
491/// };
492/// @endcode
493/// Next, we declare the free operators for `Employee`:
494/// @code
495/// /// Return `true` if the specified `lhs` and `rhs` objects have the same
496/// /// value, and `false` otherwise. Two `Employee` objects have the
497/// /// same value if all of their corresponding values of their
498/// /// `firstName`, `lastName`, and `id` attributes are the same.
499/// inline
500/// bool operator==(const Employee& lhs, const Employee& rhs);
501///
502/// /// Return `true` if the specified `lhs` and `rhs` objects do not have
503/// /// the same value, and `false` otherwise. Two `Employee` objects do
504/// /// not have the same value if any of the corresponding values of their
505/// /// `firstName`, `lastName`, or `id` attributes are not the same.
506/// inline
507/// bool operator!=(const Employee& lhs, const Employee& rhs);
508/// @endcode
509/// Then, we implement the various methods of the `Employee` class:
510/// @code
511/// // CREATORS
512/// inline
513/// Employee::Employee(bslma::Allocator *basicAllocator)
514/// : d_firstName(basicAllocator)
515/// , d_lastName(basicAllocator)
516/// , d_id(0)
517/// {
518/// }
519///
520/// inline
521/// Employee::Employee(const bsl::string_view& firstName,
522/// const bsl::string_view& lastName,
523/// int id,
524/// bslma::Allocator *basicAllocator)
525/// : d_firstName(firstName.begin(), firstName.end(), basicAllocator)
526/// , d_lastName(lastName.begin(), lastName.end(), basicAllocator)
527/// , d_id(id)
528/// {
529/// BSLS_ASSERT_SAFE(!firstName.empty());
530/// BSLS_ASSERT_SAFE(!lastName.empty());
531/// }
532///
533/// inline
534/// Employee::Employee(const Employee& original,
535/// bslma::Allocator *basicAllocator)
536/// : d_firstName(original.d_firstName, basicAllocator)
537/// , d_lastName(original.d_lastName, basicAllocator)
538/// , d_id(original.d_id)
539/// {
540/// }
541/// @endcode
542/// Notice that the `basicAllocator` parameter can simply be passed as an
543/// argument to the constructor of `bsl::string`.
544///
545/// Now, we implement the remaining manipulators of the `Employee` class:
546/// @code
547/// // MANIPULATORS
548/// inline
549/// Employee& Employee::operator=(const Employee& rhs)
550/// {
551/// d_firstName = rhs.d_firstName;
552/// d_lastName = rhs.d_lastName;
553/// d_id = rhs.d_id;
554/// return *this;
555/// }
556///
557/// inline
558/// void Employee::setFirstName(const bsl::string_view& value)
559/// {
560/// BSLS_ASSERT_SAFE(!value.empty());
561///
562/// d_firstName.assign(value.begin(), value.end());
563/// }
564///
565/// inline
566/// void Employee::setLastName(const bsl::string_view& value)
567/// {
568/// BSLS_ASSERT_SAFE(!value.empty());
569///
570/// d_lastName.assign(value.begin(), value.end());
571/// }
572///
573/// inline
574/// void Employee::setId(int value)
575/// {
576/// d_id = value;
577/// }
578///
579/// // ACCESSORS
580/// inline
581/// const bsl::string& Employee::firstName() const
582/// {
583/// return d_firstName;
584/// }
585///
586/// inline
587/// const bsl::string& Employee::lastName() const
588/// {
589/// return d_lastName;
590/// }
591///
592/// inline
593/// int Employee::id() const
594/// {
595/// return d_id;
596/// }
597/// @endcode
598/// Finally, we implement the free operators for `Employee` class:
599/// @code
600/// inline
601/// bool operator==(const Employee& lhs, const Employee& rhs)
602/// {
603/// return lhs.firstName() == rhs.firstName()
604/// && lhs.lastName() == rhs.lastName()
605/// && lhs.id() == rhs.id();
606/// }
607///
608/// inline
609/// bool operator!=(const Employee& lhs, const Employee& rhs)
610/// {
611/// return lhs.firstName() != rhs.firstName()
612/// || lhs.lastName() != rhs.lastName()
613/// || lhs.id() != rhs.id();
614/// }
615/// @endcode
616///
617/// ### Example 3: A stream text replacement filter {#bslstl_string-example-3-a-stream-text-replacement-filter}
618///
619///
620/// In this example, we will utilize the `string` type and its associated
621/// utility functions to define a function that reads data from an input stream,
622/// replaces all occurrences of a specified text fragment with another text
623/// fragment, and writes the resulting text to an output stream.
624///
625/// First, we define the signature of the function, `replace`:
626/// @code
627/// /// Read data from the specified `inputStream` and replace all
628/// /// occurrences of the text contained in the specified `oldString` in
629/// /// the stream with the text contained in the specified `newString`.
630/// /// Write the modified data to the specified `outputStream`.
631/// void replace(bsl::ostream& outputStream,
632/// bsl::istream& inputStream,
633/// const bsl::string& oldString,
634/// const bsl::string& newString)
635/// @endcode
636/// Then, we provide the implementation for `replace`:
637/// @code
638/// {
639/// const bsl::string::size_type oldStringSize = oldString.size();
640/// const bsl::string::size_type newStringSize = newString.size();
641/// bsl::string line;
642///
643/// bsl::getline(inputStream, line);
644/// @endcode
645/// Notice that we can use the `getline` free function defined in this component
646/// to read a single line of data from an input stream into a `bsl::string`.
647/// @code
648/// if (!inputStream) {
649/// return; // RETURN
650/// }
651///
652/// do {
653/// @endcode
654/// Next, we use the `find` function to search the contents of `line` for
655/// characters matching the contents of `oldString`:
656/// @code
657/// int pos = line.find(oldString);
658/// while (bsl::string::npos != pos) {
659/// @endcode
660/// Now, we use the `replace` method to modify the contents of `line` matching
661/// `oldString` to `newString`:
662/// @code
663/// line.replace(pos, oldStringSize, newString);
664/// pos = line.find(oldString, pos + newStringSize);
665/// @endcode
666/// Notice that we provide `find` with the starting position from which to start
667/// searching.
668/// @code
669/// }
670/// @endcode
671/// Finally, we write the updated contents of `line` to the output stream:
672/// @code
673/// outputStream << line;
674///
675/// bsl::getline(inputStream, line);
676/// } while (inputStream);
677/// }
678/// @endcode
679/// @}
680/** @} */
681/** @} */
682
683/** @addtogroup bsl
684 * @{
685 */
686/** @addtogroup bslstl
687 * @{
688 */
689/** @addtogroup bslstl_string
690 * @{
691 */
692
693#include <bslscm_version.h>
694
695#include <bslstl_algorithm.h>
696#include <bslstl_compare.h>
697#include <bslstl_hash.h>
698#include <bslstl_iterator.h>
699#include <bslstl_iteratorutil.h>
700#include <bslstl_stdexceptutil.h>
701#include <bslstl_stringrefdata.h>
702#include <bslstl_stringview.h>
703
704#include <bslalg_containerbase.h>
707
708#include <bslh_hash.h>
709
710#include <bslma_allocator.h>
712#include <bslma_allocatorutil.h>
713#include <bslma_isstdallocator.h>
714#include <bslma_bslallocator.h>
716
717#include <bslmf_assert.h>
718#include <bslmf_enableif.h>
721#include <bslmf_isconvertible.h>
722#include <bslmf_issame.h>
723#include <bslmf_matchanytype.h>
725#include <bslmf_movableref.h>
727#include <bslmf_nil.h>
728#include <bslmf_voidtype.h>
729
730#include <bsls_alignedbuffer.h>
731#include <bsls_alignment.h>
733#include <bsls_assert.h>
735#include <bsls_keyword.h>
736#include <bsls_libraryfeatures.h>
737#include <bsls_performancehint.h>
738#include <bsls_platform.h>
739
740#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
741# include <initializer_list>
742#endif
743
744#include <istream> // for 'std::basic_istream', 'sentry'
745#include <limits> // for 'std::numeric_limits'
746#include <locale> // for 'std::ctype', 'locale'
747#include <ostream> // for 'std::basic_ostream', 'sentry'
748#include <string> // for 'std::char_traits'
749
750#ifndef BDE_OMIT_INTERNAL_DEPRECATED
751#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
752
753#include <bsls_nativestd.h>
754
755#include <exception>
756#include <stdexcept>
757
758#if defined(BDE_BUILD_TARGET_STLPORT)
759// Code in Robo depends on these headers included transitively with <string>
760// and it fails to build otherwise in the stlport4 mode on Sun.
761
762# include <stdio.h>
763# include <stdlib.h>
764# include <string.h>
765#endif
766
767#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
768#endif // BDE_OMIT_INTERNAL_DEPRECATED
769
770namespace bsl {
771
772// Import @ref char_traits into the `bsl` namespace so that @ref basic_string and
773// @ref char_traits are always in the same namespace.
774using std::char_traits;
775
776template <class CHAR_TYPE,
777 class CHAR_TRAITS = char_traits<CHAR_TYPE>,
778 class ALLOCATOR = allocator<CHAR_TYPE> >
779class basic_string;
780
781// TYPEDEFS
784
785#if defined(BSLS_COMPILERFEATURES_SUPPORT_UTF8_CHAR_TYPE)
786typedef basic_string<char8_t> u8string;
787#endif
788
789#if defined(BSLS_COMPILERFEATURES_SUPPORT_UNICODE_CHAR_TYPES)
790typedef basic_string<char16_t> u16string;
791typedef basic_string<char32_t> u32string;
792#endif
793
794#if defined(BSLS_LIBRARYFEATURES_STDCPP_LIBCSTD)
795/// This `class` provides an implementation of the `find` function for the
796/// (template parameter) type `ORIGINAL_TRAITS`. This is an alternate
797/// representation for Sun's `char_traits::find` that returns an incorrect
798/// result for character types other than `char` (such as `wchar`).
799///
800/// See @ref bslstl_string
801template <class ORIGINAL_TRAITS>
802class String_Traits {
803
804 // PRIVATE TYPES
805 typedef typename ORIGINAL_TRAITS::char_type char_type;
806 typedef std::size_t size_type;
807
808 public:
809 // CLASS METHODS
810
811 /// Return an address providing non-modifiable access to the first
812 /// character that matches the specified character `a` in the specified
813 /// `n` characters of the specified `s` string. The behavior is
814 /// undefined unless `s` holds at least `n` characters.
815 static const char_type *find(const char_type *s,
816 size_type n,
817 const char_type& a);
818};
819
820/// Sun implemented `find` for `char` properly, so this specialization
821/// simply forwards the call to Sun.
822template <>
823class String_Traits<std::char_traits<char> > {
824
825 // PRIVATE TYPES
826 typedef std::size_t size_type;
827
828 public:
829 // CLASS METHODS
830
831 /// Return an address providing non-modifiable access to the first
832 /// character that matches the specified character `a` in the specified
833 /// `n` characters of the specified `s` string. The behavior is
834 /// undefined unless `s` holds at least `n` characters.
835 static const char *find(const char *s, size_type n, const char& a);
836};
837
838// CLASS METHODS
839template <class ORIGINAL_TRAITS>
840const typename ORIGINAL_TRAITS::char_type *
841String_Traits<ORIGINAL_TRAITS>::find(const char_type *s,
842 size_type n,
843 const char_type& a)
844{
845 while (n > 0 && !ORIGINAL_TRAITS::eq(*s, a)) {
846 --n;
847 ++s;
848 }
849 return n > 0 ? s : 0;
850}
851
852inline
853const char *
854String_Traits<std::char_traits<char> >::find(const char *s,
855 size_type n,
856 const char& a)
857{
858 return std::char_traits<char>::find(s, n, a);
859}
860
861#define BSLSTL_CHAR_TRAITS String_Traits<CHAR_TRAITS>
862
863#else
864
865#define BSLSTL_CHAR_TRAITS CHAR_TRAITS
866
867#endif
868
869#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
870// The usual practice of using a 'bslmf::MovableRef<>' cannot be applied, since
871// compilers on Solaris cannot compile such heavy code. Therefore, it was
872// decided to add 'operator+' accepting rvalue references only for platforms
873// and compilers that support them.
874
875#define BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
876#endif
877
878#ifdef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
879template <class CHAR_TRAITS, class = void>
880struct String_ComparisonCategory
881{
882 using type = weak_ordering;
883};
884template <class CHAR_TRAITS>
885struct String_ComparisonCategory<CHAR_TRAITS,
886 bsl::void_t<typename CHAR_TRAITS::comparison_category>>
887{
888 using type = typename CHAR_TRAITS::comparison_category;
889};
890
891template <class CHAR_TRAITS>
892using String_ComparisonCategoryType =
893 typename String_ComparisonCategory<CHAR_TRAITS>::type;
894#endif
895
896 // =======================================
897 // struct String_IsConvertibleToStringView
898 // =======================================
899
900/// This component-private `struct` template implements a meta-function to
901/// determine if the (template parameter) `TYPE` is convertible to the
902/// `bsl::string_view<`CHAR_TYPE', CHAR_TRAITS>'.
903template <class CHAR_TYPE, class CHAR_TRAITS, class TYPE>
905: bsl::is_convertible<TYPE, bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS> > {
906};
907
908/// This partial specialization of `String_IsConvertibleToStringView` is
909/// instantiated when `const CHAR_TYPE (&)[]` is tested for convertibility
910/// to the `bsl::string_view<`CHAR_TYPE', CHAR_TRAITS>'.
911template <class CHAR_TYPE, class CHAR_TRAITS>
913 CHAR_TRAITS,
914 const CHAR_TYPE (&)[]>
915: bsl::true_type {
916};
917
918 // ====================================
919 // struct String_IsConvertibleToCString
920 // ====================================
921
922/// This component-private `struct` template implements a meta-function to
923/// determine if the (template parameter) `TYPE` is convertible to the
924/// (template parameter) `const CHAR_TYPE *`.
925template <class CHAR_TYPE, class TYPE>
927: bsl::is_convertible<TYPE, const CHAR_TYPE *> {
928};
929
930
931/// This partial specialization of `String_IsConvertibleToStringView` is
932/// instantiated when `const CHAR_TYPE (&)[]` is tested for convertibility
933/// to the `const CHAR_TYPE *`.
934template <class CHAR_TYPE>
935struct String_IsConvertibleToCString<CHAR_TYPE, const CHAR_TYPE (&)[]>
936: bsl::true_type {
937};
938
939#if defined(BSLS_PLATFORM_CMP_MSVC) && BSLS_PLATFORM_CMP_VERSION <= 1900
940#define BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE \
941 const STRING_VIEW_LIKE_TYPE &
942 // MSVC 2015's limited SFINAE support means we are cannot use 'sizeof' to
943 // detect incomplete types. In this case it is safe to not perform this
944 // detection, as it is only required for the C++03 deficiencies in Sun and
945 // AIX compilers.
946#else
947/// We need to use an intermediate completeness test to work around
948/// deficiencies with SFINAE in the Sun and AIX compilers.
949#define BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE \
950typename bsl::enable_if<0 != sizeof(STRING_VIEW_LIKE_TYPE), \
951 const STRING_VIEW_LIKE_TYPE&>::type
952#endif
953
954#define BSLSTL_STRING_DEFINE_ONLY_CONVERTIBLE_TO_STRINGVIEW_RETURN_TYPE \
955 typename bsl::enable_if< \
956 String_IsConvertibleToStringView< \
957 CHAR_TYPE, \
958 CHAR_TRAITS, \
959 BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE>::value \
960 && !String_IsConvertibleToCString< \
961 CHAR_TYPE, \
962 BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE>::value, \
963 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>&>::type
964
965#define BSLSTL_STRING_DECLARE_CONVERTIBLE_TO_STRINGVIEW_PARAM_VOID , \
966 typename bsl::enable_if< \
967 String_IsConvertibleToStringView< \
968 CHAR_TYPE, \
969 CHAR_TRAITS, \
970 BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE>::value \
971 >::type * = 0
972
973#define BSLSTL_STRING_DEFINE_CONVERTIBLE_TO_STRINGVIEW_PARAM_VOID , \
974 typename bsl::enable_if< \
975 String_IsConvertibleToStringView< \
976 CHAR_TYPE, \
977 CHAR_TRAITS, \
978 BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE>::value \
979 >::type *
980
981#define BSLSTL_STRING_DECLARE_ONLY_CONVERTIBLE_TO_STRINGVIEW_PARAM_VOID , \
982 typename bsl::enable_if< \
983 String_IsConvertibleToStringView< \
984 CHAR_TYPE, \
985 CHAR_TRAITS, \
986 BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE>::value \
987 && !String_IsConvertibleToCString< \
988 CHAR_TYPE, \
989 BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE>::value \
990 >::type * = 0
991
992#define BSLSTL_STRING_DEFINE_ONLY_CONVERTIBLE_TO_STRINGVIEW_PARAM_VOID , \
993 typename bsl::enable_if< \
994 String_IsConvertibleToStringView< \
995 CHAR_TYPE, \
996 CHAR_TRAITS, \
997 BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE>::value \
998 && !String_IsConvertibleToCString< \
999 CHAR_TYPE, \
1000 BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE>::value \
1001 >::type *
1002
1003#define BSLSTL_STRING_DECLARE_ONLY_CONVERTIBLE_TO_STRINGVIEW_PARAM_ALLOC , \
1004 typename bsl::enable_if< \
1005 String_IsConvertibleToStringView< \
1006 CHAR_TYPE, \
1007 CHAR_TRAITS, \
1008 BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE>::value \
1009 && !String_IsConvertibleToCString< \
1010 CHAR_TYPE, \
1011 BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE>::value \
1012 , const ALLOCATOR&>::type basicAllocator = ALLOCATOR()
1013
1014#define BSLSTL_STRING_DEFINE_ONLY_CONVERTIBLE_TO_STRINGVIEW_PARAM_ALLOC , \
1015 typename bsl::enable_if< \
1016 String_IsConvertibleToStringView< \
1017 CHAR_TYPE, \
1018 CHAR_TRAITS, \
1019 BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE>::value \
1020 && !String_IsConvertibleToCString< \
1021 CHAR_TYPE, \
1022 BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE>::value \
1023 , const ALLOCATOR&>::type basicAllocator
1024
1025 // ================
1026 // class String_Imp
1027 // ================
1028
1029/// This component private `class` describes the basic data layout for a
1030/// string class and provides methods to help encapsulate internal string
1031/// implementation details. It is parameterized by `CHAR_TYPE` and
1032/// `SIZE_TYPE` only, and implements the portion of @ref basic_string that does
1033/// not need to know about its (template parameter) types `CHAR_TRAITS` or
1034/// `ALLOCATOR`. It contains the following data fields: pointer to string,
1035/// short string buffer, length, and capacity. The purpose of the short
1036/// string buffer is to implement a "short string optimization" such that
1037/// strings with lengths shorter than a certain number of characters are
1038/// stored directly inside the string object (inside the short string
1039/// buffer), and thereby avoid memory allocations/deallocations.
1040///
1041/// See @ref bslstl_string
1042template <class CHAR_TYPE, class SIZE_TYPE>
1044
1045 public:
1046 // TYPES
1047
1048 /// This `enum` contains values necessary to calculate the size of the
1049 /// short string buffer. The starting value is
1050 /// `SHORT_BUFFER_MIN_BYTES`, which defines the minimal number of bytes
1051 /// (or `char` values) that the short string buffer should be able to
1052 /// contain. Then this value is aligned to a word boundary. Then we
1053 /// make sure that it fits at least one `CHAR_TYPE` character (because
1054 /// the default state of the string object requires that the first
1055 /// character is initialized with a NULL-terminator). The final output
1056 /// of this enum used by `String_Imp` is the `SHORT_BUFFER_CAPACITY`
1057 /// value. It defines the capacity of the short string buffer and also
1058 /// the capacity of the default-constructed empty string object.
1060
1061 SHORT_BUFFER_MIN_BYTES = 20, // minimum required size of the short
1062 // string buffer in bytes
1063
1065 (SHORT_BUFFER_MIN_BYTES + sizeof(SIZE_TYPE) - 1)
1066 & ~(sizeof(SIZE_TYPE) - 1),
1067 // round it to a word boundary
1068
1069 SHORT_BUFFER_BYTES = sizeof(CHAR_TYPE) < SHORT_BUFFER_NEED_BYTES
1071 : sizeof(CHAR_TYPE),
1072 // in case 'CHAR_TYPE' is very large
1073
1074 SHORT_BUFFER_LENGTH = SHORT_BUFFER_BYTES / sizeof(CHAR_TYPE),
1075
1076 SHORT_BUFFER_CAPACITY = SHORT_BUFFER_LENGTH - 1
1077 // short string buffer capacity (not
1078 // including the null-terminator)
1079 };
1080
1081 // Make sure the buffer is large enough to fit a pointer.
1082 BSLMF_ASSERT(SHORT_BUFFER_BYTES >= sizeof(CHAR_TYPE *));
1083
1085 // These configurable parameters define various aspects of the string
1086 // behavior when it's not strictly defined by the Standard.
1087
1091
1092 // DATA
1093
1094 /// This is the union of the string storage options: it can either be
1095 /// stored inside the short string buffer, `d_short`, or in the
1096 /// externally allocated memory, pointed to by `d_start_p`.
1097 union {
1098
1099 BloombergLP::bsls::AlignedBuffer<
1100 SHORT_BUFFER_BYTES,
1101 BloombergLP::bsls::AlignmentFromType<CHAR_TYPE>::VALUE>
1102 d_short; // short string buffer
1103 CHAR_TYPE *d_start_p; // pointer to the data on heap
1104 };
1105
1106 SIZE_TYPE d_length; // length of the string
1107 SIZE_TYPE d_capacity; // capacity to which the string can grow
1108 // without reallocation
1109
1110 // TRAITS
1111
1112 // `CHAR_TYPE` is required to be a POD as per the Standard, which makes
1113 // `CHAR_TYPE` bitwise-movable, so `String_Imp` is also bitwise-movable.
1115 BloombergLP::bslmf::IsBitwiseMoveable);
1116
1117 // CLASS METHODS
1118
1119 /// Compute and return the capacity required for a string having the
1120 /// specified `newLength` and using the specified `oldCapacity` to
1121 /// exercise an exponential capacity growth necessary to ensure the
1122 /// amortized linear complexity of `push_back` and other operations and
1123 /// ensuring that the new capacity does not exceed the specified
1124 /// `maxSize`. Note that the behavior is undefined unless
1125 /// `newLength > oldCapacity`, `newLength < maxSize`, and
1126 /// `oldCapacity < maxSize`.
1127 static SIZE_TYPE computeNewCapacity(SIZE_TYPE newLength,
1128 SIZE_TYPE oldCapacity,
1129 SIZE_TYPE maxSize);
1130
1131 // CREATORS
1132
1133 /// Create a `String_Imp` object having (default) attribute values
1134 /// except that the `d_capacity` attribute is initialized with
1135 /// `SHORT_BUFFER_CAPACITY`.
1137
1138 /// Create a `String_Imp` object and initialize the `d_length` and
1139 /// `d_capacity` attributes with the specified `length` and specified
1140 /// `capacity`, respectively. If `capacity` is less than
1141 /// `SHORT_BUFFER_CAPACITY`, then d_capacity is set to
1142 /// `SHORT_BUFFER_CAPACITY`. The value of the `d_short` and `d_start_p`
1143 /// fields are left uninitialized. @ref basic_string is required to assign
1144 /// either d_short or d_start_p to a proper value before using any
1145 /// methods of this class.
1146 String_Imp(SIZE_TYPE length, SIZE_TYPE capacity);
1147
1148 /// Create a `String_Imp` object having the same value as the specified
1149 /// `original` object. Note that this copy constructor is generated by
1150 /// the compiler.
1151 String_Imp(const String_Imp& original) = default;
1152
1153 /// Destroy this object. Note that this destructor is generated by the
1154 /// compiler.
1155 ~String_Imp() = default;
1156
1157 /// Assign to this object the value of the specified `rhs` object, and
1158 /// return a reference providing modifiable access to this object. Note
1159 /// that this assignment operator is generated by the compiler.
1160 String_Imp& operator=(const String_Imp& rhs) = default;
1161
1162 // MANIPULATORS
1163
1164 /// Efficiently exchange the value of this object with the value of the
1165 /// specified `other` object. This method provides the no-throw
1166 /// exception-safety guarantee.
1167 void swap(String_Imp& other);
1168
1169 /// Reset all fields of this object to their default-constructed state.
1171
1172 /// Return an address providing modifiable access to the NULL-terminated
1173 /// C-string stored by this string object. Note that the returned
1174 /// address can point to either the internal short string buffer or the
1175 /// externally allocated memory depending on the type of the string
1176 /// defined by the return value of `isShortString`.
1177 CHAR_TYPE *dataPtr();
1178
1179 // ACCESSORS
1180
1181 /// Return `true` if this object contains a short string and the string
1182 /// data is stored in the short string buffer, and `false` if the object
1183 /// contains a long string (and the short string buffer contains a
1184 /// pointer to the string data allocated externally).
1185 bool isShortString() const;
1186
1187 /// Return an address providing non-modifiable access to the
1188 /// NULL-terminated C-string stored by this string object. Note that
1189 /// the returned address can point to either the internal short string
1190 /// buffer or the externally allocated memory depending on the type of
1191 /// the string defined by the return value of `isShortString`.
1192 const CHAR_TYPE *dataPtr() const;
1193};
1194
1195/// This component private `class` implements a proctor that sets the length
1196/// of a string to zero, and, if `release` is not called, will restore that
1197/// string upon it's destruction. The intended usage is to implement
1198/// `assign` methods in terms of `append` (by clearing the string before
1199/// appending to it), while maintaining the strong exceptions guarantee.
1200/// Note that after constructing this proctor for a string `s`, the
1201/// invariant `s[s.length()] == CHAR_TYPE()` is violated for non-empty `s`.
1202/// This invariant will be restored by either a successful `append` or by
1203/// the proctor's destructor if an exception is thrown. Note that the
1204/// template parameter was renamed from STRING_TYPE to FULL_STRING_TYPE due
1205/// to a name clash with a define elsewhere in the code base (see DRQS
1206/// 112049582).
1207///
1208/// See @ref bslstl_string
1209template<class FULL_STRING_TYPE>
1211
1212 // PRIVATE TYPES
1213 typedef typename FULL_STRING_TYPE::size_type size_type;
1214
1215 // DATA
1216 FULL_STRING_TYPE *d_string_p; // pointer to the string supplied at
1217 // construction (held, not owned)
1218
1219 size_type d_originalLength; // original length of the string
1220 // supplied at construction
1221
1222 public:
1223 // CREATORS
1224
1225 /// Create a `String_ClearProctor` for the specified `stringPtr`, and
1226 /// set both the length of `stringPtr` to 0 and the first character of
1227 /// `stringPtr` to `CHAR_TYPE()`.
1228 explicit String_ClearProctor(FULL_STRING_TYPE *stringPtr);
1229
1230 /// Destroy this object, and if `release` has not been called, restore
1231 /// the original state of the string supplied at construction.
1233
1234 // MANIPULATORS
1235
1236 /// Release the proctor indicating that the string state need not to be
1237 /// restored.
1238 void release();
1239};
1240
1241 // =======================
1242 // class bsl::basic_string
1243 // =======================
1244
1245/// This class template provides an STL-compliant `string` that conforms to
1246/// the `bslma::Allocator` model. For the requirements of a string class,
1247/// consult the second revision of the ISO/IEC 14882 Programming Language
1248/// C++ (2003). Note that the (template parameter) `CHAR_TYPE` must be
1249/// *equal* to `ALLOCATOR::value_type`. In addition, this implementation
1250/// offers strong exception guarantees (see below), with the general rules
1251/// that:
1252///
1253/// 1. any method that would result in a string of length larger than the
1254/// size returned by @ref max_size throws `std::length_error`, and
1255/// 2. any method that attempts to access a position outside the valid range
1256/// of a string throws `std::out_of_range`.
1257///
1258/// Circumstances where a method throws `bsl::length_error` (1) are clear
1259/// and not repeated in the individual function-level documentations below.
1260///
1261/// More generally, this class supports an almost complete set of *in-core*
1262/// *value* *semantic* operations, including copy construction, assignment,
1263/// equality comparison (but excluding `ostream` printing since this
1264/// component is below STL). A precise operational definition of when two
1265/// objects have the same value can be found in the description of
1266/// `operator==` for the class. This class is *exception* *neutral* with
1267/// full guarantee of rollback: if an exception is thrown during the
1268/// invocation of a method on a pre-existing object, the object is left
1269/// unchanged. In no event is memory leaked.
1270///
1271/// Note that *aliasing* (e.g., using all or part of an object as both
1272/// source and destination) is supported in all cases in the public
1273/// interface of @ref basic_string . However, the private interface (`...Raw`
1274/// methods) should be assumed to be not alias-safe unless specifically
1275/// noted otherwise.
1276template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
1278 : private String_Imp<CHAR_TYPE,
1279 typename allocator_traits<ALLOCATOR>::size_type>
1280 , private BloombergLP::bslalg::ContainerBase<ALLOCATOR>
1281{
1282
1283 // PRIVATE TYPES
1284
1285 /// This `typedef` is a convenient alias for the utility associated with
1286 /// movable references.
1287 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
1288
1289 /// This `typedef` is an alias for a utility class that provides many
1290 /// useful functions that operate on allocators.
1291 typedef BloombergLP::bslma::AllocatorUtil AllocatorUtil;
1292
1293 /// This `typedef` is an alias for the allocator traits type associated
1294 /// with this container.
1296
1297 public:
1298 // PUBLIC TYPES
1299 typedef CHAR_TRAITS traits_type;
1300 typedef typename CHAR_TRAITS::char_type value_type;
1301
1302 typedef ALLOCATOR allocator_type;
1307
1310 typedef CHAR_TYPE *iterator;
1311 typedef const CHAR_TYPE *const_iterator;
1312 typedef bsl::reverse_iterator<iterator> reverse_iterator;
1313
1314 /// These types satisfy the `ReversibleSequence` requirements.
1315 typedef bsl::reverse_iterator<const_iterator> const_reverse_iterator;
1316
1317 // TRAITS
1318
1319 /// `CHAR_TYPE` is required to be a POD as per the Standard, which makes
1320 /// `CHAR_TYPE` bitwise-movable, so @ref basic_string is bitwise-movable as
1321 /// long as the (template parameter) type `ALLOCATOR` is also
1322 /// bitwise-movable.
1325 BloombergLP::bslmf::IsBitwiseMoveable,
1326 BloombergLP::bslmf::IsBitwiseMoveable<ALLOCATOR>::value);
1327
1328 private:
1329 // PRIVATE TYPES
1331
1332 typedef BloombergLP::bslalg::ContainerBase<ALLOCATOR> ContainerBase;
1333
1334 // FRIENDS
1335
1336 friend string to_string(int);
1337 friend string to_string(long);
1338 friend string to_string(long long);
1339 friend string to_string(unsigned);
1340 friend string to_string(unsigned long);
1341 /// `to_string` functions are made friends to allow access to the
1342 /// internal short string buffer.
1343 friend string to_string(unsigned long long);
1344
1345 /// `String_ClearProctor` is made friend to allow access to internal
1346 /// buffer and length.
1347 friend class String_ClearProctor<basic_string>;
1348
1349 // PRIVATE CLASS METHODS
1350
1351 /// Throw `length_error` with the specified `message` if the specified
1352 /// `maxLengthExceeded` is `true`. Otherwise, this method has no
1353 /// effect.
1354 static void privateThrowLengthError(bool maxLengthExceeded,
1355 const char *message);
1356
1357 /// Throw `out_of_range` with the specified `message` if the specified
1358 /// `outOfRange` is `true`. Otherwise, this method has no effect.
1359 static void privateThrowOutOfRange(bool outOfRange, const char *message);
1360
1361 // PRIVATE MANIPULATORS
1362
1363 // Note: '...Raw' functions are low level private manipulators and they do
1364 // not perform checks for exceptions. '...Dispatch' functions perform
1365 // overload selection for iterator types in order to resolve ambiguities
1366 // between template and non-template method overloads.
1367
1368 /// Allocate and return a buffer capable of holding the specified
1369 /// `numChars` number of characters.
1370 CHAR_TYPE *privateAllocate(size_type numChars);
1371
1372 /// Deallocate the internal string buffer, which was allocated with
1373 /// `privateAllocate` and stored in `String_Imp::d_start_p` without
1374 /// modifying any data members.
1375 void privateDeallocate();
1376
1377 /// Copy the specified `original` string content into this string
1378 /// object, assuming that the default copy constructor of the
1379 /// `String_Imp` base class and the appropriate copy constructor of the
1380 /// `ContainerBase` base class have just been run. The behavior is
1381 /// undefined unless `original` holds an out-of-place representation of
1382 /// a string. Note that the out-of-place representation may be short
1383 /// enough to fit into the small buffer storage.
1384 void privateCopyFromOutOfPlaceBuffer(const basic_string& original);
1385
1386 /// Append to this string the specified initial `numChars` characters
1387 /// from the specified `characterString`, and return a reference
1388 /// providing modifiable access to this string. Throw `length_error`
1389 /// with the specified `message` if `numChars > max_size() - length()`.
1390 /// The behavior is undefined unless `characterString` is at least
1391 /// `numChars` long.
1392 basic_string& privateAppend(const CHAR_TYPE *characterString,
1393 size_type numChars,
1394 const char *message);
1395
1396 /// Append the specified `numChars` copies of the specified `character`
1397 /// to this string. Return a reference providing modifiable access to
1398 /// this string. Throw `length_error` with the specified `message` if
1399 /// `numChars > max_size() - length()`.
1400 basic_string& privateAppend(size_type numChars,
1401 CHAR_TYPE character,
1402 const char *message);
1403
1404 /// Append the characters from the string represented by the specified
1405 /// `first` and `last` iterators. Throw `length_error` with the
1406 /// specified `message` if `length() > max_size() - (last - first)`.
1407 /// The behavior is undefined unless `first` and `last` refer to a
1408 /// sequence of valid values where `first` is at a position at or before
1409 /// `last`.
1410 basic_string& privateAppend(iterator first,
1411 iterator last,
1412 const char *message,
1413 std::forward_iterator_tag);
1414 basic_string& privateAppend(const_iterator first,
1415 const_iterator last,
1416 const char *message,
1417 std::forward_iterator_tag);
1418
1419 /// Specialized append for input iterators, using repeated `push_back`
1420 /// operations. Throw `length_error` with the specified `message` if
1421 /// `length() > max_size() - distance(first, last)`.
1422 template <class INPUT_ITER>
1423 basic_string& privateAppend(INPUT_ITER first,
1424 INPUT_ITER last,
1425 const char *message,
1426 std::input_iterator_tag);
1427
1428 /// Specialized append for forward, bidirectional, and random-access
1429 /// iterators. Throw `length_error` with the specified `message` if
1430 /// `length() > max_size() - distance(first, last)`.
1431 template <class INPUT_ITER>
1432 basic_string& privateAppend(INPUT_ITER first,
1433 INPUT_ITER last,
1434 const char *message,
1435 std::forward_iterator_tag);
1436
1437 /// Dispatch the append operation to the correct `privateAppend`
1438 /// overload using `privateAppendDispatch`.
1439 template<class INPUT_ITER>
1440 basic_string& privateAppend(INPUT_ITER first,
1441 INPUT_ITER last,
1442 const char *message);
1443
1444 /// Match integral type for `INPUT_ITER`.
1445 template <class INPUT_ITER>
1446 basic_string& privateAppendDispatch(
1447 INPUT_ITER first,
1448 INPUT_ITER last,
1449 const char *message,
1450 BloombergLP::bslmf::MatchArithmeticType,
1451 BloombergLP::bslmf::Nil);
1452
1453 /// Match non-integral type for `INPUT_ITER`.
1454 template <class INPUT_ITER>
1455 basic_string& privateAppendDispatch(
1456 INPUT_ITER first,
1457 INPUT_ITER last,
1458 const char *message,
1459 BloombergLP::bslmf::MatchAnyType,
1460 BloombergLP::bslmf::MatchAnyType);
1461
1462 /// Assign to this string the value of the string described by the
1463 /// specified `first` and `second` values, and return a reference
1464 /// providing modifiable access to this string. The (template
1465 /// parameter) types `FIRST_TYPE` and `SECOND_TYPE` may resolve to
1466 /// `const CHAR_TYPE *` and `size_type`, `size_type` and `CHAR_TYPE`, or
1467 /// a pair of iterators. This method clears the string and then
1468 /// dispatches to the corresponding `privateAppend` function. Throw
1469 /// `length_error` with the specified `message` if the length of the
1470 /// string described by `first` and `second` is greater than
1471 /// `max_size()`.
1472 template<class FIRST_TYPE, class SECOND_TYPE>
1473 basic_string& privateAssignDispatch(FIRST_TYPE first,
1474 SECOND_TYPE second,
1475 const char *message);
1476
1477 /// Return a reference providing modifiable access to the base object
1478 /// of this string.
1479 Imp& privateBase();
1480
1481 /// Reset this string object to its default-constructed value and
1482 /// deallocate its string buffer if the specified `deallocateBufferFlag`
1483 /// is `true`.
1484 void privateClear(bool deallocateBufferFlag);
1485
1486 void privateInsertDispatch(const_iterator position,
1487 iterator first,
1488 iterator last);
1489 /// Insert into this object at the specified `position` a string
1490 /// represented by the specified `first` and `last` iterators using the
1491 /// `privateInsertRaw` method for insertion. The behavior is undefined
1492 /// unless `first` and `last` refer to a sequence of valid values where
1493 /// `first` is at a position at or before `last`.
1494 void privateInsertDispatch(const_iterator position,
1495 const_iterator first,
1496 const_iterator last);
1497
1498 /// Insert into this object at the specified `position` a string
1499 /// represented by the specified `first` and `last` iterators. The
1500 /// behavior is undefined unless `first` and `last` refer to a sequence
1501 /// of valid values where `first` is at a position at or before `last`.
1502 /// Note that since the (template parameter) type `INPUT_ITER` can also
1503 /// resolve to an integral type, use the `privateReplaceDispatch` to
1504 /// disambiguate between the integral type and iterator types.
1505 template <class INPUT_ITER>
1506 void privateInsertDispatch(const_iterator position,
1507 INPUT_ITER first,
1508 INPUT_ITER last);
1509
1510 /// Insert into this object at the specified `outPosition` the specified
1511 /// initial `numChars` from the specified `characterString`. The
1512 /// behavior is undefined unless `numChars <= max_size() - length()` and
1513 /// `characterString` is at least `numChars` long. Note that this
1514 /// method is alias-safe, i.e., it works correctly even if
1515 /// `characterString` points into this string object.
1516 basic_string& privateInsertRaw(size_type outPosition,
1517 const CHAR_TYPE *characterString,
1518 size_type numChars);
1519
1520 /// Replace the specified `outNumChars` characters of this string
1521 /// starting at the specified `outPosition` with the specified initial
1522 /// `numChars` from the specified `characterString`, and return a
1523 /// reference providing modifiable access to this string. The behavior
1524 /// is undefined unless `outPosition <= length()`,
1525 /// `outNumChars <= length()`, `outPosition <= length() - outNumChars`,
1526 /// `numChars <= max_size()`,
1527 /// `length() - outNumChars <= max_size() - numChars`, and
1528 /// `characterString` is at least `numChars` long. Note that this
1529 /// method is alias-safe, i.e., it works correctly even if
1530 /// `characterString` points into this string object.
1531 basic_string& privateReplaceRaw(size_type outPosition,
1532 size_type outNumChars,
1533 const CHAR_TYPE *characterString,
1534 size_type numChars);
1535
1536 /// Replace the specified `outNumChars` characters of this string
1537 /// starting at the specified `outPosition` with the specified
1538 /// `numChars` copies of the specified `character`, and return a
1539 /// reference providing modifiable access to this string. The behavior
1540 /// is undefined unless `outPosition <= length()`,
1541 /// `outNumChars <= length()`, `outPosition <= length() - outNumChars`,
1542 /// and `length() <= max_size() - numChars`.
1543 basic_string& privateReplaceRaw(size_type outPosition,
1544 size_type outNumChars,
1545 size_type numChars,
1546 CHAR_TYPE character);
1547
1548 /// Match integral type for `INPUT_ITER`.
1549 template <class INPUT_ITER>
1550 basic_string& privateReplaceDispatch(
1551 size_type position,
1552 size_type numChars,
1553 INPUT_ITER first,
1554 INPUT_ITER last,
1555 BloombergLP::bslmf::MatchArithmeticType ,
1556 BloombergLP::bslmf::Nil );
1557
1558 /// Match non-integral type for `INPUT_ITER`.
1559 template <class INPUT_ITER>
1560 basic_string& privateReplaceDispatch(
1561 size_type position,
1562 size_type numChars,
1563 INPUT_ITER first,
1564 INPUT_ITER last,
1565 BloombergLP::bslmf::MatchAnyType ,
1566 BloombergLP::bslmf::MatchAnyType );
1567
1568 /// Specialized replacement for input iterators, using repeated
1569 /// `push_back` operations.
1570 template <class INPUT_ITER>
1571 basic_string& privateReplace(size_type position,
1572 size_type numChars,
1573 INPUT_ITER first,
1574 INPUT_ITER last,
1575 std::input_iterator_tag);
1576
1577 /// Specialized replacement for forward, bidirectional, and
1578 /// random-access iterators. Throw `length_error` if
1579 /// `length() - numChars > max_size() - distance(first, last)`.
1580 template <class INPUT_ITER>
1581 basic_string& privateReplace(size_type position,
1582 size_type numChars,
1583 INPUT_ITER first,
1584 INPUT_ITER last,
1585 std::forward_iterator_tag);
1586
1587 /// Replace the specified `numChars` characters of this object starting
1588 /// at the specified `position` with the string represented by the
1589 /// specified `first` and `last` iterators. The behavior is undefined
1590 /// unless `first` and `last` refer to a sequence of valid values where
1591 /// `first` is at a position at or before `last`.
1592 basic_string& privateReplace(size_type position,
1593 size_type numChars,
1594 iterator first,
1595 iterator last,
1596 std::forward_iterator_tag);
1597 basic_string& privateReplace(size_type position,
1598 size_type numChars,
1599 const_iterator first,
1600 const_iterator last,
1601 std::forward_iterator_tag);
1602
1603 /// Update the capacity of this object to be a value greater than or
1604 /// equal to the specified `newCapacity`. The behavior is undefined
1605 /// unless `newCapacity <= max_size()`. Note that a null-terminating
1606 /// character is not counted in `newCapacity`, and that this method has
1607 /// no effect unless `newCapacity > capacity()`.
1608 void privateReserveRaw(size_type newCapacity);
1609
1610 /// Update the capacity of this object and load into the specified
1611 /// `storage` to be a value greater than or equal to the specified
1612 /// `newCapacity`. Upon reallocation, copy the first specified
1613 /// `numChars` from the previous buffer to the new buffer, and load
1614 /// `storage` with the new capacity. If `*storage >= newCapacity`, this
1615 /// method has no effect. Return the new buffer if reallocation, and 0
1616 /// otherwise. The behavior is undefined unless `numChars <= length()`
1617 /// and `newCapacity <= max_size()`. Note that a null-terminating
1618 /// character is not counted in `*storage` nor `newCapacity`. Also note
1619 /// that the previous buffer is *not* deallocated, nor is the string
1620 /// representation changed (in case the previous buffer may contain data
1621 /// that must be copied): it is the responsibility of the caller to do
1622 /// so upon reallocation.
1623 CHAR_TYPE *privateReserveRaw(size_type *storage,
1624 size_type newCapacity,
1625 size_type numChars);
1626
1627 /// Change the length of this string to the specified `newLength`. If
1628 /// `newLength > length()`, fill in the new positions by copies of the
1629 /// specified `character`. Do not change the capacity unless
1630 /// `newLength` exceeds the current capacity. The behavior is undefined
1631 /// unless `newLength <= max_size()`.
1632 basic_string& privateResizeRaw(size_type newLength, CHAR_TYPE character);
1633
1634 /// Efficiently exchange the value and allocator of this object with the
1635 /// value and allocator of the specified `other` object. This method
1636 /// provides the no-throw exception-safety guarantee. Note that this
1637 /// method should not be called unless the allocators compare equal or
1638 /// the allocator traits support allocator propagation (`ALLOC_PROP` is
1639 /// `true`).
1640 template <bool ALLOC_PROP>
1641 void quickSwapExchangeAllocators(basic_string& other,
1643
1644 /// Efficiently exchange the value of this object with the value of the
1645 /// specified `other` object. This method provides the no-throw
1646 /// exception-safety guarantee. The behavior is undefined unless
1647 /// `*this` and `other` allocators compare equal.
1648 void quickSwapRetainAllocators(basic_string& other);
1649
1650 // PRIVATE ACCESSORS
1651
1652 /// Lexicographically compare the substring of this string starting at
1653 /// the specified `lhsPosition` of length `lhsNumChars` with the
1654 /// specified initial `otherNumChars` characters in the specified
1655 /// `other` string, and return a negative value if the indicated
1656 /// substring of this string is less than `other`, a positive value if
1657 /// it is greater than `other`, and 0 in case of equality. The behavior
1658 /// is undefined unless `lhsPosition <= length()`,
1659 /// `lhsNumChars <= length()`, and
1660 /// `lhsPosition <= length() - lhsNumChars`.
1661 int privateCompareRaw(size_type lhsPosition,
1662 size_type lhsNumChars,
1663 const CHAR_TYPE *other,
1664 size_type otherNumChars) const;
1665
1666 // INVARIANTS
1667 BSLMF_ASSERT((bsl::is_same<CHAR_TYPE,
1668 typename ALLOCATOR::value_type>::value));
1669 // This is required by the C++ standard (23.1, clause 1).
1670
1671 public:
1672 // PUBLIC CLASS DATA
1673
1674 /// Value used to denote "not-a-position", guaranteed to be outside the
1675 /// range `[0 .. max_size()]`.
1676 static const size_type npos = ~size_type(0);
1677
1678 // CREATORS
1679
1680 // *** 21.3.2 construct/copy/destroy: ***
1681
1683
1684 /// Create an empty string. Optionally specify the `basicAllocator`
1685 /// used to supply memory. If `basicAllocator` is not specified, a
1686 /// default-constructed allocator is used.
1687 explicit basic_string(const ALLOCATOR& basicAllocator)
1689
1690 /// Create a string that has the same value as the specified `original`
1691 /// string. Use the allocator returned by
1692 /// 'bsl::allocator_traits<ALLOCATOR>::
1693 /// select_on_container_copy_construction(original.get_allocator())' to
1694 /// supply memory.
1695 basic_string(const basic_string& original);
1696
1697 /// Create a string that has the same value as the specified `original`
1698 /// string and uses the specified `basicAllocator` to supply memory.
1699 ///
1700 /// Note that it is important to have two copy constructors instead of a
1701 /// single:
1702 /// @code
1703 /// basic_string(const basic_string& original,
1704 /// const ALLOCATOR& basicAllocator = ALLOCATOR());
1705 /// @endcode
1706 /// When the copy constructor with the default allocator is used, xlC10
1707 /// gets confused and refuses to use the return value optimization,
1708 /// which then causes extra allocations when returning by value in
1709 /// `operator+`.
1710 basic_string(const basic_string& original,
1711 const ALLOCATOR& basicAllocator);
1712
1713 /// Create a string that has the same value as the specified `original`
1714 /// string by moving (in constant time) the contents of `original` to
1715 /// the new string. The allocator associated with `original` is
1716 /// propagated for use in the newly-created string. `original` is left
1717 /// in a valid but unspecified state.
1718 basic_string(BloombergLP::bslmf::MovableRef<basic_string> original)
1720
1721 /// Create a string that has the same value as the specified `original`
1722 /// string that uses the specified `basicAllocator` to supply memory.
1723 /// The contents of `original` are moved (in constant time) to the new
1724 /// string if `basicAllocator == original.get_allocator()`, and are
1725 /// copied (in linear time) using `basicAllocator` otherwise.
1726 /// `original` is left in a valid but unspecified state.
1727 basic_string(BloombergLP::bslmf::MovableRef<basic_string> original,
1728 const ALLOCATOR& basicAllocator);
1729
1730 /// Create a string that has the same value as the substring starting at
1731 /// the specified `position` in the specified `original` string.
1732 /// Optionally specify the `basicAllocator` used to supply memory. If
1733 /// `basicAllocator` is not specified, a default-constructed allocator
1734 /// is used. Throw `out_of_range` if `position > original.length()`.
1735 basic_string(const basic_string& original,
1736 size_type position,
1737 const ALLOCATOR& basicAllocator = ALLOCATOR());
1738
1739 /// Create a string that has the same value as the substring of the
1740 /// specified `numChars` length starting at the specified `position` in
1741 /// the specified `original` string. If `numChars` equals `npos`, then
1742 /// the remaining length of the string is used (i.e., `numChars` is set
1743 /// to `original.length() - position`). Optionally specify the
1744 /// `basicAllocator` used to supply memory. If `basicAllocator` is not
1745 /// specified, a default-constructed allocator is used. Throw
1746 /// `out_of_range` if `position > original.length()`.
1747 basic_string(const basic_string& original,
1748 size_type position,
1749 size_type numChars,
1750 const ALLOCATOR& basicAllocator = ALLOCATOR());
1751
1752#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
1753 /// Create a string having the same value as the specified
1754 /// null-terminated `characterString` (of length
1755 /// `CHAR_TRAITS::length(characterString)`). Optionally specify a
1756 /// `basicAllocator` used to supply memory. If `basicAllocator` is not
1757 /// specified, a default-constructed allocator is used.
1758 template <class = bsl::enable_if_t<bsl::IsStdAllocator<ALLOCATOR>::value>>
1759#endif
1760 basic_string(const CHAR_TYPE *characterString,
1761 const ALLOCATOR& basicAllocator = ALLOCATOR()); // IMPLICIT
1762
1763 /// Create a string that has the same value as the substring of the
1764 /// optionally specified `numChars` length starting at the beginning of
1765 /// the specified `characterString`. If `numChars` is not specified,
1766 /// `CHAR_TRAITS::length(characterString)` is used. Optionally specify
1767 /// the `basicAllocator` used to supply memory. If `basicAllocator` is
1768 /// not specified, a default-constructed allocator is used. Throw
1769 /// `out_of_range` if `numChars >= npos`.
1770 basic_string(const CHAR_TYPE *characterString,
1771 size_type numChars,
1772 const ALLOCATOR& basicAllocator = ALLOCATOR());
1773
1774#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
1775 /// Create a string of the specified `numChars` length whose every
1776 /// position contains the specified `character`. Optionally specify a
1777 /// `basicAllocator` used to supply memory. If `basicAllocator` is not
1778 /// specified, a default-constructed allocator is used.
1779 template <class = bsl::enable_if_t<bsl::IsStdAllocator<ALLOCATOR>::value>>
1780#endif
1781 basic_string(size_type numChars,
1782 CHAR_TYPE character,
1783 const ALLOCATOR& basicAllocator = ALLOCATOR());
1784
1785 /// Create a string from the characters in the range starting at the
1786 /// specified `first` iterator and ending right before the specified
1787 /// `last` iterator of the (template parameter) type `INPUT_ITER`.
1788 /// Optionally specify a `basicAllocator` used to supply memory. If
1789 /// `basicAllocator` is not specified, a default-constructed allocator
1790 /// is used. The behavior is undefined unless `first` and `last` refer
1791 /// to a sequence of valid values where `first` is at a position at or
1792 /// before `last`.
1793 template <class INPUT_ITER>
1794 basic_string(INPUT_ITER first,
1795 INPUT_ITER last,
1796 const ALLOCATOR& basicAllocator = ALLOCATOR());
1797
1798 /// Create a string that has the same value as the specified `original`
1799 /// string, where the type `original` is the string type native to the
1800 /// compiler's library, instantiated with the same character type and
1801 /// traits type, but not necessarily the same allocator type. The
1802 /// resulting string will contain the same sequence of characters as
1803 /// `original`. Optionally specify a `basicAllocator` used to supply
1804 /// memory. If `basicAllocator` is not specified, then a
1805 /// default-constructed allocator is used.
1806 template <class ALLOC2>
1808 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& original,
1809 const ALLOCATOR& basicAllocator = ALLOCATOR()); // IMPLICIT
1810
1811 /// Create a string that has the same value as the specified `strRef`
1812 /// string. The resulting string will contain the same sequence of
1813 /// characters as `strRef`. Optionally specify a `basicAllocator` used
1814 /// to supply memory. If `basicAllocator` is not specified, then a
1815 /// default-constructed allocator is used.
1816 basic_string(const BloombergLP::bslstl::StringRefData<CHAR_TYPE>& strRef,
1817 const ALLOCATOR& basicAllocator = ALLOCATOR()); // IMPLICIT
1818
1819 /// Create a string that has the same value as the specified `object`.
1820 /// Optionally specify a `basicAllocator` used to supply memory. If
1821 /// `basicAllocator` is not specified, then a default-constructed
1822 /// allocator is used.
1823 template <class STRING_VIEW_LIKE_TYPE>
1824 explicit basic_string(
1825 const STRING_VIEW_LIKE_TYPE& object
1827
1828 /// Create a string that has the same value as the substring of the
1829 /// specified `numChars` length starting at the specified `position` in
1830 /// the specified `object`. Optionally specify a `basicAllocator` used
1831 /// to supply memory. If the `basicAllocator` is not specified, a
1832 /// default-constructed allocator is used. Throw `out_of_range` if
1833 /// `position > original.object()`.
1834 template <class STRING_VIEW_LIKE_TYPE>
1835 basic_string(const STRING_VIEW_LIKE_TYPE& object,
1836 size_type position,
1837 size_type numChars,
1838 const ALLOCATOR& basicAllocator = ALLOCATOR()
1840
1841#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1842 /// Create a string and insert (in order) each `CHAR_TYPE` object in the
1843 /// specified `values` initializer list. Optionally specify a
1844 /// `basicAllocator` used to supply memory. If `basicAllocator` is not
1845 /// specified, then a default-constructed allocator is used.
1846 basic_string(std::initializer_list<CHAR_TYPE> values,
1847 const ALLOCATOR& basicAllocator =
1848 ALLOCATOR());
1849#endif
1850
1851 /// Destroy this string object.
1852 ~basic_string();
1853
1854 // MANIPULATORS
1855
1856 // *** 21.3.2 construct/copy/destroy: ***
1857
1858 /// Assign to this string the value of the specified `rhs` string,
1859 /// propagate to this object the allocator of `rhs` if the `ALLOCATOR`
1860 /// type has trait `propagate_on_container_copy_assignment`, and return
1861 /// a reference providing modifiable access to this string.
1862 basic_string& operator=(const basic_string& rhs);
1863
1864#ifndef DOXYGEN_SKIP
1865 /// Assign to this string the value of the specified `rhs` string,
1866 /// propagate to this object the allocator of `rhs` if the `ALLOCATOR`
1867 /// type has trait `propagate_on_container_move_assignment`, and return
1868 /// a reference providing modifiable access to this string. The content
1869 /// of `rhs` is moved (in constant time) to this string if
1870 /// `get_allocator() == rhs.get_allocator()` (after accounting for the
1871 /// aforementioned trait). `rhs` is left in a valid but unspecified
1872 /// state.
1873 basic_string& operator=(BloombergLP::bslmf::MovableRef<basic_string> rhs)
1875 AllocatorTraits::propagate_on_container_move_assignment::value ||
1876 AllocatorTraits::is_always_equal::value);
1877#endif
1878
1879 /// Assign to this string the value of the specified `rhs` object, and
1880 /// return a reference providing modifiable access to this string.
1881 template <class STRING_VIEW_LIKE_TYPE>
1883 operator=(const STRING_VIEW_LIKE_TYPE& rhs);
1884
1885 /// Assign to this string the value of the specified null-terminated
1886 /// `rhs` string (of length `CHAR_TRAITS::length(characterString)`), and
1887 /// return a reference providing modifiable access to this string.
1888 basic_string& operator=(const CHAR_TYPE *rhs);
1889
1890 /// Assign to this string the value of the string of length one
1891 /// consisting of the specified `character`, and return a reference
1892 /// providing modifiable access to this string.
1893 basic_string& operator=(CHAR_TYPE character);
1894
1895 /// Assign to this string the value of the specified `rhs` string, and
1896 /// return a reference providing modifiable access to this string.
1897 template <class ALLOC2>
1899 const std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC2>& rhs);
1900
1901#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1902 /// Assign to this string the value resulting from first clearing this
1903 /// string and then inserting (in order) each `CHAR_TYPE` object in the
1904 /// specified `values` initializer list.
1905 basic_string& operator=(std::initializer_list<CHAR_TYPE> values);
1906#endif
1907
1908 // *** 21.3.4 capacity: ***
1909
1910 /// Change the length of this string to the specified `newLength`,
1911 /// erasing characters at the end if `newLength < length()` or appending
1912 /// the appropriate number of copies of the specified `character` at the
1913 /// end if `length() < newLength`.
1914 void resize(size_type newLength, CHAR_TYPE character);
1915
1916 /// Change the length of this string to the specified `newLength`,
1917 /// erasing characters at the end if `newLength < length()` or appending
1918 /// the appropriate number of copies of `CHAR_TYPE()` at the end if
1919 /// `length() < newLength`.
1920 void resize(size_type newLength);
1921
1922 /// Change the length of this string to the specified `newLength`,
1923 /// erasing characters at the end if `newLength < length()` or appending
1924 /// the appropriate number of characters at the end if
1925 /// `length() < newLength`. Subsequently, invoke the specified
1926 /// `operation` passing the address of the null-terminated buffer and
1927 /// the adjusted length of this string as parameters. Finally, change
1928 /// the length of this string to the value returned by the `operation`.
1929 /// Throw `length_error` if `newLength > max_size()`. The behavior is
1930 /// undefined unless the value returned by the `operation` is less than
1931 /// or equal to `newLength`.
1932 template <class OPERATION>
1933 void resize_and_overwrite(size_type newLength, OPERATION operation);
1934
1935 /// Change the capacity of this string to the specified `newCapacity`.
1936 /// Note that the capacity of a string is the maximum length it can
1937 /// accommodate without reallocation. The actual storage allocated may
1938 /// be higher.
1939 void reserve(size_type newCapacity = 0);
1940
1941 /// Request the removal of unused capacity by causing reallocation.
1942 /// Note that this method has no effect if the capacity is equal to the
1943 /// size. Also note that if (and only if) reallocation occurs, all
1944 /// iterators, including the past the end iterator, and all references
1945 /// to the elements are invalidated.
1946 void shrink_to_fit();
1947
1948 /// Reset this string to an empty value. Note that the capacity may
1949 /// change (or not if `BASIC_STRING_DEALLOCATE_IN_CLEAR` is `false`).
1950 /// Note that the Standard doesn't allow to reduce capacity on `clear`.
1951 void clear() BSLS_KEYWORD_NOEXCEPT;
1952
1953 // *** 21.3.3 iterators: ***
1954
1955 /// Return an iterator referring to the first character in this
1956 /// modifiable string (or the past-the-end iterator if this string is
1957 /// empty).
1959
1960 /// Return the past-the-end iterator for this modifiable string.
1962
1963 /// Return a reverse iterator referring to the last character in this
1964 /// modifiable string (or the past-the-end reverse iterator if this
1965 /// string is empty).
1967
1968 /// Return the past-the-end reverse iterator for this modifiable string.
1970
1971 // *** 21.3.5 element access: ***
1972
1973 /// Return a reference providing modifiable access to the character at
1974 /// the specified `position` in this string if `position < length()`, or
1975 /// a reference providing non-modifiable access to the null-terminating
1976 /// character if `position == length()`. The behavior is undefined
1977 /// unless `position <= length()`, and, in the case of
1978 /// `position == length()`, the null-terminating character is not
1979 /// modified through the returned reference.
1980 reference operator[](size_type position);
1981
1982 /// Return a reference providing modifiable access to the character at
1983 /// the specified `position` in this string. Throw `out_of_range` if
1984 /// `position >= length()`.
1985 reference at(size_type position);
1986
1987 /// Return a reference providing modifiable access to the character at
1988 /// the first position in this string. The behavior is undefined if
1989 /// this string is empty.
1990 CHAR_TYPE& front();
1991
1992 /// Return a reference providing modifiable access to the character at
1993 /// the last position in this string. The behavior is undefined if this
1994 /// string is empty. Note that the last position is `length() - 1`.
1995 CHAR_TYPE& back();
1996
1997 // *** 21.3.6 modifiers: ***
1998
1999 /// Append the specified `rhs` string to this string, and return a
2000 /// reference providing modifiable access to this string.
2001 basic_string& operator+=(const basic_string& rhs);
2002
2003 /// Append the specified null-terminated `rhs` string (of length
2004 /// `CHAR_TRAITS::length(rhs)`) to this string, and return a reference
2005 /// providing modifiable access to this string.
2006 basic_string& operator+=(const CHAR_TYPE *rhs);
2007
2008 /// Append the specified `character` to this string, and return a
2009 /// reference providing modifiable access to this string.
2010 basic_string& operator+=(CHAR_TYPE character);
2011
2012 /// Append the specified `rhs` to this string, and return a reference
2013 /// providing modifiable access to this string.
2014 template <class STRING_VIEW_LIKE_TYPE>
2016 operator+=(const STRING_VIEW_LIKE_TYPE& rhs);
2017
2018 /// Append the specified `rhs` string to this string, and return a
2019 /// reference providing modifiable access to this string.
2020 template <class ALLOC2>
2021 basic_string& operator+=(
2022 const std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC2>& rhs);
2023
2024 /// Append to this string the specified `suffix`, and return a reference
2025 /// providing modifiable access to this string.
2026 basic_string& append(const basic_string& suffix);
2027
2028 /// Append to this string the optionally specified `numChars` characters
2029 /// starting at the specified `position` in the specified `suffix`, or
2030 /// the tail of `suffix` starting at `position` if
2031 /// `position + numChars > suffix.length()`. If `numChars` is not
2032 /// specified, `npos` is used. Return a reference providing modifiable
2033 /// access to this string. Throw `out_of_range` if
2034 /// `position > suffix.length()`.
2035 basic_string& append(const basic_string& suffix,
2036 size_type position,
2037 size_type numChars = npos);
2038
2039 /// Append to this string the specified initial `numChars` characters
2040 /// from the specified `characterString`, and return a reference
2041 /// providing modifiable access to this string. The behavior is
2042 /// undefined unless `characterString` is at least `numChars` long.
2043 basic_string& append(const CHAR_TYPE *characterString,
2044 size_type numChars);
2045
2046 /// Append the specified null-terminated `characterString` (of length
2047 /// `CHAR_TRAITS::length(characterString)`) to this string, and return a
2048 /// reference providing modifiable access to this string.
2049 basic_string& append(const CHAR_TYPE *characterString);
2050
2051 /// Append the specified `numChars` copies of the specified `character`
2052 /// to this string, and return a reference providing modifiable access
2053 /// to this string.
2054 basic_string& append(size_type numChars, CHAR_TYPE character);
2055
2056 /// Append to this string the `bsl::string_view` object, obtained from
2057 /// the specified `suffix`, and return a reference providing modifiable
2058 /// access to this string. Throw `length_error` if the length of the
2059 /// resulting string exceeds `max_size()`.
2060 template <class STRING_VIEW_LIKE_TYPE>
2062 append(const STRING_VIEW_LIKE_TYPE& suffix);
2063
2064 /// Append to this string the optionally specified `numChars` characters
2065 /// starting at the specified `position` in the `bsl::string_view`
2066 /// object, obtained from the specified `suffix`, or its tail starting
2067 /// at `position` if `numChars` exceeds the length of this tail. If
2068 /// `numChars` is not specified, `npos` is used. Return a reference
2069 /// providing modifiable access to this string. Throw `out_of_range` if
2070 /// `position > strView.length()`. Throw `length_error` if the length
2071 /// of the resulting string exceeds `max_size()`.
2072 template <class STRING_VIEW_LIKE_TYPE>
2074 append(const STRING_VIEW_LIKE_TYPE& suffix,
2075 size_type position,
2076 size_type numChars = npos);
2077
2078 /// Append to this string the characters in the range starting at the
2079 /// specified `first` iterator and ending right before the specified
2080 /// `last` iterator of the (template parameter) type `INPUT_ITER`.
2081 /// Return a reference providing modifiable access to this string. The
2082 /// behavior is undefined unless `first` and `last` refer to a sequence
2083 /// of valid values where `first` is at a position at or before `last`.
2084 template <class INPUT_ITER>
2085 basic_string& append(INPUT_ITER first, INPUT_ITER last);
2086
2087#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2088 /// Append to this string each `CHAR_TYPE` object in the specified
2089 /// `values` initializer list, and return a reference providing
2090 /// modifiable access to this string.
2091 basic_string& append(std::initializer_list<CHAR_TYPE> values);
2092#endif
2093
2094 /// Append the specified `character` to this string.
2095 void push_back(CHAR_TYPE character);
2096
2097 /// Assign to this string the value of the specified `replacement`
2098 /// string, propagate to this object the allocator of `replacement` if
2099 /// the `ALLOCATOR` type has trait
2100 /// `propagate_on_container_copy_assignment`, and return a reference
2101 /// providing modifiable access to this string. Note that this method
2102 /// has exactly the same behavior as the corresponding `operator=`.
2103 basic_string& assign(const basic_string& replacement);
2104
2105 /// Assign to this string the value of the specified `replacement`
2106 /// string, propagate to this object the allocator of `replacement` if
2107 /// the `ALLOCATOR` type has trait
2108 /// `propagate_on_container_move_assignment`, and return a reference
2109 /// providing modifiable access to this string. The content of
2110 /// `replacement` is moved (in constant time) to this string if
2111 /// `get_allocator() == rhs.get_allocator()` (after accounting for the
2112 /// aforementioned trait). `replacement` is left in a valid but
2113 /// unspecified state. Note that this method has exactly the same
2114 /// behavior as the corresponding `operator=`.
2115 basic_string& assign(
2116 BloombergLP::bslmf::MovableRef<basic_string> replacement)
2118
2119 /// Assign to this string the value of the optionally specified
2120 /// `numChars` characters starting at the specified `position` in the
2121 /// specified `replacement` string, or the suffix of `replacement`
2122 /// starting at `position` if
2123 /// `position + numChars > replacement.length()`. If `numChars` is not
2124 /// specified, `npos` is used. Return a reference providing modifiable
2125 /// access to this string. Throw `out_of_range` if
2126 /// `position > replacement.length()`.
2127 basic_string& assign(const basic_string& replacement,
2128 size_type position,
2129 size_type numChars = npos);
2130
2131 /// Assign to this string the value of the specified null-terminated
2132 /// `characterString` (of length
2133 /// `CHAR_TRAITS::length(characterString)`), and return a reference
2134 /// providing modifiable access to this string.
2135 basic_string& assign(const CHAR_TYPE *characterString);
2136
2137 /// Assign to this string the specified initial `numChars` characters in
2138 /// the specified `characterString`, and return a reference providing
2139 /// modifiable access to this string. The behavior is undefined unless
2140 /// `characterString` is at least `numChars` long.
2141 basic_string& assign(const CHAR_TYPE *characterString,
2142 size_type numChars);
2143
2144 /// Assign to this string the value of the specified `replacement`, and
2145 /// return a reference providing modifiable access to this string. Note
2146 /// that this method has exactly the same behavior as the corresponding
2147 /// `operator=`.
2148 template <class STRING_VIEW_LIKE_TYPE>
2150 assign(const STRING_VIEW_LIKE_TYPE& replacement);
2151
2152 /// Assign to this string the value of the optionally specified
2153 /// `numChars` characters starting at the specified `position` in the
2154 /// specified `replacement`, or the suffix of the `replacement` starting
2155 /// at `position` if `position + numChars > replacement.length()`. If
2156 /// `numChars` is not specified, `npos` is used. Return a reference
2157 /// providing modifiable access to this string. Throw `out_of_range` if
2158 /// `position > replacement.length()`.
2159 template <class STRING_VIEW_LIKE_TYPE>
2161 assign(const STRING_VIEW_LIKE_TYPE& replacement,
2162 size_type position,
2163 size_type numChars = npos);
2164
2165 /// Assign to this string the value of the specified `string`, and
2166 /// return a reference providing modifiable access to this string.
2167 template <class ALLOC2>
2169 const std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC2>& string);
2170
2171 /// Assign to this string the value of a string of the specified
2172 /// `numChars` length whose every character is equal to the specified
2173 /// `character`, and return a reference providing modifiable access to
2174 /// this string.
2175 basic_string& assign(size_type numChars, CHAR_TYPE character);
2176
2177 /// Assign to this string the characters in the range starting at the
2178 /// specified `first` iterator and ending right before the specified
2179 /// `last` iterator of the (template parameter) type `INPUT_ITER`.
2180 /// Return a reference providing modifiable access to this string. The
2181 /// behavior is undefined unless `first` and `last` refer to a sequence
2182 /// of valid values where `first` is at a position at or before `last`.
2183 template <class INPUT_ITER>
2184 basic_string& assign(INPUT_ITER first, INPUT_ITER last);
2185
2186#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2187 /// Assign to this string the value resulting from first clearing this
2188 /// string and then inserting (in order) each `CHAR_TYPE` object in the
2189 /// specified `values` initializer list. Return a reference providing
2190 /// modifiable access to this string.
2191 basic_string& assign(std::initializer_list<CHAR_TYPE> values);
2192#endif
2193
2194 /// Insert at the specified `position` in this string a copy of the
2195 /// specified `other` string, and return a reference providing
2196 /// modifiable access to this string. Throw `out_of_range` if
2197 /// `position > length()`.
2198 basic_string& insert(size_type position, const basic_string& other);
2199
2200 /// Insert at the specified `position` in this string the optionally
2201 /// specified `numChars` characters starting at the specified
2202 /// `sourcePosition` in the specified `other` string, or the suffix of
2203 /// `other` starting at `sourcePosition` if
2204 /// `sourcePosition + numChars > other.length()`. If `numChars` is not
2205 /// specified, `npos` is used. Return a reference providing modifiable
2206 /// access to this string. Throw `out_of_range` if
2207 /// `position > length()` or `sourcePosition > other.length()`.
2208 basic_string& insert(size_type position,
2209 const basic_string& other,
2210 size_type sourcePosition,
2211 size_type numChars = npos);
2212
2213 /// Insert at the specified `position` in this string the specified
2214 /// initial `numChars` characters in the specified `characterString`,
2215 /// and return a reference providing modifiable access to this string.
2216 /// Throw `out_of_range` if `position > length()`. The behavior is
2217 /// undefined unless `characterString` is at least `numChars` long.
2218 basic_string& insert(size_type position,
2219 const CHAR_TYPE *characterString,
2220 size_type numChars);
2221
2222 /// Insert at the specified `position` in this string the specified
2223 /// null-terminated `characterString` (of length
2224 /// `CHAR_TRAITS::length(characterString)`), and return a reference
2225 /// providing modifiable access to this string. Throw `out_of_range` if
2226 /// `position > length()`.
2227 basic_string& insert(size_type position,
2228 const CHAR_TYPE *characterString);
2229
2230 /// Insert at the specified `position` in this string the specified
2231 /// `numChars` copies of the specified `character`, and return a
2232 /// reference providing modifiable access to this string. Throw
2233 /// `out_of_range` if `position > length()`.
2234 basic_string& insert(size_type position,
2235 size_type numChars,
2236 CHAR_TYPE character);
2237
2238 /// Insert the specified `character` at the specified `position` in this
2239 /// string, and return an iterator providing modifiable access to the
2240 /// inserted character. The behavior is undefined unless `position` is
2241 /// a valid iterator on this string.
2242 iterator insert(const_iterator position, CHAR_TYPE character);
2243
2244 /// Insert at the specified `position` in this string the characters in
2245 /// the range starting at the specified `first` iterator and ending
2246 /// right before the specified `last` iterator of the (template
2247 /// parameter) type `INPUT_ITER`, and return an iterator providing
2248 /// modifiable access to the first inserted character, or a non-`const`
2249 /// copy of `position` if `first == last`. The behavior is undefined
2250 /// unless `position` is a valid iterator on this string, and `first`
2251 /// and `last` refer to a sequence of valid values where `first` is at a
2252 /// position at or before `last`.
2253 template <class INPUT_ITER>
2255 INPUT_ITER first,
2256 INPUT_ITER last);
2257
2258 /// Insert at the specified `position` in this string the specified
2259 /// `numChars` copies of the specified `character`, and return an
2260 /// iterator providing modifiable access to the first inserted
2261 /// character, or a non-`const` copy of `position` if `0 == numChars`.
2262 /// The behavior is undefined unless `position` is a valid iterator on
2263 /// this string.
2264 iterator insert(const_iterator position,
2265 size_type numChars,
2266 CHAR_TYPE character);
2267
2268 /// Insert at the specified `position` in this string the
2269 /// `bsl::string_view` object, obtained from the specified `other`, and
2270 /// return a reference providing modifiable access to this string.
2271 /// Throw `out_of_range` if `position > length()`. Throw `length_error`
2272 /// if the length of the resulting string exceeds `max_size()`.
2273 template <class STRING_VIEW_LIKE_TYPE>
2275 insert(size_type position, const STRING_VIEW_LIKE_TYPE& other);
2276
2277 /// Insert at the specified `position` in this string the optionally
2278 /// specified `numChars` characters starting at the specified
2279 /// `sourcePosition` in the `bsl::string_view` object, obtained from the
2280 /// specified `other`, or the suffix of this object starting at
2281 /// `sourcePosition` if `sourcePosition + numChars > other.length()`.
2282 /// If `numChars` is not specified, `npos` is used. Return a reference
2283 /// providing modifiable access to this string. Throw `out_of_range` if
2284 /// `position > length()` or `sourcePosition > other.length()`. Throw
2285 /// `length_error` if the length of the resulting string exceeds
2286 /// `max_size()`.
2287 template <class STRING_VIEW_LIKE_TYPE>
2289 insert(size_type position,
2290 const STRING_VIEW_LIKE_TYPE& other,
2291 size_type sourcePosition,
2292 size_type numChars = npos);
2293
2294#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
2295 /// Insert at the specified `position` in this string each `CHAR_TYPE`
2296 /// object in the specified `values` initializer list, and return an
2297 /// iterator to the first newly-inserted character. If an exception is
2298 /// thrown (other than by the copy constructor, move constructor,
2299 /// assignment operator, and move assignment operator of `CHAR_TYPE`),
2300 /// `*this` is unaffected. The behavior is undefined unless `position`
2301 /// is an iterator in the range `[begin() .. end()]` (both endpoints
2302 /// included).
2303 iterator insert(const_iterator position,
2304 std::initializer_list<CHAR_TYPE> values);
2305#endif
2306
2307 /// Erase from this string the substring of length the optionally
2308 /// specified `numChars` or `original.length() - position`, whichever is
2309 /// smaller, starting at the optionally specified `position`. If
2310 /// `position` is not specified, the first position is used (i.e.,
2311 /// `position` is set to 0). Return a reference providing modifiable
2312 /// access to this string. If `numChars` equals `npos`, then the
2313 /// remaining length of the string is erased (i.e., `numChars` is set to
2314 /// `length() - position`). Throw `out_of_range` if
2315 /// `position > length()`.
2316 basic_string& erase(size_type position = 0, size_type numChars = npos);
2317
2318 /// Erase a character at the specified `position` from this string, and
2319 /// return an iterator providing modifiable access to the character at
2320 /// `position` prior to erasing. If no such character exists, return
2321 /// `end()`. The behavior is undefined unless `position` is within the
2322 /// half-open range `[cbegin() .. cend())`.
2323 iterator erase(const_iterator position);
2324
2325 /// Erase from this string a substring defined by the specified pair of
2326 /// `first` and `last` iterators within this string. Return an iterator
2327 /// providing modifiable access to the character at the `last` position
2328 /// prior to erasing. If no such character exists, return `end()`.
2329 /// This method invalidates existing iterators pointing to `first` or a
2330 /// subsequent position. The behavior is undefined unless `first` and
2331 /// `last` are both within the range `[cbegin() .. cend()]` and `first
2332 /// <= last`.
2334
2335 /// Erase the last character from this string. The behavior is
2336 /// undefined if this string is empty.
2337 void pop_back();
2338
2339 /// Replace the specified `outNumChars` characters starting at the
2340 /// specified `outPosition` in this string (or the suffix of this string
2341 /// starting at `outPosition` if `outPosition + outNumChars > length()`)
2342 /// with the specified `replacement` string, and return a reference
2343 /// providing modifiable access to this string. Throw `out_of_range` if
2344 /// `outPosition > length()`.
2345 basic_string& replace(size_type outPosition,
2346 size_type outNumChars,
2347 const basic_string& replacement);
2348
2349 /// Replace the specified `outNumChars` characters starting at the
2350 /// specified `outPosition` in this string (or the suffix of this string
2351 /// starting at `outPosition` if `outPosition + outNumChars > length()`)
2352 /// with the optionally specified `numChars` characters starting at the
2353 /// specified `position` in the specified `replacement` string (or the
2354 /// suffix of `replacement` starting at `position` if
2355 /// `position + numChars > replacement.length()`). If `numChars` is not
2356 /// specified, `npos` is used. Return a reference providing modifiable
2357 /// access to this string. Throw `out_of_range` if
2358 /// `outPosition > length()` or `position > replacement.length()`.
2359 basic_string& replace(size_type outPosition,
2360 size_type outNumChars,
2361 const basic_string& replacement,
2362 size_type position,
2363 size_type numChars = npos);
2364
2365 /// Replace the specified `outNumChars` characters starting at the
2366 /// specified `outPosition` in this string (or the suffix of this string
2367 /// starting at `outPosition` if `outPosition + outNumChars > length()`)
2368 /// with the specified initial `numChars` characters in the specified
2369 /// `characterString`. Return a reference providing modifiable access
2370 /// to this string. Throw `out_of_range` if `outPosition > length()`.
2371 /// The behavior is undefined unless `characterString` is at least
2372 /// `numChars` long.
2373 basic_string& replace(size_type outPosition,
2374 size_type outNumChars,
2375 const CHAR_TYPE *characterString,
2376 size_type numChars);
2377
2378 /// Replace the specified `outNumChars` characters starting at the
2379 /// specified `outPosition` in this string (or the suffix of this string
2380 /// starting at `outPosition` if `outPosition + outNumChars > length()`)
2381 /// with the specified null-terminated `characterString` (of length
2382 /// `CHAR_TRAITS::length(characterString)`). Return a reference
2383 /// providing modifiable access to this string. Throw `out_of_range` if
2384 /// `outPosition > length()`.
2385 basic_string& replace(size_type outPosition,
2386 size_type outNumChars,
2387 const CHAR_TYPE *characterString);
2388
2389 /// Replace the specified `outNumChars` characters starting at the
2390 /// specified `outPosition` in this string (or the suffix of this string
2391 /// starting at `outPosition` if `outPosition + outNumChars > length()`)
2392 /// with the specified `numChars` copies of the specified `character`.
2393 /// Return a reference providing modifiable access to this string.
2394 /// Throw `out_of_range` if `outPosition > length()`.
2395 basic_string& replace(size_type outPosition,
2396 size_type outNumChars,
2397 size_type numChars,
2398 CHAR_TYPE character);
2399
2400 /// Replace the specified `outNumChars` characters starting at the
2401 /// specified `outPosition` in this string (or the suffix of this string
2402 /// starting at `outPosition` if `outPosition + outNumChars > length()`)
2403 /// with the specified `replacement`, and return a reference providing
2404 /// modifiable access to this string. Throw `out_of_range` if
2405 /// `outPosition > length()`.
2406 template <class STRING_VIEW_LIKE_TYPE>
2408 replace(size_type outPosition,
2409 size_type outNumChars,
2410 const STRING_VIEW_LIKE_TYPE& replacement);
2411
2412
2413 /// Replace the specified `outNumChars` characters starting at the
2414 /// specified `outPosition` in this string (or the suffix of this string
2415 /// starting at `outPosition` if `outPosition + outNumChars > length()`)
2416 /// with the optionally specified `numChars` characters starting at the
2417 /// specified `position` in the specified `replacement` (or the suffix
2418 /// of `replacement` starting at `position` if
2419 /// `position + numChars > replacement.length()`). If `numChars` is not
2420 /// specified, `npos` is used. Return a reference providing modifiable
2421 /// access to this string. Throw `out_of_range` if
2422 /// `outPosition > length()` or `position > replacement.length()`.
2423 template <class STRING_VIEW_LIKE_TYPE>
2425 replace(size_type outPosition,
2426 size_type outNumChars,
2427 const STRING_VIEW_LIKE_TYPE& replacement,
2428 size_type position,
2429 size_type numChars = npos);
2430
2431 /// Replace the substring in the range starting at the specified `first`
2432 /// position and ending right before the specified `last` position with
2433 /// the specified `replacement` string. Return a reference providing
2434 /// modifiable access to this string. The behavior is undefined unless
2435 /// `first` and `last` are both within the range `[cbegin() .. cend()]`
2436 /// and `first <= last`.
2437 basic_string& replace(const_iterator first,
2438 const_iterator last,
2439 const basic_string& replacement);
2440
2441 /// Replace the substring in the range starting at the specified `first`
2442 /// position and ending right before the specified `last` position with
2443 /// the specified `replacement`. Return a reference providing
2444 /// modifiable access to this string. The behavior is undefined unless
2445 /// `first` and `last` are both within the range `[cbegin() .. cend()]`
2446 /// and `first <= last`.
2447 template <class STRING_VIEW_LIKE_TYPE>
2449 replace(const_iterator first,
2450 const_iterator last,
2451 const STRING_VIEW_LIKE_TYPE& replacement);
2452
2453 /// Replace the substring in the range starting at the specified `first`
2454 /// position and ending right before the specified `last` position with
2455 /// the specified initial `numChars` characters in the specified
2456 /// `characterString`. Return a reference providing modifiable access
2457 /// to this string. The behavior is undefined unless `first` and `last`
2458 /// are both within the range `[cbegin() .. cend()]`, `first <= last`,
2459 /// and `characterString` is at least `numChars` long.
2460 basic_string& replace(const_iterator first,
2461 const_iterator last,
2462 const CHAR_TYPE *characterString,
2463 size_type numChars);
2464
2465 /// Replace the substring in the range starting at the specified `first`
2466 /// position and ending right before the specified `last` position with
2467 /// the specified null-terminated `characterString` (of length
2468 /// `CHAR_TRAITS::length(characterString)`). Return a reference
2469 /// providing modifiable access to this string. The behavior is
2470 /// undefined unless `first` and `last` are both within the range
2471 /// `[cbegin() .. cend()]` and `first <= last`.
2472 basic_string& replace(const_iterator first,
2473 const_iterator last,
2474 const CHAR_TYPE *characterString);
2475
2476 /// Replace the substring in the range starting at the specified `first`
2477 /// position and ending right before the specified `last` position with
2478 /// the specified `numChars` copies of the specified `character`.
2479 /// Return a reference providing modifiable access to this string. The
2480 /// behavior is undefined unless `first` and `last` are both within the
2481 /// range `[cbegin() .. cend()]` and `first <= last`.
2482 basic_string& replace(const_iterator first,
2483 const_iterator last,
2484 size_type numChars,
2485 CHAR_TYPE character);
2486
2487 /// Replace the substring in the range starting at the specified `first`
2488 /// position and ending right before the specified `last` position with
2489 /// the characters in the range starting at the specified `stringFirst`
2490 /// iterator and ending right before the specified `stringLast` iterator
2491 /// of the (template parameter) type `INPUT_ITER`. Return a reference
2492 /// providing modifiable access to this string. The behavior is
2493 /// undefined unless `first` and `last` are both within the range
2494 /// `[cbegin() .. cend()]`, `first <= last`, and `stringFirst` and
2495 /// `stringLast` refer to a sequence of valid values where `stringFirst`
2496 /// is at a position at or before `stringLast`.
2497 template <class INPUT_ITER>
2499 const_iterator last,
2500 INPUT_ITER stringFirst,
2501 INPUT_ITER stringLast);
2502
2503 // *** 21.3.7 string operations: ***
2504
2505 /// Return an address providing modifiable access to the null-terminated
2506 /// buffer of `length() + 1` characters whose contents are identical to
2507 /// the value of this string. Note that any call to the string
2508 /// destructor or any of its manipulators invalidates the returned
2509 /// pointer.
2510 CHAR_TYPE *data() BSLS_KEYWORD_NOEXCEPT;
2511
2512 /// Exchange the value of this object with that of the specified `other`
2513 /// object; also exchange the allocator of this object with that of
2514 /// `other` if the (template parameter) type `ALLOCATOR` has the
2515 /// `propagate_on_container_swap` trait, and do not modify either
2516 /// allocator otherwise. This method provides the no-throw
2517 /// exception-safety guarantee. This operation has `O[1]` complexity if
2518 /// either this object was created with the same allocator as `other` or
2519 /// `ALLOCATOR` has the `propagate_on_container_swap` trait; otherwise,
2520 /// it has `O[n + m]` complexity, where `n` and `m` are the lengths of
2521 /// this object and `other`, respectively. Note that this method`s
2522 /// support for swapping objects created with different allocators when
2523 /// `ALLOCATOR` does not have the `propagate_on_container_swap` trait is
2524 /// a departure from the C++ Standard.
2526 AllocatorTraits::propagate_on_container_swap::value ||
2527 AllocatorTraits::is_always_equal::value);
2528
2529 // ACCESSORS
2530
2531 // *** 21.3.3 iterators: ***
2532
2534
2535 /// Return an iterator providing non-modifiable access to the first
2536 /// character of this string (or the past-the-end iterator if this
2537 /// string is empty).
2539
2541
2542 /// Return the past-the-end iterator for this string.
2544
2546
2547 /// Return a reverse iterator providing non-modifiable access to the
2548 /// last character of this string (or the past-the-end reverse iterator
2549 /// if this string is empty).
2551
2553
2554 /// Return the past-the-end reverse iterator for this string.
2556
2557 // *** 21.3.4 capacity: ***
2558
2559 /// Return the length of this string. Note that this number may differ
2560 /// from `CHAR_TRAITS::length(c_str())` in case the string contains null
2561 /// characters. Also note that a null-terminating character added by
2562 /// the `c_str` method is *not* counted in this length.
2563 size_type length() const BSLS_KEYWORD_NOEXCEPT;
2564
2565 /// Return the length of this string. Note that this number may differ
2566 /// from `CHAR_TRAITS::length(c_str())` in case the string contains null
2567 /// characters. Also note that a null-terminating character added by
2568 /// the `c_str` method is *not* counted in this length.
2569 size_type size() const BSLS_KEYWORD_NOEXCEPT;
2570
2571 /// Return the maximal possible length of this string. Note that
2572 /// requests to create a string longer than this number of characters
2573 /// are guaranteed to raise a `length_error` exception.
2574 size_type max_size() const BSLS_KEYWORD_NOEXCEPT;
2575
2576 /// Return the capacity of this string, i.e., the maximum length for
2577 /// which resizing is guaranteed not to trigger a reallocation.
2578 size_type capacity() const BSLS_KEYWORD_NOEXCEPT;
2579
2580 /// Return `true` if this string has length 0, and `false` otherwise.
2581 bool empty() const BSLS_KEYWORD_NOEXCEPT;
2582
2583 // *** 21.3.5 element access: ***
2584
2585 /// Return a reference providing non-modifiable access to the character
2586 /// at the specified `position` in this string. The behavior is
2587 /// undefined unless `position <= length()`. Note that if
2588 /// `position == length()`, a reference to the null-terminating
2589 /// character is returned.
2590 const_reference operator[](size_type position) const;
2591
2592 /// Return a reference providing non-modifiable access to the character
2593 /// at the specified `position` in this string. Throw `out_of_range` if
2594 /// `position >= length()`.
2595 const_reference at(size_type position) const;
2596
2597 /// Return a reference providing non-modifiable access to the character
2598 /// at the first position in this string. The behavior is undefined if
2599 /// this string is empty.
2600 const CHAR_TYPE& front() const;
2601
2602 /// Return a reference providing non-modifiable access to the character
2603 /// at the last position in this string. The behavior is undefined if
2604 /// this string is empty. Note that the last position is
2605 /// `length() - 1`.
2606 const CHAR_TYPE& back() const;
2607
2608 /// Copy from this string, starting from the optionally specified
2609 /// `position`, the specified `numChars` or `length() - position`
2610 /// characters, whichever is smaller, into the specified
2611 /// `characterString` buffer, and return the number of characters
2612 /// copied. If `position` is not specified, 0 is used. Throw
2613 /// `out_of_range` if `position > length()`. The behavior is undefined
2614 /// unless `characterString` is at least `numChars` long. Note that the
2615 /// output `characterString` is *not* null-terminated.
2616 size_type copy(CHAR_TYPE *characterString,
2617 size_type numChars,
2618 size_type position = 0) const;
2619
2620 // *** 21.3.7 string operations: ***
2621
2622 /// Return an address providing non-modifiable access to the
2623 /// null-terminated buffer of `length() + 1` characters whose contents
2624 /// are identical to the value of this string. Note that any call to
2625 /// the string destructor or any of its manipulators invalidates the
2626 /// returned pointer.
2627 const CHAR_TYPE *c_str() const BSLS_KEYWORD_NOEXCEPT;
2628
2629 /// Return an address providing non-modifiable access to the
2630 /// null-terminated buffer of `length() + 1` characters whose contents
2631 /// are identical to the value of this string. Note that any call to
2632 /// the string destructor or any of its manipulators invalidates the
2633 /// returned pointer.
2634 const CHAR_TYPE *data() const BSLS_KEYWORD_NOEXCEPT;
2635
2636 /// Return the allocator used by this string to supply memory.
2637 allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT;
2638
2639 /// Return the starting position of the *first* occurrence of the
2640 /// specified `substring`, if such a substring can be found in this
2641 /// string (on or *after* the optionally specified `position` if such a
2642 /// `position` is specified) using `CHAR_TRAITS::eq` to compare
2643 /// characters, and return `npos` otherwise.
2644 size_type find(const basic_string& substring,
2645 size_type position = 0) const
2647
2648 /// Return the starting position of the *first* occurrence of the
2649 /// specified `substring`, if such a substring can be found in this
2650 /// string (on or *after* the optionally specified `position` if such a
2651 /// `position` is specified) using `CHAR_TRAITS::eq` to compare
2652 /// characters, and return `npos` otherwise. The behavior is undefined
2653 /// unless the conversion from `STRING_VIEW_LIKE_TYPE` to
2654 /// `bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS>` does not throw any
2655 /// exception. Note that this behavior differs from the behavior
2656 /// implemented in the standard container, where the following noexcept
2657 /// specification is used:
2658 /// @code
2659 /// noexcept(
2660 /// std::is_nothrow_convertible_v<const T&,
2661 /// std::basic_string_view<CharT,
2662 /// Traits> >)
2663 /// @endcode
2664 template <class STRING_VIEW_LIKE_TYPE>
2666 const STRING_VIEW_LIKE_TYPE& substring,
2667 size_type position = 0
2670
2671 /// Return the starting position of the *first* occurrence of the
2672 /// specified `substring` of the optionally specified `numChars` length,
2673 /// if such a substring can be found in this string (on or *after* the
2674 /// optionally specified `position` if such a `position` is specified)
2675 /// using `CHAR_TRAITS::eq` to compare characters, and return `npos`
2676 /// otherwise. If `numChars` is not specified,
2677 /// `CHAR_TRAITS::length(substring)` is used.
2678 size_type find(const CHAR_TYPE *substring,
2679 size_type position,
2680 size_type numChars) const;
2681 size_type find(const CHAR_TYPE *substring,
2682 size_type position = 0) const;
2683
2684 /// Return the position of the *first* occurrence of the specified
2685 /// `character`, if such an occurrence can be found in this string (on
2686 /// or *after* the optionally specified `position` if such a `position`
2687 /// is specified), and return `npos` otherwise.
2688 size_type find(CHAR_TYPE character, size_type position = 0) const;
2689
2690 /// Return the starting position of the *last* occurrence of the
2691 /// specified `substring` within this string, if such a sequence can be
2692 /// found in this string (on or *before* the optionally specified
2693 /// `position` if such a `position` is specified) using
2694 /// `CHAR_TRAITS::eq` to compare characters, and return `npos`
2695 /// otherwise.
2696 size_type rfind(const basic_string& substring,
2697 size_type position = npos) const
2699
2700 /// Return the starting position of the *last* occurrence of the
2701 /// specified `substring` within this string, if such a sequence can be
2702 /// found in this string (on or *before* the optionally specified
2703 /// `position` if such a `position` is specified) using
2704 /// `CHAR_TRAITS::eq` to compare characters, and return `npos`
2705 /// otherwise. The behavior is undefined unless the conversion from
2706 /// `STRING_VIEW_LIKE_TYPE` to
2707 /// `bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS>` does not throw any
2708 /// exception. Note that this behavior differs from the behavior
2709 /// implemented in the standard container, where the following noexcept
2710 /// specification is used:
2711 /// @code
2712 /// noexcept(
2713 /// std::is_nothrow_convertible_v<const T&,
2714 /// std::basic_string_view<CharT,
2715 /// Traits> >)
2716 /// @endcode
2717 template <class STRING_VIEW_LIKE_TYPE>
2719 const STRING_VIEW_LIKE_TYPE& substring,
2720 size_type position = npos
2723
2724 /// Return the starting position of the *last* occurrence of a substring
2725 /// whose value equals that of the specified `characterString` of the
2726 /// optionally specified `numChars` length, if such a substring can be
2727 /// found in this string (on or *before* the optionally specified
2728 /// `position` if such a `position` is specified), and return `npos`
2729 /// otherwise. If `numChars` is not specified,
2730 /// `CHAR_TRAITS::length(characterString)` is used.
2731 size_type rfind(const CHAR_TYPE *characterString,
2732 size_type position,
2733 size_type numChars) const;
2734 size_type rfind(const CHAR_TYPE *characterString,
2735 size_type position = npos) const;
2736
2737 /// Return the position of the *last* occurrence of the specified
2738 /// `character`, if such an occurrence can be found in this string (on
2739 /// or *before* the optionally specified `position` if such a `position`
2740 /// is specified), and return `npos` otherwise.
2741 size_type rfind(CHAR_TYPE character, size_type position = npos) const;
2742
2743 /// Return the position of the *first* occurrence of a character
2744 /// belonging to the specified `characterString`, if such an occurrence
2745 /// can be found in this string (on or *after* the optionally specified
2746 /// `position` if such a `position` is specified), and return `npos`
2747 /// otherwise.
2748 size_type find_first_of(const basic_string& characterString,
2749 size_type position = 0) const
2751
2752 /// Return the position of the *first* occurrence of a character
2753 /// belonging to the specified `characterString`, if such an occurrence
2754 /// can be found in this string (on or *after* the optionally specified
2755 /// `position` if such a `position` is specified), and return `npos`
2756 /// otherwise. The behavior is undefined unless the conversion from
2757 /// `STRING_VIEW_LIKE_TYPE` to
2758 /// `bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS>` does not throw any
2759 /// exception. Note that this behavior differs from the behavior
2760 /// implemented in the standard container, where the following noexcept
2761 /// specification is used:
2762 /// @code
2763 /// noexcept(
2764 /// std::is_nothrow_convertible_v<const T&,
2765 /// std::basic_string_view<CharT,
2766 /// Traits> >)
2767 /// @endcode
2768 template <class STRING_VIEW_LIKE_TYPE>
2769 size_type find_first_of(
2770 const STRING_VIEW_LIKE_TYPE& characterString,
2771 size_type position = 0
2774
2775 /// Return the position of the *first* occurrence of a character
2776 /// belonging to the specified `characterString` of the optionally
2777 /// specified `numChars` length, if such an occurrence can be found in
2778 /// this string (on or *after* the optionally specified `position` if
2779 /// such a `position` is specified), and return `npos` otherwise. If
2780 /// `numChars` is not specified, `CHAR_TRAITS::length(characterString)`
2781 /// is used.
2782 size_type find_first_of(const CHAR_TYPE *characterString,
2783 size_type position,
2784 size_type numChars) const;
2785 size_type find_first_of(const CHAR_TYPE *characterString,
2786 size_type position = 0) const;
2787
2788 /// Return the position of the *first* occurrence of the specified
2789 /// `character`, if such an occurrence can be found in this string (on
2790 /// or *after* the optionally specified `position` if such a `position`
2791 /// is specified), and return `npos` otherwise.
2792 size_type find_first_of(CHAR_TYPE character,
2793 size_type position = 0) const;
2794
2795 /// Return the position of the *last* occurrence of a character
2796 /// belonging to the specified `characterString`, if such an occurrence
2797 /// can be found in this string (on or *before* the optionally specified
2798 /// `position` if such a `position` is specified), and return `npos`
2799 /// otherwise.
2800 size_type find_last_of(const basic_string& characterString,
2801 size_type position = npos) const
2803
2804 /// Return the position of the *last* occurrence of a character
2805 /// belonging to the specified `characterString`, if such an occurrence
2806 /// can be found in this string (on or *before* the optionally specified
2807 /// `position` if such a `position` is specified), and return `npos`
2808 /// otherwise. The behavior is undefined unless the conversion from
2809 /// `STRING_VIEW_LIKE_TYPE` to
2810 /// `bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS>` does not throw any
2811 /// exception. Note that this behavior differs from the behavior
2812 /// implemented in the standard container, where the following noexcept
2813 /// specification is used:
2814 /// @code
2815 /// noexcept(
2816 /// std::is_nothrow_convertible_v<const T&,
2817 /// std::basic_string_view<CharT,
2818 /// Traits> >)
2819 /// @endcode
2820 template <class STRING_VIEW_LIKE_TYPE>
2821 size_type find_last_of(
2822 const STRING_VIEW_LIKE_TYPE& characterString,
2823 size_type position = npos
2826
2827 /// Return the position of the *last* occurrence of a character
2828 /// belonging to the specified `characterString` of the optionally
2829 /// specified `numChars` length, if such an occurrence can be found in
2830 /// this string (on or *before* the optionally specified `position` if
2831 /// such a `position` is specified), and return `npos` otherwise. If
2832 /// `numChars` is not specified, `CHAR_TRAITS::length(characterString)`
2833 /// is used.
2834 size_type find_last_of(const CHAR_TYPE *characterString,
2835 size_type position,
2836 size_type numChars) const;
2837 size_type find_last_of(const CHAR_TYPE *characterString,
2838 size_type position = npos) const;
2839
2840 /// Return the position of the *last* occurrence of the specified
2841 /// `character`, if such an occurrence can be found in this string (on
2842 /// or *before* the optionally specified `position` if such a `position`
2843 /// is specified), and return `npos` otherwise.
2844 size_type find_last_of(CHAR_TYPE character,
2845 size_type position = npos) const;
2846
2847 /// Return the position of the *first* occurrence of a character *not*
2848 /// belonging to the specified `characterString`, if such an occurrence
2849 /// can be found in this string (on or *after* the optionally specified
2850 /// `position` if such a `position` is specified), and return `npos`
2851 /// otherwise.
2852 size_type find_first_not_of(const basic_string& characterString,
2853 size_type position = 0) const
2855
2856 /// Return the position of the *first* occurrence of a character *not*
2857 /// belonging to the specified `characterString`, if such an occurrence
2858 /// can be found in this string (on or *after* the optionally specified
2859 /// `position` if such a `position` is specified), and return `npos`
2860 /// otherwise. The behavior is undefined unless the conversion from
2861 /// `STRING_VIEW_LIKE_TYPE` to
2862 /// `bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS>` does not throw any
2863 /// exception. Note that this behavior differs from the behavior
2864 /// implemented in the standard container, where the following noexcept
2865 /// specification is used:
2866 /// @code
2867 /// noexcept(
2868 /// std::is_nothrow_convertible_v<const T&,
2869 /// std::basic_string_view<CharT,
2870 /// Traits> >)
2871 /// @endcode
2872 template <class STRING_VIEW_LIKE_TYPE>
2873 size_type find_first_not_of(
2874 const STRING_VIEW_LIKE_TYPE& characterString,
2875 size_type position = 0
2878
2879 /// Return the position of the *first* occurrence of a character *not*
2880 /// belonging to the specified `characterString` of the optionally
2881 /// specified `numChars` length, if such an occurrence can be found in
2882 /// this string (on or *after* the optionally specified `position` if
2883 /// such a `position` is specified), and return `npos` otherwise. If
2884 /// `numChars` is not specified, `CHAR_TRAITS::length(characterString)`
2885 /// is used.
2886 size_type find_first_not_of(const CHAR_TYPE *characterString,
2887 size_type position,
2888 size_type numChars) const;
2889 size_type find_first_not_of(const CHAR_TYPE *characterString,
2890 size_type position = 0) const;
2891
2892 /// Return the position of the *first* occurrence of a character
2893 /// *different* from the specified `character`, if such an occurrence
2894 /// can be found in this string (on or *after* the optionally specified
2895 /// `position` if such a `position` is specified), and return `npos`
2896 /// otherwise.
2897 size_type find_first_not_of(CHAR_TYPE character,
2898 size_type position = 0) const;
2899
2900 /// Return the position of the *last* occurrence of a character *not*
2901 /// belonging to the specified `characterString`, if such an occurrence
2902 /// can be found in this string (on or *before* the optionally specified
2903 /// `position` if such a `position` is specified), and return `npos`
2904 /// otherwise.
2905 size_type find_last_not_of(const basic_string& characterString,
2906 size_type position = npos) const
2908
2909 /// Return the position of the *last* occurrence of a character *not*
2910 /// belonging to the specified `characterString`, if such an occurrence
2911 /// can be found in this string (on or *before* the optionally specified
2912 /// `position` if such a `position` is specified), and return `npos`
2913 /// otherwise. The behavior is undefined unless the conversion from
2914 /// `STRING_VIEW_LIKE_TYPE` to
2915 /// `bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS>` does not throw any
2916 /// exception. Note that this behavior differs from the behavior
2917 /// implemented in the standard container, where the following noexcept
2918 /// specification is used:
2919 /// @code
2920 /// noexcept(
2921 /// std::is_nothrow_convertible_v<const T&,
2922 /// std::basic_string_view<CharT,
2923 /// Traits> >)
2924 /// @endcode
2925 template <class STRING_VIEW_LIKE_TYPE>
2926 size_type find_last_not_of(
2927 const STRING_VIEW_LIKE_TYPE& characterString,
2928 size_type position = npos
2931
2932 /// Return the position of the *last* occurrence of a character *not*
2933 /// belonging to the specified `characterString` of the optionally
2934 /// specified `numChars` length, if such an occurrence can be found in
2935 /// this string (on or *before* the optionally specified `position` if
2936 /// such a `position` is specified), and return `npos` otherwise. If
2937 /// `numChars` is not specified, `CHAR_TRAITS::length(characterString)`
2938 /// is used.
2939 size_type find_last_not_of(const CHAR_TYPE *characterString,
2940 size_type position,
2941 size_type numChars) const;
2942 size_type find_last_not_of(const CHAR_TYPE *characterString,
2943 size_type position = npos) const;
2944
2945 /// Return the position of the *last* occurrence of a character
2946 /// *different* from the specified `character`, if such an occurrence
2947 /// can be found in this string (on or *before* the optionally specified
2948 /// `position` if such a `position` is specified), and return `npos`
2949 /// otherwise.
2950 size_type find_last_not_of(CHAR_TYPE character,
2951 size_type position = npos) const;
2952
2953 /// Return `true` if the length of this string is equal to or greater
2954 /// than the length of the specified `characterString` and the first
2955 /// `characterString.length()` characters of this string are equal to
2956 /// the characters of the `characterString`, and `false` otherwise.
2957 /// `CHAR_TRAITS::compare` is used to compare characters. See
2958 /// {Lexicographical Comparisons}.
2959 bool starts_with(basic_string_view<CHAR_TYPE, CHAR_TRAITS> characterString)
2961
2962 /// Return `true` if this string contains at least one symbol and the
2963 /// last symbol of this string is equal to the specified `character`,
2964 /// and `false` otherwise. `CHAR_TRAITS::eq` is used to compare
2965 /// characters. See {Lexicographical Comparisons}.
2966 bool starts_with(CHAR_TYPE character) const BSLS_KEYWORD_NOEXCEPT;
2967
2968 /// Return `true` if the length of this string is equal to or greater
2969 /// than the length of the specified `characterString` and the first
2970 /// `CHAR_TRAITS::length(characterString)` characters of this string are
2971 /// equal to the characters of the `characterString`, and `false`
2972 /// otherwise. `CHAR_TRAITS::compare` is used to compare characters.
2973 /// See {Lexicographical Comparisons}.
2974 bool starts_with(const CHAR_TYPE *characterString) const;
2975
2976 /// Return `true` if the length of this string is equal to or greater
2977 /// than the length of the specified `characterString` and the last
2978 /// `characterString.length()` characters of this string are equal to
2979 /// the characters of the `characterString`, and `false` otherwise.
2980 /// `CHAR_TRAITS::compare` is used to compare characters. See
2981 /// {Lexicographical Comparisons}.
2982 bool ends_with(basic_string_view<CHAR_TYPE, CHAR_TRAITS> characterString)
2984
2985 /// Return `true` if this string contains at least one symbol and the
2986 /// last symbol of this string is equal to the specified `character`,
2987 /// and `false` otherwise. `CHAR_TRAITS::eq` is used to compare
2988 /// characters. See {Lexicographical Comparisons}.
2989 bool ends_with(CHAR_TYPE character) const BSLS_KEYWORD_NOEXCEPT;
2990
2991 /// Return `true` if the length of this string is equal to or greater
2992 /// than the length of the specified `characterString` and the last
2993 /// `CHAR_TRAITS::length(characterString)` characters of this string are
2994 /// equal to the characters of the `characterString`, and `false`
2995 /// otherwise. `CHAR_TRAITS::compare` is used to compare characters.
2996 /// See {Lexicographical Comparisons}.
2997 bool ends_with(const CHAR_TYPE *characterString) const;
2998
2999 /// Return a string whose value is the substring starting at the
3000 /// optionally specified `position` in this string, of length the
3001 /// optionally specified `numChars` or `length() - position`, whichever
3002 /// is smaller. If `position` is not specified, 0 is used (i.e., the
3003 /// substring is from the beginning of this string). If `numChars` is
3004 /// not specified, `npos` is used (i.e., the entire suffix from
3005 /// `position` to the end of the string is returned).
3006 basic_string substr(size_type position = 0,
3007 size_type numChars = npos) const;
3008
3009 /// Lexicographically compare this string with the specified `other`
3010 /// string, and return a negative value if this string is less than
3011 /// `other`, a positive value if it is greater than `other`, and 0 in
3012 /// case of equality. `CHAR_TRAITS::lt` is used to compare characters.
3013 /// See {Lexicographical Comparisons}.
3014 int compare(const basic_string& other) const BSLS_KEYWORD_NOEXCEPT;
3015
3016 /// Lexicographically compare the substring of this string of the
3017 /// specified `numChars` length starting at the specified `position` (or
3018 /// the suffix of this string starting at `position` if
3019 /// `position + numChars > length()`) with the specified `other` string,
3020 /// and return a negative value if the indicated substring of this
3021 /// string is less than `other`, a positive value if it is greater than
3022 /// `other`, and 0 in case of equality. `CHAR_TRAITS::lt` is used to
3023 /// compare characters. See {Lexicographical Comparisons}. Throw
3024 /// `out_of_range` if `position > length()`.
3025 int compare(size_type position,
3026 size_type numChars,
3027 const basic_string& other) const;
3028
3029 /// Lexicographically compare the substring of this string of the
3030 /// specified `lhsNumChars` length starting at the specified
3031 /// `lhsPosition` (or the suffix of this string starting at
3032 /// `lhsPosition` if `lhsPosition + lhsNumChars > length()`) with the
3033 /// substring of the specified `other` string of the optionally
3034 /// specified `otherNumChars` length starting at the specified
3035 /// `otherPosition` (or the suffix of `other` starting at
3036 /// `otherPosition` if
3037 /// `otherPosition + otherNumChars > other.length()`). If `numChars` is
3038 /// not specified, `npos` is used. Return a negative value if the
3039 /// indicated substring of this string is less than the indicated
3040 /// substring of `other`, a positive value if it is greater than the
3041 /// indicated substring of `other`, and 0 in case of equality.
3042 /// `CHAR_TRAITS::lt` is used to compare characters. Throw
3043 /// `out_of_range` if `lhsPosition > length()` or
3044 /// `otherPosition > other.length()`. See {Lexicographical
3045 /// Comparisons}.
3046 int compare(size_type lhsPosition,
3047 size_type lhsNumChars,
3048 const basic_string& other,
3049 size_type otherPosition,
3050 size_type otherNumChars = npos) const;
3051
3052 /// Lexicographically compare this string with the specified
3053 /// null-terminated `other` string (of length
3054 /// `CHAR_TRAITS::length(other)`), and return a negative value if this
3055 /// string is less than `other`, a positive value if it is greater than
3056 /// `other`, and 0 in case of equality. `CHAR_TRAITS::lt` is used to
3057 /// compare characters. See {Lexicographical Comparisons}.
3058 int compare(const CHAR_TYPE *other) const;
3059
3060 /// Lexicographically compare the substring of this string of the
3061 /// specified `lhsNumChars` length starting at the specified
3062 /// `lhsPosition` (or the suffix of this string starting at
3063 /// `lhsPosition` if `lhsPosition + lhsNumChars > length()`) with the
3064 /// specified `other` string of the specified `otherNumChars` length,
3065 /// and return a negative value if the indicated substring of this
3066 /// string is less than `other`, a positive value if it is greater than
3067 /// `other`, and 0 in case of equality. `CHAR_TRAITS::lt` is used to
3068 /// compare characters. Throw `out_of_range` if
3069 /// `lhsPosition > length()`. See {Lexicographical Comparisons}.
3070 int compare(size_type lhsPosition,
3071 size_type lhsNumChars,
3072 const CHAR_TYPE *other,
3073 size_type otherNumChars) const;
3074
3075 /// Lexicographically compare the substring of this string of the
3076 /// specified `lhsNumChars` length starting at the specified
3077 /// `lhsPosition` (or the suffix of this string starting at
3078 /// `lhsPosition` if `lhsPosition + lhsNumChars > length()`) with the
3079 /// specified null-terminated `other` string (of length
3080 /// `CHAR_TRAITS::length(other)`), and return a negative value if the
3081 /// indicated substring of this string is less than `other`, a positive
3082 /// value if it is greater than `other`, and 0 in case of equality.
3083 /// `CHAR_TRAITS::lt` is used to compare characters. Throw
3084 /// `out_of_range` if `lhsPosition > length()`. See {Lexicographical
3085 /// Comparisons}.
3086 int compare(size_type lhsPosition,
3087 size_type lhsNumChars,
3088 const CHAR_TYPE *other) const;
3089
3090 /// Lexicographically compare this string with the specified `other`,
3091 /// and return a negative value if this string is less than `other`, a
3092 /// positive value if it is greater than `other`, and 0 in case of
3093 /// equality. `CHAR_TRAITS::lt` is used to compare characters. See
3094 /// {Lexicographical Comparisons}. The behavior is undefined unless the
3095 /// conversion from `STRING_VIEW_LIKE_TYPE` to
3096 /// `bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS>` does not throw any
3097 /// exception. Note that this behavior differs from the behavior
3098 /// implemented in the standard container, where the following noexcept
3099 /// specification is used:
3100 /// @code
3101 /// noexcept(
3102 /// std::is_nothrow_convertible_v<const T&,
3103 /// std::basic_string_view<CharT,
3104 /// Traits> >)
3105 /// @endcode
3106 template <class STRING_VIEW_LIKE_TYPE>
3107 int compare(
3108 const STRING_VIEW_LIKE_TYPE& other
3111
3112 /// Lexicographically compare the substring of this string of the
3113 /// specified `numChars` length starting at the specified `position` (or
3114 /// the suffix of this string starting at `position` if
3115 /// `position + numChars > length()`) with the specified `other`, and
3116 /// return a negative value if the indicated substring of this string is
3117 /// less than `other`, a positive value if it is greater than `other`,
3118 /// and 0 in case of equality. `CHAR_TRAITS::lt` is used to compare
3119 /// characters. See {Lexicographical Comparisons}. Throw
3120 /// `out_of_range` if `position > length()`.
3121 template <class STRING_VIEW_LIKE_TYPE>
3122 int compare(
3123 size_type position,
3124 size_type numChars,
3125 const STRING_VIEW_LIKE_TYPE& other
3127
3128 /// Lexicographically compare the substring of this string of the
3129 /// specified `lhsNumChars` length starting at the specified
3130 /// `lhsPosition` (or the suffix of this string starting at
3131 /// `lhsPosition` if `lhsPosition + lhsNumChars > length()`) with the
3132 /// substring of the specified `other` of the optionally specified
3133 /// `otherNumChars` length starting at the specified `otherPosition` (or
3134 /// the suffix of `other` starting at `otherPosition` if
3135 /// `otherPosition + otherNumChars > other.length()`). If `numChars` is
3136 /// not specified, `npos` is used. Return a negative value if the
3137 /// indicated substring of this string is less than the indicated
3138 /// substring of `other`, a positive value if it is greater than the
3139 /// indicated substring of `other`, and 0 in case of equality.
3140 /// `CHAR_TRAITS::lt` is used to compare characters. See
3141 /// {Lexicographical Comparisons}. Throw `out_of_range` if
3142 /// `lhsPosition > length()` or `otherPosition > other.length()`.
3143 template <class STRING_VIEW_LIKE_TYPE>
3144 int compare(
3145 size_type lhsPosition,
3146 size_type lhsNumChars,
3147 const STRING_VIEW_LIKE_TYPE& other,
3148 size_type otherPosition,
3149 size_type otherNumChars = npos
3151
3152 // *** BDE compatibility with platform libraries: ***
3153
3154 /// Convert this object to a string type native to the compiler's
3155 /// library, instantiated with the same character type and traits type,
3156 /// but not necessarily the same allocator type. The return string will
3157 /// contain the same sequence of characters as `orig` and will have a
3158 /// default-constructed allocator. Note that this conversion operator
3159 /// can be invoked implicitly (e.g., during argument passing).
3160 template <class ALLOC2>
3161 operator std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>() const
3162 {
3163 // See {DRQS 131792157} for why this is inline.
3164 std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2> result;
3165 result.assign(data(), length());
3166 return result;
3167 }
3168
3169 /// Convert this object to a @ref string_view type instantiated with the
3170 /// same character type and traits type. The return view will contain
3171 /// the same sequence of characters as this object. Note that this
3172 /// conversion operator can be invoked implicitly (e.g., during argument
3173 /// passing).
3175};
3176
3177#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
3178// CLASS TEMPLATE DEDUCTION GUIDES
3179
3180/// Deduce the template parameters `CHAR_TYPE`, `TRAITS`, and `ALLOCATOR`
3181/// from the corresponding template parameters of the `bsl::basic_string`
3182/// passed to the constructor of @ref basic_string . This deduction guide does
3183/// not participate unless the specified `ALLOC` is convertible to
3184/// `ALLOCATOR`.
3185template <
3186 class CHAR_TYPE,
3187 class CHAR_TRAITS,
3188 class ALLOCATOR,
3189 class ALLOC,
3190 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC, ALLOCATOR>>
3191 >
3192basic_string(basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>, ALLOC)
3193-> basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>;
3194
3195/// Deduce the template parameter `CHAR_TYPE` from the parameters passed to
3196/// the constructor of @ref basic_string . This deduction guide does not
3197/// participate unless the specified `ALLOC` is convertible to
3198/// `bsl::allocator<CHAR_TYPE>`.
3199template <
3200 class CHAR_TYPE,
3201 class ALLOC,
3202 class DEFAULT_ALLOCATOR = bsl::allocator<CHAR_TYPE>,
3203 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
3204 >
3205basic_string(const CHAR_TYPE *, ALLOC *)
3206-> basic_string<CHAR_TYPE>;
3207
3208/// Deduce the template parameter `CHAR_TYPE` from the parameters passed to
3209/// the constructor of @ref basic_string . This deduction guide does not
3210/// participate unless the specified `ALLOC` is convertible to
3211/// `bsl::allocator<CHAR_TYPE>`.
3212template <
3213 class CHAR_TYPE,
3214 class ALLOC,
3215 class SZ,
3216 class DEFAULT_ALLOCATOR = bsl::allocator<CHAR_TYPE>,
3217 class = bsl::enable_if_t<
3218 bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>,
3219 class = bsl::enable_if_t<!bsl::is_pointer_v<SZ>>
3220 // this last check eliminates an ambiguity for the case
3221 // basic_string(const char *, const char *, Allocator *)
3222 >
3223basic_string(const CHAR_TYPE *, SZ, ALLOC *)
3224-> basic_string<CHAR_TYPE>;
3225
3226/// Deduce the template parameter `CHAR_TYPE` from the parameters passed to
3227/// the constructor of @ref basic_string . This deduction guide does not
3228/// participate unless the specified `ALLOC` is convertible to
3229/// `bsl::allocator<CHAR_TYPE>`.
3230template <
3231 class CHAR_TYPE,
3232 class ALLOC,
3233 class DEFAULT_ALLOCATOR = bsl::allocator<CHAR_TYPE>,
3235 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
3236 >
3237basic_string(SZ, CHAR_TYPE, ALLOC *)
3238-> basic_string<CHAR_TYPE>;
3239
3240/// Deduce the template parameters `CHAR_TYPE`, `TRAITS`, and `ALLOCATOR`
3241/// from the corresponding template parameters of the `bsl::basic_string`
3242/// passed to the constructor of @ref basic_string . This deduction guide does
3243/// not participate unless the specified `ALLOC` is convertible to
3244/// `ALLOCATOR`.
3245template <
3246 class CHAR_TYPE,
3247 class CHAR_TRAITS,
3248 class ALLOCATOR,
3249 class ALLOC,
3250 class SZ = typename allocator_traits<ALLOCATOR>::size_type,
3251 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, ALLOCATOR>>
3252 >
3253basic_string(basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>, SZ, SZ, ALLOC *)
3254-> basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>;
3255
3256/// Deduce the template parameter `CHAR_TYPE` from the `value_type` of the
3257/// iterators passed to passed to the constructor of @ref basic_string . Deduce
3258/// the template parameter `ALLOCATOR` from the optional argument passed to
3259/// the constructor. This deduction guide does not participate unless the
3260/// specified `ALLOCATOR` meets the requirements of a standard allocator.
3261template <
3262 class INPUT_ITER,
3263 class CHAR_TYPE =
3264 typename BloombergLP::bslstl::IteratorUtil::IterVal_t<INPUT_ITER>,
3265 class ALLOCATOR = bsl::allocator<CHAR_TYPE>,
3266 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
3267 >
3268basic_string(INPUT_ITER, INPUT_ITER, ALLOCATOR = ALLOCATOR())
3269 -> basic_string<CHAR_TYPE, char_traits<CHAR_TYPE>, ALLOCATOR>;
3270
3271/// Deduce the template parameter `CHAR_TYPE` from the `value_type` of the
3272/// iterators passed to passed to the constructor of @ref basic_string . This
3273/// deduction guide does not participate unless the specified `ALLOC` is
3274/// convertible to `bsl::allocator<CHAR_TYPE>`.
3275template <
3276 class INPUT_ITER,
3277 class CHAR_TYPE =
3278 typename BloombergLP::bslstl::IteratorUtil::IterVal_t<INPUT_ITER>,
3279 class ALLOC,
3280 class DEFAULT_ALLOCATOR = bsl::allocator<CHAR_TYPE>,
3281 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
3282 >
3283basic_string(INPUT_ITER, INPUT_ITER, ALLOC *)
3284 -> basic_string<CHAR_TYPE>;
3285
3286/// Deduce the template parameters `CHAR_TYPE` and `TRAITS` from the
3287/// corresponding template parameters of the `bsl::basic_string_view` passed
3288/// to the constructor of @ref basic_string . Deduce the template parameter
3289/// `ALLOCATOR` from the optional argument passed to the constructor. This
3290/// deduction guide does not participate unless the specified `ALLOCATOR`
3291/// meets the requirements of a standard allocator.
3292template <
3293 class CHAR_TYPE,
3294 class CHAR_TRAITS,
3295 class ALLOCATOR = allocator<CHAR_TYPE>,
3296 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>
3297 >
3298basic_string(basic_string_view<CHAR_TYPE, CHAR_TRAITS>,
3299 ALLOCATOR = ALLOCATOR())
3300 -> basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>;
3301
3302/// Deduce the template parameters `CHAR_TYPE` and `TRAITS` from the
3303/// corresponding template parameters of the `bsl::basic_string_view` passed
3304/// to the constructor of @ref basic_string . This deduction guide does not
3305/// participate unless the specified `ALLOC` is convertible to
3306/// `bsl::allocator<CHAR_TYPE>`.
3307template <
3308 class CHAR_TYPE,
3309 class CHAR_TRAITS,
3310 class ALLOC,
3311 class DEFAULT_ALLOCATOR = bsl::allocator<CHAR_TYPE>,
3312 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
3313 >
3314basic_string(basic_string_view<CHAR_TYPE, CHAR_TRAITS>, ALLOC *)
3315 -> basic_string<CHAR_TYPE, CHAR_TRAITS>;
3316
3317/// Deduce the template parameter `CHAR_TYPE` from the `value_type` of the
3318/// @ref initializer_list passed to the constructor of @ref basic_string . This
3319/// deduction guide does not participate unless the specified `ALLOC` is
3320/// convertible to `bsl::allocator<CHAR_TYPE>`.
3321template<
3322 class CHAR_TYPE,
3323 class ALLOC,
3324 class DEFAULT_ALLOCATOR = bsl::allocator<CHAR_TYPE>,
3325 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
3326 >
3327basic_string(std::initializer_list<CHAR_TYPE>, ALLOC *)
3328-> basic_string<CHAR_TYPE>;
3329
3330#endif
3331
3332// FREE OPERATORS
3333template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3337template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3338bool
3340 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
3342
3343/// Return `true` if the specified `lhs` string has the same value as the
3344/// specified `rhs` string, and `false` otherwise. Two strings have the
3345/// same value if they have the same length, and the characters at each
3346/// respective position have the same value according to `CHAR_TRAITS::eq`.
3347template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3349 const CHAR_TYPE *rhs);
3350
3351#ifdef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
3352
3353template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3354String_ComparisonCategoryType<CHAR_TRAITS>
3355operator<=>(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
3358
3359/// Perform a lexicographic three-way comparison of the specified `lhs` and
3360/// the specified `rhs` strings by using `CHAR_TRAITS::eq` on each
3361/// character; return the result of that comparison.
3362template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3363String_ComparisonCategoryType<CHAR_TRAITS>
3364operator<=>(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
3365 const CHAR_TYPE *rhs);
3366template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3367String_ComparisonCategoryType<CHAR_TRAITS>
3369 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
3371
3372#else
3373
3374/// Return `true` if the specified `lhs` string has the same value as the
3375/// specified `rhs` string, and `false` otherwise. Two strings have the
3376/// same value if they have the same length, and the characters at each
3377/// respective position have the same value according to `CHAR_TRAITS::eq`.
3378template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3379bool
3380operator==(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3383template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3384bool operator==(const CHAR_TYPE *lhs,
3386
3387/// Return `true` if the specified `lhs` string has a different value from
3388/// the specified `rhs` string, and `false` otherwise. Two strings have the
3389/// same value if they have the same length, and the characters at each
3390/// respective position have the same value according to `CHAR_TRAITS::eq`.
3391template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3395template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3396bool
3397operator!=(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3400template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3401bool
3403 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
3405
3406template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3407bool operator!=(const CHAR_TYPE *lhs,
3409template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3411 const CHAR_TYPE *rhs);
3412
3413/// Return `true` if the specified `lhs` string has a lexicographically
3414/// smaller value than the specified `rhs` string, and `false` otherwise.
3415/// See {Lexicographical Comparisons}.
3416template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3420template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3421bool
3422operator<(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3425template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3426bool
3428 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
3430template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3431
3432bool operator<(const CHAR_TYPE *lhs,
3434template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3436 const CHAR_TYPE *rhs);
3437
3438template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3442template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3443bool
3444operator>(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3447template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3448bool
3450 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
3452
3453/// Return `true` if the specified `lhs` string has a lexicographically
3454/// larger value than the specified `rhs` string, and `false` otherwise.
3455/// See {Lexicographical Comparisons}.
3456template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3457bool operator>(const CHAR_TYPE *lhs,
3459template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3461 const CHAR_TYPE *rhs);
3462
3463/// Return `true` if the specified `lhs` string has a value
3464/// lexicographically smaller than or or equal to the specified `rhs`
3465/// string, and `false` otherwise. See {Lexicographical Comparisons}.
3466template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3470template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3471bool
3472operator<=(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3475template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3476bool
3478 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
3480
3481template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3482bool operator<=(const CHAR_TYPE *lhs,
3484template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3486 const CHAR_TYPE *rhs);
3487
3488/// Return `true` if the specified `lhs` string has a value
3489/// lexicographically larger than or equal to the specified `rhs` string,
3490/// and `false` otherwise. See {Lexicographical Comparisons}.
3491template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3495template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3496bool
3497operator>=(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3500template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3501bool
3503 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
3505
3506template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3507bool operator>=(const CHAR_TYPE *lhs,
3509template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
3511 const CHAR_TYPE *rhs);
3512#endif
3513
3514/// Return the concatenation of strings constructed from the specified `lhs`
3515/// and `rhs` arguments, i.e., `basic_string(lhs).append(rhs)`. The
3516/// allocator of the returned string is determined per the rules in P1165
3517/// (https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1165r1.html).
3518/// Note that overloads that accept rvalue references are implemented for
3519/// C++11 and later only.
3520template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3524#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3525template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3529template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3533template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3537#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3538template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3540operator+(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3542#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3543template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3545operator+(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
3547#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3548template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3551 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs);
3552#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3553template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
3556 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs);
3557#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3558template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3560operator+(const CHAR_TYPE *lhs,
3562#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3563template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3565operator+(const CHAR_TYPE *lhs,
3567#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3568template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3570operator+(CHAR_TYPE lhs,
3572#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3573template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3575operator+(CHAR_TYPE lhs,
3577#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3578template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3581 const CHAR_TYPE *rhs);
3582#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3583template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3586 const CHAR_TYPE *rhs);
3587#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3588template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3591 CHAR_TYPE rhs);
3592#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3593template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3596 CHAR_TYPE rhs);
3597#endif // BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
3598
3599/// Write the string specified by `str` into the output stream specified by
3600/// `os`, and return `os`. If the string is shorter than `os.width()`, then
3601/// it is padded to `os.width()` with the current `os.fill()` character.
3602/// The padding, if any, is output after the string (on the right) if
3603/// `os.flags() | ios::left` is non-zero and before the string otherwise.
3604/// This function will do nothing unless `os.good()` is true on entry.
3605template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3606std::basic_ostream<CHAR_TYPE, CHAR_TRAITS>&
3607operator<<(std::basic_ostream<CHAR_TYPE, CHAR_TRAITS>& os,
3609
3610/// Replace the contents of the specified `str` string with a word read from
3611/// the specified `is` input stream, and return `is`. The word begins at
3612/// the first non-whitespace character on the input stream and ends when
3613/// another whitespace character (or eof) is found. The trailing whitespace
3614/// character is left on the input stream. If `is.good()` is not true on
3615/// entry or if eof is found before any non-whitespace characters, then
3616/// `str` is unchanged and `is.fail()` is becomes true. If eof is detected
3617/// after some characters have been read into `str`, then `is.eof()` becomes
3618/// true, but `is.fail()` does not.
3619template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3620std::basic_istream<CHAR_TYPE, CHAR_TRAITS>&
3621operator>>(std::basic_istream<CHAR_TYPE, CHAR_TRAITS>& is,
3623
3624#if defined (BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY) && \
3625 defined (BSLS_COMPILERFEATURES_SUPPORT_INLINE_NAMESPACE)
3626inline namespace literals {
3627inline namespace string_literals {
3628/// Convert a character sequence of the specified `length` excluding the
3629/// terminating null character starting at the beginning of the specified
3630/// `characterString` to a string object of the indicated return type. Use
3631/// the `bslma::Default::defaultAllocator()` to supply memory. (See the
3632/// "User-Defined Literals" section in the component-level documentation.)
3633///
3634/// Example:
3635/// @code
3636/// using namespace bsl::string_literals;
3637/// bsl::string str1 = "123\0abc";
3638/// bsl::string str2 = "123\0abc"_s;
3639/// assert(3 == str1.size());
3640/// assert(7 == str2.size());
3641///
3642/// bsl::wstring str3 = L"123\0abc"_s;
3643/// assert(7 == str3.size());
3644/// @endcode
3645 string operator ""_s(const char *characterString, std::size_t length);
3646wstring operator ""_s(const wchar_t *characterString, std::size_t length);
3647
3648#if !defined(BSLS_PLATFORM_OS_SOLARIS) || \
3649 (defined(BSLS_PLATFORM_CMP_GNU) && BSLS_PLATFORM_CMP_VERSION >= 800000)
3650/// Convert a character sequence of the specified `length` excluding the
3651/// terminating null character starting at the beginning of the specified
3652/// `characterString` to a string object of the indicated return type. Use
3653/// the `bslma::Default::globalAllocator()` to supply memory. (See the
3654/// "Memory Allocation For a File-Scope Strings" section in the
3655/// component-level documentation.)
3656///
3657/// Example:
3658/// @code
3659/// using namespace bsl::string_literals;
3660/// static const bsl::string g_str1 = "123\0abc"_S;
3661/// static const bsl::wstring g_str2 = L"123\0abc"_S;
3662/// @endcode
3663 string operator ""_S(const char *characterString, std::size_t length);
3664wstring operator ""_S(const wchar_t *characterString, std::size_t length);
3665#endif
3666}
3667}
3668
3669#endif // BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY &&
3670 // BSLS_COMPILERFEATURES_SUPPORT_INLINE_NAMESPACE
3671
3672// FREE FUNCTIONS
3673
3674/// Exchange the value of the specified `a` object with that of the
3675/// specified `b` object; also exchange the allocator of `a` with that of
3676/// `b` if the (template parameter) type `ALLOCATOR` has the
3677/// `propagate_on_container_swap` trait, and do not modify either allocator
3678/// otherwise. This function provides the no-throw exception-safety
3679/// guarantee. This operation has `O[1]` complexity if either `a` was
3680/// created with the same allocator as `b` or `ALLOCATOR` has the
3681/// `propagate_on_container_swap` trait; otherwise, it has `O[n + m]`
3682/// complexity, where `n` and `m` are the lengths of `a` and `b`,
3683/// respectively. Note that this function`s support for swapping objects
3684/// created with different allocators when `ALLOCATOR` does not have the
3685/// `propagate_on_container_swap` trait is a departure from the C++
3686/// Standard.
3687template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3692
3693/// Replace the contents of the specified `str` string by extracting
3694/// characters from the specified `is` stream until the specified `delim`
3695/// character is extracted, and return `is`. The `delim` character is
3696/// removed from the input stream but is not appended to `str`. If an `eof`
3697/// is detected before `delim`, then the characters up to the `eof` are put
3698/// into `str` and `is.eof()` becomes true. If `is.good()` is false on
3699/// entry, then do nothing, otherwise if no characters are extracted (e.g.,
3700/// because because the stream is at eof), `str` will become empty and
3701/// `is.fail()` will become true.
3702template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3703std::basic_istream<CHAR_TYPE, CHAR_TRAITS>&
3704getline(std::basic_istream<CHAR_TYPE, CHAR_TRAITS>& is,
3706 CHAR_TYPE delim);
3707
3708/// Replace the contents of the specified `str` string by extracting
3709/// characters from the specified `is` stream until a newline character
3710/// (is.widen('\n') is extracted, and return `is`. The newline character is
3711/// removed from the input stream but is not appended to `str`. If an `eof`
3712/// is detected before the newline, then the characters up to the `eof` are
3713/// put into `str` and `is.eof()` becomes true. If `is.good()` is false on
3714/// entry, then do nothing, otherwise if no characters are extracted (e.g.,
3715/// because because the stream is at eof), `str` will become empty and
3716/// `is.fail()` will become true.
3717template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3718std::basic_istream<CHAR_TYPE, CHAR_TRAITS>&
3719getline(std::basic_istream<CHAR_TYPE, CHAR_TRAITS>& is,
3721
3722int stoi(const string& str, std::size_t *pos = 0, int base = 10);
3723int stoi(const wstring& str, std::size_t *pos = 0, int base = 10);
3724long stol(const string& str, std::size_t *pos = 0, int base = 10);
3725long stol(const wstring& str, std::size_t *pos = 0, int base = 10);
3726unsigned long stoul(const string& str, std::size_t *pos = 0, int base = 10);
3727unsigned long stoul(const wstring& str, std::size_t *pos = 0, int base = 10);
3728long long stoll(const string& str, std::size_t *pos = 0, int base = 10);
3729long long stoll(const wstring& str, std::size_t *pos = 0, int base = 10);
3730
3731unsigned long long stoull(const string& str,
3732 std::size_t *pos = 0,
3733 int base = 10);
3734unsigned long long stoull(const wstring& str,
3735 std::size_t *pos = 0,
3736 int base = 10);
3737
3738float stof(const string& str, std::size_t *pos =0);
3739float stof(const wstring& str, std::size_t *pos =0);
3740double stod(const string& str, std::size_t *pos =0);
3741/// Return the value of the specified `str` by parsing the string and
3742/// interpreting its content as an integral number. Optionally specify
3743/// `pos` whose value is set to the position of the next character in `str`
3744/// after the numerical value. Optionally specify `base` used to change the
3745/// interpretation of `str` to a integral number written in the given
3746/// `base`. Valid bases are bases in the range of [2,36] and base 0, where
3747/// base 0 automatically determines the base while parsing the string: the
3748/// base will be 16 if the number is prefixed with `0x` or `0X`, base 8 if
3749/// the number is prefixed with a `0`, and base 10 otherwise. The function
3750/// ignores leading white space characters and interprets as many characters
3751/// possible to form a valid integral number in the chosen base. If no
3752/// conversion could be performed, then an @ref invalid_argument exception is
3753/// thrown. If the value read is out of range of the return type, then an
3754/// `out_of_range` exception is thrown. The behavior is undefined unless
3755/// `base` is valid. Note that negative numbers are parsed by interpreting
3756/// the numeric sequence following the `-` character, and then negating the
3757/// result, so that `stoul` and `stoull` have defined results for negative
3758/// numbers where the absolute value falls in the valid range for the
3759/// corresponding signed conversion.
3760double stod(const wstring& str, std::size_t *pos =0);
3761
3762long double stold(const string& str, std::size_t *pos =0);
3763/// Parses `str` interpreting its contents as a floating point number. In
3764/// C++11 if the number in `str` is prefixed with `0x` or `0X` the string
3765/// will be interpreted as a hex number. If there is no leading 0x or 0X
3766/// the string will be interpreted as a decimal number. Optionally specify
3767/// `pos` whose value is set to the position of the next character after the
3768/// numerical value. The function ignores leading white space characters
3769/// and interprets as many characters possible to form a valid floating
3770/// point number. If no conversion could be performed, then an
3771/// @ref invalid_argument exception is thrown. If the value read is out of
3772/// range of the return type, then an `out_of_range` exception is thrown.
3773long double stold(const wstring& str, std::size_t *pos =0);
3774
3775/// Constructs a string with contents equal to the specified `value`. The
3776/// contents of the string will be the same as what
3777/// `std::sprintf(buf, "%d", value)` would produce with a sufficiently large
3778/// buffer.
3779string to_string(int value);
3780
3781/// Constructs a string with contents equal to the specified `value`. The
3782/// contents of the string will be the same as what
3783/// `std::sprintf(buf, "%ld", value)` would produce with a sufficiently
3784/// large buffer.
3785string to_string(long value);
3786
3787/// Constructs a string with contents equal to the specified `value`. The
3788/// contents of the string will be the same as what
3789/// `std::sprintf(buf, "%lld", value)` would produce with a sufficiently
3790/// large buffer.
3791string to_string(long long value);
3792
3793/// Constructs a string with contents equal to the specified `value`. The
3794/// contents of the string will be the same as what
3795/// `std::sprintf(buf, "%u", value)` would produce with a sufficiently large
3796/// buffer.
3797string to_string(unsigned value);
3798
3799/// Constructs a string with contents equal to the specified `value`. The
3800/// contents of the string will be the same as what
3801/// `std::sprintf(buf, "%lu", value)` would produce with a sufficiently
3802/// large buffer.
3803string to_string(unsigned long value);
3804
3805/// Constructs a string with contents equal to the specified `value`. The
3806/// contents of the string will be the same as what
3807/// `std::sprintf(buf, "%llu", value)` would produce with a sufficiently
3808/// large buffer.
3809string to_string(unsigned long long value);
3810
3811string to_string(float value);
3812/// converts a floating point value to a string with the same contents as
3813/// what `std::sprintf(buf, "%f", value)` would produce for a sufficiently
3814/// large buffer.
3815string to_string(double value);
3816
3817/// converts a floating point value to a string with the same contents as
3818/// what `std::sprintf(buf, "%Lf", value)` would produce for a sufficiently
3819/// large buffer.
3820string to_string(long double value);
3821
3822/// Constructs a string with contents equal to the specified `value`. The
3823/// contents of the string will be the same as what
3824/// `std::swprintf(buf, L"%d", value)` would produce with a sufficiently
3825/// large buffer.
3827
3828/// Constructs a string with contents equal to the specified `value`. The
3829/// contents of the string will be the same as what
3830/// `std::swprintf(buf, L"%ld", value)` would produce with a sufficiently
3831/// large buffer.
3833
3834/// Constructs a string with contents equal to the specified `value`. The
3835/// contents of the string will be the same as what
3836/// `std::swprintf(buf, L"%lld", value)` would produce with a sufficiently
3837/// large buffer.
3838wstring to_wstring(long long value);
3839
3840/// Constructs a string with contents equal to the specified `value`. The
3841/// contents of the string will be the same as what
3842/// `std::swprintf(buf, L"%u", value)` would produce with a sufficiently
3843/// large buffer.
3844wstring to_wstring(unsigned value);
3845
3846/// Constructs a string with contents equal to the specified `value`. The
3847/// contents of the string will be the same as what
3848/// `std::swprintf(buf, L"%lu", value)` would produce with a sufficiently
3849/// large buffer.
3850wstring to_wstring(unsigned long value);
3851
3852/// Constructs a string with contents equal to the specified `value`. The
3853/// contents of the string will be the same as what
3854/// `std::swprintf(buf, L"%llu", value)` would produce with a sufficiently
3855/// large buffer.
3856wstring to_wstring(unsigned long long value);
3857
3858wstring to_wstring(float value);
3859/// converts a floating point value to a string with the same contents as
3860/// what `std::sprintf(buf, sz, L"%f", value)` would produce for a
3861/// sufficiently large buffer.
3862wstring to_wstring(double value);
3863
3864/// converts a floating point value to a string with the same contents as
3865/// `what std::sprintf(buf, sz, L"%Lf", value)` would produce for a
3866/// sufficiently large buffer.
3867wstring to_wstring(long double value);
3868
3869/// Erase (in-place) all the elements from the specified `str` that compare
3870/// equal to the specified `c`, and return the number of erased elements.
3871template <class CHAR_TYPE,
3872 class CHAR_TRAITS,
3873 class ALLOCATOR,
3874 class OTHER_CHAR_TYPE>
3877 const OTHER_CHAR_TYPE& c);
3878
3879/// Erase (in-place) all the elements from the specified `str` where the
3880/// specified `pred` returns `true`, and return the number of erased
3881/// elements.
3882template <class CHAR_TYPE,
3883 class CHAR_TRAITS,
3884 class ALLOCATOR,
3885 class UNARY_PREDICATE>
3888 const UNARY_PREDICATE& pred);
3889
3890/// This `enum` give upper bounds on the maximum string lengths storing each
3891/// scalar numerical type. It is safe to use stack-allocated buffers of
3892/// these sizes for generating decimal representations of the corresponding
3893/// type, including sign and terminating null character, using the default
3894/// precision of 6 significant digits for floating point types.
3905
3906// HASH SPECIALIZATIONS
3907
3908/// Pass the specified `input` string to the specified `hashAlg` hashing
3909/// algorithm of the (template parameter) type `HASHALG`.
3910template <class HASHALG, class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3911void hashAppend(HASHALG& hashAlg,
3913
3914/// Return a hash value for the specified `str`.
3915template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3916std::size_t
3918
3919/// Return a hash value for the specified `str`.
3920std::size_t hashBasicString(const string& str);
3921
3922/// Return a hash value for the specified `str`.
3923std::size_t hashBasicString(const wstring& str);
3924
3925/// Specialize `bsl::hash` for strings, including an overload for pointers
3926/// to allow character arrays to be hashed without converting them first.
3927template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3928struct hash<basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR> >
3929 : ::BloombergLP::bslh::Hash<>
3930{
3931 // PUBLIC ACCESSORS
3932
3933 /// Compute and return the hash value of the specified `input`.
3934 std::size_t operator()(
3936
3937 /// Compute and return the hash value of the contents of the specified
3938 /// null-terminated `input`. This value will be the same as the hash
3939 /// value of a @ref basic_string constructed from `input`.
3940 std::size_t operator()(const CHAR_TYPE *input) const;
3941};
3942
3943#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
3944// DRQS 132030795
3945
3946// Sun CC 12.3 has trouble with the partial specializations above in certain
3947// circumstances (see DRQS 132030795). Adding these explicit specializations
3948// for `string` and `wstring` makes the problematic cases work.
3949
3950template <>
3951struct hash<string> : ::BloombergLP::bslh::Hash<>
3952{
3953 // PUBLIC ACCESSORS
3954
3955 /// Compute and return the hash value of the specified `input`.
3956 std::size_t operator()(const string& input) const;
3957
3958 /// Compute and return the hash value of the contents of the specified
3959 /// null-terminated `input`. This value will be the same as the hash
3960 /// value of a @ref basic_string constructed from `input`.
3961 std::size_t operator()(const char *input) const;
3962};
3963
3964template <>
3965struct hash<wstring> : ::BloombergLP::bslh::Hash<>
3966{
3967 // PUBLIC ACCESSORS
3968
3969 /// Compute and return the hash value of the specified `input`.
3970 std::size_t operator()(const wstring& input) const;
3971
3972 /// Compute and return the hash value of the contents of the specified
3973 /// null-terminated `input`. This value will be the same as the hash
3974 /// value of a @ref basic_string constructed from `input`.
3975 std::size_t operator()(const wchar_t *input) const;
3976};
3977
3978#endif
3979
3980} // close namespace bsl
3981
3982
3983namespace bslh {
3984
3985/// Pass the specified `input` string to the specified `hashAlg` hashing
3986/// algorithm of the (template parameter) type `HASHALG`. Note that this
3987/// function violates the BDE coding standard, adding a function for a
3988/// namespace for a different package, and none of the function parameters
3989/// are from this package either. This is necessary in order to provide an
3990/// implementation of `bslh::hashAppend` for the (native) standard library
3991/// `string` type as we are not allowed to add overloads directly into
3992/// namespace `std`, and this component essentially provides the interface
3993/// between `bsl` and `std` string types.
3994template <class HASHALG, class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
3996void hashAppend(
3997 HASHALG& hashAlg,
3998 const std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& input);
3999
4000} // close namespace bslh
4001
4002
4003// ============================================================================
4004// FUNCTION TEMPLATE DEFINITIONS
4005// ============================================================================
4006// See IMPLEMENTATION NOTES in the '.cpp' before modifying anything below.
4007
4008namespace bsl {
4009 // ----------------
4010 // class String_Imp
4011 // ----------------
4012
4013// CLASS METHODS
4014template <class CHAR_TYPE, class SIZE_TYPE>
4015SIZE_TYPE
4017 SIZE_TYPE oldCapacity,
4018 SIZE_TYPE maxSize)
4019{
4020 BSLS_ASSERT_SAFE(newLength >= oldCapacity);
4021
4022 // We must exercise an exponential growth, otherwise we cannot
4023 // guarantee amortized time for `append`, `insert`, `push_back`,
4024 // `replace`, etc. 1.5 growth factor helps to reuse previously
4025 // allocated and freed memory blocks on frequent re-allocations due to
4026 // a continuous string growth (for example, when calling `push_back` in
4027 // a loop).
4028 //
4029 // TBD: consider bounding the exponential growth when `newCapacity` is
4030 // about several megabytes.
4031 SIZE_TYPE newCapacity = oldCapacity + (oldCapacity >> 1);
4032
4033 if (newLength > newCapacity) {
4034 newCapacity = newLength;
4035 }
4036
4037 if (newCapacity < oldCapacity || newCapacity > maxSize) { // overflow
4038 newCapacity = maxSize;
4039 }
4040
4041 return newCapacity;
4042}
4043
4044// CREATORS
4045template <class CHAR_TYPE, class SIZE_TYPE>
4048: d_start_p(0)
4049, d_length(0)
4050, d_capacity(this->SHORT_BUFFER_CAPACITY) // See {DRQS 131792157} for 'this'.
4051{
4052}
4053
4054template <class CHAR_TYPE, class SIZE_TYPE>
4057 SIZE_TYPE capacity)
4058: d_start_p(0)
4059, d_length(length)
4060, d_capacity(capacity <= static_cast<SIZE_TYPE>(this->SHORT_BUFFER_CAPACITY)
4061 ? static_cast<SIZE_TYPE>(this->SHORT_BUFFER_CAPACITY)
4062 : capacity) // See {DRQS 131792157} for 'this'.
4063{
4064}
4065
4066// MANIPULATORS
4067template <class CHAR_TYPE, class SIZE_TYPE>
4069{
4070 if (!isShortString() && !other.isShortString()) {
4071 // If both strings are long, swap the individual fields.
4072 BloombergLP::bslalg::ScalarPrimitives::swap(d_length, other.d_length);
4073 BloombergLP::bslalg::ScalarPrimitives::swap(d_capacity,
4074 other.d_capacity);
4075 BloombergLP::bslalg::ScalarPrimitives::swap(d_start_p,
4076 other.d_start_p);
4077 }
4078 else {
4079 // Otherwise bitwise-swap the whole objects (relies on the
4080 // BitwiseMoveable type trait).
4081 BloombergLP::bslalg::ScalarPrimitives::swap(*this, other);
4082 }
4083}
4084
4085// PRIVATE MANIPULATORS
4086template <class CHAR_TYPE, class SIZE_TYPE>
4087inline
4089{
4090 d_start_p = 0;
4091 d_length = 0;
4092 d_capacity = this->SHORT_BUFFER_CAPACITY;
4093 // See {DRQS 131792157} for 'this'.
4094}
4095
4096template <class CHAR_TYPE, class SIZE_TYPE>
4097inline
4099{
4100 return isShortString()
4101 ? reinterpret_cast<CHAR_TYPE *>((void *)d_short.buffer())
4102 : d_start_p;
4103}
4104
4105// PRIVATE ACCESSORS
4106template <class CHAR_TYPE, class SIZE_TYPE>
4107inline
4109{
4110 // suppress buggy warning in GCC 12 and later {DRQS 176453450}
4111#ifdef BSLS_PLATFORM_PRAGMA_GCC_DIAGNOSTIC_GCC
4112#pragma GCC diagnostic push
4113#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
4114#endif
4115 return d_capacity == this->SHORT_BUFFER_CAPACITY;
4116 // See {DRQS 131792157} for `this`.
4117#ifdef BSLS_PLATFORM_PRAGMA_GCC_DIAGNOSTIC_GCC
4118#pragma GCC diagnostic pop
4119#endif
4120}
4121
4122template <class CHAR_TYPE, class SIZE_TYPE>
4123inline
4125{
4126 return isShortString()
4127 ? reinterpret_cast<const CHAR_TYPE *>((const void *)d_short.buffer())
4128 : d_start_p;
4129}
4130
4131 // ------------------------------
4132 // class bsl::String_ClearProctor
4133 // ------------------------------
4134
4135// CREATORS
4136template <class FULL_STRING_TYPE>
4138 FULL_STRING_TYPE *stringPtr)
4139: d_string_p(stringPtr)
4140, d_originalLength(stringPtr->d_length)
4141{
4142 d_string_p->d_length = 0;
4143}
4144
4145template <class FULL_STRING_TYPE>
4147{
4148 if (d_string_p) {
4149 d_string_p->d_length = d_originalLength;
4150 }
4151}
4152
4153// MANIPULATORS
4154template <class FULL_STRING_TYPE>
4156{
4157 d_string_p = 0;
4158}
4159
4160 // -----------------------
4161 // class bsl::basic_string
4162 // -----------------------
4163
4164// CLASS DATA
4165template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4168
4169// PRIVATE CLASS METHODS
4170template<class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4171inline
4172void
4174 bool maxLengthExceeded,
4175 const char *message)
4176{
4177 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(maxLengthExceeded)) {
4179 BloombergLP::bslstl::StdExceptUtil::throwLengthError(message);
4180 }
4181}
4182
4183template<class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4184inline
4185void
4186basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::privateThrowOutOfRange(
4187 bool outOfRange,
4188 const char *message)
4189{
4190 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(outOfRange)) {
4192 BloombergLP::bslstl::StdExceptUtil::throwOutOfRange(message);
4193 }
4194}
4195
4196// PRIVATE MANIPULATORS
4197template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4198inline
4199CHAR_TYPE *
4200basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateAllocate(
4201 size_type numChars)
4202{
4203 return AllocatorUtil::allocateObject<CHAR_TYPE>(this->allocatorRef(),
4204 numChars + 1);
4205}
4206
4207template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4208inline
4209void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateDeallocate()
4210{
4211 if (!this->isShortString()) {
4212 AllocatorUtil::deallocateObject(this->allocatorRef(),
4213 this->d_start_p, this->d_capacity + 1);
4214 }
4215}
4216
4217template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4218inline
4219void
4220basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateCopyFromOutOfPlaceBuffer(
4221 const basic_string& original)
4222{
4223 BSLS_ASSERT_SAFE(!this->isShortString());
4224 BSLS_ASSERT_SAFE(!original.isShortString());
4225
4226 // Note that it is possible that 'original' is not a short-string, but its
4227 // length has been updated to fit in the short-string buffer (so 'this'
4228 // copy should be a short-string).
4229
4230 static_cast<Imp &>(*this) = Imp(original.length(), original.length());
4231
4232 if (!this->isShortString()) {
4233 this->d_start_p = privateAllocate(this->d_capacity);
4234 }
4235
4236 CHAR_TRAITS::copy(this->dataPtr(), original.data(), this->d_length + 1);
4237}
4238
4239template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4240basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4241basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateAppend(
4242 const CHAR_TYPE *characterString,
4243 size_type numChars,
4244 const char *message)
4245{
4246 privateThrowLengthError(numChars > max_size() - length(), message);
4247
4248 size_type newLength = this->d_length + numChars;
4249 size_type newStorage = this->d_capacity;
4250 CHAR_TYPE *newBuffer = privateReserveRaw(&newStorage,
4251 newLength,
4252 this->d_length);
4253
4254 if (newBuffer) {
4255 CHAR_TRAITS::copy(newBuffer + this->d_length,
4256 characterString,
4257 numChars);
4258 CHAR_TRAITS::assign(*(newBuffer + newLength), CHAR_TYPE());
4259
4260 privateDeallocate();
4261
4262 this->d_start_p = newBuffer;
4263 this->d_capacity = newStorage;
4264 }
4265 else {
4266 CHAR_TRAITS::move(this->dataPtr() + length(),
4267 characterString,
4268 numChars);
4269 CHAR_TRAITS::assign(*(this->dataPtr() + newLength), CHAR_TYPE());
4270 }
4271
4272 this->d_length = newLength;
4273 return *this;
4274}
4275
4276template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4277basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4278basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateAppend(
4279 size_type numChars,
4280 CHAR_TYPE character,
4281 const char *message)
4282{
4283 privateThrowLengthError(numChars > max_size() - length(), message);
4284
4285 size_type newLength = this->d_length + numChars;
4286 privateReserveRaw(newLength);
4287 CHAR_TRAITS::assign(this->dataPtr() + this->d_length, numChars, character);
4288 this->d_length = newLength;
4289 CHAR_TRAITS::assign(*(this->dataPtr() + newLength), CHAR_TYPE());
4290 return *this;
4291}
4292
4293template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4294inline
4295basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4296basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateAppend(
4297 iterator first,
4298 iterator last,
4299 const char *message,
4300 std::forward_iterator_tag)
4301{
4302 BSLS_ASSERT_SAFE(first <= last);
4303
4304 return privateAppend(const_iterator(first),
4305 const_iterator(last),
4306 message,
4307 std::forward_iterator_tag());
4308}
4309
4310template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4311inline
4312basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4313basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateAppend(
4314 const_iterator first,
4315 const_iterator last,
4316 const char *message,
4317 std::forward_iterator_tag)
4318{
4319 BSLS_ASSERT_SAFE(first <= last);
4320 return privateAppend(&*first, last - first, message);
4321}
4322
4323template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4324template <class INPUT_ITER>
4325inline
4326basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4328 INPUT_ITER first,
4329 INPUT_ITER last,
4330 const char *message,
4331 std::input_iterator_tag)
4332{
4333 basic_string temp(get_allocator());
4334 for (; first != last; ++first) {
4335 temp.push_back(*first);
4336 }
4337 if (length() == 0 && capacity() <= temp.capacity()) {
4338 quickSwapRetainAllocators(temp);
4339
4340 // This object may not have been null-terminated because of
4341 // String_ClearProctor, so force null termination in the swapped-into
4342 // temporary.
4343 CHAR_TRAITS::assign(*(temp.dataPtr()), CHAR_TYPE());
4344 return *this; // RETURN
4345 }
4346 return privateAppend(temp.data(), temp.length(), message);
4347}
4348
4349template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4350template <class INPUT_ITER>
4351inline
4354 INPUT_ITER first,
4355 INPUT_ITER last,
4356 const char *message,
4357 std::forward_iterator_tag)
4358{
4359 size_type numChars = bsl::distance(first, last);
4360 privateThrowLengthError(numChars > max_size() - length(), message);
4361
4362 size_type newLength = this->d_length + numChars;
4363 size_type newStorage = this->d_capacity;
4364 CHAR_TYPE *newBuffer = privateReserveRaw(&newStorage,
4365 newLength,
4366 this->d_length);
4367
4368 if (newBuffer) {
4369 for (size_type pos = this->d_length; first != last; ++first, ++pos) {
4370 CHAR_TRAITS::assign(*(newBuffer + pos), *first);
4371 }
4372
4373 privateDeallocate();
4374
4375 this->d_start_p = newBuffer;
4376 this->d_capacity = newStorage;
4377 }
4378 else {
4379 for (size_type pos = this->d_length; first != last; ++first, ++pos) {
4380 CHAR_TRAITS::assign(*(this->dataPtr() + pos), *first);
4381 }
4382 }
4383
4384 CHAR_TRAITS::assign(*(this->dataPtr() + newLength), CHAR_TYPE());
4385 this->d_length = newLength;
4386 return *this;
4387}
4388
4389template<class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4390template<class INPUT_ITER>
4391inline
4394 INPUT_ITER first,
4395 INPUT_ITER last,
4396 const char *message)
4397{
4398 return privateAppendDispatch(first,
4399 last,
4400 message,
4401 first,
4402 BloombergLP::bslmf::Nil());
4403}
4404
4405template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4406template <class INPUT_ITER>
4407inline
4410 INPUT_ITER first,
4411 INPUT_ITER last,
4412 const char *message,
4413 BloombergLP::bslmf::MatchArithmeticType,
4414 BloombergLP::bslmf::Nil )
4415{
4416 return privateAppend((size_type)first, (CHAR_TYPE)last, message);
4417}
4418
4419template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4420template <class INPUT_ITER>
4421inline
4424 INPUT_ITER first,
4425 INPUT_ITER last,
4426 const char *message,
4427 BloombergLP::bslmf::MatchAnyType,
4428 BloombergLP::bslmf::MatchAnyType )
4429{
4430 typename iterator_traits<INPUT_ITER>::iterator_category tag;
4431 return privateAppend(first, last, message, tag);
4432}
4433
4434template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4435template <class FIRST_TYPE, class SECOND_TYPE>
4436inline
4439 FIRST_TYPE first,
4440 SECOND_TYPE second,
4441 const char *message)
4442{
4443 {
4445 privateAppend(first, second, message);
4446 guard.release();
4447 }
4448
4449 return *this;
4450}
4451
4452template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4453inline
4456{
4457 return *static_cast<Imp *>(this);
4458}
4459
4460template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4461void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateClear(
4462 bool deallocateBufferFlag)
4463{
4464 if (deallocateBufferFlag) {
4465 privateDeallocate();
4466 this->resetFields();
4467 }
4468 else {
4469 this->d_length = 0;
4470 }
4471
4472 CHAR_TRAITS::assign(*begin(), CHAR_TYPE());
4473}
4474
4475template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4476inline
4477void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateInsertDispatch(
4478 const_iterator position,
4479 iterator first,
4480 iterator last)
4481{
4482 BSLS_ASSERT_SAFE(first <= last);
4483
4484 privateInsertDispatch(position,
4485 const_iterator(first),
4486 const_iterator(last));
4487}
4488
4489template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4490void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateInsertDispatch(
4491 const_iterator position,
4492 const_iterator first,
4493 const_iterator last)
4494{
4495 BSLS_ASSERT_SAFE(first <= last);
4496
4497 size_type pos = position - cbegin();
4498 privateThrowOutOfRange(
4499 pos > length(),
4500 "string<...>::insert<Iter>(pos,i,j): invalid position");
4501
4502 size_type numChars = last - first;
4503 privateThrowLengthError(
4504 numChars > max_size() - length(),
4505 "string<...>::insert<Iter>(pos,i,j): string too long");
4506
4507 privateInsertRaw(pos, &*first, numChars);
4508}
4509
4510template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4511template <class INPUT_ITER>
4512inline
4513void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateInsertDispatch(
4514 const_iterator position,
4515 INPUT_ITER first,
4516 INPUT_ITER last)
4517{
4518 size_type pos = position - cbegin();
4519 privateReplaceDispatch(pos,
4520 size_type(0),
4521 first,
4522 last,
4523 first,
4524 BloombergLP::bslmf::Nil());
4525}
4526
4527template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4528basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4529basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateInsertRaw(
4530 size_type outPosition,
4531 const CHAR_TYPE *characterString,
4532 size_type numChars)
4533{
4534 BSLS_ASSERT_SAFE(outPosition <= length());
4535 BSLS_ASSERT_SAFE(numChars <= max_size() - length());
4536 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
4537
4538 size_type newLength = this->d_length + numChars;
4539 size_type newStorage = this->d_capacity;
4540 CHAR_TYPE *newBuffer = privateReserveRaw(&newStorage,
4541 newLength,
4542 outPosition);
4543
4544 if (newBuffer) {
4545 // Source and destination cannot overlap, order of next two copies is
4546 // arbitrary. Do it left to right to maintain cache consistency.
4547
4548 const CHAR_TYPE *tail = this->dataPtr() + outPosition;
4549 size_type tailLen = this->d_length - outPosition;
4550
4551 CHAR_TRAITS::copy(newBuffer + outPosition, characterString, numChars);
4552 CHAR_TRAITS::copy(newBuffer + outPosition + numChars, tail, tailLen);
4553 CHAR_TRAITS::assign(*(newBuffer + newLength), CHAR_TYPE());
4554
4555 privateDeallocate();
4556
4557 this->d_start_p = newBuffer;
4558 this->d_capacity = newStorage;
4559 }
4560 else {
4561 // Because of possible aliasing, we have to be very careful in which
4562 // order to move blocks. If 'characterString' overlaps with tail, or
4563 // is entirely contained: in the former case, 'characterString' is
4564 // shifted by 'numChars' (takes 'first' onto 'last'); in the latter,
4565 // the tail moves in by 'numChars', so cannot overwrite
4566 // 'characterString'!
4567
4568 const CHAR_TYPE *first = characterString;
4569 const CHAR_TYPE *last = characterString + numChars;
4570 CHAR_TYPE *tail = this->dataPtr() + outPosition;
4571 size_type tailLen = this->d_length - outPosition;
4572 const CHAR_TYPE *shifted = (tail < first && last <= tail + tailLen)
4573 ? last // 'first' shifted by 'numChars'
4574 : first; // 'no shift
4575
4576 CHAR_TRAITS::move(tail + numChars, tail, tailLen);
4577 CHAR_TRAITS::move(tail, shifted, numChars);
4578 CHAR_TRAITS::assign(*(this->dataPtr() + newLength), CHAR_TYPE());
4579 }
4580
4581 this->d_length = newLength;
4582 return *this;
4583}
4584
4585template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4586basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4587basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateReplaceRaw(
4588 size_type outPosition,
4589 size_type outNumChars,
4590 const CHAR_TYPE *characterString,
4591 size_type numChars)
4592{
4593 BSLS_ASSERT_SAFE(outPosition <= length());
4594 BSLS_ASSERT_SAFE(outNumChars <= length());
4595 BSLS_ASSERT_SAFE(outPosition <= length() - outNumChars);
4596 BSLS_ASSERT_SAFE(length() - outNumChars <= max_size() - numChars);
4597 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
4598
4599 const difference_type displacement =
4600 static_cast<difference_type>(numChars - outNumChars);
4601
4602 size_type newLength = this->d_length + displacement;
4603 size_type newStorage = this->d_capacity;
4604 CHAR_TYPE *newBuffer = privateReserveRaw(&newStorage,
4605 newLength,
4606 outPosition);
4607
4608 const CHAR_TYPE *tail = this->dataPtr() + outPosition + outNumChars;
4609 size_type tailLen = this->d_length - outPosition - outNumChars;
4610
4611 if (newBuffer) {
4612 // Source and destination cannot overlap, order of next two copies is
4613 // arbitrary. Do it left to right to maintain cache consistency.
4614
4615 CHAR_TRAITS::copy(newBuffer + outPosition, characterString, numChars);
4616 CHAR_TRAITS::copy(newBuffer + outPosition + numChars, tail, tailLen);
4617 CHAR_TRAITS::assign(*(newBuffer + newLength), CHAR_TYPE());
4618
4619 privateDeallocate();
4620
4621 this->d_start_p = newBuffer;
4622 this->d_capacity = newStorage;
4623 this->d_length = newLength;
4624 return *this; // RETURN
4625 }
4626
4627 // Because of possible aliasing, we have to be very careful in which order
4628 // to move blocks. There are up to three blocks if 'characterString'
4629 // overlaps with the tail.
4630
4631 CHAR_TYPE *dest = this->dataPtr() + outPosition;
4632 const CHAR_TYPE *first = characterString;
4633 const CHAR_TYPE *last = characterString + numChars;
4634
4635 if (tail < last && last <= tail + tailLen) {
4636 // Either 'characterString' overlaps with tail, or is entirely
4637 // contained.
4638
4639 if (first < tail) {
4640 // Not entirely contained: break '[first .. last)' at 'tail', and
4641 // move it in two steps, the second shifted but not the first.
4642
4643 size_type prefix = tail - first, suffix = last - tail;
4644 if (outNumChars < numChars) {
4645 CHAR_TRAITS::move(dest + numChars, tail, tailLen);
4646 CHAR_TRAITS::move(dest, first, prefix);
4647 }
4648 else {
4649 CHAR_TRAITS::move(dest, first, prefix);
4650 CHAR_TRAITS::move(dest + numChars, tail, tailLen);
4651 }
4652 CHAR_TRAITS::move(dest + prefix,
4653 last - suffix + displacement,
4654 suffix);
4655 }
4656 else {
4657 // Entirely contained: copy 'tail' first, and copy
4658 // '[first .. last)' shifted by 'displacement'.
4659
4660 CHAR_TRAITS::move(dest + numChars, tail, tailLen);
4661 CHAR_TRAITS::copy(dest, first + displacement, numChars);
4662 }
4663 }
4664 else {
4665 // Note: no aliasing in tail.
4666
4667 if (outNumChars < numChars) {
4668 CHAR_TRAITS::move(dest + numChars, tail, tailLen);
4669 CHAR_TRAITS::move(dest, characterString, numChars);
4670 }
4671 else {
4672 CHAR_TRAITS::move(dest, characterString, numChars);
4673 CHAR_TRAITS::move(dest + numChars, tail, tailLen);
4674 }
4675 }
4676 CHAR_TRAITS::assign(*(this->dataPtr() + newLength), CHAR_TYPE());
4677 this->d_length = newLength;
4678 return *this;
4679}
4680
4681template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4682basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4683basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateReplaceRaw(
4684 size_type outPosition,
4685 size_type outNumChars,
4686 size_type numChars,
4687 CHAR_TYPE character)
4688{
4689 BSLS_ASSERT_SAFE(outPosition <= length());
4690 BSLS_ASSERT_SAFE(outNumChars <= length());
4691 BSLS_ASSERT_SAFE(outPosition <= length() - outNumChars);
4692 BSLS_ASSERT_SAFE(length() <= max_size() - numChars);
4693
4694 size_type newLength = this->d_length - outNumChars + numChars;
4695 size_type newStorage = this->d_capacity;
4696 CHAR_TYPE *newBuffer = privateReserveRaw(&newStorage,
4697 newLength,
4698 outPosition);
4699
4700 const CHAR_TYPE *tail = this->dataPtr() + outPosition + outNumChars;
4701 size_type tailLen = this->d_length - outPosition - outNumChars;
4702
4703 if (newBuffer) {
4704 CHAR_TYPE *dest = newBuffer + outPosition;
4705
4706 CHAR_TRAITS::assign(dest, numChars, character);
4707 CHAR_TRAITS::copy(dest + numChars, tail, tailLen);
4708 CHAR_TRAITS::assign(*(newBuffer + newLength), CHAR_TYPE());
4709
4710 privateDeallocate();
4711
4712 this->d_start_p = newBuffer;
4713 this->d_capacity = newStorage;
4714 }
4715 else {
4716 CHAR_TYPE *dest = this->dataPtr() + outPosition;
4717
4718 CHAR_TRAITS::move(dest + numChars, tail, tailLen);
4719 CHAR_TRAITS::assign(dest, numChars, character);
4720 CHAR_TRAITS::assign(*(this->dataPtr() + newLength), CHAR_TYPE());
4721 }
4722
4723 this->d_length = newLength;
4724 return *this;
4725}
4726
4727template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4728template <class INPUT_ITER>
4729inline
4730basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4732 size_type position,
4733 size_type numChars,
4734 INPUT_ITER first,
4735 INPUT_ITER last,
4736 BloombergLP::bslmf::MatchArithmeticType ,
4737 BloombergLP::bslmf::Nil )
4738{
4739 return replace(position, numChars, (size_type)first, (CHAR_TYPE)last);
4740}
4741
4742template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4743template <class INPUT_ITER>
4744inline
4747 size_type position,
4748 size_type numChars,
4749 INPUT_ITER first,
4750 INPUT_ITER last,
4751 BloombergLP::bslmf::MatchAnyType ,
4752 BloombergLP::bslmf::MatchAnyType )
4753{
4754 typename iterator_traits<INPUT_ITER>::iterator_category tag;
4755 return privateReplace(position, numChars, first, last, tag);
4756}
4757
4758template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4759template <class INPUT_ITER>
4762 size_type outPosition,
4763 size_type outNumChars,
4764 INPUT_ITER first,
4765 INPUT_ITER last,
4766 std::input_iterator_tag)
4767{
4768 privateThrowOutOfRange(
4769 length() < outPosition,
4770 "string<...>::replace<InputIter>(pos,n,i,j): invalid position");
4771
4772 basic_string temp(get_allocator());
4773 for (; first != last; ++first) {
4774 temp.push_back(*first);
4775 }
4776 if (outPosition == 0 && length() <= outNumChars) {
4777 // Note: can potentially shrink the capacity, hence the reserve.
4778
4779 temp.privateReserveRaw(capacity());
4780 quickSwapRetainAllocators(temp);
4781 return *this; // RETURN
4782 }
4783 return privateReplaceRaw(outPosition,
4784 outNumChars,
4785 temp.data(),
4786 temp.length());
4787}
4788
4789template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4790template <class INPUT_ITER>
4793 size_type outPosition,
4794 size_type outNumChars,
4795 INPUT_ITER first,
4796 INPUT_ITER last,
4797 std::forward_iterator_tag)
4798{
4799 privateThrowOutOfRange(
4800 length() < outPosition,
4801 "string<...>::replace<Iter>(pos,n,i,j): invalid position");
4802
4803 size_type numChars = bsl::distance(first, last);
4804 privateThrowLengthError(
4805 max_size() - (length() - outPosition) < numChars,
4806 "string<...>::replace<Iter>(pos,n,i,j): string too long");
4807
4808 // Create a temp string because the 'first'/'last' iterator pair can alias
4809 // the current string; not using the constructor with two iterators because
4810 // it recurses back here.
4811 basic_string temp(numChars, CHAR_TYPE());
4812
4813 for (size_type pos = 0; pos != numChars; ++first, ++pos) {
4814 temp[pos] = *first;
4815 }
4816
4817 return privateReplaceRaw(outPosition,
4818 outNumChars,
4819 temp.data(),
4820 temp.length());
4821}
4822
4823template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4826 size_type position,
4827 size_type numChars,
4828 const_iterator first,
4829 const_iterator last,
4830 std::forward_iterator_tag)
4831{
4832 BSLS_ASSERT_SAFE(first <= last);
4833
4834 privateThrowOutOfRange(
4835 length() < position,
4836 "string<...>::replace<Iter>(pos,n,i,j): invalid position");
4837
4838 size_type numNewChars = bsl::distance(first, last);
4839 privateThrowLengthError(
4840 max_size() - (length() - position) < numNewChars,
4841 "string<...>::replace<Iter>(pos,n,i,j): string too long");
4842
4843 return privateReplaceRaw(position, numChars, &*first, numNewChars);
4844}
4845
4846template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4848basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4849basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateReplace(
4850 size_type position,
4851 size_type numChars,
4852 iterator first,
4853 iterator last,
4854 std::forward_iterator_tag)
4855{
4856 BSLS_ASSERT_SAFE(first <= last);
4857
4858 return privateReplace(position,
4859 numChars,
4860 const_iterator(first),
4861 const_iterator(last),
4862 std::forward_iterator_tag());
4863}
4864
4865template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4866void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateReserveRaw(
4867 size_type newCapacity)
4868{
4869 BSLS_ASSERT_SAFE(newCapacity <= max_size());
4870
4871 if (this->d_capacity < newCapacity) {
4872 size_type newStorage = this->computeNewCapacity(newCapacity,
4873 this->d_capacity,
4874 max_size());
4875 CHAR_TYPE *newBuffer = privateAllocate(newStorage);
4876
4877 CHAR_TRAITS::copy(newBuffer, this->dataPtr(), this->d_length + 1);
4878
4879 privateDeallocate();
4880
4881 this->d_start_p = newBuffer;
4882 this->d_capacity = newStorage;
4883 }
4884}
4885
4886template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4887CHAR_TYPE *
4888basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateReserveRaw(
4889 size_type *storage,
4890 size_type newCapacity,
4891 size_type numChars)
4892{
4893 BSLS_ASSERT_SAFE(numChars <= length());
4894 BSLS_ASSERT_SAFE(newCapacity <= max_size());
4895 BSLS_ASSERT_SAFE(storage != 0);
4896
4897 if (*storage >= newCapacity) {
4898 return 0; // RETURN
4899 }
4900
4901 *storage = this->computeNewCapacity(newCapacity,
4902 *storage,
4903 max_size());
4904
4905 CHAR_TYPE *newBuffer = privateAllocate(*storage);
4906
4907 CHAR_TRAITS::copy(newBuffer, this->dataPtr(), numChars);
4908 return newBuffer;
4909}
4910
4911template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4912basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
4913basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateResizeRaw(
4914 size_type newLength,
4915 CHAR_TYPE character)
4916{
4917 BSLS_ASSERT_SAFE(newLength <= max_size());
4918
4919 privateReserveRaw(newLength);
4920
4921 if (newLength > this->d_length) {
4922 CHAR_TRAITS::assign(this->dataPtr() + this->d_length,
4923 newLength - this->d_length,
4924 character);
4925 }
4926 this->d_length = newLength;
4927 CHAR_TRAITS::assign(*(this->dataPtr() + this->d_length), CHAR_TYPE());
4928 return *this;
4929}
4930
4931template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4932template <bool ALLOC_PROP>
4933inline
4934void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::
4935quickSwapExchangeAllocators(basic_string& other,
4937{
4938 privateBase().swap(other.privateBase());
4939 AllocatorUtil::swap(&this->allocatorRef(), &other.allocatorRef(),
4940 Propagate);
4941}
4942
4943template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4944inline
4945void basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::
4946 quickSwapRetainAllocators(basic_string& other)
4947{
4948 privateBase().swap(other.privateBase());
4949}
4950
4951// PRIVATE ACCESSORS
4952template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4953int basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::privateCompareRaw(
4954 size_type lhsPosition,
4955 size_type lhsNumChars,
4956 const CHAR_TYPE *other,
4957 size_type otherNumChars) const
4958{
4959 BSLS_ASSERT_SAFE(lhsPosition <= length());
4960 BSLS_ASSERT_SAFE(lhsNumChars <= length());
4961 BSLS_ASSERT_SAFE(lhsPosition <= length() - lhsNumChars);
4962 BSLS_ASSERT_SAFE(other);
4963
4964 size_type numChars = lhsNumChars < otherNumChars ? lhsNumChars
4965 : otherNumChars;
4966 int cmpResult = CHAR_TRAITS::compare(this->dataPtr() + lhsPosition,
4967 other,
4968 numChars);
4969 if (cmpResult) {
4970 return cmpResult; // RETURN
4971 }
4972 if (lhsNumChars < otherNumChars) {
4973 return -1; // RETURN
4974 }
4975 if (lhsNumChars > otherNumChars) {
4976 return 1; // RETURN
4977 }
4978 return 0;
4979}
4980
4981// CREATORS
4982
4983 // *** 21.3.2 construct/copy/destroy: ***
4984
4985template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4986inline
4989: Imp()
4990, BloombergLP::bslalg::ContainerBase<allocator_type>(ALLOCATOR())
4991{
4992 CHAR_TRAITS::assign(*begin(), CHAR_TYPE());
4993}
4994
4995template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
4996inline
4998 const ALLOCATOR& basicAllocator)
5000: Imp()
5001, ContainerBase(basicAllocator)
5002{
5003 CHAR_TRAITS::assign(*begin(), CHAR_TYPE());
5004}
5005
5006template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5009 const basic_string& original)
5010: Imp(original)
5011, ContainerBase(AllocatorTraits::select_on_container_copy_construction(
5012 original.get_allocator()))
5013{
5014 if (!this->isShortString()) {
5015 // Copy out-of-place string into either short buffer or new long
5016 // buffer, according to size.
5017
5018 privateCopyFromOutOfPlaceBuffer(original);
5019 }
5020}
5021
5022template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5025 const basic_string& original,
5026 const ALLOCATOR& basicAllocator)
5027: Imp(original)
5028, ContainerBase(basicAllocator)
5029{
5030 if (!this->isShortString()) {
5031 // Copy out-of-place string into either short buffer or new long
5032 // buffer, according to size.
5033
5034 privateCopyFromOutOfPlaceBuffer(original);
5035 }
5036}
5037
5038template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5039inline
5041 BloombergLP::bslmf::MovableRef<basic_string> original)
5043: Imp(original)
5044, ContainerBase(MoveUtil::access(original).get_allocator())
5045{
5046 if (!this->isShortString()) { // nothing to fix up if string is short
5047 basic_string& originalRef = MoveUtil::access(original);
5048 originalRef.resetFields();
5049 }
5050}
5051
5052template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5053inline
5055 BloombergLP::bslmf::MovableRef<basic_string> original,
5056 const ALLOCATOR& basicAllocator)
5057: Imp(original)
5058, ContainerBase(basicAllocator)
5059{
5060 if (!this->isShortString()) { // nothing to fix up if string is short
5061 basic_string& originalRef = MoveUtil::access(original);
5062
5063 if (this->get_allocator() == originalRef.get_allocator()) {
5064 originalRef.resetFields();
5065 }
5066 else {
5067 privateCopyFromOutOfPlaceBuffer(originalRef);
5068 }
5069 }
5070}
5071
5072template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5075 const basic_string& original,
5076 size_type position,
5077 const ALLOCATOR& basicAllocator)
5078: Imp()
5079, ContainerBase(basicAllocator)
5080{
5081 assign(original, position, npos);
5082}
5083
5084template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5087 const basic_string& original,
5088 size_type position,
5089 size_type numChars,
5090 const ALLOCATOR& basicAllocator)
5091: Imp()
5092, ContainerBase(basicAllocator)
5093{
5094 assign(original, position, numChars);
5095}
5096
5097template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5098#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
5099template <class>
5100#endif
5103 const CHAR_TYPE *characterString,
5104 const ALLOCATOR& basicAllocator)
5105: Imp()
5106, ContainerBase(basicAllocator)
5107{
5108 BSLS_ASSERT_SAFE(characterString);
5109
5110 assign(characterString);
5111}
5112
5113template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5116 const CHAR_TYPE *characterString,
5117 size_type numChars,
5118 const ALLOCATOR& basicAllocator)
5119: Imp()
5120, ContainerBase(basicAllocator)
5121{
5122 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
5123
5124 assign(characterString, numChars);
5125}
5126
5127template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5128#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
5129template <class>
5130#endif
5133 size_type numChars,
5134 CHAR_TYPE character,
5135 const ALLOCATOR& basicAllocator)
5136: Imp()
5137, ContainerBase(basicAllocator)
5138{
5139 assign(numChars, character);
5140}
5141
5142template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5143template <class INPUT_ITER>
5144inline
5146 INPUT_ITER first,
5147 INPUT_ITER last,
5148 const ALLOCATOR& basicAllocator)
5149: Imp()
5150, ContainerBase(basicAllocator)
5151{
5152 append(first, last);
5153}
5154
5155template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5156template <class ALLOC2>
5159 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& original,
5160 const ALLOCATOR& basicAllocator)
5161: Imp()
5162, ContainerBase(basicAllocator)
5163{
5164 this->assign(original.data(), original.length());
5165}
5166
5167template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5168inline
5170 const BloombergLP::bslstl::StringRefData<CHAR_TYPE>& strRef,
5171 const ALLOCATOR& basicAllocator)
5172: Imp()
5173, ContainerBase(basicAllocator)
5174{
5175 assign(strRef.data(), strRef.length());
5176}
5177
5178template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5179template <class STRING_VIEW_LIKE_TYPE>
5180inline
5182 const STRING_VIEW_LIKE_TYPE& object
5184: Imp()
5185, ContainerBase(basicAllocator)
5186{
5188 assign(strView.data(), strView.length());
5189}
5190
5191template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5192template <class STRING_VIEW_LIKE_TYPE>
5193inline
5195 const STRING_VIEW_LIKE_TYPE& object,
5196 size_type position,
5197 size_type numChars,
5198 const ALLOCATOR& basicAllocator
5200: Imp()
5201, ContainerBase(basicAllocator)
5202{
5204 privateThrowOutOfRange(
5205 position > strView.length(),
5206 "string<...>::assign(const string_view&,pos,n): invalid position");
5207
5208 if (numChars > strView.length() - position) {
5209 numChars = strView.length() - position;
5210 }
5211
5212 assign(strView.data() + position, numChars);
5213}
5214
5215#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
5216template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5217inline
5219 std::initializer_list<CHAR_TYPE> values,
5220 const ALLOCATOR& basicAllocator)
5221: Imp()
5222, ContainerBase(basicAllocator)
5223{
5224 append(values.begin(), values.end());
5225}
5226#endif
5227
5228template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5231{
5232 // perform a validity check
5233 BSLS_ASSERT_SAFE((*this)[this->d_length] == CHAR_TYPE());
5234 BSLS_ASSERT_SAFE(capacity() >= length());
5235
5236 privateDeallocate();
5237 this->d_length = npos; // invalid length
5238}
5239
5240// MANIPULATORS
5241
5242 // *** 21.3.2 construct/copy/destroy: ***
5243
5244template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5248 const basic_string& rhs)
5249{
5250 typedef typename
5252
5253 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(this != &rhs)) {
5254 if (Propagate::value) {
5255 basic_string other(rhs, rhs.get_allocator());
5256 quickSwapExchangeAllocators(other, Propagate());
5257 }
5258 else {
5259 privateAssignDispatch(
5260 rhs.data(),
5261 rhs.size(),
5262 "string<...>::operator=(const string&...): string too long");
5263 }
5264 }
5265 return *this;
5266}
5267
5268template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5269inline
5272 BloombergLP::bslmf::MovableRef<basic_string> rhs)
5274 AllocatorTraits::propagate_on_container_move_assignment::value ||
5275 AllocatorTraits::is_always_equal::value)
5276{
5277 typedef typename
5278 AllocatorTraits::propagate_on_container_move_assignment Propagate;
5279
5280 basic_string& lvalue = rhs;
5281
5282 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(this != &lvalue)) {
5283 if (Propagate::value) {
5284 basic_string other(MoveUtil::move(lvalue));
5285 quickSwapExchangeAllocators(other, Propagate());
5286 }
5287 else if (get_allocator() == lvalue.get_allocator()) {
5288 basic_string other(MoveUtil::move(lvalue));
5289 quickSwapRetainAllocators(other);
5290 }
5291 else {
5292 privateAssignDispatch(
5293 lvalue.data(),
5294 lvalue.size(),
5295 "string<...>::operator=(MovableRef<...>): string too long");
5296 }
5297 }
5298 return *this;
5299}
5300
5301template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5302template <class STRING_VIEW_LIKE_TYPE>
5303inline
5306 const STRING_VIEW_LIKE_TYPE& rhs)
5307{
5309 return privateAssignDispatch(
5310 strView.data(),
5311 strView.size(),
5312 "string<>::operator=(basic_string_view&): string too long");
5313}
5314
5315template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5319{
5320 BSLS_ASSERT_SAFE(rhs);
5321
5322 return assign(rhs);
5323}
5324
5325template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5329{
5330 return assign(1, character);
5331}
5332
5333template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5334template <class ALLOC2>
5338 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
5339{
5340 return privateAssignDispatch(
5341 rhs.data(),
5342 rhs.size(),
5343 "string<...>::operator=(std::string&...): string too long");
5344}
5345
5346#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
5347template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5351 std::initializer_list<CHAR_TYPE> values)
5352{
5353 return privateAssignDispatch(
5354 values.begin(),
5355 values.end(),
5356 "string<...>::operator=(initializer_list): string too long");
5357}
5358#endif
5359
5360 // *** 21.3.4 capacity: ***
5361
5362template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5365 CHAR_TYPE character)
5366{
5367 privateThrowLengthError(newLength > max_size(),
5368 "string<...>::resize(n,c): string too long");
5369 privateResizeRaw(newLength, character);
5370}
5371
5372template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5375{
5376 privateThrowLengthError(newLength > max_size(),
5377 "string<...>::resize(n): string too long");
5378 privateResizeRaw(newLength, CHAR_TYPE());
5379}
5380
5381template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5382template <class OPERATION>
5384 size_type newLength,
5385 OPERATION operation)
5386{
5387 privateThrowLengthError(newLength > max_size(),
5388 "string<...>::resize_and_overwrite(n, op): string too long");
5389
5390 privateReserveRaw(newLength);
5391 this->d_length = newLength;
5392
5393#ifdef BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES
5394 size_type finalLength = static_cast<size_type>(
5395 MoveUtil::move(operation)(this->dataPtr(), newLength));
5396#else
5397 size_type finalLength = static_cast<size_type>(
5398 operation(this->dataPtr(), newLength));
5399#endif
5400 BSLS_ASSERT(finalLength <= newLength);
5401 this->d_length = finalLength;
5402 CHAR_TRAITS::assign(*(this->dataPtr() + this->d_length), CHAR_TYPE());
5403}
5404
5405template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5408 size_type newCapacity)
5409{
5410 privateThrowLengthError(newCapacity > max_size(),
5411 "string<...>::reserve(n): string too long");
5412 privateReserveRaw(newCapacity);
5413}
5414
5415template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5418{
5419 if (this->size() < this->d_capacity) {
5420 basic_string temp(this->get_allocator());
5421 temp.privateAppend(this->data(),
5422 this->length(),
5423 "string<...>::shrink_to_fit(): string too long");
5424 quickSwapRetainAllocators(temp);
5425 }
5426}
5427
5428template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5432{
5433 // Note: Stlport and Dinkumware do not deallocate the allocated buffer in
5434 // long string representation, ApacheSTL does.
5435
5436 privateClear(Imp::BASIC_STRING_DEALLOCATE_IN_CLEAR);
5437}
5438
5439 // *** 21.3.3 iterators: ***
5440
5441template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5442inline
5445{
5446 return this->dataPtr();
5447}
5448
5449template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5450inline
5456
5457template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5458inline
5464
5465template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5466inline
5472
5473 // *** 21.3.5 element access: ***
5474
5475template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5476inline
5479{
5480 BSLS_ASSERT_SAFE(position <= length());
5481
5482 return *(begin() + position);
5483}
5484
5485template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5488{
5489 // Note: deliberately not inline, because 1) this is not a very widely used
5490 // function, and 2) it is very convenient to have at least one non-inlined
5491 // element accessor for debugging.
5492
5493 privateThrowOutOfRange(position >= length(),
5494 "string<...>::at(n): invalid position");
5495
5496 return *(begin() + position);
5497}
5498
5499template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5500inline
5501CHAR_TYPE&
5508
5509template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5510inline
5511CHAR_TYPE&
5513{
5515
5516 return *(begin() + length() - 1);
5517}
5518
5519 // *** 21.3.6 modifiers: ***
5520
5521template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5525 const basic_string& rhs)
5526{
5527 return append(rhs);
5528}
5529
5530template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5534 const CHAR_TYPE *rhs)
5535{
5536 BSLS_ASSERT_SAFE(rhs);
5537
5538 return append(rhs);
5539}
5540
5541template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5545{
5546 push_back(character);
5547 return *this;
5548}
5549
5550template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5551template <class STRING_VIEW_LIKE_TYPE>
5555 const STRING_VIEW_LIKE_TYPE& rhs)
5556{
5558 return append(strView.data(),strView.length());
5559}
5560
5561template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5562template <class ALLOC2>
5566 const std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC2>& rhs)
5567{
5568 return append(rhs.begin(),rhs.end());
5569}
5570
5571template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5575 const basic_string& suffix)
5576{
5577 return append(suffix, size_type(0), npos);
5578}
5579
5580template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5583 const basic_string& suffix,
5584 size_type position,
5585 size_type numChars)
5586{
5587 privateThrowOutOfRange(
5588 position > suffix.length(),
5589 "string<...>::append(const string&,pos,n): invalid position");
5590
5591 if (numChars > suffix.length() - position) {
5592 numChars = suffix.length() - position;
5593 }
5594 return privateAppend(
5595 suffix.data() + position,
5596 numChars,
5597 "string<...>::append(const string&,pos,n): string too long");
5598}
5599
5600template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5604 const CHAR_TYPE *characterString,
5605 size_type numChars)
5606{
5607 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
5608
5609 return privateAppend(characterString,
5610 numChars,
5611 "string<...>::append(char*...): string too long");
5612}
5613
5614template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5618 const CHAR_TYPE *characterString)
5619{
5620 BSLS_ASSERT_SAFE(characterString);
5621
5622 return append(characterString, CHAR_TRAITS::length(characterString));
5623}
5624
5625template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5629 CHAR_TYPE character)
5630{
5631 return privateAppend(numChars,
5632 character,
5633 "string<...>::append(n,c): string too long");
5634}
5635
5636template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5637template <class STRING_VIEW_LIKE_TYPE>
5641 const STRING_VIEW_LIKE_TYPE& suffix)
5642{
5644 return privateAppend(
5645 strView.data(),
5646 strView.length(),
5647 "string<...>::append(basic_string_view): string too long");
5648}
5649
5650template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5651template <class STRING_VIEW_LIKE_TYPE>
5654 const STRING_VIEW_LIKE_TYPE& suffix,
5655 size_type position,
5656 size_type numChars)
5657{
5659 privateThrowOutOfRange(
5660 position > strView.length(),
5661 "string<...>::append(basic_string_view,pos,n): invalid position");
5662
5663 if (numChars > strView.length() - position) {
5664 numChars = strView.length() - position;
5665 }
5666 return privateAppend(
5667 strView.data() + position,
5668 numChars,
5669 "string<...>::append(basic_string_view,pos,n): string too long");
5670}
5671
5672template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5673template <class INPUT_ITER>
5677 INPUT_ITER last)
5678{
5679 return privateAppend(first,
5680 last,
5681 "string<...>::append<Iter>(i,j): string too long");
5682}
5683
5684#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
5685template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5689 std::initializer_list<CHAR_TYPE> values)
5690{
5691 return privateAppend(
5692 values.begin(),
5693 values.end(),
5694 "string<...>::append(initializer_list): string too long");
5695}
5696#endif
5697
5698template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5700 CHAR_TYPE character)
5701{
5702 privateThrowLengthError(length() >= max_size(),
5703 "string<...>::push_back(char): string too long");
5704
5705 if (length() + 1 > capacity()) {
5706 privateReserveRaw(length() + 1);
5707 }
5708 CHAR_TRAITS::assign(*(begin() + length()), character);
5709 ++this->d_length;
5710 CHAR_TRAITS::assign(*(begin() + length()), CHAR_TYPE());
5711}
5712
5713template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5717 const basic_string& replacement)
5718{
5719 return this->operator=(replacement);
5720}
5721
5722template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5723inline
5726 BloombergLP::bslmf::MovableRef<basic_string> replacement)
5728{
5729 basic_string& other = replacement;
5730 return this->operator=(MoveUtil::move(other));
5731}
5732
5733template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5736 const basic_string& replacement,
5737 size_type position,
5738 size_type numChars)
5739{
5740 privateThrowOutOfRange(
5741 position > replacement.length(),
5742 "string<...>::assign(const string&,pos,n): invalid position");
5743
5744 if (numChars > replacement.length() - position) {
5745 numChars = replacement.length() - position;
5746 }
5747 return privateAssignDispatch(
5748 replacement.data() + position,
5749 numChars,
5750 "string<...>::assign(const string&,pos,n): invalid position");
5751}
5752
5753template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5757 const CHAR_TYPE *characterString)
5758{
5759 BSLS_ASSERT_SAFE(characterString);
5760
5761 return assign(characterString, CHAR_TRAITS::length(characterString));
5762}
5763
5764template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5768 const CHAR_TYPE *characterString,
5769 size_type numChars)
5770{
5771 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
5772
5773 return privateAssignDispatch(
5774 characterString,
5775 numChars,
5776 "string<...>::assign(char*...): string too long");
5777}
5778
5779template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5780template <class STRING_VIEW_LIKE_TYPE>
5784 const STRING_VIEW_LIKE_TYPE& replacement)
5785{
5786 const bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS> strView = replacement;
5787
5788 return this->operator=(strView);
5789}
5790
5791template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5792template <class STRING_VIEW_LIKE_TYPE>
5796 const STRING_VIEW_LIKE_TYPE& replacement,
5797 size_type position,
5798 size_type numChars)
5799{
5800 const bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS> strView = replacement;
5801
5802 privateThrowOutOfRange(
5803 position > strView.length(),
5804 "string<...>::assign(const StrViewLike&,pos,n): invalid position");
5805
5806 if (numChars > strView.length() - position) {
5807 numChars = strView.length() - position;
5808 }
5809 return privateAssignDispatch(
5810 strView.data() + position,
5811 numChars,
5812 "string<...>::assign(const StrViewLike&,pos,n): invalid position");
5813}
5814
5815template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5816template <class ALLOC2>
5820 const std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC2>& string)
5821{
5822 return this->operator=(string);
5823}
5824
5825template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5829 CHAR_TYPE character)
5830{
5831 return privateAssignDispatch(
5832 numChars,
5833 character,
5834 "string<...>::assign(n,c): string too long");
5835}
5836
5837template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5838template <class INPUT_ITER>
5842 INPUT_ITER last)
5843{
5844 return privateAssignDispatch(
5845 first,
5846 last,
5847 "string<...>::assign<Iter>(i,j): string too long");
5848}
5849
5850#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
5851template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5855 std::initializer_list<CHAR_TYPE> values)
5856{
5857 return privateAssignDispatch(
5858 values.begin(),
5859 values.end(),
5860 "string<...>::assign(initializer_list): string too long");
5861}
5862#endif
5863
5864template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5866basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
5868 size_type position,
5869 const basic_string& other)
5870{
5871 return insert(position, other, size_type(0), npos);
5872}
5873
5874template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5877 size_type position,
5878 const basic_string& other,
5879 size_type sourcePosition,
5880 size_type numChars)
5881{
5882 privateThrowOutOfRange(
5883 position > length(),
5884 "string<...>::insert(pos,const string&...): invalid position");
5885 privateThrowOutOfRange(
5886 sourcePosition > other.length(),
5887 "string<...>::insert(pos,const string&...): invalid source position");
5888
5889 if (numChars > other.length() - sourcePosition) {
5890 numChars = other.length() - sourcePosition;
5891 }
5892 privateThrowLengthError(
5893 numChars > max_size() - length(),
5894 "string<...>::insert(pos,const string&...): string too long");
5895 return privateInsertRaw(position, other.data() + sourcePosition, numChars);
5896}
5897
5898template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5901 size_type position,
5902 const CHAR_TYPE *characterString,
5903 size_type numChars)
5904{
5905 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
5906
5907 privateThrowOutOfRange(
5908 position > length(),
5909 "string<...>::insert(pos,char*...): invalid position");
5910
5911 privateThrowLengthError(
5912 numChars > max_size() - length(),
5913 "string<...>::insert(pos,char*...): string too long");
5914 return privateInsertRaw(position, characterString, numChars);
5915}
5916
5917template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5921 size_type position,
5922 const CHAR_TYPE *characterString)
5923{
5924 BSLS_ASSERT_SAFE(characterString);
5925
5926 return insert(position,
5927 characterString,
5928 CHAR_TRAITS::length(characterString));
5929}
5930
5931template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5934 size_type numChars,
5935 CHAR_TYPE character)
5936{
5937 privateThrowOutOfRange(position > length(),
5938 "string<...>::insert(pos,n,c): invalid position");
5939
5940 privateThrowLengthError(numChars > max_size() - length(),
5941 "string<...>::insert(pos,n,c): string too long");
5942 return privateReplaceRaw(position, size_type(0), numChars, character);
5943}
5944
5945template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5948 CHAR_TYPE character)
5949{
5950 BSLS_ASSERT_SAFE(position >= cbegin());
5951 BSLS_ASSERT_SAFE(position <= cend());
5952
5953 size_type pos = position - cbegin();
5954 insert(pos, size_type(1), character);
5955 return begin() + pos;
5956}
5957
5958#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
5959 // Sun CC compiler doesn't like that 'iterator' return type of 'insert'
5960 // method with an additional 'INPUT_ITER' template parameter depends on
5961 // template parameters of the primary template class @ref basic_string .
5962 // However, it happily accepts 'CHAR_TYPE *', which is how 'iterator' is
5963 // currently defined. It will also accept an inline definition of this
5964 // method (this workaround should be used when 'iterator' becomes a real
5965 // class and the current workaround stops working).
5966# define BSLSTL_INSERT_RETURN_TYPE CHAR_TYPE *
5967#else
5968# define BSLSTL_INSERT_RETURN_TYPE \
5969 typename basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::iterator
5970#endif
5971
5972template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5973template <class INPUT_ITER>
5974inline
5977 INPUT_ITER first,
5978 INPUT_ITER last)
5979{
5980 BSLS_ASSERT_SAFE(position >= cbegin());
5981 BSLS_ASSERT_SAFE(position <= cend());
5982
5983 size_type pos = position - cbegin();
5984 privateInsertDispatch(position, first, last);
5985 return begin() + pos;
5986}
5987
5988#undef BSLSTL_INSERT_RETURN_TYPE
5989
5990template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
5991inline
5994 size_type numChars,
5995 CHAR_TYPE character)
5996{
5997 BSLS_ASSERT_SAFE(position >= cbegin());
5998 BSLS_ASSERT_SAFE(position <= cend());
5999
6000 size_type pos = position - cbegin();
6001 insert(pos, numChars, character);
6002 return begin() + pos;
6003}
6004
6005template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6006template <class STRING_VIEW_LIKE_TYPE>
6009 size_type position,
6010 const STRING_VIEW_LIKE_TYPE& other)
6011{
6013 privateThrowOutOfRange(
6014 position > length(),
6015 "string<...>::insert(pos,const string_view&): invalid position");
6016 privateThrowLengthError(
6017 strView.length() > max_size() - length(),
6018 "string<...>::insert(pos,const string_view&): string too long");
6019 return privateInsertRaw(position, strView.data(), strView.length());
6020}
6021
6022template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6023template <class STRING_VIEW_LIKE_TYPE>
6026 size_type position,
6027 const STRING_VIEW_LIKE_TYPE& other,
6028 size_type sourcePosition,
6029 size_type numChars)
6030{
6032 privateThrowOutOfRange(
6033 position > length(),
6034 "string<...>::insert(pos,const string_view&...): invalid position");
6035 privateThrowOutOfRange(sourcePosition > strView.length(),
6036 "string<...>::insert(pos,const string_view&...): "
6037 "invalid source position");
6038
6039 if (numChars > strView.length() - sourcePosition) {
6040 numChars = strView.length() - sourcePosition;
6041 }
6042 privateThrowLengthError(
6043 numChars > max_size() - length(),
6044 "string<...>::insert(pos,const string&...): string too long");
6045 return privateInsertRaw(position,
6046 strView.data() + sourcePosition,
6047 numChars);
6048}
6049
6050#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
6051template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6052inline
6055 const_iterator position,
6056 std::initializer_list<CHAR_TYPE> values)
6057{
6058 BSLS_ASSERT_SAFE(position >= cbegin());
6059 BSLS_ASSERT_SAFE(position <= cend());
6060
6061 size_type pos = position - cbegin();
6062 privateInsertDispatch(position, values.begin(), values.end());
6063 return begin() + pos;
6064}
6065#endif
6066
6067template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6068basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>&
6070 size_type numChars)
6071{
6072 privateThrowOutOfRange(position > length(),
6073 "string<...>::erase(pos,n): invalid position");
6074
6075 if (numChars > length() - position) {
6076 numChars = length() - position;
6077 }
6078 if (numChars) {
6079 this->d_length -= numChars;
6080 CHAR_TRAITS::move(this->dataPtr() + position,
6081 this->dataPtr() + position + numChars,
6082 this->d_length - position);
6083 CHAR_TRAITS::assign(*(begin() + length()), CHAR_TYPE());
6084 }
6085 return *this;
6086}
6087
6088template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6091{
6092 BSLS_ASSERT_SAFE(position >= cbegin());
6093 BSLS_ASSERT_SAFE(position < cend());
6094
6095 const_iterator postPosition = position;
6096 iterator dstPosition = begin() + (position - cbegin());
6097
6098 ++postPosition;
6099 CHAR_TRAITS::move(&*dstPosition, &*postPosition, cend() - postPosition);
6100
6101 --this->d_length;
6102 CHAR_TRAITS::assign(*(this->dataPtr() + length()), CHAR_TYPE());
6103
6104 return dstPosition;
6105}
6106
6107template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6110 const_iterator last)
6111{
6112 BSLS_ASSERT_SAFE(first >= cbegin());
6113 BSLS_ASSERT_SAFE(first <= cend());
6114 BSLS_ASSERT_SAFE(last >= cbegin());
6115 BSLS_ASSERT_SAFE(last <= cend());
6116 BSLS_ASSERT_SAFE(last - first >= 0);
6117
6118 iterator dstFirst = begin() + (first - cbegin());
6119
6120 if (first != last) {
6121 CHAR_TRAITS::move(&*dstFirst, &*last, cend() - last);
6122
6123 this->d_length -= last - first;
6124 CHAR_TRAITS::assign(*(this->dataPtr() + length()), CHAR_TYPE());
6125 }
6126
6127 return dstFirst;
6128}
6129
6130template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6131inline
6133{
6135
6136 --this->d_length;
6137 CHAR_TRAITS::assign(*(begin() + length()), CHAR_TYPE());
6138}
6139
6140template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6143 size_type outPosition,
6144 size_type outNumChars,
6145 const basic_string& replacement)
6146{
6147 privateThrowOutOfRange(
6148 length() < outPosition,
6149 "string<...>::replace(pos,const string&...): invalid position");
6150 if (outNumChars > length() - outPosition) {
6151 outNumChars = length() - outPosition;
6152 }
6153 privateThrowLengthError(
6154 replacement.length() > outNumChars &&
6155 replacement.length() - outNumChars > max_size() - length(),
6156 "string<...>::replace(pos,const string&...): string too long");
6157 return privateReplaceRaw(outPosition,
6158 outNumChars,
6159 replacement.data(),
6160 replacement.length());
6161}
6162
6163template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6166 size_type outPosition,
6167 size_type outNumChars,
6168 const basic_string& replacement,
6169 size_type position,
6170 size_type numChars)
6171{
6172 privateThrowOutOfRange(
6173 length() < outPosition,
6174 "string<...>::replace(pos,const string&...): invalid position");
6175
6176 if (outNumChars > length() - outPosition) {
6177 outNumChars = length() - outPosition;
6178 }
6179 privateThrowOutOfRange(
6180 position > replacement.length(),
6181 "string<...>::replace(pos,const string&...): invalid position");
6182
6183 if (numChars > replacement.length() - position) {
6184 numChars = replacement.length() - position;
6185 }
6186 privateThrowLengthError(
6187 numChars > outNumChars &&
6188 numChars - outNumChars > max_size() - length(),
6189 "string<...>::replace(pos,const string&...): string too long");
6190 return privateReplaceRaw(outPosition,
6191 outNumChars,
6192 replacement.data() + position,
6193 numChars);
6194}
6195
6196template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6199 size_type outPosition,
6200 size_type outNumChars,
6201 const CHAR_TYPE *characterString,
6202 size_type numChars)
6203{
6204 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
6205
6206 privateThrowOutOfRange(
6207 length() < outPosition,
6208 "string<...>::replace(pos,char*...): invalid position");
6209
6210 if (outNumChars > length() - outPosition) {
6211 outNumChars = length() - outPosition;
6212 }
6213
6214 privateThrowLengthError(
6215 numChars > outNumChars &&
6216 numChars - outNumChars > max_size() - length(),
6217 "string<...>::replace(pos,char*...): string too long");
6218 return privateReplaceRaw(outPosition,
6219 outNumChars,
6220 characterString,
6221 numChars);
6222}
6223
6224template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6228 size_type outPosition,
6229 size_type outNumChars,
6230 const CHAR_TYPE *characterString)
6231{
6232 BSLS_ASSERT_SAFE(characterString);
6233
6234 return replace(outPosition,
6235 outNumChars,
6236 characterString,
6237 CHAR_TRAITS::length(characterString));
6238}
6239
6240template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6243 size_type outNumChars,
6244 size_type numChars,
6245 CHAR_TYPE character)
6246{
6247 privateThrowOutOfRange(
6248 length() < outPosition,
6249 "string<...>::replace(pos,n,c): invalid position");
6250 if (outNumChars > length() - outPosition) {
6251 outNumChars = length() - outPosition;
6252 }
6253 privateThrowLengthError(
6254 numChars > outNumChars &&
6255 numChars - outNumChars > max_size() - length(),
6256 "string<...>::replace(pos,n,c): string too long");
6257 return privateReplaceRaw(outPosition,
6258 outNumChars,
6259 numChars,
6260 character);
6261}
6262
6263template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6264template <class STRING_VIEW_LIKE_TYPE>
6267 size_type outPosition,
6268 size_type outNumChars,
6269 const STRING_VIEW_LIKE_TYPE& replacement)
6270{
6271 privateThrowOutOfRange(
6272 length() < outPosition,
6273 "string<...>::replace(pos,const strView&...): invalid position");
6274 if (outNumChars > length() - outPosition) {
6275 outNumChars = length() - outPosition;
6276 }
6277
6279 privateThrowLengthError(
6280 strView.length() > outNumChars &&
6281 strView.length() - outNumChars > max_size() - length(),
6282 "string<...>::replace(pos,const strView&...): string too long");
6283 return privateReplaceRaw(outPosition,
6284 outNumChars,
6285 strView.data(),
6286 strView.length());
6287}
6288
6289template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6290template <class STRING_VIEW_LIKE_TYPE>
6293 size_type outPosition,
6294 size_type outNumChars,
6295 const STRING_VIEW_LIKE_TYPE& replacement,
6296 size_type position,
6297 size_type numChars)
6298{
6299 privateThrowOutOfRange(
6300 length() < outPosition,
6301 "string<...>::replace(pos,const strView&...): invalid position");
6302
6303 if (outNumChars > length() - outPosition) {
6304 outNumChars = length() - outPosition;
6305 }
6306
6308 privateThrowOutOfRange(
6309 position > strView.length(),
6310 "string<...>::replace(pos,const strView&...): invalid position");
6311
6312 if (numChars > strView.length() - position) {
6313 numChars = strView.length() - position;
6314 }
6315 privateThrowLengthError(
6316 numChars > outNumChars &&
6317 numChars - outNumChars > max_size() - length(),
6318 "string<...>::replace(pos,const strView&...): string too long");
6319 return privateReplaceRaw(outPosition,
6320 outNumChars,
6321 strView.data() + position,
6322 numChars);
6323}
6324
6325template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6328 const_iterator first,
6329 const_iterator last,
6330 const basic_string& replacement)
6331{
6332 BSLS_ASSERT_SAFE(first >= cbegin());
6333 BSLS_ASSERT_SAFE(first <= cend());
6334 BSLS_ASSERT_SAFE(first <= last);
6335 BSLS_ASSERT_SAFE(last <= cend());
6336
6337 size_type outPosition = first - cbegin();
6338 size_type outNumChars = last - first;
6339
6340 privateThrowLengthError(
6341 replacement.length() > outNumChars &&
6342 replacement.length() - outNumChars > max_size() - length(),
6343 "string<...>::replace(const string&...): string too long");
6344
6345 return privateReplaceRaw(outPosition,
6346 outNumChars,
6347 replacement.data(),
6348 replacement.length());
6349}
6350
6351template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6352template <class STRING_VIEW_LIKE_TYPE>
6355 const_iterator first,
6356 const_iterator last,
6357 const STRING_VIEW_LIKE_TYPE& replacement)
6358{
6359 BSLS_ASSERT_SAFE(first >= cbegin());
6360 BSLS_ASSERT_SAFE(first <= cend());
6361 BSLS_ASSERT_SAFE(first <= last);
6362 BSLS_ASSERT_SAFE(last <= cend());
6363
6364 size_type outPosition = first - cbegin();
6365 size_type outNumChars = last - first;
6366
6368 privateThrowLengthError(
6369 strView.length() > outNumChars &&
6370 strView.length() - outNumChars > max_size() - length(),
6371 "string<...>::replace(const strView&...): string too long");
6372
6373 return privateReplaceRaw(outPosition,
6374 outNumChars,
6375 strView.data(),
6376 strView.length());
6377}
6378
6379
6380template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6383 const_iterator first,
6384 const_iterator last,
6385 const CHAR_TYPE *characterString,
6386 size_type numChars)
6387{
6388 BSLS_ASSERT_SAFE(first >= cbegin());
6389 BSLS_ASSERT_SAFE(first <= cend());
6390 BSLS_ASSERT_SAFE(first <= last);
6391 BSLS_ASSERT_SAFE(last <= cend());
6392 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
6393
6394 size_type outPosition = first - cbegin();
6395 size_type outNumChars = last - first;
6396 privateThrowLengthError(
6397 numChars > outNumChars &&
6398 numChars - outNumChars > max_size() - length(),
6399 "string<...>::replace(char*...): string too long");
6400 return privateReplaceRaw(outPosition,
6401 outNumChars,
6402 characterString,
6403 numChars);
6404}
6405
6406template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6410 const_iterator first,
6411 const_iterator last,
6412 const CHAR_TYPE *characterString)
6413{
6414 BSLS_ASSERT_SAFE(first >= cbegin());
6415 BSLS_ASSERT_SAFE(first <= cend());
6416 BSLS_ASSERT_SAFE(first <= last);
6417 BSLS_ASSERT_SAFE(last <= cend());
6418 BSLS_ASSERT_SAFE(characterString);
6419
6420 return replace(first,
6421 last,
6422 characterString,
6423 CHAR_TRAITS::length(characterString));
6424}
6425
6426template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6429 const_iterator first,
6430 const_iterator last,
6431 size_type numChars,
6432 CHAR_TYPE character)
6433{
6434 BSLS_ASSERT_SAFE(first >= cbegin());
6435 BSLS_ASSERT_SAFE(first <= cend());
6436 BSLS_ASSERT_SAFE(first <= last);
6437 BSLS_ASSERT_SAFE(last <= cend());
6438
6439 size_type outPosition = first - cbegin();
6440 size_type outNumChars = last - first;
6441 privateThrowLengthError(numChars > outNumChars &&
6442 numChars - outNumChars > max_size() - length(),
6443 "string<...>::replace(n,c): string too long");
6444 return privateReplaceRaw(outPosition, outNumChars, numChars, character);
6445}
6446
6447template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6448template <class INPUT_ITER>
6449inline
6452 const_iterator first,
6453 const_iterator last,
6454 INPUT_ITER stringFirst,
6455 INPUT_ITER stringLast)
6456{
6457 BSLS_ASSERT_SAFE(first >= cbegin());
6458 BSLS_ASSERT_SAFE(first <= cend());
6459 BSLS_ASSERT_SAFE(first <= last);
6460 BSLS_ASSERT_SAFE(last <= cend());
6461
6462 size_type outPosition = first - cbegin();
6463 size_type outNumChars = last - first;
6464 return privateReplaceDispatch(outPosition,
6465 outNumChars,
6466 stringFirst,
6467 stringLast,
6468 stringFirst,
6469 BloombergLP::bslmf::Nil());
6470}
6471
6472 // *** 21.3.7 string operations: ***
6473
6474template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6475inline
6476CHAR_TYPE *
6481
6482template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6483void
6486 AllocatorTraits::propagate_on_container_swap::value ||
6487 AllocatorTraits::is_always_equal::value)
6488{
6489 typedef typename
6490 AllocatorTraits::propagate_on_container_swap Propagate;
6491
6492 if (Propagate::value) {
6493 quickSwapExchangeAllocators(other, Propagate());
6494 }
6496 get_allocator() == other.get_allocator())) {
6497 quickSwapRetainAllocators(other);
6498 }
6499 else {
6501
6502 basic_string toThisCopy(MoveUtil::move(other), get_allocator());
6503 basic_string toOtherCopy(MoveUtil::move(*this),
6504 other.get_allocator());
6505
6506 this->quickSwapRetainAllocators(toThisCopy);
6507 other.quickSwapRetainAllocators(toOtherCopy);
6508 }
6509}
6510
6511// ACCESSORS
6512
6513 // *** 21.3.3 iterators: ***
6514
6515template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6516inline
6520{
6521 return this->dataPtr();
6522}
6523
6524template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6525inline
6532
6533template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6534inline
6538{
6539 return begin() + this->d_length;
6540}
6541
6542template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6543inline
6550
6551template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6552inline
6559
6560template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6561inline
6568
6569template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6577
6578template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6586
6587 // *** 21.3.4 capacity: ***
6588
6589template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6590inline
6594{
6595 return this->d_length;
6596}
6597
6598template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6599inline
6603{
6604 return this->d_length;
6605}
6606
6607template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6608inline
6612{
6613 // Must take into account the null-terminating character.
6614
6615 size_type stringMaxSize = ~size_type(0) / sizeof(CHAR_TYPE) - 1;
6616 size_type allocMaxSize = AllocatorTraits::max_size(get_allocator()) - 1;
6617 return allocMaxSize < stringMaxSize ? allocMaxSize : stringMaxSize;
6618}
6619
6620template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6621inline
6625{
6626 return this->d_capacity;
6627}
6628
6629template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6630inline
6633{
6634 return this->d_length == 0;
6635}
6636
6637 // *** 21.3.5 element access: ***
6638
6639template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6640inline
6643 size_type position) const
6644{
6645 BSLS_ASSERT_SAFE(position <= length());
6646
6647 return *(begin() + position);
6648}
6649
6650template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6654{
6655 // Note: deliberately not inlined (see comment in non-'const' version).
6656
6657 privateThrowOutOfRange(position >= length(),
6658 "const string<...>::at(n): invalid position");
6659 return *(begin() + position);
6660}
6661
6662template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6663inline
6664const CHAR_TYPE&
6671
6672template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6673inline
6674const CHAR_TYPE&
6676{
6678
6679 return *(end() - 1);
6680}
6681
6682template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6685 size_type numChars,
6686 size_type position) const
6687{
6688 BSLS_ASSERT_SAFE(characterString);
6689
6690 privateThrowOutOfRange(
6691 length() < position,
6692 "const string<...>::copy(str,pos,n): invalid position");
6693 if (numChars > length() - position) {
6694 numChars = length() - position;
6695 }
6696 CHAR_TRAITS::move(characterString, this->dataPtr() + position, numChars);
6697 return numChars;
6698}
6699
6700 // *** 21.3.7 string operations: ***
6701
6702template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6703inline
6704const CHAR_TYPE *
6707{
6708 return this->dataPtr();
6709}
6710
6711template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6712inline
6713const CHAR_TYPE *
6716{
6717 return this->dataPtr();
6718}
6719
6720template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6721inline
6725{
6726 return this->allocatorRef();
6727}
6728
6729template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6733 const basic_string& substring,
6734 size_type position) const
6736{
6737 return find(substring.data(), position, substring.length());
6738}
6739
6740template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6741template <class STRING_VIEW_LIKE_TYPE>
6745 const STRING_VIEW_LIKE_TYPE& substring,
6746 size_type position
6749{
6751 return find(strView.data(), position, strView.length());
6752}
6753
6754template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6757 const CHAR_TYPE *substring,
6758 size_type position,
6759 size_type numChars) const
6760{
6761 BSLS_ASSERT_SAFE(substring);
6762
6763 size_type remChars = length() - position;
6764 if (position > length() || numChars > remChars) {
6765 return npos; // RETURN
6766 }
6767 if (0 == numChars) {
6768 return position; // RETURN
6769 }
6770 const CHAR_TYPE *thisString = this->dataPtr() + position;
6771 const CHAR_TYPE *nextString;
6772 for (remChars -= numChars - 1;
6773 0 != (nextString = BSLSTL_CHAR_TRAITS::find(thisString,
6774 remChars,
6775 *substring));
6776 remChars -= ++nextString - thisString, thisString = nextString)
6777 {
6778 if (0 == CHAR_TRAITS::compare(nextString, substring, numChars)) {
6779 return nextString - this->dataPtr(); // RETURN
6780 }
6781 }
6782 return npos;
6783}
6784
6785template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6789 const CHAR_TYPE *substring,
6790 size_type position) const
6791{
6792 BSLS_ASSERT_SAFE(substring);
6793
6794 return find(substring, position, CHAR_TRAITS::length(substring));
6795}
6796
6797template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6800 size_type position) const
6801{
6802 if (position >= length()) {
6803 return npos; // RETURN
6804 }
6805 const CHAR_TYPE *result =
6806 BSLSTL_CHAR_TRAITS::find(this->dataPtr() + position,
6807 length() - position,
6808 character);
6809 return result ? result - this->dataPtr() : npos;
6810}
6811
6812template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6816 const basic_string& substring,
6817 size_type position) const
6819{
6820 return rfind(substring.data(), position, substring.length());
6821}
6822
6823template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6824template <class STRING_VIEW_LIKE_TYPE>
6828 const STRING_VIEW_LIKE_TYPE& substring,
6829 size_type position
6832{
6834 return rfind(strView.data(), position, strView.length());
6835}
6836
6837template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6840 const CHAR_TYPE *characterString,
6841 size_type position,
6842 size_type numChars) const
6843{
6844 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
6845
6846 if (0 == numChars) {
6847 return position > length() ? length() : position; // RETURN
6848 }
6849 if (numChars <= length()) {
6850 if (position > length() - numChars) {
6851 position = length() - numChars;
6852 }
6853 const CHAR_TYPE *thisString = this->dataPtr() + position;
6854 for (; position != npos; --thisString, --position) {
6855 if (0 == CHAR_TRAITS::compare(thisString,
6856 characterString,
6857 numChars)) {
6858 return position; // RETURN
6859 }
6860 }
6861 }
6862 return npos;
6863}
6864
6865template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6869 const CHAR_TYPE *characterString,
6870 size_type position) const
6871{
6872 BSLS_ASSERT_SAFE(characterString);
6873
6874 return rfind(characterString,
6875 position,
6876 CHAR_TRAITS::length(characterString));
6877}
6878
6879template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6883 size_type position) const
6884{
6885 return rfind(&character, position, size_type(1));
6886}
6887
6888template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6892 const basic_string& characterString,
6893 size_type position) const
6895{
6896 return find_first_of(characterString.data(),
6897 position,
6898 characterString.length());
6899}
6900
6901template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6902template <class STRING_VIEW_LIKE_TYPE>
6906 const STRING_VIEW_LIKE_TYPE& characterString,
6907 size_type position
6910{
6911 bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS> strView = characterString;
6912 return find_first_of(strView.data(), position, strView.length());
6913}
6914
6915template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6918 const CHAR_TYPE *characterString,
6919 size_type position,
6920 size_type numChars) const
6921{
6922 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
6923
6924 if (0 < numChars && position < length()) {
6925 for (const CHAR_TYPE *current = this->dataPtr() + position;
6926 current != this->dataPtr() + length();
6927 ++current)
6928 {
6929 if (BSLSTL_CHAR_TRAITS::find(characterString, numChars, *current)
6930 != 0) {
6931 return current - this->dataPtr(); // RETURN
6932 }
6933 }
6934 }
6935 return npos;
6936}
6937
6938template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6942 const CHAR_TYPE *characterString,
6943 size_type position) const
6944{
6945 BSLS_ASSERT_SAFE(characterString);
6946
6947 return find_first_of(characterString,
6948 position,
6949 CHAR_TRAITS::length(characterString));
6950}
6951
6952template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6956 CHAR_TYPE character,
6957 size_type position) const
6958{
6959 return find_first_of(&character, position, size_type(1));
6960}
6961
6962template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6966 const basic_string& characterString,
6967 size_type position) const
6969{
6970 return find_last_of(characterString.data(),
6971 position,
6972 characterString.length());
6973}
6974
6975template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6976template <class STRING_VIEW_LIKE_TYPE>
6980 const STRING_VIEW_LIKE_TYPE& characterString,
6981 size_type position
6984{
6985 bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS> strView = characterString;
6986 return find_last_of(strView.data(), position, strView.length());
6987}
6988
6989template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
6992 const CHAR_TYPE *characterString,
6993 size_type position,
6994 size_type numChars) const
6995{
6996 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
6997
6998 if (0 < numChars && 0 < length()) {
6999 size_type remChars = position < length() ? position : length() - 1;
7000 for (const CHAR_TYPE *current = this->dataPtr() + remChars;
7001 ;
7002 --current)
7003 {
7004 if (BSLSTL_CHAR_TRAITS::find(
7005 characterString, numChars, *current)) {
7006 return current - this->dataPtr(); // RETURN
7007 }
7008 if (current == this->dataPtr()) {
7009 break;
7010 }
7011 }
7012 }
7013 return npos;
7014}
7015
7016template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7020 const CHAR_TYPE *characterString,
7021 size_type position) const
7022{
7023 BSLS_ASSERT_SAFE(characterString);
7024
7025 return find_last_of(characterString,
7026 position,
7027 CHAR_TRAITS::length(characterString));
7028}
7029
7030template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7034 CHAR_TYPE character,
7035 size_type position) const
7036{
7037 return find_last_of(&character, position, size_type(1));
7038}
7039
7040template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7044 const basic_string& characterString,
7045 size_type position) const
7047{
7048 return find_first_not_of(characterString.data(),
7049 position,
7050 characterString.length());
7051}
7052
7053template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7054template <class STRING_VIEW_LIKE_TYPE>
7058 const STRING_VIEW_LIKE_TYPE& characterString,
7059 size_type position
7062{
7063 bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS> strView = characterString;
7064 return find_first_not_of(strView.data(), position, strView.length());
7065}
7066
7067template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7070 const CHAR_TYPE *characterString,
7071 size_type position,
7072 size_type numChars) const
7073{
7074 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
7075
7076 if (position < length()) {
7077 const CHAR_TYPE *last = this->dataPtr() + length();
7078 for (const CHAR_TYPE *current = this->dataPtr() + position;
7079 current != last;
7080 ++current)
7081 {
7082 if (!BSLSTL_CHAR_TRAITS::find(
7083 characterString, numChars, *current)) {
7084 return current - this->dataPtr(); // RETURN
7085 }
7086 }
7087 }
7088 return npos;
7089}
7090
7091template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7095 const CHAR_TYPE *characterString,
7096 size_type position) const
7097{
7098 BSLS_ASSERT_SAFE(characterString);
7099
7100 return find_first_not_of(characterString,
7101 position,
7102 CHAR_TRAITS::length(characterString));
7103}
7104
7105template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7109 CHAR_TYPE character,
7110 size_type position) const
7111{
7112 return find_first_not_of(&character, position, size_type(1));
7113}
7114
7115template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7119 const basic_string& characterString,
7120 size_type position) const
7122{
7123 return find_last_not_of(characterString.data(),
7124 position,
7125 characterString.length());
7126}
7127
7128template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7129template <class STRING_VIEW_LIKE_TYPE>
7133 const STRING_VIEW_LIKE_TYPE& characterString,
7134 size_type position
7137{
7138 bsl::basic_string_view<CHAR_TYPE, CHAR_TRAITS> strView = characterString;
7139 return find_last_not_of(strView.data(), position, strView.length());
7140}
7141
7142template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7145 const CHAR_TYPE *characterString,
7146 size_type position,
7147 size_type numChars) const
7148{
7149 BSLS_ASSERT_SAFE(characterString || 0 == numChars);
7150
7151 if (0 < length()) {
7152 size_type remChars = position < length() ? position : length() - 1;
7153 for (const CHAR_TYPE *current = this->dataPtr() + remChars;
7154 remChars != npos;
7155 --current, --remChars)
7156 {
7157 if (!BSLSTL_CHAR_TRAITS::find(
7158 characterString, numChars, *current)) {
7159 return current - this->dataPtr(); // RETURN
7160 }
7161 }
7162 }
7163 return npos;
7164}
7165
7166template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7170 const CHAR_TYPE *characterString,
7171 size_type position) const
7172{
7173 BSLS_ASSERT_SAFE(characterString);
7174
7175 return find_last_not_of(characterString,
7176 position,
7177 CHAR_TRAITS::length(characterString));
7178}
7179
7180template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7184 CHAR_TYPE character,
7185 size_type position) const
7186{
7187 return find_last_not_of(&character, position, size_type(1));
7188}
7189
7190template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7195{
7196 return (length() >= characterString.length() &&
7197 0 == CHAR_TRAITS::compare(data(),
7198 characterString.data(),
7199 characterString.size()));
7200}
7201
7202template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7205 CHAR_TYPE character) const BSLS_KEYWORD_NOEXCEPT
7206{
7207 return (0 < length() && CHAR_TRAITS::eq(*data(), character));
7208}
7209
7210template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7213 const CHAR_TYPE *characterString) const
7214{
7215 BSLS_ASSERT_SAFE(characterString);
7216
7217 std::size_t strLength = CHAR_TRAITS::length(characterString);
7218 return (length() >= strLength &&
7219 0 == CHAR_TRAITS::compare(data(),
7220 characterString,
7221 strLength));
7222}
7223
7224template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7229{
7230 return (length() >= characterString.length() &&
7231 0 == CHAR_TRAITS::compare(
7232 data() + length() - characterString.length(),
7233 characterString.data(),
7234 characterString.size()));
7235}
7236
7237template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7240 CHAR_TYPE character) const BSLS_KEYWORD_NOEXCEPT
7241{
7242 return (0 < length() &&
7243 CHAR_TRAITS::eq(*(data()+ length() - 1), character));
7244}
7245
7246template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7249 const CHAR_TYPE *characterString) const
7250{
7251 BSLS_ASSERT_SAFE(characterString);
7252
7253 std::size_t strLength = CHAR_TRAITS::length(characterString);
7254 return (length() >= strLength &&
7255 0 == CHAR_TRAITS::compare(data() + length() - strLength,
7256 characterString,
7257 strLength));
7258}
7259
7260template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7264 size_type numChars) const
7265{
7266 return basic_string<CHAR_TYPE,
7267 CHAR_TRAITS,
7268 ALLOCATOR>(*this, position, numChars);
7269}
7270
7271template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7274 const basic_string& other) const
7276{
7277 return privateCompareRaw(size_type(0),
7278 length(),
7279 other.data(),
7280 other.length());
7281}
7282
7283template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7285 size_type position,
7286 size_type numChars,
7287 const basic_string& other) const
7288{
7289 privateThrowOutOfRange(
7290 length() < position,
7291 "const string<...>::compare(pos,n,...): invalid position");
7292 if (numChars > length() - position) {
7293 numChars = length() - position;
7294 }
7295 return privateCompareRaw(position, numChars, other.data(), other.length());
7296}
7297
7298template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7300 size_type lhsPosition,
7301 size_type lhsNumChars,
7302 const basic_string& other,
7303 size_type otherPosition,
7304 size_type otherNumChars) const
7305{
7306 privateThrowOutOfRange(
7307 length() < lhsPosition,
7308 "const string<...>::compare(pos,n,...): invalid position");
7309 if (lhsNumChars > length() - lhsPosition) {
7310 lhsNumChars = length() - lhsPosition;
7311 }
7312 privateThrowOutOfRange(
7313 other.length() < otherPosition,
7314 "const string<...>::compare(pos,n,...): invalid position");
7315 if (otherNumChars > other.length() - otherPosition) {
7316 otherNumChars = other.length() - otherPosition;
7317 }
7318 return privateCompareRaw(lhsPosition,
7319 lhsNumChars,
7320 other.dataPtr() + otherPosition,
7321 otherNumChars);
7322}
7323
7324template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7327 const CHAR_TYPE *other) const
7328{
7329 BSLS_ASSERT_SAFE(other);
7330
7331 return privateCompareRaw(size_type(0),
7332 length(),
7333 other,
7334 CHAR_TRAITS::length(other));
7335}
7336
7337template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7339 size_type lhsPosition,
7340 size_type lhsNumChars,
7341 const CHAR_TYPE *other,
7342 size_type otherNumChars) const
7343{
7344 BSLS_ASSERT_SAFE(other);
7345
7346 privateThrowOutOfRange(
7347 length() < lhsPosition,
7348 "const string<...>::compare(pos,n,...): invalid position");
7349 if (lhsNumChars > length() - lhsPosition) {
7350 lhsNumChars = length() - lhsPosition;
7351 }
7352 return privateCompareRaw(lhsPosition,
7353 lhsNumChars,
7354 other,
7355 otherNumChars);
7356}
7357
7358template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7361 size_type lhsPosition,
7362 size_type lhsNumChars,
7363 const CHAR_TYPE *other) const
7364{
7365 BSLS_ASSERT_SAFE(other);
7366
7367 return compare(lhsPosition,
7368 lhsNumChars,
7369 other,
7370 CHAR_TRAITS::length(other));
7371}
7372
7373template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7374template <class STRING_VIEW_LIKE_TYPE>
7377 const STRING_VIEW_LIKE_TYPE& other
7380{
7382
7383 return privateCompareRaw(size_type(0),
7384 length(),
7385 strView.data(),
7386 strView.length());
7387}
7388
7389template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7390template <class STRING_VIEW_LIKE_TYPE>
7392 size_type position,
7393 size_type numChars,
7394 const STRING_VIEW_LIKE_TYPE& other
7396{
7397 privateThrowOutOfRange(
7398 length() < position,
7399 "string<...>::compare(pos,n,StrViewLike): invalid position");
7400
7402
7403 if (numChars > length() - position) {
7404 numChars = length() - position;
7405 }
7406 return privateCompareRaw(position,
7407 numChars,
7408 strView.data(),
7409 strView.length());
7410}
7411
7412template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7413template <class STRING_VIEW_LIKE_TYPE>
7415 size_type lhsPosition,
7416 size_type lhsNumChars,
7417 const STRING_VIEW_LIKE_TYPE& other,
7418 size_type otherPosition,
7419 size_type otherNumChars
7421{
7422 privateThrowOutOfRange(
7423 length() < lhsPosition,
7424 "string<...>::compare(pos,n, StrViewLike,...): invalid lhs position");
7425
7427
7428 privateThrowOutOfRange(
7429 strView.length() < otherPosition,
7430 "string<...>::compare(pos,n, StrViewLike,...): invalid rhs position");
7431
7432 if (lhsNumChars > length() - lhsPosition) {
7433 lhsNumChars = length() - lhsPosition;
7434 }
7435 if (otherNumChars > other.length() - otherPosition) {
7436 otherNumChars = other.length() - otherPosition;
7437 }
7438 return privateCompareRaw(lhsPosition,
7439 lhsNumChars,
7440 strView.data() + otherPosition,
7441 otherNumChars);
7442}
7443
7444template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7451
7452// PUBLIC ACCESSORS
7453template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7456operator()(const basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& input) const
7457{
7458 using ::BloombergLP::bslh::hashAppend;
7459 ::BloombergLP::bslh::Hash<>::HashAlgorithm hashAlg;
7460 hashAlg(input.data(), sizeof(CHAR_TYPE) * input.size());
7461 hashAppend(hashAlg, input.size());
7462 return static_cast<std::size_t>(hashAlg.computeHash());
7463}
7464
7465template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7468operator()(const CHAR_TYPE *input) const
7469{
7470 BSLS_ASSERT_SAFE(input);
7471 using ::BloombergLP::bslh::hashAppend;
7472 std::size_t length = CHAR_TRAITS::length(input);
7473 ::BloombergLP::bslh::Hash<>::HashAlgorithm hashAlg;
7474 hashAlg(input, sizeof(CHAR_TYPE) * length);
7475 hashAppend(hashAlg, length);
7476 return static_cast<std::size_t>(hashAlg.computeHash());
7477}
7478
7479#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
7480// DRQS 132030795
7481inline
7482std::size_t hash<string>::operator()(const string& input) const
7483{
7484 using ::BloombergLP::bslh::hashAppend;
7485 ::BloombergLP::bslh::Hash<>::HashAlgorithm hashAlg;
7486 hashAlg(input.data(), input.size());
7487 hashAppend(hashAlg, input.size());
7488 return static_cast<std::size_t>(hashAlg.computeHash());
7489}
7490
7491inline
7492std::size_t hash<string>::operator()(const char *input) const
7493{
7494 BSLS_ASSERT_SAFE(input);
7495 using ::BloombergLP::bslh::hashAppend;
7496 std::size_t length = char_traits<char>::length(input);
7497 ::BloombergLP::bslh::Hash<>::HashAlgorithm hashAlg;
7498 hashAlg(input, length);
7499 hashAppend(hashAlg, length);
7500 return static_cast<std::size_t>(hashAlg.computeHash());
7501}
7502
7503inline
7504std::size_t hash<wstring>::operator()(const wstring& input) const
7505{
7506 using ::BloombergLP::bslh::hashAppend;
7507 ::BloombergLP::bslh::Hash<>::HashAlgorithm hashAlg;
7508 hashAlg(input.data(), sizeof(wchar_t) * input.size());
7509 hashAppend(hashAlg, input.size());
7510 return static_cast<std::size_t>(hashAlg.computeHash());
7511}
7512
7513inline
7514std::size_t hash<wstring>::operator()(const wchar_t *input) const
7515{
7516 BSLS_ASSERT_SAFE(input);
7517 using ::BloombergLP::bslh::hashAppend;
7518 std::size_t length = char_traits<wchar_t>::length(input);
7519 ::BloombergLP::bslh::Hash<>::HashAlgorithm hashAlg;
7520 hashAlg(input, sizeof(wchar_t) * length);
7521 hashAppend(hashAlg, length);
7522 return static_cast<std::size_t>(hashAlg.computeHash());
7523}
7524
7525#endif
7526
7527} // close namespace bsl
7528
7529// FREE FUNCTIONS
7530template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7531inline
7532void bsl::swap(basic_string<CHAR_TYPE,CHAR_TRAITS, ALLOCATOR>& a,
7533 basic_string<CHAR_TYPE,CHAR_TRAITS, ALLOCATOR>& b)
7536{
7537 a.swap(b);
7538}
7539
7540template <class CHAR_TYPE,
7541 class CHAR_TRAITS,
7542 class ALLOCATOR,
7543 class OTHER_CHAR_TYPE>
7544inline
7546bsl::erase(basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& str,
7547 const OTHER_CHAR_TYPE& c)
7548{
7549 typename basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::iterator it =
7550 bsl::remove(str.begin(), str.end(), c);
7551
7552 typename basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::size_type
7553 result = bsl::distance(it, str.end());
7554
7555 str.erase(it, str.end());
7556
7557 return result;
7558}
7559
7560template <class CHAR_TYPE,
7561 class CHAR_TRAITS,
7562 class ALLOCATOR,
7563 class UNARY_PREDICATE>
7564inline
7566bsl::erase_if(basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& str,
7567 const UNARY_PREDICATE& pred)
7568{
7569 typename basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::iterator it =
7570 bsl::remove_if(str.begin(), str.end(), pred);
7571
7572 typename basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>::size_type
7573 result = bsl::distance(it, str.end());
7574
7575 str.erase(it, str.end());
7576
7577 return result;
7578}
7579
7580// FREE OPERATORS
7581template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7582inline
7583bool bsl::operator==(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
7584 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
7586{
7587 return lhs.size() == rhs.size()
7588 && 0 == CHAR_TRAITS::compare(lhs.data(), rhs.data(), lhs.size());
7589}
7590
7591template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
7592inline
7593bool
7595 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
7597{
7598 return lhs.size() == rhs.size()
7599 && 0 == CHAR_TRAITS::compare(lhs.data(), rhs.data(), lhs.size());
7600}
7601
7602template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7603inline
7604bool bsl::operator==(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
7605 const CHAR_TYPE *rhs)
7606{
7607 BSLS_ASSERT_SAFE(rhs);
7608
7609 std::size_t len = CHAR_TRAITS::length(rhs);
7610 return lhs.size() == len
7611 && 0 == CHAR_TRAITS::compare(lhs.data(), rhs, len);
7612}
7613
7614#ifdef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
7615
7616template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7617inline bsl::String_ComparisonCategoryType<CHAR_TRAITS>
7618bsl::operator<=>(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
7619 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
7621{
7622 return static_cast<String_ComparisonCategoryType<CHAR_TRAITS>>(
7623 lhs.compare(rhs) <=> 0);
7624}
7625
7626template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7627inline bsl::String_ComparisonCategoryType<CHAR_TRAITS>
7628bsl::operator<=>(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
7629 const CHAR_TYPE *rhs)
7630{
7631 BSLS_ASSERT_SAFE(rhs);
7632 return static_cast<String_ComparisonCategoryType<CHAR_TRAITS>>(
7633 lhs.compare(rhs) <=> 0);
7634}
7635
7636template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
7637inline bsl::String_ComparisonCategoryType<CHAR_TRAITS>
7638bsl::operator<=>(const bsl::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
7639 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
7641{
7642 return static_cast<String_ComparisonCategoryType<CHAR_TRAITS>>(
7643 lhs.compare(rhs) <=> 0);
7644}
7645
7646#else
7647
7648template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
7649inline
7650bool
7651bsl::operator==(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
7654{
7655 return lhs.size() == rhs.size()
7656 && 0 == CHAR_TRAITS::compare(lhs.data(), rhs.data(), lhs.size());
7657}
7658
7659template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7660inline
7661bool bsl::operator==(const CHAR_TYPE *lhs,
7662 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
7663{
7664 BSLS_ASSERT_SAFE(lhs);
7665
7666 std::size_t len = CHAR_TRAITS::length(lhs);
7667 return len == rhs.size()
7668 && 0 == CHAR_TRAITS::compare(lhs, rhs.data(), len);
7669}
7670
7671template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7672inline
7673bool bsl::operator!=(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
7674 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
7676{
7677 return !(lhs == rhs);
7678}
7679
7680template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
7681inline
7682bool
7683bsl::operator!=(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
7686{
7687 return !(lhs == rhs);
7688}
7689
7690template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
7691inline
7692bool
7694 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
7696{
7697 return !(lhs == rhs);
7698}
7699
7700template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7701inline
7702bool bsl::operator!=(const CHAR_TYPE *lhs,
7703 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
7704{
7705 BSLS_ASSERT_SAFE(lhs);
7706
7707 return !(lhs == rhs);
7708}
7709
7710template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7711inline
7712bool bsl::operator!=(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
7713 const CHAR_TYPE *rhs)
7714{
7715 BSLS_ASSERT_SAFE(rhs);
7716
7717 return !(lhs == rhs);
7718}
7719
7720template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7721bool bsl::operator<(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
7722 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
7724{
7725 const std::size_t minLen = lhs.length() < rhs.length()
7726 ? lhs.length() : rhs.length();
7727
7728 int ret = CHAR_TRAITS::compare(lhs.data(), rhs.data(), minLen);
7729 if (0 == ret) {
7730 return lhs.length() < rhs.length(); // RETURN
7731 }
7732 return ret < 0;
7733}
7734
7735template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
7736bool
7737bsl::operator<(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
7740{
7741 const std::size_t minLen = lhs.length() < rhs.length()
7742 ? lhs.length() : rhs.length();
7743
7744 int ret = CHAR_TRAITS::compare(lhs.data(), rhs.data(), minLen);
7745 if (0 == ret) {
7746 return lhs.length() < rhs.length(); // RETURN
7747 }
7748 return ret < 0;
7749}
7750
7751template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
7752bool
7754 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
7756{
7757 const std::size_t minLen = lhs.length() < rhs.length()
7758 ? lhs.length() : rhs.length();
7759
7760 int ret = CHAR_TRAITS::compare(lhs.data(), rhs.data(), minLen);
7761 if (0 == ret) {
7762 return lhs.length() < rhs.length(); // RETURN
7763 }
7764 return ret < 0;
7765}
7766
7767template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7768bool bsl::operator<(const CHAR_TYPE *lhs,
7769 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
7770{
7771 BSLS_ASSERT_SAFE(lhs);
7772
7773 const std::size_t lhsLen = CHAR_TRAITS::length(lhs);
7774 const std::size_t minLen = lhsLen < rhs.length() ? lhsLen : rhs.length();
7775
7776 int ret = CHAR_TRAITS::compare(lhs, rhs.data(), minLen);
7777 if (0 == ret) {
7778 return lhsLen < rhs.length(); // RETURN
7779 }
7780 return ret < 0;
7781}
7782
7783template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7784bool bsl::operator<(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
7785 const CHAR_TYPE *rhs)
7786{
7787 BSLS_ASSERT_SAFE(rhs);
7788
7789 const std::size_t rhsLen = CHAR_TRAITS::length(rhs);
7790 const std::size_t minLen = rhsLen < lhs.length() ? rhsLen : lhs.length();
7791
7792 int ret = CHAR_TRAITS::compare(lhs.data(), rhs, minLen);
7793 if (0 == ret) {
7794 return lhs.length() < rhsLen; // RETURN
7795 }
7796 return ret < 0;
7797}
7798
7799template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7800inline
7801bool bsl::operator>(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
7802 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
7804{
7805 return rhs < lhs;
7806}
7807
7808template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
7809inline
7810bool
7811bsl::operator>(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
7814{
7815 return rhs < lhs;
7816}
7817
7818template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
7819inline
7820bool
7822 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
7824{
7825 return rhs < lhs;
7826}
7827
7828template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7829inline
7830bool bsl::operator>(const CHAR_TYPE *lhs,
7831 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
7832{
7833 BSLS_ASSERT_SAFE(lhs);
7834
7835 return rhs < lhs;
7836}
7837
7838template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7839inline
7840bool bsl::operator>(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
7841 const CHAR_TYPE *rhs)
7842{
7843 BSLS_ASSERT_SAFE(rhs);
7844
7845 return rhs < lhs;
7846}
7847
7848template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7849inline
7850bool bsl::operator<=(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
7851 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
7853{
7854 return !(rhs < lhs);
7855}
7856
7857template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
7858inline
7859bool
7860bsl::operator<=(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
7863{
7864 return !(rhs < lhs);
7865}
7866
7867template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
7868inline
7869bool
7871 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
7873{
7874 return !(rhs < lhs);
7875}
7876
7877template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7878inline
7879bool bsl::operator<=(const CHAR_TYPE *lhs,
7880 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
7881{
7882 BSLS_ASSERT_SAFE(lhs);
7883
7884 return !(rhs < lhs);
7885}
7886
7887template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7888inline
7889bool bsl::operator<=(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
7890 const CHAR_TYPE *rhs)
7891{
7892 BSLS_ASSERT_SAFE(rhs);
7893
7894 return !(rhs < lhs);
7895}
7896
7897template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7898inline
7899bool bsl::operator>=(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
7900 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
7902{
7903 return !(lhs < rhs);
7904}
7905
7906template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
7907inline
7908bool
7909bsl::operator>=(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
7912{
7913 return !(lhs < rhs);
7914}
7915
7916template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
7917inline
7918bool
7920 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
7922{
7923 return !(lhs < rhs);
7924}
7925
7926template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7927inline
7928bool bsl::operator>=(const CHAR_TYPE *lhs,
7929 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& rhs)
7930{
7931 BSLS_ASSERT_SAFE(lhs);
7932
7933 return !(lhs < rhs);
7934}
7935
7936template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
7937inline
7938bool bsl::operator>=(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC>& lhs,
7939 const CHAR_TYPE *rhs)
7940{
7941 BSLS_ASSERT_SAFE(rhs);
7942
7943 return !(lhs < rhs);
7944}
7945
7946#endif // BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
7947
7948template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7950bsl::operator+(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& lhs,
7951 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& rhs)
7952{
7953 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR> result(
7955 select_on_container_copy_construction(lhs.get_allocator()));
7956 result.reserve(lhs.length() + rhs.length());
7957 result += lhs;
7958 result += rhs;
7959 return result;
7960}
7961
7962#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
7963template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7966 const basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& rhs)
7967{
7968 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lvalue = lhs;
7969 lvalue.append(rhs);
7970 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>(
7971 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
7972}
7973
7974template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7976bsl::operator+(const basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lhs,
7978{
7979 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lvalue = rhs;
7980 lvalue.insert(0, lhs);
7981 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>(
7982 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
7983}
7984
7985template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
7989{
7990 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lvalue = lhs;
7991 lvalue.append(rhs);
7992 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>(
7993 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
7994}
7995#endif
7996
7997template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
7999bsl::operator+(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
8001{
8004 select_on_container_copy_construction(rhs.get_allocator()));
8005 result.reserve(lhs.length() + rhs.length());
8006 result.append(lhs.c_str(), lhs.length());
8007 result += rhs;
8008 return result;
8009}
8010
8011#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8012template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8014bsl::operator+(const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC1>& lhs,
8016{
8017 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC2>& lvalue = rhs;
8018 lvalue.insert(0, lhs.c_str(), lhs.size());
8019 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC2>(
8020 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8021}
8022#endif
8023
8024template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8027 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
8028{
8031 select_on_container_copy_construction(lhs.get_allocator()));
8032 result.reserve(lhs.length() + rhs.length());
8033 result += lhs;
8034 result.append(rhs.c_str(), rhs.length());
8035 return result;
8036}
8037
8038#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8039template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC1, class ALLOC2>
8042 const std::basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOC2>& rhs)
8043{
8044 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC1>& lvalue = lhs;
8045 lvalue.append(rhs.c_str(), rhs.length());
8046 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC1>(
8047 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8048}
8049#endif
8050
8051template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8053bsl::operator+(const CHAR_TYPE *lhs,
8054 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& rhs)
8055{
8056 BSLS_ASSERT_SAFE(lhs);
8057
8058 typename basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::size_type
8059 lhsLength = CHAR_TRAITS::length(lhs);
8060
8061 basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR> result(
8063 select_on_container_copy_construction(rhs.get_allocator()));
8064 result.reserve(lhsLength + rhs.length());
8065 result.append(lhs, lhsLength);
8066 result += rhs;
8067 return result;
8068}
8069
8070#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8071template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8073bsl::operator+(const CHAR_TYPE *lhs,
8075{
8076 BSLS_ASSERT_SAFE(lhs);
8077
8078 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lvalue = rhs;
8079 lvalue.insert(0, lhs);
8080 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>(
8081 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8082}
8083#endif
8084
8085template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8087bsl::operator+(CHAR_TYPE lhs,
8088 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& rhs)
8089{
8090 basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR> result(
8092 select_on_container_copy_construction(rhs.get_allocator()));
8093 result.reserve(1 + rhs.length());
8094 result.push_back(lhs);
8095 result += rhs;
8096 return result;
8097}
8098
8099#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8100template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8102bsl::operator+(CHAR_TYPE lhs,
8104{
8105 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lvalue = rhs;
8106 lvalue.insert(lvalue.begin(), lhs);
8107 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>(
8108 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8109}
8110#endif
8111
8112
8113template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8115bsl::operator+(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& lhs,
8116 const CHAR_TYPE *rhs)
8117{
8118 BSLS_ASSERT_SAFE(rhs);
8119 typename basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>::size_type
8120 rhsLength = CHAR_TRAITS::length(rhs);
8121
8122 basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR> result(
8124 select_on_container_copy_construction(lhs.get_allocator()));
8125 result.reserve(lhs.length() + rhsLength);
8126 result += lhs;
8127 result.append(rhs, rhsLength);
8128 return result;
8129}
8130
8131#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8132template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8135 const CHAR_TYPE *rhs)
8136{
8137 BSLS_ASSERT_SAFE(rhs);
8138
8139 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lvalue = lhs;
8140 lvalue.append(rhs);
8141 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>(
8142 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8143}
8144#endif
8145
8146template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8148bsl::operator+(const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& lhs,
8149 CHAR_TYPE rhs)
8150{
8151 basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR> result(
8153 select_on_container_copy_construction(lhs.get_allocator()));
8154 result.reserve(lhs.length() + 1);
8155 result += lhs;
8156 result.push_back(rhs);
8157 return result;
8158}
8159
8160#ifdef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8161template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8164 CHAR_TYPE rhs)
8165{
8166 basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& lvalue = lhs;
8167 lvalue.push_back(rhs);
8168 return basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>(
8169 BloombergLP::bslmf::MovableRefUtil::move(lvalue));
8170}
8171#endif
8172
8173/// Do not use, for internal use by `operator<<` only.
8174template <class CHAR_TYPE, class CHAR_TRAITS>
8175bool bslstl_string_fill(std::basic_ostream<CHAR_TYPE, CHAR_TRAITS>& os,
8176 std::basic_streambuf<CHAR_TYPE, CHAR_TRAITS> *buf,
8177 std::size_t n)
8178{
8179 BSLS_ASSERT_SAFE(buf);
8180
8181 CHAR_TYPE fillChar = os.fill();
8182
8183 for (std::size_t i = 0; i < n; ++i) {
8184 if (CHAR_TRAITS::eq_int_type(buf->sputc(fillChar), CHAR_TRAITS::eof()))
8185 {
8186 return false; // RETURN
8187 }
8188 }
8189
8190 return true;
8191}
8192
8193template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8194std::basic_ostream<CHAR_TYPE, CHAR_TRAITS>&
8195bsl::operator<<(std::basic_ostream<CHAR_TYPE, CHAR_TRAITS>& os,
8196 const basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& str)
8197{
8198 typedef std::basic_ostream<CHAR_TYPE, CHAR_TRAITS> Ostrm;
8199 typename Ostrm::sentry sentry(os);
8200 bool ok = false;
8201
8202 if (sentry) {
8203 ok = true;
8204 std::size_t n = str.size();
8205 std::size_t padLen = 0;
8206 bool left = (os.flags() & Ostrm::left) != 0;
8207 std::streamsize w = os.width(0);
8208
8209 std::basic_streambuf<CHAR_TYPE, CHAR_TRAITS> *buf = os.rdbuf();
8210
8211 if (w > 0 && std::size_t(w) > n) {
8212 padLen = std::size_t(w) - n;
8213 }
8214
8215 if (!left) {
8216 ok = bslstl_string_fill(os, buf, padLen);
8217 }
8218
8219 ok = ok && (buf->sputn(str.data(), std::streamsize(n)) ==
8220 std::streamsize(n));
8221
8222 if (left) {
8223 ok = ok && bslstl_string_fill(os, buf, padLen);
8224 }
8225 }
8226
8227 if (!ok) {
8228 os.setstate(Ostrm::failbit);
8229 }
8230
8231 return os;
8232}
8233
8234template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8235std::basic_istream<CHAR_TYPE, CHAR_TRAITS>&
8236bsl::operator>>(std::basic_istream<CHAR_TYPE, CHAR_TRAITS>& is,
8237 basic_string<CHAR_TYPE,CHAR_TRAITS, ALLOCATOR>& str)
8238{
8239 typedef std::basic_istream<CHAR_TYPE, CHAR_TRAITS> Istrm;
8240 typename Istrm::sentry sentry(is);
8241
8242 if (sentry) {
8243 std::basic_streambuf<CHAR_TYPE, CHAR_TRAITS> *buf = is.rdbuf();
8244 typedef std::ctype<CHAR_TYPE> CType;
8245
8246 const std::locale& loc = is.getloc();
8247 const CType& ctype = std::use_facet<CType>(loc);
8248
8249 str.clear();
8250 std::streamsize n = is.width(0);
8251 if (n <= 0) {
8252 n = std::numeric_limits<std::streamsize>::max();
8253 }
8254 else {
8255 str.reserve(n);
8256 }
8257
8258 while (n-- > 0) {
8259 typename CHAR_TRAITS::int_type c1 = buf->sbumpc();
8260 if (CHAR_TRAITS::eq_int_type(c1, CHAR_TRAITS::eof())) {
8261 is.setstate(Istrm::eofbit);
8262 break;
8263 }
8264 else {
8265 CHAR_TYPE c = CHAR_TRAITS::to_char_type(c1);
8266
8267 if (ctype.is(CType::space, c)) {
8268 if (CHAR_TRAITS::eq_int_type(buf->sputbackc(c),
8269 CHAR_TRAITS::eof())) {
8270 is.setstate(Istrm::failbit);
8271 }
8272 break;
8273 }
8274 else {
8275 str.push_back(c);
8276 }
8277 }
8278 }
8279
8280 // If we have read no characters, then set failbit.
8281
8282 if (str.size() == 0) {
8283 is.setstate(Istrm::failbit);
8284 }
8285 }
8286 else {
8287 is.setstate(Istrm::failbit);
8288 }
8289
8290 return is;
8291}
8292
8293template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8294std::basic_istream<CHAR_TYPE, CHAR_TRAITS>&
8295bsl::getline(std::basic_istream<CHAR_TYPE, CHAR_TRAITS>& is,
8296 basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& str,
8297 CHAR_TYPE delim)
8298{
8299 typedef std::basic_istream<CHAR_TYPE, CHAR_TRAITS> Istrm;
8300 std::size_t nread = 0;
8301 typename Istrm::sentry sentry(is, true);
8302 if (sentry) {
8303 std::basic_streambuf<CHAR_TYPE, CHAR_TRAITS> *buf = is.rdbuf();
8304 str.clear();
8305
8306 while (nread < str.max_size()) {
8307 int c1 = buf->sbumpc();
8308 if (CHAR_TRAITS::eq_int_type(c1, CHAR_TRAITS::eof())) {
8309 is.setstate(Istrm::eofbit);
8310 break;
8311 }
8312
8313 ++nread;
8314 CHAR_TYPE c = CHAR_TRAITS::to_char_type(c1);
8315 if (!CHAR_TRAITS::eq(c, delim)) {
8316 str.push_back(c);
8317 }
8318 else {
8319 break; // character is extracted but not appended
8320 }
8321 }
8322 }
8323 if (nread == 0 || nread >= str.max_size()) {
8324 is.setstate(Istrm::failbit);
8325 }
8326
8327 return is;
8328}
8329
8330template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8331inline
8332std::basic_istream<CHAR_TYPE, CHAR_TRAITS>&
8333bsl::getline(std::basic_istream<CHAR_TYPE, CHAR_TRAITS>& is,
8334 basic_string<CHAR_TYPE,CHAR_TRAITS,ALLOCATOR>& str)
8335{
8336 return getline(is, str, is.widen('\n'));
8337}
8338
8339// HASH SPECIALIZATIONS
8340template <class HASHALG, class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8341inline
8342void bsl::hashAppend(
8343 HASHALG& hashAlg,
8344 const basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& input)
8345{
8346 using ::BloombergLP::bslh::hashAppend;
8347 hashAlg(input.data(), sizeof(CHAR_TYPE)*input.size());
8348 hashAppend(hashAlg, input.size());
8349}
8350
8351template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8353std::size_t bsl::hashBasicString(
8354 const basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& str)
8355{
8356 return ::BloombergLP::bslh::Hash<>()(str);
8357}
8358
8359
8360
8361template <class HASHALG, class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
8363void bslh::hashAppend(
8364 HASHALG& hashAlg,
8365 const std::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOCATOR>& input)
8366{
8367 hashAlg(input.data(), sizeof(CHAR_TYPE)*input.size());
8368 hashAppend(hashAlg, input.size());
8369}
8370
8371
8372
8373// ============================================================================
8374// TYPE TRAITS
8375// ============================================================================
8376
8377// Type traits for STL *sequence* containers:
8378// o A sequence container defines STL iterators.
8379// o A sequence container is bitwise movable if the allocator is bitwise
8380// movable.
8381// o A sequence container uses 'bslma' allocators if the (template parameter)
8382// type 'ALLOCATOR' is convertible from 'bslma::Allocator *'.
8383
8384
8385
8386namespace bslalg {
8387
8388template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8389struct HasStlIterators<bsl::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC> >
8391{};
8392
8393} // close namespace bslalg
8394
8395namespace bslma {
8396
8397template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOC>
8398struct UsesBslmaAllocator<bsl::basic_string<CHAR_TYPE, CHAR_TRAITS, ALLOC> >
8399 : bsl::is_convertible<Allocator *, ALLOC>
8400{};
8401
8402} // close namespace bslma
8403
8404
8405
8406#undef BSLSTL_CHAR_TRAITS
8407
8408#ifdef BSLS_COMPILERFEATURES_SUPPORT_EXTERN_TEMPLATE
8411extern template class bsl::basic_string<char>;
8412extern template class bsl::basic_string<wchar_t>;
8413
8414# if defined(BSLS_COMPILERFEATURES_SUPPORT_UTF8_CHAR_TYPE)
8416extern template class bsl::basic_string<char8_t>;
8417# endif
8418
8419# if defined(BSLS_COMPILERFEATURES_SUPPORT_UNICODE_CHAR_TYPES)
8422extern template class bsl::basic_string<char16_t>;
8423extern template class bsl::basic_string<char32_t>;
8424# endif
8425
8426#endif
8427
8428#undef BSLSTL_STRING_SUPPORT_RVALUE_ADDITION_OPERATORS
8429
8430#undef BSLSTL_STRING_DEFINE_STRINGVIEW_LIKE_TYPE_IF_COMPLETE
8431#undef BSLSTL_STRING_DEFINE_ONLY_CONVERTIBLE_TO_STRINGVIEW_RETURN_TYPE
8432#undef BSLSTL_STRING_DECLARE_CONVERTIBLE_TO_STRINGVIEW_PARAM_VOID
8433#undef BSLSTL_STRING_DEFINE_CONVERTIBLE_TO_STRINGVIEW_PARAM_VOID
8434#undef BSLSTL_STRING_DECLARE_ONLY_CONVERTIBLE_TO_STRINGVIEW_PARAM_VOID
8435#undef BSLSTL_STRING_DEFINE_ONLY_CONVERTIBLE_TO_STRINGVIEW_PARAM_VOID
8436#undef BSLSTL_STRING_DECLARE_ONLY_CONVERTIBLE_TO_STRINGVIEW_PARAM_ALLOC
8437#undef BSLSTL_STRING_DEFINE_ONLY_CONVERTIBLE_TO_STRINGVIEW_PARAM_ALLOC
8438
8439#undef BSLSTL_STRING_DEDUCE_RVREF
8440#undef BSLSTL_STRING_DEDUCE_RVREF_1
8441#undef BSLSTL_STRING_DEDUCE_RVREF_2
8442
8443#endif
8444
8445// ----------------------------------------------------------------------------
8446// Copyright 2013 Bloomberg Finance L.P.
8447//
8448// Licensed under the Apache License, Version 2.0 (the "License");
8449// you may not use this file except in compliance with the License.
8450// You may obtain a copy of the License at
8451//
8452// http://www.apache.org/licenses/LICENSE-2.0
8453//
8454// Unless required by applicable law or agreed to in writing, software
8455// distributed under the License is distributed on an "AS IS" BASIS,
8456// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8457// See the License for the specific language governing permissions and
8458// limitations under the License.
8459// ----------------------------- END-OF-FILE ----------------------------------
8460
8461/** @} */
8462/** @} */
8463/** @} */
#define BSLSTL_STRING_DECLARE_CONVERTIBLE_TO_STRINGVIEW_PARAM_VOID
Definition bslstl_string.h:965
#define BSLSTL_STRING_DEFINE_ONLY_CONVERTIBLE_TO_STRINGVIEW_PARAM_VOID
Definition bslstl_string.h:992
#define BSLSTL_INSERT_RETURN_TYPE
Definition bslstl_string.h:5968
#define BSLSTL_STRING_DEFINE_CONVERTIBLE_TO_STRINGVIEW_PARAM_VOID
Definition bslstl_string.h:973
#define BSLSTL_STRING_DEFINE_ONLY_CONVERTIBLE_TO_STRINGVIEW_RETURN_TYPE
Definition bslstl_string.h:954
#define BSLSTL_STRING_DECLARE_ONLY_CONVERTIBLE_TO_STRINGVIEW_PARAM_ALLOC
Definition bslstl_string.h:1003
#define BSLSTL_STRING_DEFINE_ONLY_CONVERTIBLE_TO_STRINGVIEW_PARAM_ALLOC
Definition bslstl_string.h:1014
#define BSLSTL_STRING_DECLARE_ONLY_CONVERTIBLE_TO_STRINGVIEW_PARAM_VOID
Definition bslstl_string.h:981
Definition bslstl_string.h:1210
String_ClearProctor(FULL_STRING_TYPE *stringPtr)
Definition bslstl_string.h:4137
void release()
Definition bslstl_string.h:4155
~String_ClearProctor()
Definition bslstl_string.h:4146
Definition bslstl_string.h:1043
bool isShortString() const
Definition bslstl_string.h:4108
String_Imp()
Definition bslstl_string.h:4047
~String_Imp()=default
SIZE_TYPE d_length
Definition bslstl_string.h:1106
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:4016
ShortBufferConstraints
Definition bslstl_string.h:1059
@ SHORT_BUFFER_MIN_BYTES
Definition bslstl_string.h:1061
@ SHORT_BUFFER_NEED_BYTES
Definition bslstl_string.h:1064
String_Imp(SIZE_TYPE length, SIZE_TYPE capacity)
Definition bslstl_string.h:4056
BSLMF_ASSERT(SHORT_BUFFER_BYTES >=sizeof(CHAR_TYPE *))
ConfigurableParameters
Definition bslstl_string.h:1084
@ BASIC_STRING_DEALLOCATE_IN_CLEAR
Definition bslstl_string.h:1088
@ BASIC_STRING_HONOR_SHRINK_REQUEST
Definition bslstl_string.h:1089
void swap(String_Imp &other)
Definition bslstl_string.h:4068
SIZE_TYPE d_capacity
Definition bslstl_string.h:1107
BloombergLP::bsls::AlignedBuffer< SHORT_BUFFER_BYTES, BloombergLP::bsls::AlignmentFromType< CHAR_TYPE >::VALUE > d_short
Definition bslstl_string.h:1102
CHAR_TYPE * dataPtr()
Definition bslstl_string.h:4098
const CHAR_TYPE * dataPtr() const
Definition bslstl_string.h:4124
void resetFields()
Reset all fields of this object to their default-constructed state.
Definition bslstl_string.h:4088
CHAR_TYPE * d_start_p
Definition bslstl_string.h:1103
String_Imp & operator=(const String_Imp &rhs)=default
Definition bslma_bslallocator.h:580
Definition bslstl_stringview.h:441
BSLS_KEYWORD_CONSTEXPR size_type length() const BSLS_KEYWORD_NOEXCEPT
Return the length of this view.
Definition bslstl_stringview.h:1685
BSLS_KEYWORD_CONSTEXPR const_pointer data() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stringview.h:1760
BSLS_KEYWORD_CONSTEXPR size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the length of this view.
Definition bslstl_stringview.h:1676
Definition bslstl_string.h:1281
bsl::reverse_iterator< iterator > reverse_iterator
Definition bslstl_string.h:1312
friend string to_string(long)
size_type length() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6601
const_reverse_iterator crbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6563
reference operator[](size_type position)
Definition bslstl_string.h:5478
size_type find_last_of(const basic_string &characterString, size_type position=npos) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6965
size_type find_first_of(const basic_string &characterString, size_type position=0) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6891
basic_string substr(size_type position=0, size_type numChars=npos) const
Definition bslstl_string.h:7263
basic_string() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:4987
int compare(const basic_string &other) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7273
basic_string & operator=(const std::basic_string< CHAR_TYPE, CHAR_TRAITS, ALLOC2 > &rhs)
basic_string & replace(const_iterator first, const_iterator last, INPUT_ITER stringFirst, INPUT_ITER stringLast)
basic_string & operator+=(const basic_string &rhs)
Definition bslstl_string.h:5524
basic_string(const STRING_VIEW_LIKE_TYPE &object, size_type position, size_type numChars, const ALLOCATOR &basicAllocator=ALLOCATOR() BSLSTL_STRING_DECLARE_CONVERTIBLE_TO_STRINGVIEW_PARAM_VOID)
const CHAR_TYPE * c_str() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6705
void reserve(size_type newCapacity=0)
Definition bslstl_string.h:5407
basic_string & assign(const basic_string &replacement)
Definition bslstl_string.h:5716
iterator insert(const_iterator position, INPUT_ITER first, INPUT_ITER last)
size_type size() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6592
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Return the allocator used by this string to supply memory.
Definition bslstl_string.h:6723
CHAR_TYPE & front()
Definition bslstl_string.h:5502
basic_string(const std::basic_string< CHAR_TYPE, CHAR_TRAITS, ALLOC2 > &original, const ALLOCATOR &basicAllocator=ALLOCATOR())
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:6142
basic_string & assign(INPUT_ITER first, INPUT_ITER last)
AllocatorTraits::size_type size_type
Definition bslstl_string.h:1303
size_type find(const basic_string &substring, size_type position=0) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6732
void shrink_to_fit()
Definition bslstl_string.h:5417
void push_back(CHAR_TYPE character)
Append the specified character to this string.
Definition bslstl_string.h:5699
const_reverse_iterator crend() const BSLS_KEYWORD_NOEXCEPT
Return the past-the-end reverse iterator for this string.
Definition bslstl_string.h:6581
AllocatorTraits::pointer pointer
Definition bslstl_string.h:1305
static const size_type npos
Definition bslstl_string.h:1676
~basic_string()
Destroy this string object.
Definition bslstl_string.h:5230
BSLSTL_STRING_DEFINE_ONLY_CONVERTIBLE_TO_STRINGVIEW_RETURN_TYPE assign(const STRING_VIEW_LIKE_TYPE &replacement)
CHAR_TYPE & back()
Definition bslstl_string.h:5512
bool empty() const BSLS_KEYWORD_NOEXCEPT
Return true if this string has length 0, and false otherwise.
Definition bslstl_string.h:6631
CHAR_TYPE * iterator
Definition bslstl_string.h:1310
friend string to_string(long long)
CHAR_TRAITS traits_type
Definition bslstl_string.h:1299
BSLSTL_STRING_DEFINE_ONLY_CONVERTIBLE_TO_STRINGVIEW_RETURN_TYPE assign(const STRING_VIEW_LIKE_TYPE &replacement, size_type position, size_type numChars=npos)
const_iterator cbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6527
iterator end() BSLS_KEYWORD_NOEXCEPT
Return the past-the-end iterator for this modifiable string.
Definition bslstl_string.h:5452
CHAR_TYPE * data() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6477
bool starts_with(basic_string_view< CHAR_TYPE, CHAR_TRAITS > characterString) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7192
size_type find_last_not_of(const basic_string &characterString, size_type position=npos) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7118
AllocatorTraits::difference_type difference_type
Definition bslstl_string.h:1304
reference at(size_type position)
Definition bslstl_string.h:5487
void resize(size_type newLength, CHAR_TYPE character)
Definition bslstl_string.h:5364
void swap(basic_string &other) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:2533
size_type max_size() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6610
basic_string & operator=(const basic_string &rhs)
Definition bslstl_string.h:5247
void pop_back()
Definition bslstl_string.h:6132
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:7043
value_type & reference
Definition bslstl_string.h:1308
ALLOCATOR allocator_type
Definition bslstl_string.h:1302
size_type rfind(const basic_string &substring, size_type position=npos) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6815
AllocatorTraits::const_pointer const_pointer
Definition bslstl_string.h:1306
const CHAR_TYPE * const_iterator
Definition bslstl_string.h:1311
bsl::reverse_iterator< const_iterator > const_reverse_iterator
These types satisfy the ReversibleSequence requirements.
Definition bslstl_string.h:1315
reverse_iterator rend() BSLS_KEYWORD_NOEXCEPT
Return the past-the-end reverse iterator for this modifiable string.
Definition bslstl_string.h:5468
void resize_and_overwrite(size_type newLength, OPERATION operation)
Definition bslstl_string.h:5383
const_iterator cend() const BSLS_KEYWORD_NOEXCEPT
Return the past-the-end iterator for this string.
Definition bslstl_string.h:6545
basic_string & insert(size_type position, const basic_string &other)
Definition bslstl_string.h:5867
basic_string & assign(const std::basic_string< CHAR_TYPE, CHAR_TRAITS, ALLOC2 > &string)
size_type copy(CHAR_TYPE *characterString, size_type numChars, size_type position=0) const
Definition bslstl_string.h:6684
reverse_iterator rbegin() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:5460
bool ends_with(basic_string_view< CHAR_TYPE, CHAR_TRAITS > characterString) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:7226
void clear() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:5430
CHAR_TRAITS::char_type value_type
Definition bslstl_string.h:1300
basic_string & erase(size_type position=0, size_type numChars=npos)
Definition bslstl_string.h:6069
const value_type & const_reference
Definition bslstl_string.h:1309
size_type capacity() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6623
basic_string & append(const basic_string &suffix)
Definition bslstl_string.h:5574
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_NOEXCEPT_OPERATOR(...)
Definition bsls_keyword.h:635
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:632
#define BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(...)
Definition bsls_keyword.h:634
#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:836
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:8175
void hashAppend(HASH_ALGORITHM &hashAlg, const baljsn::EncoderTestAddress &object)
Definition baljsn_encoder_testtypes.h:9236
Definition bdlb_printmethods.h:283
unsigned long stoul(const string &str, std::size_t *pos=0, int base=10)
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:1611
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:950
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:1358
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)
deque< VALUE_TYPE, ALLOCATOR >::size_type erase(deque< VALUE_TYPE, ALLOCATOR > &deq, const BDE_OTHER_TYPE &value)
Definition bslstl_deque.h:4126
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:1495
bool operator==(const memory_resource &a, const memory_resource &b)
T::const_iterator cbegin(const T &container)
Definition bslstl_iterator.h:1553
std::basic_ostream< CHAR_TYPE, TRAITS > & operator<<(std::basic_ostream< CHAR_TYPE, TRAITS > &os, const bitset< N > &x)
Definition bslstl_bitset.h:1402
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)
BSLS_KEYWORD_CONSTEXPR size_t size(const TYPE(&)[DIMENSION]) BSLS_KEYWORD_NOEXCEPT
Return the dimension of the specified array argument.
Definition bslstl_iterator.h:1331
double stod(const string &str, std::size_t *pos=0)
string to_string(int value)
basic_string< wchar_t > wstring
Definition bslstl_string.h:783
T::iterator end(T &container)
Definition bslstl_iterator.h:1523
basic_string< char > string
Definition bslstl_string.h:782
deque< VALUE_TYPE, ALLOCATOR >::size_type erase_if(deque< VALUE_TYPE, ALLOCATOR > &deq, PREDICATE predicate)
Definition bslstl_deque.h:4135
long double stold(const string &str, std::size_t *pos=0)
BSLS_KEYWORD_CONSTEXPR CONTAINER::value_type * data(CONTAINER &container)
Definition bslstl_iterator.h:1231
bool operator!=(const memory_resource &a, const memory_resource &b)
BSLS_KEYWORD_CONSTEXPR bool empty(const CONTAINER &container)
Definition bslstl_iterator.h:1279
MaxDecimalStringLengths
Definition bslstl_string.h:3895
@ e_MAX_LONGDOUBLE_STRLEN10
Definition bslstl_string.h:3902
@ e_MAX_INT_STRLEN10
Definition bslstl_string.h:3898
@ e_MAX_SHORT_STRLEN10
Definition bslstl_string.h:3897
@ e_MAX_INT64_STRLEN10
Definition bslstl_string.h:3899
@ e_MAX_FLOAT_STRLEN10
Definition bslstl_string.h:3900
@ e_MAX_DOUBLE_STRLEN10
Definition bslstl_string.h:3901
@ e_MAX_SCALAR_STRLEN10
Definition bslstl_string.h:3903
Definition bdlc_flathashmap.h:1805
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:638
Definition balxml_encoderoptions.h:68
Definition bdlbb_blob.h:576
Definition bdldfp_decimal.h:5188
Definition bslstl_string.h:927
Definition bslstl_string.h:905
Definition bslma_allocatortraits.h:1061
BloombergLP::bslma::AllocatorTraits_ConstPointerType< ALLOCATOR >::type const_pointer
Definition bslma_allocatortraits.h:1152
BloombergLP::bslma::AllocatorTraits_PropOnCopyAssign< ALLOCATOR >::type propagate_on_container_copy_assignment
Definition bslma_allocatortraits.h:1297
BloombergLP::bslma::AllocatorTraits_SizeType< ALLOCATOR >::type size_type
Definition bslma_allocatortraits.h:1165
BloombergLP::bslma::AllocatorTraits_PointerType< ALLOCATOR >::type pointer
Definition bslma_allocatortraits.h:1149
BloombergLP::bslma::AllocatorTraits_DifferenceType< ALLOCATOR >::type difference_type
Definition bslma_allocatortraits.h:1162
Definition bslstl_hash.h:498
std::size_t operator()(const TYPE &value) const
Definition bslstl_hash.h:1031
Definition bslmf_isconvertible.h:867
Definition bslmf_issame.h:146
Definition bslalg_hasstliterators.h:99
Definition bslma_usesbslmaallocator.h:343