Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bslstl_stringref
[Package bslstl]

Provide a reference to a const string. More...

Namespaces

namespace  bslstl

Detailed Description

Outline
Purpose:
Provide a reference to a const string.
Classes:
bslstl::StringRefImp reference wrapper for a generic string
bslstl::StringRef reference wrapper for a char string
bslstl::StringRefWide reference wrapper for a wchar_t string
See also:
Component bdlb_stringrefutil
Description:
This component defines two classes, bslstl::StringRef and bslstl::StringRefWide, each providing a reference to a non-modifiable string value having an external representation. The type of characters in the string value can be either char (for bslstl::StringRef) or wchar_t (for bslstl::StringRefWide).
The invariant of bslstl::StringRef is that it always has a valid non-modifiable std::string value, where non-empty string values have an external representation. Empty string values do not need to have an external representation. Most operations on bslstl::StringRef objects have reference semantics and apply to the string value: e.g., operator== compares string values, not whether bslstl::StringRef objects reference the same string object.
The only operations that do not apply to the string value (i.e., that have pointer semantics) are copy construction and assignment. These operations produce a bslstl::StringRef object with the same external representation as the original bslstl::StringRef object, which is a stronger post-condition than having operator== return true for two bslstl::StringRef objects that have the same value.
The standard notion of substitutability defined by the operator== does not necessarily apply to bslstl::StringRef since bslstl::StringRef is not a value-semantic type (because of the external representation). Therefore there can be a plausible sequence of operations applied to two "equal" bslstl::StringRef objects that result in objects that don't compare equal.
The string value that is represented by a bslstl::StringRef object need not be null-terminated. Moreover, the string may contain embedded null characters. As such, the string referenced by bslstl::StringRef, in general, is not a C-style string. Moreover, the notion of a null-string value is not supported.
The address of the string referenced by bslstl::StringRef is indicated by the data accessor. Its extent is indicated by the length and size accessors. The referenced string is also indicated by the begin and end accessors that return STL-compatible iterators to the beginning of the string and one character past the end of the string, respectively. An overloaded operator[] is also provided for direct by-index access to individual characters in the string.
Several overloaded free operators are provided for bslstl::StringRef objects (as well as variants for all combinations involving bslstl::StringRef and std::string, and bslstl::StringRef and char *) for (1) lexicographic comparison of values, and (2) concatenation of values (producing an std::string); also provided is an overloaded free operator<< for writing the value of a bslstl::StringRef object to a specified output stream.
The bsl::hash template class is specialized for bslstl::StringRef to enable the use of bslstl::StringRef with STL hash containers (e.g., bsl::unordered_set and bsl::unordered_map).
How to include bslstl::StringRef:
To include bslstl::StringRef use #include <bsl_string.h> (not #include <bslstl_stringref.h>).
Efficiency and Usage Considerations:
Using bslstl::StringRef to pass strings as function arguments can be considerably more efficient than passing bsl::string objects by const reference. First, consider a hypothetical class method in which the parameter is a reference to a non-modifiable bsl::string:
  void MyClass::setLabel(const bsl::string& label)
  {
      d_label = label;  // 'MyClass::d_label' is of type 'bsl::string'
  }
Then, consider a typical call to this method:
  MyClass myClassObj;
  myClassObj.setLabel("hello");
As a side-effect of this call, a temporary bsl::string containing a copy of "hello" is created (using the default allocator), that value is copied to d_label, and the temporary is eventually destroyed. The call thus requires the string data to be copied twice (as well as a possible allocation and deallocation).
Next, consider the same method taking a reference to a non-modifiable bslstl::StringRef:
  void MyClass::setLabel(const bslstl::StringRef& label)
  {
      d_label.assign(label.begin(), label.end());
  }
Now:
  myClassObj.setLabel("hello");
