BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlb_indexspan.h
Go to the documentation of this file.
1/// @file bdlb_indexspan.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlb_indexspan.h -*-C++-*-
8#ifndef INCLUDED_BDLB_INDEXSPAN
9#define INCLUDED_BDLB_INDEXSPAN
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlb_indexspan bdlb_indexspan
15/// @brief Provide a value-semantic attribute type for position and length.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlb
19/// @{
20/// @addtogroup bdlb_indexspan
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlb_indexspan-purpose"> Purpose</a>
25/// * <a href="#bdlb_indexspan-classes"> Classes </a>
26/// * <a href="#bdlb_indexspan-description"> Description </a>
27/// * <a href="#bdlb_indexspan-attributes"> Attributes </a>
28/// * <a href="#bdlb_indexspan-usage"> Usage </a>
29/// * <a href="#bdlb_indexspan-example-1-a-parsed-path"> Example 1: A Parsed Path </a>
30///
31/// # Purpose {#bdlb_indexspan-purpose}
32/// Provide a value-semantic attribute type for position and length.
33///
34/// # Classes {#bdlb_indexspan-classes}
35///
36/// - bdlb::IndexSpan: value-semantic attribute type to represent position/length
37///
38/// @see bdlb_indexspanutil, bdlb_indexspanstringutil
39///
40/// # Description {#bdlb_indexspan-description}
41/// This component provides a value-semantic, constrained
42/// attribute type `IndexSpan` that stores a position and a length. The
43/// constraint is that the sum of the two attributes must be representable by
44/// the type `bsl::size_t`.
45///
46/// ## Attributes {#bdlb_indexspan-attributes}
47///
48///
49/// @code
50/// Name Type Default Simple Constraints
51/// ------------------ -------------------- ------- ------------------
52/// position IndexSpan::size_type 0 none
53/// length IndexSpan::size_type 0 none
54/// @endcode
55/// * `position`: this span starts at this position in a sequence.
56/// * `length`: this span contains this many elements.
57///
58/// For example, an `IndexSpan` describing the middle name in the string
59/// "James Tiberius Kirk" will have the position 6 (the `T` of "Tiberius" is the
60/// 7th character of the string) and the length 8 ("Tiberius" is 8 characters
61/// long).
62///
63/// Note that the sum of the two attributes must be representable by the
64/// `bsl::size_t` type.
65///
66/// ## Usage {#bdlb_indexspan-usage}
67///
68///
69/// This section illustrates intended use of this component.
70///
71/// ### Example 1: A Parsed Path {#bdlb_indexspan-example-1-a-parsed-path}
72///
73///
74/// Suppose that we work with file system paths and we frequently need the path,
75/// the base name, the extension, and the filename, as well as the full path
76/// itself. Therefore we want to create a class that stores the full path and a
77/// way to quickly access the individual parts. (To keep things simple we will
78/// make the example code work on POSIX-style paths so we do not need to deal
79/// with the difference in path separators.)
80///
81/// If we try the naive solution -- storing a `bsl::string` of the full path and
82/// `bslstl::StringRef` for path, basename and extension -- the class
83/// `bslstl::StringRef` members will reference back into memory owned by the
84/// object, and the result is the compiler-generated (and naively written) move
85/// and copy operations will be broken. In addition, explicitly implementing
86/// move and copy operations is quite difficult and error prone.
87///
88/// The simplest (most readable) solution to the problem is to store a position
89/// and a length for the path, basename, and extension (rather than a
90/// `bslstl::StringRef`) because that representation is independent of the
91/// location of the memory for the string. `IndexSpan` provides such a
92/// representation, and allow us to implement our class using a simple copy and
93/// move operations (or in other contexts, compiler supplied operations).
94///
95/// First, we define the members and interface of the class.
96/// @code
97/// class ParsedPath {
98/// private:
99/// // DATA
100/// bsl::string d_full; // The full path
101/// bdlb::IndexSpan d_path; // The path part if present, otherwise empty
102/// bdlb::IndexSpan d_base; // The base name if present, otherwise empty
103/// bdlb::IndexSpan d_ext; // The extension if present, otherwise empty
104///
105/// public:
106/// // CREATERS
107///
108/// /// Create a new `ParsedPath` object by storing and parsing the
109/// /// specified `full` path. Use the optionally specified
110/// /// `basicAllocator` to allocate memory. If `basicAllocator` is 0,
111/// /// use the currently installed default allocator.
112/// explicit ParsedPath(const bslstl::StringRef& full,
113/// bslma::Allocator *basicAllocator = 0);
114///
115/// /// Create a new `ParsedPath` object that stores the same parsed
116/// /// path as the specified `original`. Use the optionally specified
117/// /// `basicAllocator` to allocate memory. Use the currently
118/// /// installed default allocator if `basicAllocator` is zero.
119/// ParsedPath(const ParsedPath& original,
120/// bslma::Allocator *basicAllocator = 0);
121///
122/// // ACCESSORS
123///
124/// /// Return a const reference to the full path parsed by this object.
125/// const bsl::string& full() const;
126///
127/// /// Return a string reference to the path part. Note that it may be
128/// /// an empty string reference.
129/// bslstl::StringRef path() const;
130///
131/// /// Return a string reference to the base name part. Note that it
132/// /// may be an empty string reference.
133/// bslstl::StringRef base() const;
134///
135/// /// Return a string reference to the extension part. Note that it
136/// /// may be an empty string reference.
137/// bslstl::StringRef ext() const;
138/// };
139/// @endcode
140/// Next, to make the parsing code short and readable, we implement a helper
141/// function to create `IndexSpan` objects from two positions. (In practice we
142/// would use the higher level utility function
143/// `IndexSpanStringUtil::createFromPosition`.)
144/// @code
145/// /// Return an `IndexSpan` describing the specified `[startPos, endPos)`
146/// /// positions.
147/// bdlb::IndexSpan createFromPositions(bdlb::IndexSpan::size_type startPos,
148/// bdlb::IndexSpan::size_type endPos)
149/// {
150/// return bdlb::IndexSpan(startPos, endPos - startPos);
151/// }
152/// @endcode
153/// Then, we implement the parsing constructor using the `create` function.
154/// @code
155/// // CREATORS
156/// ParsedPath::ParsedPath(const bslstl::StringRef& full,
157/// bslma::Allocator *basicAllocator)
158/// : d_full(full, basicAllocator)
159/// {
160/// typedef bsl::string::size_type Size;
161///
162/// static const Size npos = bsl::string::npos;
163///
164/// const Size slashPos = d_full.rfind('/');
165/// const Size dotPos = d_full.rfind('.');
166///
167/// const bool dotIsPresent = (dotPos != npos);
168/// const bool slashIsPresent = (slashPos != npos);
169///
170/// const bool dotIsInPath = slashIsPresent && (dotPos < slashPos);
171///
172/// const bool isDotFile = dotIsPresent &&
173/// dotPos == (slashIsPresent ? slashPos + 1 : 0);
174///
175/// const bool hasExtension = dotIsPresent && !dotIsInPath && !isDotFile;
176/// const bool hasPath = slashIsPresent;
177///
178/// if (hasPath) {
179/// d_path = createFromPositions(0, slashPos + 1);
180/// }
181///
182/// d_base = createFromPositions(slashPos + 1,
183/// hasExtension ? dotPos : full.length());
184///
185/// if (hasExtension) {
186/// d_ext = createFromPositions(dotPos + 1, full.length());
187/// }
188/// }
189/// @endcode
190/// Next, we implement the (now) simple copy constructor:
191/// @code
192/// ParsedPath::ParsedPath(const ParsedPath& original,
193/// bslma::Allocator *basicAllocator)
194/// : d_full(original.d_full, basicAllocator)
195/// , d_path(original.d_path)
196/// , d_base(original.d_base)
197/// , d_ext(original.d_ext)
198/// {
199/// }
200/// @endcode
201/// Then, to make the accessors simple (and readable), we implement a helper
202/// function that creates a `StringRef` from a `StringRef` and an `IndexSpan`.
203/// (In practice we would use the higher level utility function
204/// `IndexSpanStringUtil::bind`.)
205/// @code
206/// /// Return a string reference to the substring of the specified `full`
207/// /// string defined by the specified `part`.
208/// bslstl::StringRef bindSpan(const bslstl::StringRef& full,
209/// const bdlb::IndexSpan& part)
210/// {
211/// BSLS_ASSERT(part.position() <= full.length());
212/// BSLS_ASSERT(part.position() + part.length() <= full.length());
213///
214/// return bslstl::StringRef(full.data() + part.position(), part.length());
215/// }
216/// @endcode
217/// Next, we implement the accessors:
218/// @code
219/// // ACCESSORS
220/// bslstl::StringRef ParsedPath::base() const
221/// {
222/// return bindSpan(d_full, d_base);
223/// }
224///
225/// bslstl::StringRef ParsedPath::ext() const
226/// {
227/// return bindSpan(d_full, d_ext);
228/// }
229///
230/// const bsl::string& ParsedPath::full() const
231/// {
232/// return d_full;
233/// }
234///
235/// bslstl::StringRef ParsedPath::path() const
236/// {
237/// return bindSpan(d_full, d_path);
238/// }
239/// @endcode
240/// Finally, we verify that the resulting class is copied properly. We do that
241/// by determining that the original and the copy object has equal but distinct
242/// strings and that the (other) accessors return references into those strings.
243/// @code
244/// ParsedPath aPath("path/path/basename.extension");
245/// ParsedPath theCopy(aPath);
246///
247/// assert(aPath.full() == theCopy.full());
248/// assert(aPath.full().data() != theCopy.full().data());
249///
250/// assert(aPath.path() == theCopy.path());
251/// assert(aPath.path().data() != theCopy.path().data());
252/// assert(aPath.path().data() >= aPath.full().data());
253/// assert(aPath.path().data() + aPath.path().length() <=
254/// aPath.full().data() + aPath.full().length());
255///
256/// assert(aPath.base() == theCopy.base());
257/// assert(aPath.base().data() != theCopy.base().data());
258/// assert(aPath.base().data() >= aPath.full().data());
259/// assert(aPath.base().data() + aPath.base().length() <=
260/// aPath.full().data() + aPath.full().length());
261///
262/// assert(aPath.ext() == theCopy.ext());
263/// assert(aPath.ext().data() != theCopy.ext().data());
264/// assert(aPath.ext().data() >= aPath.full().data());
265/// assert(aPath.ext().data() + aPath.ext().length() <=
266/// aPath.full().data() + aPath.full().length());
267/// @endcode
268/// @}
269/** @} */
270/** @} */
271
272/** @addtogroup bdl
273 * @{
274 */
275/** @addtogroup bdlb
276 * @{
277 */
278/** @addtogroup bdlb_indexspan
279 * @{
280 */
281
282#include <bdlscm_version.h>
283
284#include <bdlb_printmethods.h> // 'bdlb::HasPrintMethod'
285
286#include <bslh_hash.h>
287
290
291#include <bsls_assert.h>
292
293#include <bsl_cstddef.h>
294#include <bsl_iosfwd.h>
295#include <bsl_limits.h>
296
297
298namespace bdlb {
299
300 // ===============
301 // class IndexSpan
302 // ===============
303
304/// A constrained attribute type that represents a position and a length.
305/// The constraint is that the sum of the position and length attributes
306/// must be representable by the `bsl::size_t` type.
307///
308/// See @ref bdlb_indexspan
310
311 public:
312 // TYPES
313
314 /// The type of the position and length attributes.
315 typedef bsl::size_t size_type;
316
317 private:
318 // DATA
319 size_type d_position; // The spans starts at this position
320 size_type d_length; // The span has this length
321
322 public:
323 // TRAITS
326
327 // CREATORS
328
329 /// Create an `IndexSpan` object with position and length of 0.
330 IndexSpan();
331
332 /// Create an `IndexSpan` object with the specified `position` and `length`.
333 ///
334 /// \pre The behavior is undefined unless
335 /// `position <= bsl::numeric_limits<size_t>::max() - length`.
337
338 /// Create an index span having the value of the specified `original` index span.
339 ///
340 /// \note Note that this trivial copy constructor is generated by
341 /// the compiler.
342 IndexSpan(const IndexSpan& original) = default;
343
344 /// Destroy this index span object.
345 /// \note Note that this trivial destructor
346 /// is generated by the compiler.
347 ~IndexSpan() = default;
348
349 // MANIPULATORS
350
351 /// Assign to this index span the value of the specified `rhs` index
352 /// span, and return a reference providing modifiable access to this object.
353 ///
354 /// \note Note that this trivial assignment operation is generated by
355 /// the compiler.
356 IndexSpan& operator=(const IndexSpan& rhs) = default;
357
358 // ACCESSORS
359
360 /// Return `true` if the length attribute is 0; and return `false`
361 /// otherwise.
362 bool isEmpty() const;
363
364 /// Return the length attribute.
365 size_type length() const;
366
367 /// Return the position attribute.
368 size_type position() const;
369
370 // Aspects
371
372 /// Format this object to the specified output `stream` at the (absolute
373 /// value of) the optionally specified indentation `level` and return a
374 /// reference to `stream`. If `level` is specified, optionally specify
375 /// `spacesPerLevel`, the number of spaces per indentation level for
376 /// this and all of its nested objects. If `level` is negative,
377 /// suppress indentation of the first line. If `spacesPerLevel` is
378 /// negative, format the entire output on one line, suppressing all but
379 /// the initial indentation (as governed by `level`). If `stream` is
380 /// not valid on entry, this operation has no effect.
381 bsl::ostream& print(bsl::ostream& stream,
382 int level = 0,
383 int spacesPerLevel = 4) const;
384};
385
386// FREE OPERATORS
387
388/// Return `true` if the specified `lhs` and `rhs` index span objects have
389/// the same value, and `false` otherwise. Two index span objects have the
390/// same value if their position and length attributes compare equal.
391bool operator==(const IndexSpan& lhs, const IndexSpan& rhs);
392
393/// Return `true` if the specified `lhs` and `rhs` index span objects do not
394/// have the same value, and `false` otherwise. Two index span objects do
395/// not have the same value if either their position or length attributes
396/// do not compare equal.
397bool operator!=(const IndexSpan& lhs, const IndexSpan& rhs);
398
399/// Write the value of the specified `object` to the specified output
400/// `stream` in a single-line format, and return a reference to `stream`.
401/// If `stream` is not valid on entry, this operation has no effect.
402///
403/// \note Note that this human-readable format is not fully specified, can change
404/// without notice, and is logically equivalent to:
405/// @code
406/// print(stream, 0, -1);
407/// @endcode
408bsl::ostream& operator<<(bsl::ostream& stream, const IndexSpan& object);
409
410/// Invoke the specified `hashAlgorithm` on the attributes of the specified
411/// `object`.
412template <class HASH_ALGORITHM>
413void hashAppend(HASH_ALGORITHM& hashAlgorithm, const IndexSpan& object);
414
415// ============================================================================
416// INLINE DEFINITIONS
417// ============================================================================
418
419 // ---------------
420 // class IndexSpan
421 // ---------------
422
423// CREATORS
424inline
426: d_position(0u)
427, d_length(0u)
428{
429}
430
431inline
433: d_position(position)
434, d_length(length)
435{
436 BSLS_ASSERT(position <= bsl::numeric_limits<size_t>::max() - length);
437}
438
439// ACCESSORS
440inline
442{
443 return 0 == d_length;
444}
445
446inline
448{
449 return d_length;
450}
451
452inline
454{
455 return d_position;
456}
457
458} // close package namespace
459
460// FREE OPERATORS
461inline
462bool bdlb::operator==(const IndexSpan& lhs, const IndexSpan& rhs)
463{
464 return lhs.position() == rhs.position()
465 && lhs.length() == rhs.length();
466}
467
468inline
469bool bdlb::operator!=(const IndexSpan& lhs, const IndexSpan& rhs)
470{
471 return !(lhs == rhs);
472}
473
474inline
475bsl::ostream& bdlb::operator<<(bsl::ostream& stream,
476 const IndexSpan& object)
477{
478 return object.print(stream, 0, -1);
479}
480
481template <class HASH_ALGORITHM>
482inline
483void bdlb::hashAppend(HASH_ALGORITHM& hashAlgorithm, const IndexSpan& object)
484{
485 const IndexSpan::size_type pos = object.position();
486 const IndexSpan::size_type len = object.length();
487
488 using bslh::hashAppend;
489 hashAppend(hashAlgorithm, pos);
490 hashAppend(hashAlgorithm, len);
491}
492
493
494
495#endif
496
497// ----------------------------------------------------------------------------
498// Copyright 2018 Bloomberg Finance L.P.
499//
500// Licensed under the Apache License, Version 2.0 (the "License");
501// you may not use this file except in compliance with the License.
502// You may obtain a copy of the License at
503//
504// http://www.apache.org/licenses/LICENSE-2.0
505//
506// Unless required by applicable law or agreed to in writing, software
507// distributed under the License is distributed on an "AS IS" BASIS,
508// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
509// See the License for the specific language governing permissions and
510// limitations under the License.
511// ----------------------------- END-OF-FILE ----------------------------------
512
513/** @} */
514/** @} */
515/** @} */
Definition bdlb_indexspan.h:309
IndexSpan & operator=(const IndexSpan &rhs)=default
BSLMF_NESTED_TRAIT_DECLARATION(IndexSpan, bdlb::HasPrintMethod)
IndexSpan(const IndexSpan &original)=default
IndexSpan()
Create an IndexSpan object with position and length of 0.
Definition bdlb_indexspan.h:425
size_type position() const
Return the position attribute.
Definition bdlb_indexspan.h:453
BSLMF_NESTED_TRAIT_DECLARATION(IndexSpan, bsl::is_trivially_copyable)
bsl::size_t size_type
The type of the position and length attributes.
Definition bdlb_indexspan.h:315
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
size_type length() const
Return the length attribute.
Definition bdlb_indexspan.h:447
~IndexSpan()=default
bool isEmpty() const
Definition bdlb_indexspan.h:441
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlb_algorithmworkaroundutil.h:74
bool operator!=(const BigEndianInt16 &lhs, const BigEndianInt16 &rhs)
bsl::ostream & operator<<(bsl::ostream &stream, const BigEndianInt16 &integer)
void hashAppend(HASH_ALGORITHM &hashAlgorithm, const BigEndianInt16 &object)
bool operator==(const BigEndianInt16 &lhs, const BigEndianInt16 &rhs)
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
ALLOCATOR & lhs
Definition bslstl_string.h:3917
bsl::enable_if<(bsl::is_integral< TYPE >::value||bsl::is_pointer< TYPE >::value||bsl::is_enum< TYPE >::value)&&!bsl::is_same< TYPE, bool >::value >::type hashAppend(HASH_ALGORITHM &hashAlg, TYPE input)
Definition bslh_hash.h:643
Definition bdlb_printmethods.h:306
Definition bslmf_istriviallycopyable.h:324