BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlb_stringviewutil.h
Go to the documentation of this file.
1/// @file bdlb_stringviewutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlb_stringviewutil.h -*-C++-*-
8#ifndef INCLUDED_BDLB_STRINGVIEWUTIL
9#define INCLUDED_BDLB_STRINGVIEWUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlb_stringviewutil bdlb_stringviewutil
15/// @brief Provide utility functions on `bsl::string_view` containers.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlb
19/// @{
20/// @addtogroup bdlb_stringviewutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlb_stringviewutil-purpose"> Purpose</a>
25/// * <a href="#bdlb_stringviewutil-classes"> Classes </a>
26/// * <a href="#bdlb_stringviewutil-description"> Description </a>
27/// * <a href="#bdlb_stringviewutil-synopsis-of-bsl-string_view"> Synopsis of bsl::string_view </a>
28/// * <a href="#bdlb_stringviewutil-function-synopsis"> Function Synopsis </a>
29/// * <a href="#bdlb_stringviewutil-character-encoding"> Character Encoding </a>
30/// * <a href="#bdlb_stringviewutil-caseless-comparisons"> Caseless Comparisons </a>
31/// * <a href="#bdlb_stringviewutil-whitespace-character-specification"> Whitespace Character Specification </a>
32/// * <a href="#bdlb_stringviewutil-usage"> Usage </a>
33/// * <a href="#bdlb_stringviewutil-example-1-trimming-whitespace"> Example 1: Trimming Whitespace </a>
34///
35/// # Purpose {#bdlb_stringviewutil-purpose}
36/// Provide utility functions on `bsl::string_view` containers.
37///
38/// # Classes {#bdlb_stringviewutil-classes}
39///
40/// - bdlb::StringViewUtil: namespace for functions on @ref string_view containers
41///
42/// @see bslstl_stringview
43///
44/// # Description {#bdlb_stringviewutil-description}
45/// This component defines a utility `struct`,
46/// `bdlb::StringViewUtil`, that provides a suite of functions that operate on
47/// `bsl::string_view` containers.
48///
49/// ## Synopsis of bsl::string_view {#bdlb_stringviewutil-synopsis-of-bsl-string_view}
50///
51///
52/// The `bsl::string_view` class provides `bsl::string`-like access to an array
53/// of bytes that need not be null terminated and that can have non-ASCII values
54/// (i.e., `[128 .. 255]`). Although a `bsl::string_view` object can itself be
55/// changed, it cannot change its referent data (the array of bytes). The
56/// lifetime of the referent data must exceed that of all `bsl::string_view`
57/// objects referring to it. Equality comparison of `bsl::string_view` objects
58/// compares the content of the referent data (not whether or not the object
59/// refer to the same array of bytes). See @ref bslstl_stringview for full
60/// details.
61///
62/// ## Function Synopsis {#bdlb_stringviewutil-function-synopsis}
63///
64///
65/// The table below provides an outline of the functions provided by this
66/// component.
67/// @code
68/// Function Purpose
69/// -------------------------- ------------------------------------------------
70/// areEqualCaseless(SV, SV) case-insensitive equality comparison
71/// lowerCaseCmp (SV, SV) lexical comparison of lower-case conversion
72/// upperCaseCmp (SV, SV) lexical comparison of upper-case conversion
73///
74/// ltrim(SV) exclude whitespace from left side of string
75/// rtrim(SV) exclude whitespace from right side of string
76/// trim(SV) exclude whitespace from both sides of string
77///
78/// substr(SV, pos, num) substring, `num` characters from `pos`
79///
80/// strstr (SV, SUBSV) find first substring in string
81/// strstrCaseless (SV, SUBSV) find first substring in string, case insensitive
82/// strrstr (SV, SUBSV) find last substring in string
83/// strrstrCaseless(SV, SUBSV) find last substring in string, case insensitive
84///
85/// findFirstOf (SV, ch, p) find first occurrence of any character from `ch`
86/// findLastOf (SV, ch, p) find last occurrence of any character from `ch`
87/// findFirstNotOf(SV, ch, p) find first occurrence of any char not from `ch`
88/// findLastNotOf (SV, ch, p) find last occurrence of any char not from `ch`
89///
90/// startsWith(SV, ch) find out if string starts with `ch`
91/// endsWith(SV, ch) find out if string ends with `ch`
92/// @endcode
93/// Since `bsl::string_view` objects know the length of the referent data these
94/// utility functions can make certain performance improvements over the
95/// classic, similarly named C language functions.
96///
97/// ## Character Encoding {#bdlb_stringviewutil-character-encoding}
98///
99///
100/// These utilities assume ASCII encoding for character data when doing case
101/// conversions and when determining if a character is in the whitespace
102/// character set.
103///
104/// ### Caseless Comparisons {#bdlb_stringviewutil-caseless-comparisons}
105///
106///
107/// Caseless (i.e., case-insensitive) comparisons treat characters in the
108/// sequence `[a .. z]` as equivalent to the respective characters in the
109/// sequence `[A .. Z]`. This equivalence matches that of `bsl::toupper`.
110///
111/// ### Whitespace Character Specification {#bdlb_stringviewutil-whitespace-character-specification}
112///
113///
114/// The following characters are classified as "whitespace":
115/// @code
116/// Character Description
117/// --------- ---------------
118/// ' ' blank-space
119/// '\f' form-feed
120/// '\n' newline
121/// '\r' carriage return
122/// '\t' horizontal tab
123/// '\v' vertical tab
124/// @endcode
125/// This classification matches that of `bsl::isspace`.
126///
127/// ## Usage {#bdlb_stringviewutil-usage}
128///
129///
130/// This section illustrates the intended use of this component.
131///
132/// ### Example 1: Trimming Whitespace {#bdlb_stringviewutil-example-1-trimming-whitespace}
133///
134///
135/// Many applications must normalize user input by removing leading and trailing
136/// whitespace characters to obtain the essential text that is the intended
137/// input. Naturally, one would prefer to do this as efficiently as possible.
138///
139/// Suppose the response entered by a user is captured in `rawInput` below:
140/// @code
141/// const char * const rawInput = " \t\r\n Hello, world! \r\n";
142/// //1234 5 6 789 1234 5 6
143/// // 123456789ABCD
144/// // Note lengths of whitespace and
145/// // non-whitespace substrings for later.
146/// @endcode
147/// First, for this pedagogical example, we copy the contents at `rawInput` for
148/// later reference:
149/// @code
150/// const bsl::string copyRawInput(rawInput);
151/// @endcode
152/// Then, we create a `bsl::string_view` object referring to the raw data.
153/// Given a single argument of `const char *`, the constructor assumes the data
154/// is a null-terminated string and implicitly calculates the length for the
155/// reference:
156/// @code
157/// bsl::string_view text(rawInput);
158///
159/// assert(rawInput == text.data());
160/// assert(9 + 13 + 6 == text.length());
161/// @endcode
162/// Now, we invoke the `bdlb::StringViewUtil::trim` method to find the "Hello,
163/// world!" sequence in `rawInput`.
164/// @code
165/// bsl::string_view textOfInterest = bdlb::StringViewUtil::trim(text);
166/// @endcode
167/// Finally, we observe the results:
168/// @code
169/// assert(bsl::string_view("Hello, world!") == textOfInterest);
170/// assert(13 == textOfInterest.length());
171///
172/// assert(text.data() + 9 == textOfInterest.data());
173/// assert(text.length() - 9 - 6 == textOfInterest.length());
174///
175/// assert(rawInput == copyRawInput);
176/// @endcode
177/// Notice that, as expected, the `textOfInterest` object refers to the "Hello,
178/// world!" sub-sequence within the `rawInput` byte array while the data at
179/// `rawInput` remains *unchanged*.
180/// @}
181/** @} */
182/** @} */
183
184/** @addtogroup bdl
185 * @{
186 */
187/** @addtogroup bdlb
188 * @{
189 */
190/** @addtogroup bdlb_stringviewutil
191 * @{
192 */
193
194#include <bdlscm_version.h>
195
196#include <bsls_review.h>
197
198#include <bsl_algorithm.h> // bsl::min
199#include <bsl_string_view.h>
200
201
202namespace bdlb {
203 // =====================
204 // struct StringViewUtil
205 // =====================
206
207/// This `struct` provides a namespace for a suite of functions on
208/// `bsl::string_view` containers.
209///
210/// See @ref bdlb_stringviewutil
212
213 // PUBLIC TYPES
214
215 /// Size type of string_view containers.
217
218 // PUBLIC CLASS DATA
219
220 /// Value used to denote "not-a-position", guaranteed to be outside the
221 /// `range[0 .. bsl::string_view::max_size()]`.
223
224 // CLASS METHODS
225 // Comparison
226
227 /// Compare (the referent data of) the specified `lhs` and `rhs`.
228 /// Return `true` if `lhs` and `rhs` are equal up to a case conversion,
229 /// and `false` otherwise. See {Caseless Comparisons}.
230 static bool areEqualCaseless(const bsl::string_view& lhs,
231 const bsl::string_view& rhs);
232
233 /// Compare (the referent data of) the specified `lhs` and `rhs`.
234 /// Return 1 if, after a conversion to lower case, `lhs` is greater than
235 /// `rhs`, 0 if `lhs` and `rhs` are equal up to a case conversion, and
236 /// -1 otherwise. See {Caseless Comparisons}.
237 static int lowerCaseCmp(const bsl::string_view& lhs,
238 const bsl::string_view& rhs);
239
240 /// Compare (the referent data of) the specified `lhs` and `rhs`.
241 /// Return 1 if, after a conversion to upper case, `lhs` is greater than
242 /// `rhs`, 0 if `lhs` and `rhs` are equal up to a case conversion, and
243 /// -1 otherwise. See {Caseless Comparisons}.
244 static int upperCaseCmp(const bsl::string_view& lhs,
245 const bsl::string_view& rhs);
246
247 // Trim
248
249 /// Return a `bsl::string_view` object referring to the substring of
250 /// (the referent data of) the specified `string` that excludes all
251 /// leading whitespace. See {Whitespace Character Specification}. If
252 /// `string` consists entirely of whitespace, return a zero-length
253 /// reference to the end of `string` (i.e.,
254 /// `bsl::string_view(string.end(), 0)`).
256
257 /// Return a `bsl::string_view` object referring to the substring of
258 /// (the referent data of) the specified `string` that excludes all
259 /// trailing whitespace. See {Whitespace Character Specification}. If
260 /// `string` consists entirely of whitespace, return a zero-length
261 /// reference to the beginning of (the referent data of) `string`
262 /// (i.e., `bsl::string_view(string.data(), 0)`).
264
265 /// Return a `bsl::string_view` object referring to the substring of
266 /// (the referent data of) the specified `string` that excludes all
267 /// leading and trailing whitespace. See {Whitespace Character
268 /// Specification}. If `string` consists entirely of whitespace, return
269 /// a zero-length reference to the beginning of (the referent data of)
270 /// `string` (i.e., `bsl::string_view(string.data(), 0)`).
271 static bsl::string_view trim(const bsl::string_view& string);
272
273 // Create `subString`
274
275 /// Return a string whose value is the substring starting at the
276 /// optionally specified `position` in the specified `string`, of length
277 /// the optionally specified `numChars` or `length() - position`,
278 /// whichever is smaller. If `position` is not specified, 0 is used
279 /// (i.e., the substring is from the beginning of this string). If
280 /// `numChars` is not specified, `k_NPOS` is used (i.e., the entire
281 /// suffix from `position` to the end of the string is returned).
282 ///
283 /// \pre The behavior is undefined unless `position` is within the string
284 /// boundaries (`0 <= position <= string.length()`).
285 static bsl::string_view substr(const bsl::string_view& string,
286 size_type position = 0,
287 size_type numChars = k_NPOS);
288
289 // Find `subString`
290
291 /// Return a `bsl::string_view` object referring to the first occurrence
292 /// in (the referent data of) the specified `string` at which (the
293 /// referent data of) the specified `subString` is found, or
294 /// `bsl::string_view()` if there is no such occurrence. If `subString`
295 /// has zero length then a zero-length reference to the beginning of
296 /// `string` is returned (i.e., `bsl::string_view(string.data(), 0)`);
298 const bsl::string_view& subString);
299
300 /// Return a `bsl::string_view` object referring to the first occurrence
301 /// in (the referent data of) the specified `string` at which (the
302 /// referent data of) the specified `subString` is found using
303 /// case-insensitive comparisons, or `bsl::string_view()` if there is no
304 /// such occurrence. See {Caseless Comparisons}. If `subString` has
305 /// zero length then a zero-length reference to the beginning of
306 /// `string` is returned (i.e., `bsl::string_view(string.data(), 0)`);
308 const bsl::string_view& subString);
309
310 /// Return a `bsl::string_view` object referring to the last occurrence
311 /// in (the referent data of) the specified `string` at which (the
312 /// referent data of) the specified `subString` is found, or
313 /// `bsl::string_view()` if there is no such occurrence. If `subString`
314 /// has zero length then a zero-length reference to the end of `string`
315 /// is returned (i.e., `bsl::string_view(string.end(), 0)`);
317 const bsl::string_view& subString);
318
319 /// Return a `bsl::string_view` object referring to the last occurrence
320 /// in (the referent data of) the specified `string` at which (the
321 /// referent data of) the specified `subString` is found using
322 /// case-insensitive comparisons, or `bsl::string_view()` if there is no
323 /// such occurrence. See {Caseless Comparisons}. If `subString` has
324 /// zero length then a zero-length reference to the end of `string` is
325 /// returned (i.e., `bsl::string_view(string.end(), 0)`);
327 const bsl::string_view& subString);
328
329 // Find first/last of/not of
330
331 /// Return the position of the *first* occurrence of a character
332 /// belonging to the specified `characters`, if such an occurrence can
333 /// can be found in the specified `string` (on or *after* the optionally
334 /// specified `position` if such a `position` is specified), and return
335 /// `k_NPOS` otherwise.
337 const bsl::string_view& characters,
338 size_type position = 0);
339
340 /// Return the position of the *last* occurrence of a character
341 /// belonging to the specified `characters`, if such an occurrence can
342 /// can be found in the specified `string` (on or *before* the
343 /// optionally specified `position` if such a `position` is specified),
344 /// and return `k_NPOS` otherwise.
346 const bsl::string_view& characters,
347 size_type position = k_NPOS);
348
349 /// Return the position of the *first* occurrence of a character *not*
350 /// belonging to the specified `characters`, if such an occurrence can
351 /// be found in the specified `string` (on or *after* the optionally
352 /// specified `position` if such a `position` is specified), and return
353 /// `k_NPOS` otherwise.
355 const bsl::string_view& characters,
356 size_type position = 0);
357
358 /// Return the position of the *last* occurrence of a character *not*
359 /// belonging to the specified `characters`, if such an occurrence can
360 /// be found in the specified `string` (on or *before* the optionally
361 /// specified `position` if such a `position` is specified), and return
362 /// `k_NPOS` otherwise.
364 const bsl::string_view& characters,
365 size_type position = k_NPOS);
366
367 // Starts/ends with
368
369 /// Return `true` if the specified `string` begins with the specified
370 /// `characters`, and `false` otherwise.
371 static bool startsWith(const bsl::string_view& string,
372 const bsl::string_view& characters);
373 static bool startsWith(const bsl::string_view& string,
374 const char *characters);
375
376 /// Return `true` if the specified `string` begins with the specified
377 /// `character`, and `false` otherwise.
378 static bool startsWith(const bsl::string_view& string, char character);
379
380 /// Return `true` if the specified `string` ends with the specified
381 /// `characters`, and `false` otherwise.
382 static bool endsWith(const bsl::string_view& string,
383 const bsl::string_view& characters);
384 static bool endsWith(const bsl::string_view& string,
385 const char *characters);
386
387 /// Return `true` if the specified `string` ends with the specified
388 /// `character`, and `false` otherwise.
389 static bool endsWith(const bsl::string_view& string, char character);
390};
391
392// ============================================================================
393// INLINE DEFINITIONS
394// ============================================================================
395
396 // ---------------------
397 // struct StringViewUtil
398 // ---------------------
399
400// CLASS METHODS
401
402 // Comparison
403
404inline
406 const bsl::string_view& rhs)
407{
408 if (lhs.length() != rhs.length()) {
409 return false; // RETURN
410 }
411
412 return 0 == lowerCaseCmp(lhs, rhs);
413}
414
415 // Trim
416
417inline
419{
420 return ltrim(rtrim(string));
421}
422
423 // Substring
424
425inline
427 size_type position,
428 size_type numChars)
429{
430 BSLS_ASSERT(position <= string.length());
431
432 return bsl::string_view(string.data() + position,
433 bsl::min(numChars, string.length() - position));
434}
435
436 // Starts/ends with
437
438inline
440 const bsl::string_view& characters)
441{
442 if (characters.length() > string.length()) {
443 return false; // RETURN
444 }
445 return characters == bsl::string_view(string.data(), characters.length());
446}
447
448inline
450 const char *characters)
451{
452 BSLS_ASSERT_SAFE(characters);
453
454 const char *nextChar = characters;
455 bsl::string_view::const_iterator stringIt = string.begin();
456 while (stringIt != string.end()) {
457 if (0 == *nextChar) {
458 return true; // RETURN
459 }
460 if (*nextChar != *stringIt) {
461 return false; // RETURN
462 }
463 ++stringIt;
464 ++nextChar;
465 }
466 return 0 == *nextChar;
467}
468
469inline
470bool StringViewUtil::startsWith(const bsl::string_view& string, char character)
471{
472 return (!string.empty() && character == string.front());
473}
474
475inline
477 const bsl::string_view& characters)
478{
479 if (string.length() < characters.length()) {
480 return false; // RETURN
481 }
482
483 bsl::string_view::size_type pos = string.length() - characters.length();
484 return 0 == bsl::string_view::traits_type::compare(string.data() + pos,
485 characters.data(),
486 characters.length());
487}
488
489inline
491 const char *characters)
492{
493 BSLS_ASSERT_SAFE(characters);
494
495 return endsWith(string, bsl::string_view(characters));
496}
497
498inline
499bool StringViewUtil::endsWith(const bsl::string_view& string, char character)
500{
501 return (!string.empty() && character == string.back());
502}
503
504} // close package namespace
505
506
507#endif
508
509// ----------------------------------------------------------------------------
510// Copyright 2020 Bloomberg Finance L.P.
511//
512// Licensed under the Apache License, Version 2.0 (the "License"); you may not
513// use this file except in compliance with the License. You may obtain a copy
514// of the License at
515//
516// http://www.apache.org/licenses/LICENSE-2.0
517//
518// Unless required by applicable law or agreed to in writing, software
519// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
520// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
521// License for the specific language governing permissions and limitations
522// under the License.
523// ----------------------------- END-OF-FILE ----------------------------------
524
525/** @} */
526/** @} */
527/** @} */
Definition bslstl_stringview.h:471
std::size_t size_type
Definition bslstl_stringview.h:487
BSLS_KEYWORD_CONSTEXPR size_type length() const BSLS_KEYWORD_NOEXCEPT
Return the length of this view.
Definition bslstl_stringview.h:1913
BSLS_KEYWORD_CONSTEXPR const_pointer data() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stringview.h:1988
BSLS_KEYWORD_CONSTEXPR_CPP17 int compare(basic_string_view other) const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stringview.h:2046
static const size_type npos
Definition bslstl_stringview.h:495
const value_type * const_iterator
Definition bslstl_stringview.h:481
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#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
Definition bdlb_algorithmworkaroundutil.h:74
basic_string_view< char > string_view
Definition bslstl_stringview.h:1253
Definition bdlb_stringviewutil.h:211
static size_type findFirstNotOf(const bsl::string_view &string, const bsl::string_view &characters, size_type position=0)
static const size_type k_NPOS
Definition bdlb_stringviewutil.h:222
static bsl::string_view rtrim(const bsl::string_view &string)
static int lowerCaseCmp(const bsl::string_view &lhs, const bsl::string_view &rhs)
static bsl::string_view ltrim(const bsl::string_view &string)
bsl::string_view::size_type size_type
Size type of string_view containers.
Definition bdlb_stringviewutil.h:216
static size_type findLastNotOf(const bsl::string_view &string, const bsl::string_view &characters, size_type position=k_NPOS)
static bsl::string_view strrstr(const bsl::string_view &string, const bsl::string_view &subString)
static bsl::string_view strrstrCaseless(const bsl::string_view &string, const bsl::string_view &subString)
static bsl::string_view substr(const bsl::string_view &string, size_type position=0, size_type numChars=k_NPOS)
Definition bdlb_stringviewutil.h:426
static size_type findLastOf(const bsl::string_view &string, const bsl::string_view &characters, size_type position=k_NPOS)
static int upperCaseCmp(const bsl::string_view &lhs, const bsl::string_view &rhs)
static bool areEqualCaseless(const bsl::string_view &lhs, const bsl::string_view &rhs)
Definition bdlb_stringviewutil.h:405
static bool startsWith(const bsl::string_view &string, const bsl::string_view &characters)
Definition bdlb_stringviewutil.h:439
static bsl::string_view trim(const bsl::string_view &string)
Definition bdlb_stringviewutil.h:418
static bool endsWith(const bsl::string_view &string, const bsl::string_view &characters)
Definition bdlb_stringviewutil.h:476
static size_type findFirstOf(const bsl::string_view &string, const bsl::string_view &characters, size_type position=0)
static bsl::string_view strstrCaseless(const bsl::string_view &string, const bsl::string_view &subString)
static bsl::string_view strstr(const bsl::string_view &string, const bsl::string_view &subString)