This call has the side-effect of creating a temporary bslstl::StringRef object, which is likely to be more efficient than creating a temporary bsl::string (even when implemented using the short-string optimization). In this case, instead of copying the contents of "hello", the address of the literal string is copied. In addition, bsl::strlen is applied to the string in order to locate its end. There are no allocations done on behalf of the temporary object.
Caveats:
1) The string referenced by bslstl::StringRef need not be null-terminated, and, in fact, may contain embedded null characters. Thus, it is generally not valid to pass the address returned by the data accessor to Standard C functions that expect a null-terminated string (e.g., std::strlen, std::strcmp, etc.).
2) The string referenced by bslstl::StringRef must remain valid as long as the bslstl::StringRef references that string. Lifetime issues should be carefully considered when, for example, returning a bslstl::StringRef object from a function or storing a bslstl::StringRef object in a container.
3) Passing a null string to any function (e.g., operator==) without also passing a 0 length results in undefined behavior.
Usage:
This section illustrates intended use of this component.
Example 1: Basic Operations:
The following snippets of code illustrate basic and varied use of the bslstl::StringRef class.
First, we define a function, getNumBlanks, that returns the number of blank (' ') characters contained in the string referenced by a specified bslstl::StringRef:
  #include <algorithm>

   bslstl::StringRef::size_type
   getNumBlanks(const bslstl::StringRef& stringRef)
      // Return the number of blank (' ') characters in the string referenced
      // by the specified 'stringRef'.
  {
      return std::count(stringRef.begin(), stringRef.end(), ' ');
  }
Notice that the function delegates the work to the std::count STL algorithm. This delegation is made possible by the STL-compatible iterators provided by the begin and end accessors.
Then, call getNumBlanks on a default constructed bslstl::StringRef:
  bslstl::StringRef            emptyRef;
  bslstl::StringRef::size_type numBlanks = getNumBlanks(emptyRef);
  assert(0 == numBlanks);

  assert(""         == emptyRef);
  assert("anything" >= emptyRef);
Notice that the behavior a default constructed bslstl::StringRef object behaves the same as if it referenced an empty string.
Next, we (implicitly) construct a bsl::string object from bslstl::StringRef:
  bsl::string empty(emptyRef);
  assert(0 == empty.size());
Then, we call getNumBlanks on a string literal and assert that the number of blanks returned is as expected:
  numBlanks = getNumBlanks("Good things come to those who wait.");
  assert(6 == numBlanks);
Next, we define a longer string literal, poem, that we will use in the rest of this usage example:
  const char poem[] =                  // by William Butler Yeats (1865-1939)
      |....5....|....5....|....5....|....5....|   //  length  blanks
                                                  //
      "O love is the crooked thing,\n"            //    29      5
      "There is nobody wise enough\n"             //    28      4
      "To find out all that is in it,\n"          //    31      7
      "For he would be thinking of love\n"        //    33      6
      "Till the stars had run away\n"             //    28      5
      "And the shadows eaten the moon.\n"         //    32      5
      "Ah, penny, brown penny, brown penny,\n"    //    37      5
      "One cannot begin it too soon.";            //    29      5
                                                  //          ----
                                                  //    total: 42

  numBlanks = getNumBlanks(poem);
  assert(42 == numBlanks);
Then, we construct a bslstl::StringRef object, line, that refers to only the first line of the poem:
  bslstl::StringRef line(poem, 29);
  numBlanks = getNumBlanks(line);

  assert( 5 == numBlanks);
  assert(29 == line.length());
  assert( 0 == std::strncmp(poem, line.data(), line.length()));
Next, we use the assign method to make line refer to the second line of the poem:
  line.assign(poem + 29, poem + 57);
  numBlanks = getNumBlanks(line);
  assert(4 == numBlanks);
  assert((57 - 29) == line.length());
  assert("There is nobody wise enough\n" == line);
Then, we call getNumBlanks with a bsl::string initialized to the contents of the poem:
  const bsl::string poemString(poem);
  numBlanks = getNumBlanks(poemString);
  assert(42 == numBlanks);
  assert(bslstl::StringRef(poemString) == poemString);
  assert(bslstl::StringRef(poemString) == poemString.c_str());
Next, we make a bslstl::StringRef object that refers to a string that will be able to hold embedded null characters:
  char poemWithNulls[512];
  const bsl::size_t poemLength = std::strlen(poem);
  assert(poemLength < 512);

  std::memcpy(poemWithNulls, poem, poemLength + 1);
  assert(0 == std::strcmp(poem, poemWithNulls));
Now, we replace each occurrence of a \n in poemWithNulls with a yielding \0:
  std::replace(poemWithNulls, poemWithNulls + poemLength, '\n', '\0');
  assert(0 != std::strcmp(poem, poemWithNulls));
Finally, we observe that poemWithNulls has the same number of blank characters as the original poem:
  numBlanks = getNumBlanks(bslstl::StringRef(poemWithNulls, poemLength));
  assert(42 == numBlanks);