BDE 4.14.0 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
333 /// `length`. The behavior is undefined unless
334 /// `position <= bsl::numeric_limits<size_t>::max() - length`.
336
337 /// Create an index span having the value of the specified `original`
338 /// index span. Note that this trivial copy constructor is generated by
339 /// the compiler.
340 IndexSpan(const IndexSpan& original) = default;
341
342 /// Destroy this index span object. Note that this trivial destructor
343 /// is generated by the compiler.
344 ~IndexSpan() = default;
345
346 // MANIPULATORS
347
348 /// Assign to this index span the value of the specified `rhs` index
349 /// span, and return a reference providing modifiable access to this
350 /// object. Note that this trivial assignment operation is generated by
351 /// the compiler.
352 IndexSpan& operator=(const IndexSpan& rhs) = default;
353
354 // ACCESSORS
355
356 /// Return `true` if the length attribute is 0; and return `false`
357 /// otherwise.
358 bool isEmpty() const;
359
360 /// Return the length attribute.
361 size_type length() const;
362
363 /// Return the position attribute.
364 size_type position() const;
365
366 // Aspects
367
368 /// Format this object to the specified output `stream` at the (absolute
369 /// value of) the optionally specified indentation `level` and return a
370 /// reference to `stream`. If `level` is specified, optionally specify
371 /// `spacesPerLevel`, the number of spaces per indentation level for
372 /// this and all of its nested objects. If `level` is negative,
373 /// suppress indentation of the first line. If `spacesPerLevel` is
374 /// negative, format the entire output on one line, suppressing all but
375 /// the initial indentation (as governed by `level`). If `stream` is
376 /// not valid on entry, this operation has no effect.
377 bsl::ostream& print(bsl::ostream& stream,
378 int level = 0,
379 int spacesPerLevel = 4) const;
380};
381
382// FREE OPERATORS
383
384/// Return `true` if the specified `lhs` and `rhs` index span objects have
385/// the same value, and `false` otherwise. Two index span objects have the
386/// same value if their position and length attributes compare equal.
387bool operator==(const IndexSpan& lhs, const IndexSpan& rhs);
388
389/// Return `true` if the specified `lhs` and `rhs` index span objects do not
390/// have the same value, and `false` otherwise. Two index span objects do
391/// not have the same value if either their position or length attributes
392/// do not compare equal.
393bool operator!=(const IndexSpan& lhs, const IndexSpan& rhs);
394
395/// Write the value of the specified `object` to the specified output
396/// `stream` in a single-line format, and return a reference to `stream`.
397/// If `stream` is not valid on entry, this operation has no effect. Note
398/// that this human-readable format is not fully specified, can change
399/// without notice, and is logically equivalent to:
400/// @code
401/// print(stream, 0, -1);
402/// @endcode
403bsl::ostream& operator<<(bsl::ostream& stream, const IndexSpan& object);
404
405/// Invoke the specified `hashAlgorithm` on the attributes of the specified
406/// `object`.
407template <class HASH_ALGORITHM>
408void hashAppend(HASH_ALGORITHM& hashAlgorithm, const IndexSpan& object);
409
410// ============================================================================
411// INLINE DEFINITIONS
412// ============================================================================
413
414 // ---------------
415 // class IndexSpan
416 // ---------------
417
418// CREATORS
419inline
421: d_position(0u)
422, d_length(0u)
423{
424}
425
426inline
428: d_position(position)
429, d_length(length)
430{
431 BSLS_ASSERT(position <= bsl::numeric_limits<size_t>::max() - length);
432}
433
434// ACCESSORS
435inline
437{
438 return 0 == d_length;
439}
440
441inline
443{
444 return d_length;
445}
446
447inline
449{
450 return d_position;
451}
452
453} // close package namespace
454
455// FREE OPERATORS
456inline
457bool bdlb::operator==(const IndexSpan& lhs, const IndexSpan& rhs)
458{
459 return lhs.position() == rhs.position()
460 && lhs.length() == rhs.length();
461}
462
463inline
464bool bdlb::operator!=(const IndexSpan& lhs, const IndexSpan& rhs)
465{
466 return !(lhs == rhs);
467}
468
469inline
470bsl::ostream& bdlb::operator<<(bsl::ostream& stream,
471 const IndexSpan& object)
472{
473 return object.print(stream, 0, -1);
474}
475
476template <class HASH_ALGORITHM>
477inline
478void bdlb::hashAppend(HASH_ALGORITHM& hashAlgorithm, const IndexSpan& object)
479{
480 const IndexSpan::size_type pos = object.position();
481 const IndexSpan::size_type len = object.length();
482
483 using bslh::hashAppend;
484 hashAppend(hashAlgorithm, pos);
485 hashAppend(hashAlgorithm, len);
486}
487
488
489
490#endif
491
492// ----------------------------------------------------------------------------
493// Copyright 2018 Bloomberg Finance L.P.
494//
495// Licensed under the Apache License, Version 2.0 (the "License");
496// you may not use this file except in compliance with the License.
497// You may obtain a copy of the License at
498//
499// http://www.apache.org/licenses/LICENSE-2.0
500//
501// Unless required by applicable law or agreed to in writing, software
502// distributed under the License is distributed on an "AS IS" BASIS,
503// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
504// See the License for the specific language governing permissions and
505// limitations under the License.
506// ----------------------------- END-OF-FILE ----------------------------------
507
508/** @} */
509/** @} */
510/** @} */
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:420
size_type position() const
Return the position attribute.
Definition bdlb_indexspan.h:448
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:442
~IndexSpan()=default
bool isEmpty() const
Definition bdlb_indexspan.h:436
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
void hashAppend(HASH_ALGORITHM &hashAlg, const baljsn::EncoderTestAddress &object)
Definition baljsn_encoder_testtypes.h:9236
Definition 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)
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:638
Definition bdlb_printmethods.h:306
Definition bslmf_istriviallycopyable.h:329