BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslstl_stringref.h
Go to the documentation of this file.
1/// @file bslstl_stringref.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_stringref.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_STRINGREF
9#define INCLUDED_BSLSTL_STRINGREF
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_stringref bslstl_stringref
15/// @brief Provide a reference to a `const` string.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_stringref
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_stringref-purpose"> Purpose</a>
25/// * <a href="#bslstl_stringref-classes"> Classes </a>
26/// * <a href="#bslstl_stringref-description"> Description </a>
27/// * <a href="#bslstl_stringref-how-to-include-bslstl-stringref"> How to include bslstl::StringRef </a>
28/// * <a href="#bslstl_stringref-efficiency-and-usage-considerations"> Efficiency and Usage Considerations </a>
29/// * <a href="#bslstl_stringref-caveats"> Caveats </a>
30/// * <a href="#bslstl_stringref-usage"> Usage </a>
31/// * <a href="#bslstl_stringref-example-1-basic-operations"> Example 1: Basic Operations </a>
32///
33/// # Purpose {#bslstl_stringref-purpose}
34/// Provide a reference to a `const` string.
35///
36/// # Classes {#bslstl_stringref-classes}
37///
38/// - bslstl::StringRefImp: reference wrapper for a generic string
39/// - bslstl::StringRef: reference wrapper for a `char` string
40/// - bslstl::StringRefWide: reference wrapper for a `wchar_t` string
41///
42/// **Canonical header:** bsl_string.h
43///
44/// @see bdlb_stringrefutil
45///
46/// # Description {#bslstl_stringref-description}
47/// This component defines two classes, `bslstl::StringRef` and
48/// `bslstl::StringRefWide`, each providing a reference to a non-modifiable
49/// string value having an external representation. The type of characters in
50/// the string value can be either `char` (for `bslstl::StringRef`) or `wchar_t`
51/// (for `bslstl::StringRefWide`).
52///
53/// The invariant of `bslstl::StringRef` is that it always has a valid
54/// non-modifiable `std::string` value, where non-empty string values have an
55/// external representation. Empty string values do not need to have an
56/// external representation. Most operations on `bslstl::StringRef` objects
57/// have reference semantics and apply to the string value: e.g., `operator==`
58/// compares string values, not whether `bslstl::StringRef` objects reference
59/// the same string object.
60///
61/// The only operations that do not apply to the string value (i.e., that have
62/// pointer semantics) are copy construction and assignment. These operations
63/// produce a `bslstl::StringRef` object with the same external representation
64/// as the original `bslstl::StringRef` object, which is a stronger
65/// post-condition than having `operator==` return `true` for two
66/// `bslstl::StringRef` objects that have the same value.
67///
68/// The standard notion of substitutability defined by the `operator==` does not
69/// necessarily apply to `bslstl::StringRef` since `bslstl::StringRef` is not a
70/// value-semantic type (because of the external representation). Therefore
71/// there can be a plausible sequence of operations applied to two "equal"
72/// `bslstl::StringRef` objects that result in objects that don't compare equal.
73///
74/// The string value that is represented by a `bslstl::StringRef` object need
75/// not be null-terminated. Moreover, the string may contain embedded null
76/// characters. As such, the string referenced by `bslstl::StringRef`, in
77/// general, is not a C-style string. Moreover, the notion of a null-string
78/// value is not supported.
79///
80/// The address of the string referenced by `bslstl::StringRef` is indicated by
81/// the `data` accessor. Its extent is indicated by the `length` and `size`
82/// accessors. The referenced string is also indicated by the `begin` and `end`
83/// accessors that return STL-compatible iterators to the beginning of the
84/// string and one character past the end of the string, respectively. An
85/// overloaded `operator[]` is also provided for direct by-index access to
86/// individual characters in the string.
87///
88/// Several overloaded free operators are provided for `bslstl::StringRef`
89/// objects (as well as variants for all combinations involving
90/// `bslstl::StringRef` and `std::string`, and `bslstl::StringRef` and `char *`)
91/// for (1) lexicographic comparison of values, and (2) concatenation of values
92/// (producing an `std::string`); also provided is an overloaded free
93/// `operator<<` for writing the value of a `bslstl::StringRef` object to a
94/// specified output stream.
95///
96/// The `bsl::hash` template class is specialized for `bslstl::StringRef` to
97/// enable the use of `bslstl::StringRef` with STL hash containers (e.g.,
98/// `bsl::unordered_set` and `bsl::unordered_map`).
99///
100/// ## How to include bslstl::StringRef {#bslstl_stringref-how-to-include-bslstl-stringref}
101///
102///
103/// To include `bslstl::StringRef` use `#include <bsl_string.h>` (*not*
104/// `#include <bslstl_stringref.h>`).
105///
106/// ## Efficiency and Usage Considerations {#bslstl_stringref-efficiency-and-usage-considerations}
107///
108///
109/// Using `bslstl::StringRef` to pass strings as function arguments can be
110/// considerably more efficient than passing `bsl::string` objects by `const`
111/// reference. First, consider a hypothetical class method in which the
112/// parameter is a reference to a non-modifiable `bsl::string`:
113/// @code
114/// void MyClass::setLabel(const bsl::string& label)
115/// {
116/// d_label = label; // `MyClass::d_label` is of type `bsl::string`
117/// }
118/// @endcode
119/// Then, consider a typical call to this method:
120/// @code
121/// MyClass myClassObj;
122/// myClassObj.setLabel("hello");
123/// @endcode
124/// As a side-effect of this call, a temporary `bsl::string` containing a *copy*
125/// of "hello" is created (using the default allocator), that value is copied to
126/// `d_label`, and the temporary is eventually destroyed. The call thus
127/// requires the string data to be copied twice (as well as a possible
128/// allocation and deallocation).
129///
130/// Next, consider the same method taking a reference to a non-modifiable
131/// `bslstl::StringRef`:
132/// @code
133/// void MyClass::setLabel(const bslstl::StringRef& label)
134/// {
135/// d_label.assign(label.begin(), label.end());
136/// }
137/// @endcode
138/// Now:
139/// @code
140/// myClassObj.setLabel("hello");
141/// @endcode
142/// This call has the side-effect of creating a temporary `bslstl::StringRef`
143/// object, which is likely to be more efficient than creating a temporary
144/// `bsl::string` (even when implemented using the short-string optimization).
145/// In this case, instead of copying the *contents* of "hello", the *address* of
146/// the literal string is copied. In addition, `bsl::strlen` is applied to the
147/// string in order to locate its end. There are *no* allocations done on
148/// behalf of the temporary object.
149///
150/// ## Caveats {#bslstl_stringref-caveats}
151///
152///
153/// 1) The string referenced by `bslstl::StringRef` need not be null-terminated,
154/// and, in fact, may *contain* embedded null characters. Thus, it is generally
155/// not valid to pass the address returned by the `data` accessor to Standard C
156/// functions that expect a null-terminated string (e.g., `std::strlen`,
157/// `std::strcmp`, etc.).
158///
159/// 2) The string referenced by `bslstl::StringRef` must remain valid as long as
160/// the `bslstl::StringRef` references that string. Lifetime issues should be
161/// carefully considered when, for example, returning a `bslstl::StringRef`
162/// object from a function or storing a `bslstl::StringRef` object in a
163/// container.
164///
165/// 3) Passing a null string to any function (e.g., `operator==`) without also
166/// passing a 0 length results in undefined behavior.
167///
168/// ## Usage {#bslstl_stringref-usage}
169///
170///
171/// This section illustrates intended use of this component.
172///
173/// ### Example 1: Basic Operations {#bslstl_stringref-example-1-basic-operations}
174///
175///
176/// The following snippets of code illustrate basic and varied use of the
177/// `bslstl::StringRef` class.
178///
179/// First, we define a function, `getNumBlanks`, that returns the number of
180/// blank (` `) characters contained in the string referenced by a specified
181/// `bslstl::StringRef`:
182/// @code
183/// #include <algorithm>
184///
185/// // Return the number of blank (` `) characters in the string referenced
186/// // by the specified `stringRef`.
187/// bslstl::StringRef::size_type
188/// getNumBlanks(const bslstl::StringRef& stringRef)
189/// {
190/// return std::count(stringRef.begin(), stringRef.end(), ' ');
191/// }
192/// @endcode
193/// Notice that the function delegates the work to the `std::count` STL
194/// algorithm. This delegation is made possible by the STL-compatible iterators
195/// provided by the `begin` and `end` accessors.
196///
197/// Then, call `getNumBlanks` on a default constructed `bslstl::StringRef`:
198/// @code
199/// bslstl::StringRef emptyRef;
200/// bslstl::StringRef::size_type numBlanks = getNumBlanks(emptyRef);
201/// assert(0 == numBlanks);
202///
203/// assert("" == emptyRef);
204/// assert("anything" >= emptyRef);
205/// @endcode
206/// Notice that the behavior a default constructed `bslstl::StringRef` object
207/// behaves the same as if it referenced an empty string.
208///
209/// Next, we (implicitly) construct a `bsl::string` object from
210/// `bslstl::StringRef`:
211/// @code
212/// bsl::string empty(emptyRef);
213/// assert(0 == empty.size());
214/// @endcode
215/// Then, we call `getNumBlanks` on a string literal and assert that the number
216/// of blanks returned is as expected:
217/// @code
218/// numBlanks = getNumBlanks("Good things come to those who wait.");
219/// assert(6 == numBlanks);
220/// @endcode
221/// Next, we define a longer string literal, `poem`, that we will use in the
222/// rest of this usage example:
223/// @code
224/// const char poem[] = // by William Butler Yeats (1865-1939)
225/// |....5....|....5....|....5....|....5....| // length blanks
226/// //
227/// "O love is the crooked thing,\n" // 29 5
228/// "There is nobody wise enough\n" // 28 4
229/// "To find out all that is in it,\n" // 31 7
230/// "For he would be thinking of love\n" // 33 6
231/// "Till the stars had run away\n" // 28 5
232/// "And the shadows eaten the moon.\n" // 32 5
233/// "Ah, penny, brown penny, brown penny,\n" // 37 5
234/// "One cannot begin it too soon."; // 29 5
235/// // ----
236/// // total: 42
237///
238/// numBlanks = getNumBlanks(poem);
239/// assert(42 == numBlanks);
240/// @endcode
241/// Then, we construct a `bslstl::StringRef` object, `line`, that refers to only
242/// the first line of the `poem`:
243/// @code
244/// bslstl::StringRef line(poem, 29);
245/// numBlanks = getNumBlanks(line);
246///
247/// assert( 5 == numBlanks);
248/// assert(29 == line.length());
249/// assert( 0 == std::strncmp(poem, line.data(), line.length()));
250/// @endcode
251/// Next, we use the `assign` method to make `line` refer to the second line of
252/// the `poem`:
253/// @code
254/// line.assign(poem + 29, poem + 57);
255/// numBlanks = getNumBlanks(line);
256/// assert(4 == numBlanks);
257/// assert((57 - 29) == line.length());
258/// assert("There is nobody wise enough\n" == line);
259/// @endcode
260/// Then, we call `getNumBlanks` with a `bsl::string` initialized to the
261/// contents of the `poem`:
262/// @code
263/// const bsl::string poemString(poem);
264/// numBlanks = getNumBlanks(poemString);
265/// assert(42 == numBlanks);
266/// assert(bslstl::StringRef(poemString) == poemString);
267/// assert(bslstl::StringRef(poemString) == poemString.c_str());
268/// @endcode
269/// Next, we make a `bslstl::StringRef` object that refers to a string that will
270/// be able to hold embedded null characters:
271/// @code
272/// char poemWithNulls[512];
273/// const bsl::size_t poemLength = std::strlen(poem);
274/// assert(poemLength < 512);
275///
276/// std::memcpy(poemWithNulls, poem, poemLength + 1);
277/// assert(0 == std::strcmp(poem, poemWithNulls));
278/// @endcode
279/// Now, we replace each occurrence of a '\n' in `poemWithNulls` with a yielding
280/// '\0':
281/// @code
282/// std::replace(poemWithNulls, poemWithNulls + poemLength, '\n', '\0');
283/// assert(0 != std::strcmp(poem, poemWithNulls));
284/// @endcode
285/// Finally, we observe that `poemWithNulls` has the same number of blank
286/// characters as the original `poem`:
287/// @code
288/// numBlanks = getNumBlanks(bslstl::StringRef(poemWithNulls, poemLength));
289/// assert(42 == numBlanks);
290/// @endcode
291/// @}
292/** @} */
293/** @} */
294
295/** @addtogroup bsl
296 * @{
297 */
298/** @addtogroup bslstl
299 * @{
300 */
301/** @addtogroup bslstl_stringref
302 * @{
303 */
304
305#include <bslscm_version.h>
306
307#include <bslstl_string.h>
308
309#include <bslmf_enableif.h>
310#include <bslmf_isintegral.h>
313#include <bslmf_nil.h>
314
315#include <bsls_assert.h>
317#include <bsls_libraryfeatures.h>
318#include <bsls_performancehint.h>
319#include <bsls_platform.h>
320#include <bsls_types.h>
321
322#include <algorithm> // for 'std::min'
323#include <cstddef> // for 'std::size_t'
324#include <cstring>
325#include <iosfwd>
326
327
328namespace bslstl {
329
330#if defined(BSLS_PLATFORM_OS_AIX)
331
332// These 'using's are necessary for a compiler bug on Aix where sometimes when
333// 'bslstl::StringRef's are compared, the ADL doesn't look in the namespace of
334// the base class for candidates.
335
336using BloombergLP::bslstl_stringview_relops::operator==;
337using BloombergLP::bslstl_stringview_relops::operator!=;
338using BloombergLP::bslstl_stringview_relops::operator<;
339using BloombergLP::bslstl_stringview_relops::operator>;
340using BloombergLP::bslstl_stringview_relops::operator<=;
341using BloombergLP::bslstl_stringview_relops::operator>=;
342
343#endif
344
345 // =============================
346 // class StringRefImp<CHAR_TYPE>
347 // =============================
348
349/// This class provides a reference-semantic-like (see below) mechanism that
350/// allows `const` `std::string` values, which are represented externally as
351/// either an `std::string` or null-terminated c-style string (or parts
352/// thereof), to be treated both uniformly and efficiently when passed as an
353/// argument to a function in which the string's length will be needed. The
354/// interface of this class provides a subset of accessor methods found on
355/// `std::string` (but none of the manipulators) -- all of which apply to
356/// the referenced string. But, because only non-modifiable access is
357/// afforded to the referenced string value, each of the manipulators on
358/// this type -- assignment in particular -- apply to this string-reference
359/// object itself (as if it had pointer semantics). Hence, this class has a
360/// hybrid of reference- and pointer-semantics.
361///
362/// This class:
363/// * supports a complete set of *value-semantic* operations
364/// - except for `bdex` serialization
365/// * is *exception-neutral* (agnostic)
366/// * is *alias-safe*
367/// * is `const` *thread-safe*
368/// For terminology see @ref bsldoc_glossary .
369///
370/// See @ref bslstl_stringref
371template <class CHAR_TYPE>
372class StringRefImp : public StringRefData<CHAR_TYPE> {
373
374 private:
375 // PRIVATE TYPES
377
378 public:
379 // PUBLIC TYPES
380 typedef const CHAR_TYPE value_type;
381 typedef const CHAR_TYPE& reference;
382 typedef const CHAR_TYPE& const_reference;
383 typedef const CHAR_TYPE *iterator;
384 typedef const CHAR_TYPE *const_iterator;
385 typedef bsl::reverse_iterator<const_iterator> const_reverse_iterator;
386 typedef std::ptrdiff_t difference_type;
387
388 /// Standard Library general container requirements.
389 typedef std::size_t size_type;
390
391 public:
392 // TRAITS
394
395 private:
396 // PRIVATE ACCESSORS
397
398 /// Write the value of this string reference to the specified output
399 /// `stream` in the unformatted way.
400 void write(std::basic_ostream<CHAR_TYPE>& stream) const;
401
402 public:
403 // CREATORS
404
405 /// Create an object representing an empty `std::string` value that is
406 /// independent of any external representation and with the following
407 /// attribute values:
408 /// @code
409 /// begin() == end()
410 /// isEmpty() == true
411 /// @endcode
412 StringRefImp();
413
414 /// Create a string-reference object having a valid `std::string` value,
415 /// whose external representation begins at the specified `data` address
416 /// and extends for the specified `length`. The external representation
417 /// must remain valid as long as it is bound to this string reference.
418 /// Passing 0 has the same effect as default construction. The behavior
419 /// is undefined unless `0 <= length` and, if `0 == data`, then
420 /// `0 == length`. Note that, like an `std::string`, the `data` need
421 /// not be null-terminated and may contain embedded null characters.
422 /// Note that the template and non-template versions combine to allow
423 /// various integral and enumeration types to be used for length while
424 /// preventing `(char *, 0)` initializer arguments from matching the
425 /// two-iterator constructor below.
426 template <class INT_TYPE>
427 StringRefImp(const CHAR_TYPE *data,
428 INT_TYPE length,
430 bslmf::Nil>::type = bslmf::Nil());
431 StringRefImp(const CHAR_TYPE *data, size_type length);
432
433 /// Create a string-reference object having a valid `std::string` value,
434 /// whose external representation begins at the specified `begin`
435 /// iterator and extends up to, but not including, the specified `end`
436 /// iterator. The external representation must remain valid as long as
437 /// it is bound to this string reference. The behavior is undefined
438 /// unless `begin <= end`. Note that, like an `std::string`, the string
439 /// need not be null-terminated and may contain embedded null
440 /// characters.
442
443 /// Create a string-reference object having a valid `std::string` value,
444 /// whose external representation begins at the specified `data` address
445 /// and extends for `std::char_traits<CHAR_TYPE>::length(data)`
446 /// characters. The external representation must remain valid as long
447 /// as it is bound to this string reference. The behavior is undefined
448 /// unless `data` is null-terminated.
449 StringRefImp(const CHAR_TYPE *data); // IMPLICIT
450
451 /// Create a string-reference object having a valid `std::string` value,
452 /// whose external representation is defined by the specified `str`
453 /// object. The external representation must remain valid as long as it
454 /// is bound to this string reference.
455 StringRefImp(const bsl::basic_string_view<CHAR_TYPE>& str); // IMPLICIT
456 StringRefImp(const std::basic_string<CHAR_TYPE>& str); // IMPLICIT
457 StringRefImp(const bsl::basic_string<CHAR_TYPE>& str); // IMPLICIT
458#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
459 StringRefImp(const std::pmr::basic_string<CHAR_TYPE>& str); // IMPLICIT
460#endif
461
462 /// Create a string-reference object having a valid `std::string` value,
463 /// whose external representation is defined by the specified `original`
464 /// object. The external representation must remain valid as long as it
465 /// is bound to this string reference. Note that this trivial copy
466 /// constructor's definition is compiler generated.
467 StringRefImp(const StringRefImp& original) = default;
468
469 /// Create a string-reference object having a valid `std::string` value,
470 /// whose external representation begins at the specified `startIndex`
471 /// in the specified `original` string reference, and extends either the
472 /// specified `numCharacters` or until the end of the `original` string
473 /// reference, whichever comes first. The external representation must
474 /// remain valid as long as it is bound to this string reference. The
475 /// behavior is undefined unless `startIndex <= original.length()`.
476 /// Note that if `startIndex` is `original.length()` an empty string
477 /// reference is returned.
478 StringRefImp(const StringRefImp& original,
479 size_type startIndex,
480 size_type numCharacters);
481
482 /// Destroy this object.
483 ~StringRefImp() = default;
484
485 // MANIPULATORS
486
487 /// Modify this string reference to refer to the same string as the
488 /// specified `rhs` string reference and return a reference providing
489 /// modifiable access to this object. The assigned object is guaranteed
490 /// to have values of attributes `begin` and `end` equal to the `rhs`
491 /// object's attributes.
492 StringRefImp& operator=(const StringRefImp& rhs) = default;
493
494 /// Bind this string reference to the string at the specified `data`
495 /// address and extending for the specified `length` characters. The
496 /// string indicated by `data` and `length` must remain valid as long as
497 /// it is bound to this object. The behavior is undefined unless
498 /// `0 <= length` or `0 == data && 0 == length`. Note that the string
499 /// need not be null-terminated and may contain embedded null
500 /// characters. Note that the template and non-template versions
501 /// combine to allow various integral and enumeration types to be used
502 /// for length while preventing `(char *, 0)` initializer arguments from
503 /// matching the two-iterator overload of `assign` below.
504 template <class INT_TYPE>
505 void assign(const CHAR_TYPE *data,
506 INT_TYPE length,
508 bslmf::Nil>::type = bslmf::Nil());
509 void assign(const CHAR_TYPE *data, size_type length);
510
511 /// Bind this string reference to the string at the specified `begin`
512 /// iterator, extending up to, but not including, the character at the
513 /// specified `end` iterator. The string indicated by `begin` and `end`
514 /// must remain valid as long as it is bound to this object. The
515 /// behavior is undefined unless `begin <= end`. Note that the string
516 /// need not be null-terminated and may contain embedded null
517 /// characters.
519
520 /// Bind this string reference to the string at the specified `data`
521 /// address and extending for
522 /// `std::char_traits<CHAR_TYPE>::length(data)` characters. The string
523 /// at the `data` address must remain valid as long as it is bound to
524 /// this string reference. The behavior is undefined unless `data` is
525 /// null-terminated.
526 void assign(const CHAR_TYPE *data);
527
528 /// Bind this string reference to the specified `str` string. The
529 /// string indicated by `str` must remain valid as long as it is bound
530 /// to this object.
531 void assign(const bsl::basic_string<CHAR_TYPE>& str);
532
533 /// Modify this string reference to refer to the same string as the
534 /// specified `stringRef`. Note, that the string bound to `stringRef`
535 /// must remain valid as long as it is bound to this object.
536 void assign(const StringRefImp<CHAR_TYPE>& stringRef);
537
538 /// Reset this string reference to the default-constructed state having
539 /// an empty `std::string` value and the following attribute values:
540 /// @code
541 /// begin() == end()
542 /// isEmpty() == true
543 /// @endcode
544 void reset();
545
546 // ACCESSORS
547
548 /// Return a reference providing a non-modifiable access to the
549 /// character at the specified `index` in the string bound to this
550 /// reference. This reference remains valid as long as the string
551 /// currently bound to this object remains valid. The behavior is
552 /// undefined unless `0 <= index < length()`.
554
555 /// Return an `std::basic_string` (synonymous with
556 /// `std::basic_string`) having the value of the string bound to
557 /// this string reference.
558 operator std::basic_string<CHAR_TYPE>() const;
559
560 /// Return an STL-compatible iterator to the first character of the
561 /// string bound to this string reference or `end()` if the string
562 /// reference is empty. The iterator remains valid as long as this
563 /// object is valid and is bound to the same string.
564 const_iterator begin() const;
565
566 /// Return an STL-compatible iterator one-past-the-last character of the
567 /// string bound to this string reference or `begin()` if the string
568 /// reference is empty. The iterator remains valid as long as this
569 /// object is valid and is bound to the same string.
570 const_iterator end() const;
571
572 /// Return an STL-compatible reverse iterator to the last character of
573 /// the string bound to this string reference or `rend()` if the string
574 /// reference is empty. The iterator remains valid as long as this
575 /// object is valid and is bound to the same string.
577
578 /// Return an STL-compatible reverse iterator to the
579 /// prior-to-the-beginning character of the string bound to this string
580 /// reference or `rbegin()` if the string reference is empty. The
581 /// iterator remains valid as long as this object is valid and is bound
582 /// to the same string.
584
585 /// Return the address of the first character of the string bound to
586 /// this string reference such that `[data() .. data()+length())` is a
587 /// valid half-open range of characters. Note that the range of
588 /// characters might not be null-terminated and may contain embedded
589 /// null characters.
590 const CHAR_TYPE *data() const;
591
592 /// Return `true` if this object represents an empty string value, and
593 /// `false` otherwise. This object represents an empty string value if
594 /// `begin() == end()`. Note that this method is functionally identical
595 /// with the `isEmpty` method and allows developers to avoid distracting
596 /// syntax differences when `StringRef` appears in juxtaposition with
597 /// `string`, which defines `empty` but not `isEmpty`.
598 bool empty() const;
599
600 /// Return `true` if this object represents an empty string value, and
601 /// `false` otherwise. This object represents an empty string value if
602 /// `begin() == end()`.
603 bool isEmpty() const;
604
605 /// Return the length of the string referred to by this object. Note
606 /// that this call is equivalent to `end() - begin()`.
607 size_type length() const;
608
609 /// Return the number of characters in the string referred to by this
610 /// object. Note that this call is equivalent to `end() - begin()`.
611 size_type size() const;
612
613 /// Compare this and the specified `other` string objects using a
614 /// lexicographical comparison and return a negative value if this
615 /// string is less than `other` string, a positive value if this string
616 /// is greater than `other` string, and 0 if this string is equal to
617 /// `other` string.
618 int compare(const StringRefImp& other) const;
619};
620
621 // ===============================
622 // struct StringRefImp_CompareUtil
623 // ===============================
624
625/// [**PRIVATE**] This class provides a namespace for private comparison
626/// implementation functions.
628
629 // CLASS METHODS
630
631 /// Compare the specified string object `a` with the specified
632 /// null-terminated C-string `b` using a lexicographical comparison and
633 /// return a negative value if `a` is less than `b`, a positive value if
634 /// `a` is greater than `b`, and 0 if `a` is equal to `b`.
635 template <class CHAR_TYPE>
636 static
637 int compare(const StringRefImp<CHAR_TYPE>& a,
638 const CHAR_TYPE *b);
639
640 /// Return `true` if the specified `a` is equal to `b` and `false`
641 /// otherwise. Note that this function is more efficient than `compare`
642 /// for non-lexicographical equality comparisons.
643 template <class CHAR_TYPE>
644 static
646 const StringRefImp<CHAR_TYPE>& b);
647
648 /// Return `true` if the specified `a` is equal to the specified
649 /// null-terminated C-string `b` and `false` otherwise. Note that this
650 /// function is more efficient than `compare` for non-lexicographical
651 /// equality comparisons.
652 template <class CHAR_TYPE>
653 static
655 const CHAR_TYPE *b);
656};
657
658/// Return a `bsl::string` having the value of the concatenation of the
659/// strings referred to by the specified `lhs` and `rhs` values.
660template <class CHAR_TYPE>
663 const StringRefImp<CHAR_TYPE>& rhs);
664template <class CHAR_TYPE>
667 const StringRefImp<CHAR_TYPE>& rhs);
668template <class CHAR_TYPE>
672template <class CHAR_TYPE>
675 const std::basic_string<CHAR_TYPE>& rhs);
676template <class CHAR_TYPE>
678operator+(const std::basic_string<CHAR_TYPE>& lhs,
679 const StringRefImp<CHAR_TYPE>& rhs);
680template <class CHAR_TYPE>
682operator+(const CHAR_TYPE *lhs,
683 const StringRefImp<CHAR_TYPE>& rhs);
684template <class CHAR_TYPE>
687 const CHAR_TYPE *rhs);
688
689// FREE FUNCTIONS
690
691/// Pass the specified `input` to the specified `hashAlg`
692template <class CHAR_TYPE, class HASHALG>
693void hashAppend(HASHALG& hashAlg, const StringRefImp<CHAR_TYPE>& input);
694
695// ============================================================================
696// TYPEDEFS
697// ============================================================================
698
701
702// ============================================================================
703// INLINE FUNCTION DEFINITIONS
704// ============================================================================
705
706 // ------------------
707 // class StringRefImp
708 // ------------------
709
710// PRIVATE ACCESSOR
711template <class CHAR_TYPE>
712inline
714 std::basic_ostream<CHAR_TYPE>& stream) const
715{
716 if (data()) {
717 stream.write(data(), length());
718 }
719 else {
720 BSLS_ASSERT_SAFE(length() == 0);
721 }
722}
723
724// CREATORS
725template <class CHAR_TYPE>
726inline
731
732template <class CHAR_TYPE>
733template <class INT_TYPE>
734inline
736 const CHAR_TYPE *data,
737 INT_TYPE length,
739 bslmf::Nil>::type)
740: Base(data, data + length)
741{
744}
745
746template <class CHAR_TYPE>
747inline
749: Base(data, data + length)
750{
752}
753
754template <class CHAR_TYPE>
755inline
757: Base(begin, end)
758{
759 BSLS_ASSERT_SAFE((begin == 0) == (end == 0));
761}
762
763template <class CHAR_TYPE>
764inline
766: Base(data, data + Base::cStringLength(data))
767{
769}
770
771template <class CHAR_TYPE>
772inline
778
779template <class CHAR_TYPE>
780inline
782: Base(str.data(), str.data() + str.length())
783{
784}
785
786template <class CHAR_TYPE>
787inline
788StringRefImp<CHAR_TYPE>::StringRefImp(const std::basic_string<CHAR_TYPE>& str)
789: Base(str.data(), str.data() + str.length())
790{
791}
792
793#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
794template <class CHAR_TYPE>
795inline
797 const std::pmr::basic_string<CHAR_TYPE>& str)
798: Base(str.data(), str.data() + str.length())
799{
800}
801#endif
802
803template <class CHAR_TYPE>
804inline
806 const StringRefImp<CHAR_TYPE>& original,
807 size_type startIndex,
808 size_type numCharacters)
809: Base(original.begin() + startIndex,
810 original.begin() + startIndex +
811 std::min(numCharacters, original.length() - startIndex))
812{
813 BSLS_ASSERT_SAFE(startIndex <= original.length());
814}
815
816
817// MANIPULATORS
818template <class CHAR_TYPE>
819template <class INT_TYPE>
820inline
822 const CHAR_TYPE *data,
823 INT_TYPE length,
825 bslmf::Nil>::type)
826{
827 BSLS_ASSERT_SAFE(data || 0 == length);
828
829 *this = StringRefImp(data, data + length);
830}
831
832template <class CHAR_TYPE>
833inline
834void StringRefImp<CHAR_TYPE>::assign(const CHAR_TYPE *data, size_type length)
835{
836 BSLS_ASSERT_SAFE(data || 0 == length);
837
838 *this = StringRefImp(data, data + length);
839}
840
841template <class CHAR_TYPE>
842inline
844{
845 *this = StringRefImp(begin, end);
846}
847
848template <class CHAR_TYPE>
849inline
850void StringRefImp<CHAR_TYPE>::assign(const CHAR_TYPE *data)
851{
852 BSLS_ASSERT_SAFE(data);
853
854 *this = StringRefImp(
855 data,
856 data + std::char_traits<CHAR_TYPE>::length(data));
857}
858
859template <class CHAR_TYPE>
860inline
862{
863 *this = StringRefImp(str.data(), str.data() + str.length());
864}
865
866template <class CHAR_TYPE>
867inline
869{
870 *this = stringRef;
871}
872
873template <class CHAR_TYPE>
874inline
876{
877 *this = StringRefImp();
878}
879
880// ACCESSORS
881template <class CHAR_TYPE>
882inline
885{
886 BSLS_ASSERT_SAFE(index < length());
887
888 return begin()[index];
889}
890
891} // close package namespace
892
893template <class CHAR_TYPE>
894inline
895bslstl::StringRefImp<CHAR_TYPE>::operator std::basic_string<CHAR_TYPE>() const
896{
897 return std::basic_string<CHAR_TYPE>(begin(), end());
898}
899
900namespace bslstl {
901
902template <class CHAR_TYPE>
903inline
906{
907 return Base::data();
908}
909
910template <class CHAR_TYPE>
911inline
914{
915 return Base::data() + Base::size();
916}
917
918template <class CHAR_TYPE>
919inline
922{
923 return const_reverse_iterator(end());
924}
925
926template <class CHAR_TYPE>
927inline
930{
931 return const_reverse_iterator(begin());
932}
933
934template <class CHAR_TYPE>
935inline
936const CHAR_TYPE *StringRefImp<CHAR_TYPE>::data() const
937{
938 return begin();
939}
940
941template <class CHAR_TYPE>
942inline
944{
945 return begin() == end();
946}
947
948template <class CHAR_TYPE>
949inline
951{
952 return begin() == end();
953}
954
955template <class CHAR_TYPE>
956inline
959{
960 return end() - begin();
961}
962
963template <class CHAR_TYPE>
964inline
967{
968 return end() - begin();
969}
970
971template <class CHAR_TYPE>
972inline
974 const StringRefImp<CHAR_TYPE>& other) const
975{
976 // Note that, on some platforms but not others, if 'CHAR_TYPE' is signed,
977 // char_traits<CHAR_TYPE>::compare' casts the chars to their equivalent
978 // sized unsigned type before comparing them.
979
980 int result = std::char_traits<CHAR_TYPE>::compare(
981 this->data(),
982 other.data(),
983 std::min(this->length(), other.length()));
984
985 if (result == 0 && this->length() != other.length()) {
986 result = this->length() < other.length() ? -1 : 1;
987 }
988 return result;
989}
990
991 // ------------------------------
992 // class StringRefImp_CompareUtil
993 // ------------------------------
994
995template <class CHAR_TYPE>
997 const CHAR_TYPE *b)
998{
999 // Not inline.
1000
1001 typedef typename StringRefImp<CHAR_TYPE>::const_iterator const_iterator;
1002
1003 // Imitate the behavior of the other 'StringRefImp::compare' and
1004 // 'basic_string::privateCompareRaw' -- if one string is shorter, but they
1005 // match up to that point, the longer string is always greater, even if the
1006 // next character of the longer string has a negative value.
1007
1008 const const_iterator end = a.end();
1009 for (const_iterator pc = a.begin(); pc < end; ++pc, ++b) {
1010 if (0 == *b) {
1011 return +1; // RETURN
1012 }
1013
1014 if (*pc != *b) {
1015 // 'std::char_traits::compare' is a mess, usually
1016 // implemented with specialized templates, with behavior that
1017 // varies tremendously depending upon the platform, the compiler,
1018 // and 'CHAR_TYPE'. In theory, it should compare individual
1019 // characters with 'std::char_traits::lt', but in practice
1020 // that's very often not the case. Attempting to exactly
1021 // anticipate its behavior under all circumstances quickly turned
1022 // into a hopeless, brittle horror show of '#ifdef's and template
1023 // programming. So we delegate directly to
1024 // 'std::char_traits::compare' to compare individual
1025 // characters known to differ, guaranteeing that compares between
1026 // @ref basic_string s, 'StringRefImp's, and null-terminated 'const
1027 // CHAR_TYPE *'s all yield matching results.
1028
1029 return std::char_traits<CHAR_TYPE>::compare(pc,
1030 b,
1031 1); // RETURN
1032 }
1033 }
1034
1035 return *b ? -1 : 0;
1036}
1037
1038template <class CHAR_TYPE>
1039inline
1041 const StringRefImp<CHAR_TYPE>& b)
1042{
1043 return a.length() == b.length() &&
1044 (0 == a.length() ||
1045 0 == std::memcmp(
1046 a.data(), b.data(), a.length() * sizeof(CHAR_TYPE)));
1047}
1048
1049template <class CHAR_TYPE>
1051 const CHAR_TYPE *b)
1052{
1053 // Not inline.
1054
1055 typedef typename StringRefImp<CHAR_TYPE>::const_iterator const_iterator;
1056
1057 const const_iterator end = a.end();
1058 CHAR_TYPE c = *b;
1059 for (const_iterator pc = a.begin(); pc < end; ++pc, c = *++b) {
1060 if (0 == c || *pc != c) {
1061 return false; // RETURN
1062 }
1063 }
1064
1065 return 0 == c;
1066}
1067
1068} // close package namespace
1069
1070template <class CHAR_TYPE>
1072bslstl::operator+(const StringRefImp<CHAR_TYPE>& lhs,
1073 const StringRefImp<CHAR_TYPE>& rhs)
1074{
1076
1077 result.reserve(lhs.length() + rhs.length());
1078 result.assign(lhs.begin(), lhs.end());
1079 result.append(rhs.begin(), rhs.end());
1080
1081 return result;
1082}
1083
1084template <class CHAR_TYPE>
1085inline
1088 const StringRefImp<CHAR_TYPE>& rhs)
1089{
1090 return StringRefImp<CHAR_TYPE>(lhs) + rhs;
1091}
1092
1093template <class CHAR_TYPE>
1094inline
1096bslstl::operator+(const StringRefImp<CHAR_TYPE>& lhs,
1098{
1099 return lhs + StringRefImp<CHAR_TYPE>(rhs);
1100}
1101
1102template <class CHAR_TYPE>
1103inline
1105bslstl::operator+(const std::basic_string<CHAR_TYPE>& lhs,
1106 const StringRefImp<CHAR_TYPE>& rhs)
1107{
1108 return StringRefImp<CHAR_TYPE>(lhs) + rhs;
1109}
1110
1111template <class CHAR_TYPE>
1112inline
1114bslstl::operator+(const StringRefImp<CHAR_TYPE>& lhs,
1115 const std::basic_string<CHAR_TYPE>& rhs)
1116{
1117 return lhs + StringRefImp<CHAR_TYPE>(rhs);
1118}
1119
1120template <class CHAR_TYPE>
1121inline
1123bslstl::operator+(const CHAR_TYPE *lhs,
1124 const StringRefImp<CHAR_TYPE>& rhs)
1125{
1126 // We have to traverse `lhs` to know how much space to allocate in the
1127 // result anyway, so best to build a `StringRefImp` from it.
1128
1129 return StringRefImp<CHAR_TYPE>(lhs) + rhs;
1130}
1131
1132template <class CHAR_TYPE>
1133inline
1135bslstl::operator+(const StringRefImp<CHAR_TYPE>& lhs,
1136 const CHAR_TYPE *rhs)
1137{
1138 // We have to traverse `rhs` to know how much space to allocate in the
1139 // result anyway, so best to build a `StringRefImp` from it.
1140
1141 return lhs + StringRefImp<CHAR_TYPE>(rhs);
1142}
1143
1144template <class CHAR_TYPE, class HASHALG>
1145inline
1146void bslstl::hashAppend(HASHALG& hashAlg,
1147 const StringRefImp<CHAR_TYPE>& input)
1148{
1149 using ::BloombergLP::bslh::hashAppend;
1150 hashAlg(input.data(), sizeof(CHAR_TYPE)*input.length());
1151 hashAppend(hashAlg, input.length());
1152}
1153
1154#if defined(BSLS_COMPILERFEATURES_SUPPORT_EXTERN_TEMPLATE)
1155namespace bslstl {
1156extern template class bslstl::StringRefImp<char>;
1157extern template class bslstl::StringRefImp<wchar_t>;
1158
1159extern template
1161operator+(const StringRefImp<char>& lhs, const StringRefImp<char>& rhs);
1162
1163extern template
1165operator+(const StringRefImp<wchar_t>& lhs, const StringRefImp<wchar_t>& rhs);
1166
1167} // close package namespace
1168#endif
1169
1170
1171#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
1172// ============================================================================
1173// BACKWARD COMPATIBILITY
1174// ============================================================================
1175
1176#ifdef bslstl_StringRefImp
1177#undef bslstl_StringRefImp
1178#endif
1179/// This alias is defined for backward compatibility.
1180#define bslstl_StringRefImp bslstl::StringRefImp
1181
1182#ifdef bslstl_StringRefWide
1183#undef bslstl_StringRefWide
1184#endif
1185/// This alias is defined for backward compatibility.
1186#define bslstl_StringRefWide bslstl::StringRefWide
1187
1188#ifdef bslstl_StringRef
1189#undef bslstl_StringRef
1190#endif
1191/// This alias is defined for backward compatibility.
1192#define bslstl_StringRef bslstl::StringRef
1193#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
1194
1195
1196#endif
1197
1198// ----------------------------------------------------------------------------
1199// Copyright 2019 Bloomberg Finance L.P.
1200//
1201// Licensed under the Apache License, Version 2.0 (the "License");
1202// you may not use this file except in compliance with the License.
1203// You may obtain a copy of the License at
1204//
1205// http://www.apache.org/licenses/LICENSE-2.0
1206//
1207// Unless required by applicable law or agreed to in writing, software
1208// distributed under the License is distributed on an "AS IS" BASIS,
1209// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1210// See the License for the specific language governing permissions and
1211// limitations under the License.
1212// ----------------------------- END-OF-FILE ----------------------------------
1213
1214/** @} */
1215/** @} */
1216/** @} */
Definition bslstl_stringview.h:441
Definition bslstl_string.h:1281
size_type length() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6601
void reserve(size_type newCapacity=0)
Definition bslstl_string.h:5407
basic_string & assign(const basic_string &replacement)
Definition bslstl_string.h:5716
CHAR_TYPE * data() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6477
basic_string & append(const basic_string &suffix)
Definition bslstl_string.h:5574
Definition bslstl_stringrefdata.h:212
Definition bslstl_stringref.h:372
const CHAR_TYPE & const_reference
Definition bslstl_stringref.h:382
bsl::reverse_iterator< const_iterator > const_reverse_iterator
Definition bslstl_stringref.h:385
bool empty() const
Definition bslstl_stringref.h:943
BSLMF_NESTED_TRAIT_DECLARATION(StringRefImp, bsl::is_trivially_copyable)
size_type size() const
Definition bslstl_stringref.h:966
void reset()
Definition bslstl_stringref.h:875
const_reverse_iterator rend() const
Definition bslstl_stringref.h:929
std::ptrdiff_t difference_type
Definition bslstl_stringref.h:386
const_reference operator[](size_type index) const
Definition bslstl_stringref.h:884
StringRefImp(const StringRefImp &original)=default
const CHAR_TYPE & reference
Definition bslstl_stringref.h:381
int compare(const StringRefImp &other) const
Definition bslstl_stringref.h:973
const CHAR_TYPE * const_iterator
Definition bslstl_stringref.h:384
const CHAR_TYPE * data() const
Definition bslstl_stringref.h:936
const CHAR_TYPE value_type
Definition bslstl_stringref.h:380
const_iterator end() const
Definition bslstl_stringref.h:913
bool isEmpty() const
Definition bslstl_stringref.h:950
StringRefImp()
Definition bslstl_stringref.h:727
const CHAR_TYPE * iterator
Definition bslstl_stringref.h:383
size_type length() const
Definition bslstl_stringref.h:958
void assign(const CHAR_TYPE *data, INT_TYPE length, typename bsl::enable_if< bsl::is_integral< INT_TYPE >::value, bslmf::Nil >::type=bslmf::Nil())
Definition bslstl_stringref.h:821
~StringRefImp()=default
Destroy this object.
StringRefImp & operator=(const StringRefImp &rhs)=default
std::size_t size_type
Standard Library general container requirements.
Definition bslstl_stringref.h:389
const_reverse_iterator rbegin() const
Definition bslstl_stringref.h:921
const_iterator begin() const
Definition bslstl_stringref.h:905
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
void hashAppend(HASH_ALGORITHM &hashAlg, const baljsn::EncoderTestAddress &object)
Definition baljsn_encoder_testtypes.h:9236
Definition bslstl_algorithm.h:82
StringRefImp< char > StringRef
Definition bslstl_stringref.h:699
RandomAccessIterator< T, ITER_IMP, TAG_TYPE > operator+(const RandomAccessIterator< T, ITER_IMP, TAG_TYPE > &lhs, std::ptrdiff_t rhs)
void hashAppend(HASHALG &hashAlg, const StringRefImp< CHAR_TYPE > &input)
Pass the specified input to the specified hashAlg
StringRefImp< wchar_t > StringRefWide
Definition bslstl_stringref.h:700
Definition bdldfp_decimal.h:5188
Definition bslmf_enableif.h:525
Definition bslmf_isintegral.h:130
Definition bslmf_istriviallycopyable.h:329
This struct is empty and represents a nil type.
Definition bslmf_nil.h:131
Definition bslstl_stringref.h:627
static int compare(const StringRefImp< CHAR_TYPE > &a, const CHAR_TYPE *b)
Definition bslstl_stringref.h:996
static bool compareEqual(const StringRefImp< CHAR_TYPE > &a, const StringRefImp< CHAR_TYPE > &b)
Definition bslstl_stringref.h:1040