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