BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslalg_rangecompare.h
Go to the documentation of this file.
1/// @file bslalg_rangecompare.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslalg_rangecompare.h -*-C++-*-
8#ifndef INCLUDED_BSLALG_RANGECOMPARE
9#define INCLUDED_BSLALG_RANGECOMPARE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslalg_rangecompare bslalg_rangecompare
15/// @brief Provide algorithms to compare iterator-ranges of elements.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslalg
19/// @{
20/// @addtogroup bslalg_rangecompare
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslalg_rangecompare-purpose"> Purpose</a>
25/// * <a href="#bslalg_rangecompare-classes"> Classes </a>
26/// * <a href="#bslalg_rangecompare-description"> Description </a>
27/// * <a href="#bslalg_rangecompare-usage"> Usage </a>
28/// * <a href="#bslalg_rangecompare-example-1-defining-equality-comparison-operators-on-a-container"> Example 1: Defining Equality-Comparison Operators on a Container </a>
29///
30/// # Purpose {#bslalg_rangecompare-purpose}
31/// Provide algorithms to compare iterator-ranges of elements.
32///
33/// # Classes {#bslalg_rangecompare-classes}
34///
35/// - bslalg::RangeCompare: comparison algorithms for iterator ranges
36///
37/// @see bslmf_isbitwiseequalitycomparable
38///
39/// # Description {#bslalg_rangecompare-description}
40/// This component provides a utility `struct`,
41/// `bslalg::RangeCompare`, that defines two overloaded class methods, `equal`
42/// and `lexicographical`, for comparing two ranges, each specified by a pair of
43/// input iterators that are compliant with the C++11 standard [24.2.3]. The
44/// `equal` method determines whether two specified ranges compare equal. The
45/// `lexicographical` method determines whether the first range compares
46/// lexicographically less than, equal to, or greater than the second range.
47/// Under certain circumstances, `bslalg::RangeCompare::equal` and
48/// `bslalg::RangeCompare::lexicographical` may perform optimized comparisons,
49/// as described below.
50///
51/// `bslalg::RangeCompare::equal` may perform a bit-wise comparison of the two
52/// ranges when the following two criteria are met:
53/// * The input iterators are convertible to a pointer type.
54/// * The trait `bslmf::IsBitwiseEqualityComparable` is declared for
55/// the type of the objects in the ranges being compared.
56///
57/// `bslalg::RangeCompare::lexicographical` may perform a bit-wise comparison of
58/// the two ranges when the following criterion is met:
59/// * The input iterators are convertible to pointers to a wide or unsigned
60/// character type.
61///
62/// Note that a class having the `bslmf::IsBitwiseEqualityComparable`
63/// trait can be described as bit-wise comparable and should meet the following
64/// criteria:
65/// * The values represented by two objects belonging to the class are the same
66/// if and only if each of the data members in the class has the same value
67/// in both objects.
68/// * The class layout includes no padding.
69/// * The class has no virtual members.
70///
71/// Note that this component is for use primarily by the `bslstl` package.
72/// Other clients should use the STL algorithms (in headers `<bsl_algorithm.h>`
73/// and `<bsl_memory.h>`).
74///
75/// ## Usage {#bslalg_rangecompare-usage}
76///
77///
78/// This section illustrates intended use of this component.
79///
80/// ### Example 1: Defining Equality-Comparison Operators on a Container {#bslalg_rangecompare-example-1-defining-equality-comparison-operators-on-a-container}
81///
82///
83/// In this example we will use the `bslalg::RangeCompare::equal` class method
84/// to implement the equality-comparison operators for an iterable container
85/// type residing in the `bslstl` package, and highlight the circumstances under
86/// which the optimization provided by the class method may be applied.
87///
88/// Suppose that we have a new iterable container type that will be included in
89/// the `bslstl` package, and we wish to define comparison operators for the
90/// container. If the container has an iterator that provides access to the
91/// container's elements in a consistent order, and the elements themselves are
92/// equality-comparable, we can implement the container's equality-comparison
93/// operators by pair-wise comparing each of the elements over the entire range
94/// of elements in both containers. In such cases the container can use the
95/// `bslalg::RangeCompare::equal` class method to equal-compare the container's
96/// elements, taking advantage of the optimizations the class method provides
97/// for bit-wise equality-comparable objects.
98///
99/// First, we create an elided definition of a container class, `MyContainer`,
100/// which provides read-only iterators of the type `MyContainer::ConstIterator`:
101/// @code
102/// template <class VALUE_TYPE>
103/// class MyContainer {
104/// // This class implements a container, semantically similar to
105/// // 'std::vector', holding objects of the (template parameter) type
106/// // 'VALUE_TYPE'.
107///
108/// private:
109/// // DATA
110/// // ...
111///
112/// public:
113/// // PUBLIC TYPES
114/// typedef const VALUE_TYPE *ConstIterator;
115/// // This 'typedef' provides an alias for the type of iterator
116/// // providing non-modifiable access to the elements in the
117/// // container.
118///
119/// // CREATORS
120/// explicit MyContainer(bslma::Allocator *basicAllocator = 0);
121/// // Create an empty 'MyContainer' object having no capacity.
122/// // Optionally specify a 'basicAllocator' used to supply memory. If
123/// // 'basicAllocator' is 0, the currently installed default allocator
124/// // is used.
125///
126/// // ...
127///
128/// // MANIPULATORS
129/// // ...
130///
131/// void push_back(const VALUE_TYPE& value);
132/// // Append the specified 'value' at the past-the-end position in
133/// // this container, increasing the container's capacity if needed.
134///
135/// // ...
136///
137/// // ACCESSORS
138/// ConstIterator begin() const;
139/// // Return an iterator providing non-modifiable access to the first
140/// // element in this container.
141///
142/// ConstIterator end() const;
143/// // Return an iterator providing non-modifiable access to the
144/// // past-the-end element in this container.
145///
146/// std::size_t size() const;
147/// // Return the number of elements in this container.
148///
149/// // ...
150/// };
151/// @endcode
152/// Notice that `ConstIterator` is defined as a pointer type, which is one of
153/// the criteria required to enable the optimizations provided by the
154/// `bslalg::RangeCompare::equal` class method.
155///
156/// Then, we declare the equality-comparison operators for `MyContainer`:
157/// @code
158/// template <class VALUE_TYPE>
159/// bool operator==(const MyContainer<VALUE_TYPE>& lhs,
160/// const MyContainer<VALUE_TYPE>& rhs);
161/// // Return 'true' if the specified 'lhs' and 'rhs' objects have the same
162/// // value, and 'false' otherwise. Two 'MyContainer' objects have the
163/// // same value if they have the same length, and each element in 'lhs'
164/// // has the same value as the corresponding element in 'rhs'.
165///
166/// template <class VALUE_TYPE>
167/// bool operator!=(const MyContainer<VALUE_TYPE>& lhs,
168/// const MyContainer<VALUE_TYPE>& rhs);
169/// // Return 'true' if the specified 'lhs' and 'rhs' objects do not have
170/// // the same value, and 'false' otherwise. Two 'MyContainer' objects do
171/// // not have the same value if they do not have the same length, or if
172/// // any element in 'lhs' does not have the same value as the
173/// // corresponding element in 'rhs'.
174/// @endcode
175/// Next, we implement the equality-comparison operators using
176/// `bslalg::RangeCompare::equal`:
177/// @code
178/// template <class VALUE_TYPE>
179/// inline
180/// bool operator==(const MyContainer<VALUE_TYPE>& lhs,
181/// const MyContainer<VALUE_TYPE>& rhs)
182/// {
183/// return BloombergLP::bslalg::RangeCompare::equal(lhs.begin(),
184/// lhs.end(),
185/// lhs.size(),
186/// rhs.begin(),
187/// rhs.end(),
188/// rhs.size());
189/// }
190///
191/// template <class VALUE_TYPE>
192/// inline
193/// bool operator!=(const MyContainer<VALUE_TYPE>& lhs,
194/// const MyContainer<VALUE_TYPE>& rhs)
195/// {
196/// return !BloombergLP::bslalg::RangeCompare::equal(lhs.begin(),
197/// lhs.end(),
198/// lhs.size(),
199/// rhs.begin(),
200/// rhs.end(),
201/// rhs.size());
202/// }
203/// @endcode
204/// Then, we create the elided definition of a value-semantic class, `MyString`,
205/// together with its definition of `operator==`:
206/// @code
207/// class MyString {
208/// // This class provides a simple, elided string class that conforms to
209/// // the 'bslma::Allocator' model.
210///
211/// private:
212/// // DATA
213/// char *d_start_p; // storage for the string
214/// std::size_t d_length; // length of the string
215/// bslma::Allocator *d_allocator_p; // memory allocator (held, not owned)
216///
217/// // ...
218///
219/// // FRIENDS
220/// friend bool operator==(const MyString&, const MyString&);
221/// // ...
222///
223/// public:
224/// // CREATORS
225/// explicit MyString(const char *string,
226/// bslma::Allocator *basicAllocator = 0);
227/// // Create a 'MyString' object initialized to the value of the
228/// // specified 'string'. Optionally specify a 'basicAllocator' used
229/// // to supply memory. If 'basicAllocator' is 0, the currently
230/// // installed default allocator is used.
231///
232/// // ...
233/// };
234///
235/// bool operator==(const MyString& lhs, const MyString& rhs)
236/// {
237/// return lhs.d_length == rhs.d_length
238/// && 0 == std::strncmp(lhs.d_start_p, rhs.d_start_p, lhs.d_length);
239/// }
240/// @endcode
241/// Notice that `MyString` is not bit-wise comparable because the address values
242/// of the `d_start_p` pointer data members in two `MyString` objects will be
243/// different, even if the string values of the two objects are the same.
244///
245/// Next, we create two `MyContainer<MyString>` objects, and compare them using
246/// `operator==`:
247/// @code
248/// MyContainer<MyString> c1;
249/// MyContainer<MyString> c2;
250///
251/// c1.push_back(MyString("hello"));
252/// c1.push_back(MyString("goodbye"));
253///
254/// c2.push_back(MyString("hello"));
255/// c2.push_back(MyString("goodbye"));
256///
257/// assert(c1 == c2);
258/// @endcode
259/// Here, the call to the `bslalg::RangeCompare::equal` class method in
260/// `operator==` will perform an unoptimized pair-wise comparison of the
261/// elements in `c1` and `c2`.
262///
263/// Then, we create the elided definition of another value-semantic class,
264/// `MyPoint`, together with its definition of `operator==`:
265/// @code
266/// class MyPoint {
267/// // This class provides a simple, elided point type that is bit-wise
268/// // comparable with other objects of the same type.
269///
270/// private:
271/// // DATA
272/// int d_x; // the x-coordinate of the point
273/// int d_y; // the y-coordinate of the point
274///
275/// // FRIENDS
276/// friend bool operator==(const MyPoint&, const MyPoint&);
277/// // ...
278///
279/// public:
280/// // TRAITS
281/// BSLMF_NESTED_TRAIT_DECLARATION(MyPoint,
282/// BloombergLP::bslmf::IsBitwiseEqualityComparable);
283///
284/// // CREATORS
285/// MyPoint(int x, int y);
286/// // Create a 'MyPoint' object whose x- and y-coordinates have the
287/// // specified 'x' and 'y' values, respectively.
288///
289/// // ...
290/// };
291///
292/// bool operator==(const MyPoint& lhs, const MyPoint& rhs)
293/// {
294/// return lhs.d_x == rhs.d_x && lhs.d_y == rhs.d_y;
295/// }
296/// @endcode
297/// Notice that the value of a `MyPoint` object derives from the values of all
298/// of its data members, and that no padding is required for alignment.
299/// Furthermore, `MyPoint` has no virtual methods. Therefore, `MyPoint` objects
300/// are bit-wise comparable, and we can correctly declare the
301/// `bslmf::IsBitwiseEqualityComparable` trait for the class, as shown
302/// above under the public `TRAITS` section.
303///
304/// Now, we create two `MyContainer<MyPoint>` objects and compare them using
305/// `operator==`:
306/// @code
307/// MyContainer<MyPoint> c3;
308/// MyContainer<MyPoint> c4;
309///
310/// c3.push_back(MyPoint(1, 2));
311/// c3.push_back(MyPoint(3, 4));
312///
313/// c4.push_back(MyPoint(1, 2));
314/// c4.push_back(MyPoint(3, 4));
315///
316/// assert(c3 == c4); // potentially optimized
317/// @endcode
318/// Here, the call to `bslalg::RangeCompare::equal` in `operator==` may take
319/// advantage of the fact that `MyPoint` is bit-wise comparable and perform the
320/// comparison by directly bit-wise comparing the entire range of elements
321/// contained in the `MyContainer<MyPoint>` objects. This comparison can
322/// provide a significant performance boost over the comparison between two
323/// `MyContainer<MyPoint>` objects in which the nested
324/// `bslmf::IsBitwiseEqualityComparable` trait is not associated with the
325/// `MyPoint` class.
326///
327/// Finally, note that we can instantiate `MyContainer` with `int` or any other
328/// primitive type as the `VALUE_TYPE` and still benefit from the optimized
329/// comparison operators, because primitive (i.e.: fundamental, enumerated, and
330/// pointer) types are inherently bit-wise comparable:
331/// @code
332/// MyContainer<int> c5;
333/// MyContainer<int> c6;
334///
335/// c5.push_back(1);
336/// c5.push_back(2);
337/// c5.push_back(3);
338///
339/// c6.push_back(1);
340/// c6.push_back(2);
341/// c6.push_back(3);
342///
343/// assert(c5 == c6); // potentially optimized
344/// @endcode
345/// @}
346/** @} */
347/** @} */
348
349/** @addtogroup bsl
350 * @{
351 */
352/** @addtogroup bslalg
353 * @{
354 */
355/** @addtogroup bslalg_rangecompare
356 * @{
357 */
358
359#include <bslscm_version.h>
360
363#include <bslmf_isconvertible.h>
364#include <bslmf_matchanytype.h>
365
366#include <climits>
367
368#include <cstddef>
369
370#include <cstring>
371
372#include <cwchar>
373
374
375
376namespace bslalg {
377
378 // ==================
379 // class RangeCompare
380 // ==================
381
382/// This utility `struct` provides two static class methods, `equal` and
383/// `lexicographical`, for comparing two ranges of values. `equal` returns
384/// `true` if each element in one range has the same value as the
385/// corresponding element in the other range, and `false` otherwise.
386/// `lexicographical` returns 0 if the two ranges are equal, a positive
387/// value if the first range is greater than the second, and a negative
388/// value if the second range is greater than the first. A range is
389/// specified by a pair of beginning and ending iterators, with an optional
390/// length parameter. Additionally, an overload is provided for the `equal`
391/// class method that allows the end iterator for one range to be omitted.
392///
393/// `equal` requires that the elements in the ranges can be compared with
394/// `operator==`.
395///
396/// `lexicographical` requires that the elements in the ranges can be
397/// compared with `operator<`.
398///
399/// See @ref bslalg_rangecompare
401
402 // TYPES
403
404 /// `size_type` is an alias for an unsigned value representing the size
405 /// of an object or the number of elements in a range.
406 typedef std::size_t size_type;
407
408 // CLASS METHODS
409
410 /// Compare each element in the range beginning at the specified
411 /// `start1` position and ending immediately before the specified `end1`
412 /// position to the corresponding element in the range of the same
413 /// length beginning at the specified `start2` position, as if using
414 /// `operator==` element-by-element. Return `true` if every pair of
415 /// corresponding elements compares equal, and `false` otherwise.
416 ///
417 /// \note Note that this implementation uses `operator==` to perform the
418 /// comparisons, or bit-wise comparison if the value type has the
419 /// bit-wise equality-comparable trait.
420 template <class INPUT_ITER>
421 static bool equal(INPUT_ITER start1,
422 INPUT_ITER end1,
423 INPUT_ITER start2);
424
425 /// Compare each element in the range beginning at the specified
426 /// `start1` position and ending immediately before the specified `end1`
427 /// position, to the corresponding element in the range beginning at the
428 /// specified `start2` position and ending immediately before the
429 /// specified `end2` position, as if by using `operator==`
430 /// element-by-element. Optionally specify the length of each range,
431 /// `length1` and `length2`. Return `true` if the ranges have the same
432 /// length and every element in the first range compares equal with the
433 /// corresponding element in the second, and `false` otherwise.
434 ///
435 /// \pre The behavior is undefined unless `length1` is either unspecified or
436 /// equals the length of the range `[start1, end1)`, and `length2` is
437 /// either unspecified or equals the length of the range `[start2, end2)`.
438 ///
439 /// \note Note that this implementation uses `operator==`
440 /// to perform the comparisons, or bit-wise comparison if the value type
441 /// has the bit-wise equality-comparable trait. Also note that
442 /// providing lengths may reduce the runtime cost of this operation.
443 template <class INPUT_ITER>
444 static bool equal(INPUT_ITER start1,
445 INPUT_ITER end1,
446 INPUT_ITER start2,
447 INPUT_ITER end2);
448 template <class INPUT_ITER>
449 static bool equal(INPUT_ITER start1, INPUT_ITER end1, size_type length1,
450 INPUT_ITER start2, INPUT_ITER end2, size_type length2);
451
452 /// Compare each element in the range beginning at the specified
453 /// `start1` position and ending immediately before the specified `end1`
454 /// position, to the corresponding element in the range beginning at the
455 /// specified `start2` position and ending immediately before the
456 /// specified `end2` position. Optionally specify the length of each
457 /// range, `length1` and `length2`. Return a negative value if the
458 /// first range compares lexicographically less than the second range, 0
459 /// if they are the same length and compare lexicographically equal, and
460 /// a positive value if the first range compares lexicographically greater than the second range.
461 ///
462 /// \pre The behavior is undefined unless
463 /// `length1` is either unspecified or equals the length of the range
464 /// `[start1, end1)`, and `length2` is either unspecified or equals the length of the range `[start2, end2)`.
465 ///
466 /// \note Note that this implementation
467 /// uses `std::memcmp` for unsigned character comparisons,
468 /// `std::wmemcmp` for wide character comparisons, and `operator<` for
469 /// all other types.
470 template <class INPUT_ITER>
471 static int lexicographical(INPUT_ITER start1,
472 INPUT_ITER end1,
473 INPUT_ITER start2,
474 INPUT_ITER end2);
475 template <class INPUT_ITER>
476 static int lexicographical(INPUT_ITER start1,
477 INPUT_ITER end1,
478 size_type length1,
479 INPUT_ITER start2,
480 INPUT_ITER end2,
481 size_type length2);
482};
483
484 // =======================
485 // struct RangeCompare_Imp
486 // =======================
487
488/// This utility `struct` provides the implementations for
489/// `bslalg::RangeCompare`. Multiple implementations are provided for each
490/// method in `bslalg::RangeCompare`, and the most efficient version is
491/// found by disambiguating based on the iterator type, the value type, or
492/// the presence of nested traits.
493///
494/// See @ref bslalg_rangecompare
496
497 // CLASS METHODS
498
499 /// Compare the range beginning at the specified `start1` position and
500 /// ending immediately before the specified `end1` position with the
501 /// range beginning at the specified `start2` position and ending
502 /// immediately before the specified `end2` position, as if using
503 /// `operator==` element-by-element. The unnamed `VALUE_TYPE` argument
504 /// is for automatic type deduction, and is ignored. The fifth argument
505 /// is for overloading resolution, and is also ignored.
506 template <class VALUE_TYPE>
507 static bool equal(const VALUE_TYPE *start1,
508 const VALUE_TYPE *end1,
509 const VALUE_TYPE *start2,
510 const VALUE_TYPE *end2,
511 const VALUE_TYPE&,
513 template <class INPUT_ITER, class VALUE_TYPE>
514 static bool equal(INPUT_ITER start1,
515 INPUT_ITER end1,
516 INPUT_ITER start2,
517 INPUT_ITER end2,
518 const VALUE_TYPE&,
520 template <class INPUT_ITER, class VALUE_TYPE>
521 static bool equal(INPUT_ITER start1,
522 INPUT_ITER end1,
523 INPUT_ITER start2,
524 INPUT_ITER end2,
525 const VALUE_TYPE&);
526
527 /// Compare the range beginning at the specified `start1` position and
528 /// ending immediately before the specified `end1` position with the
529 /// range beginning at the specified `start2` position of the same
530 /// length (namely, `end1 - start1`), as if using `operator==`
531 /// element-by-element. The unnamed `VALUE_TYPE` argument is for
532 /// automatic type deduction, and is ignored. The fifth argument is for
533 /// overloading resolution, and is also ignored.
534 template <class INPUT_ITER, class VALUE_TYPE>
535 static bool equal(INPUT_ITER start1,
536 INPUT_ITER end1,
537 INPUT_ITER start2,
538 const VALUE_TYPE&,
540 template <class INPUT_ITER, class VALUE_TYPE>
541 static bool equal(INPUT_ITER start1,
542 INPUT_ITER end1,
543 INPUT_ITER start2,
544 const VALUE_TYPE&,
546 template <class INPUT_ITER, class VALUE_TYPE>
547 static bool equal(INPUT_ITER start1,
548 INPUT_ITER end1,
549 INPUT_ITER start2,
550 const VALUE_TYPE&);
551
552 /// Compare the range beginning at the specified `start1` position and
553 /// ending immediately before the specified `end1` position with the
554 /// range beginning at the specified `start2` position of the same
555 /// length (namely, `end1 - start1`), using bit-wise comparison across
556 /// the entire ranges. The last argument is for removing overload
557 /// ambiguities, and is not used. Return `true` if the ranges are
558 /// bit-wise equal, and `false` otherwise.
559 template <class VALUE_TYPE>
560 static bool equalBitwiseEqualityComparable(const VALUE_TYPE *start1,
561 const VALUE_TYPE *end1,
562 const VALUE_TYPE *start2,
564
565 /// Compare the range beginning at the specified `start1` position and
566 /// ending immediately before the specified `end1` position with the
567 /// range beginning at the specified `start2` position of the same
568 /// length (namely, `end1 - start1`), using `operator==`
569 /// element-by-element. The last argument is for removing overload
570 /// ambiguities, and is not used. Return `true` if each element in the
571 /// first range is equal to the corresponding element in the second
572 /// range, and `false` otherwise.
573 template <class INPUT_ITER>
574 static bool equalBitwiseEqualityComparable(INPUT_ITER start1,
575 INPUT_ITER end1,
576 INPUT_ITER start2,
578
579 /// Compare the range beginning at the specified `start1` position and
580 /// ending immediately before the specified `end1` position with the
581 /// range beginning at the specified `start2` position and ending
582 /// immediately before the specified `end2` position. The last two
583 /// arguments are for removing overload ambiguities and are not used.
584 /// Return a negative value if the
585 /// first range compares lexicographically less than the second range, 0
586 /// if they are the same length and compare lexicographically equal, and
587 /// a positive value if the first range compares lexicographically
588 /// greater than the second range.
589 template <class VALUE_TYPE>
590 static int lexicographical(const VALUE_TYPE *start1,
591 const VALUE_TYPE *end1,
592 const VALUE_TYPE *start2,
593 const VALUE_TYPE *end2,
594 const VALUE_TYPE&,
596
597 /// Compare each element in the range beginning at the specified
598 /// `start1` position and ending immediately before the specified `end1`
599 /// position with the corresponding element in the range beginning at
600 /// the specified `start2` position and ending immediately before the
601 /// specified `end2` position using `operator<`. The last two arguments
602 /// are for removing overload ambiguities and are not used. Return a
603 /// negative value if the first range compares lexicographically less
604 /// than the second range, 0 if they are the same length and compare
605 /// lexicographically equal, and a positive value if the first range
606 /// compares lexicographically greater than the second range.
607 template <class INPUT_ITER, class VALUE_TYPE>
608 static int lexicographical(INPUT_ITER start1,
609 INPUT_ITER end1,
610 INPUT_ITER start2,
611 INPUT_ITER end2,
612 const VALUE_TYPE&,
614
615 /// Compare the range beginning at the specified `start1` position and
616 /// ending immediately before the specified `end1` position with the
617 /// range beginning at the specified `start2` position and ending
618 /// immediately before the specified `end2` position. The type of the
619 /// last argument is considered in determining what optimizations, if
620 /// any, can be applied to the comparison. The last argument is not
621 /// used in any other way. Return a negative value if the
622 /// first range compares lexicographically less than the second range, 0
623 /// if they are the same length and compare lexicographically equal, and
624 /// a positive value if the first range compares lexicographically
625 /// greater than the second range.
626 template <class INPUT_ITER, class VALUE_TYPE>
627 static int lexicographical(INPUT_ITER start1,
628 INPUT_ITER end1,
629 INPUT_ITER start2,
630 INPUT_ITER end2,
631 const VALUE_TYPE&);
632
633 /// Compare the range beginning at the specified `start1` position and
634 /// ending immediately before the specified `end1` position with the
635 /// range beginning at the specified `start2` position of the same
636 /// length (namely, `end1 - start1`), using a bit-wise comparison
637 /// across the entire range, if `const char` is unsigned, and using
638 /// `operator<` otherwise. Return a negative value if the
639 /// first range compares lexicographically less than the second range, 0
640 /// if they are the same length and compare lexicographically equal, and
641 /// a positive value if the first range compares lexicographically
642 /// greater than the second range.
643 static int lexicographical(const char *start1,
644 const char *end1,
645 const char *start2);
646
647 /// Compare each element in the range beginning at the specified
648 /// `start1` position and ending immediately before the specified `end1`
649 /// position with the corresponding element in the range of the same
650 /// length beginning at the specified `start2` position. Return a
651 /// negative value if the first range compares lexicographically less
652 /// than the second range, 0 if they are the same length and compare
653 /// lexicographically equal, and a positive value if the first range
654 /// compares lexicographically greater than the second range.
655 static int lexicographical(const unsigned char *start1,
656 const unsigned char *end1,
657 const unsigned char *start2);
658 static int lexicographical(const wchar_t *start1,
659 const wchar_t *end1,
660 const wchar_t *start2);
661 template <class INPUT_ITER>
662 static int lexicographical(INPUT_ITER start1,
663 INPUT_ITER end1,
664 INPUT_ITER start2,
666 template <class INPUT_ITER>
667 static int lexicographical(INPUT_ITER start1,
668 INPUT_ITER end1,
669 INPUT_ITER start2);
670};
671
672// ============================================================================
673// INLINE AND TEMPLATE FUNCTION DEFINITIONS
674// ============================================================================
675
676 // -------------------
677 // struct RangeCompare
678 // -------------------
679
680// CLASS METHODS
681template <class INPUT_ITER>
682inline
683bool RangeCompare::equal(INPUT_ITER start1,
684 INPUT_ITER end1,
685 INPUT_ITER start2)
686{
687 if (start1 == end1) {
688 return true; // RETURN
689 }
690 return RangeCompare_Imp::equal(start1, end1, start2, *start1);
691}
692
693template <class INPUT_ITER>
694inline
695bool RangeCompare::equal(INPUT_ITER start1,
696 INPUT_ITER end1,
697 INPUT_ITER start2,
698 INPUT_ITER end2)
699{
700 if (start1 == end1) {
701 return start2 == end2; // RETURN
702 }
703 return RangeCompare_Imp::equal(start1, end1, start2, end2, *start1);
704}
705
706template <class INPUT_ITER>
707inline
708bool RangeCompare::equal(INPUT_ITER start1,
709 INPUT_ITER end1,
710 size_type length1,
711 INPUT_ITER start2,
712 INPUT_ITER,
713 size_type length2)
714{
715 if (length1 != length2) {
716 return false; // RETURN
717 }
718 if (start1 == end1) {
719 return true; // RETURN
720 }
721 return RangeCompare_Imp::equal(start1, end1, start2, *start1);
722}
723
724template <class INPUT_ITER>
725int RangeCompare::lexicographical(INPUT_ITER start1,
726 INPUT_ITER end1,
727 INPUT_ITER start2,
728 INPUT_ITER end2)
729{
730 if (start1 == end1) {
731 return start2 != end2 ? -1 : 0; // RETURN
732 }
734 end1,
735 start2,
736 end2,
737 *start1);
738}
739
740template <class INPUT_ITER>
741int RangeCompare::lexicographical(INPUT_ITER start1,
742 INPUT_ITER end1,
743 size_type length1,
744 INPUT_ITER start2,
745 INPUT_ITER end2,
746 size_type length2)
747{
748 const int result = length2 < length1
750 end2,
751 start1)
753 end1,
754 start2);
755
756 if (result < 0) {
757 return -1; // RETURN
758 }
759 if (0 < result) {
760 return 1; // RETURN
761 }
762 if (length1 < length2) {
763 return -1; // RETURN
764 }
765 if (length2 < length1) {
766 return 1; // RETURN
767 }
768 return 0;
769}
770
771 // -----------------------
772 // struct RangeCompare_Imp
773 // -----------------------
774
775// CLASS METHODS
776
777 // *** equal overloads: ***
778
779template <class VALUE_TYPE>
780inline
781bool RangeCompare_Imp::equal(const VALUE_TYPE *start1,
782 const VALUE_TYPE *end1,
783 const VALUE_TYPE *start2,
784 const VALUE_TYPE *end2,
785 const VALUE_TYPE&,
787{
788 return RangeCompare::equal(start1,
789 end1,
790 end1 - start1,
791 start2,
792 end2,
793 end2 - start2);
794}
795
796template <class INPUT_ITER, class VALUE_TYPE>
797bool RangeCompare_Imp::equal(INPUT_ITER start1,
798 INPUT_ITER end1,
799 INPUT_ITER start2,
800 INPUT_ITER end2,
801 const VALUE_TYPE&,
803{
804 for ( ; start1 != end1 && start2 != end2; ++start1, ++start2) {
805 if (!(*start1 == *start2)) {
806 return false; // RETURN
807 }
808 }
809 return start1 == end1 && start2 == end2;
810}
811
812template <class INPUT_ITER, class VALUE_TYPE>
813bool RangeCompare_Imp::equal(INPUT_ITER start1,
814 INPUT_ITER end1,
815 INPUT_ITER start2,
816 INPUT_ITER end2,
817 const VALUE_TYPE& value)
818{
820 CanUseLengthOptimization;
821
822 return equal(start1,
823 end1,
824 start2,
825 end2,
826 value,
827 CanUseLengthOptimization());
828}
829
830template <class INPUT_ITER, class VALUE_TYPE>
831inline
832bool RangeCompare_Imp::equal(INPUT_ITER start1,
833 INPUT_ITER end1,
834 INPUT_ITER start2,
835 const VALUE_TYPE&,
837{
838 // Note: We are forced to call a different function to resolve whether
839 // 'INPUT_ITER' is convertible to 'const TARGET_TYPE *' or not, otherwise
840 // we would be introducing ambiguities (the additional parameter
841 // 'CanUseBitwiseCopyOptimization' is necessary to remove further
842 // ambiguities on SunPro).
843
845 CanUseBitwiseCompareOptimization;
846
847 return equalBitwiseEqualityComparable(start1,
848 end1,
849 start2,
850 CanUseBitwiseCompareOptimization());
851}
852
853template <class INPUT_ITER, class VALUE_TYPE>
854bool RangeCompare_Imp::equal(INPUT_ITER start1,
855 INPUT_ITER end1,
856 INPUT_ITER start2,
857 const VALUE_TYPE&,
859{
860 for ( ; start1 != end1; ++start1, ++start2) {
861 if (!(*start1 == *start2)) {
862 return false; // RETURN
863 }
864 }
865 return true;
866}
867
868template <class INPUT_ITER, class VALUE_TYPE>
869inline
870bool RangeCompare_Imp::equal(INPUT_ITER start1,
871 INPUT_ITER end1,
872 INPUT_ITER start2,
873 const VALUE_TYPE& value)
874{
875 typedef typename
877 return equal(start1, end1, start2, value, Trait());
878}
879
880 // *** equalBitwiseEqualityComparable overloads: ***
881
882template <class VALUE_TYPE>
883inline
885 const VALUE_TYPE *start1,
886 const VALUE_TYPE *end1,
887 const VALUE_TYPE *start2,
889{
890 std::size_t numBytes = reinterpret_cast<const char *>(end1)
891 - reinterpret_cast<const char *>(start1);
892
893 return 0 == std::memcmp(reinterpret_cast<const void *>(start1),
894 reinterpret_cast<const void *>(start2),
895 numBytes);
896}
897
898template <class INPUT_ITER>
899inline
901 INPUT_ITER end1,
902 INPUT_ITER start2,
904{
905 // We can't be as optimized as above.
906
907 return equal(start1, end1, start2, *start1, bsl::false_type());
908}
909
910 // *** lexicographical overloads: ***
911
912template <class VALUE_TYPE>
913inline
914int RangeCompare_Imp::lexicographical(const VALUE_TYPE *start1,
915 const VALUE_TYPE *end1,
916 const VALUE_TYPE *start2,
917 const VALUE_TYPE *end2,
918 const VALUE_TYPE&,
920{
921 // In this case, we can compute the length directly, and avoid the overhead
922 // of the two comparisons in the loop condition (one is enough).
923
924 return RangeCompare::lexicographical(start1,
925 end1,
926 end1 - start1,
927 start2,
928 end2,
929 end2 - start2);
930}
931
932template <class INPUT_ITER, class VALUE_TYPE>
934 INPUT_ITER end1,
935 INPUT_ITER start2,
936 INPUT_ITER end2,
937 const VALUE_TYPE&,
938 const bsl::false_type)
939{
940 for ( ; start1 != end1 && start2 != end2; ++start1, ++start2) {
941 if (*start1 < *start2) {
942 return -1; // RETURN
943 }
944 else if (*start2 < *start1) {
945 return 1; // RETURN
946 }
947 }
948 if (start1 != end1) {
949 return 1; // RETURN
950 }
951 if (start2 != end2) {
952 return -1; // RETURN
953 }
954 return 0;
955}
956
957template <class INPUT_ITER, class VALUE_TYPE>
958inline
960 INPUT_ITER end1,
961 INPUT_ITER start2,
962 INPUT_ITER end2,
963 const VALUE_TYPE& value)
964{
966 CanUseLengthOptimization;
967
968 return lexicographical(start1, end1, start2, end2, value,
969 CanUseLengthOptimization());
970}
971
972inline
973int RangeCompare_Imp::lexicographical(const unsigned char *start1,
974 const unsigned char *end1,
975 const unsigned char *start2)
976{
977 return std::memcmp(start1, start2, end1 - start1);
978}
979
980inline
982 const char *end1,
983 const char *start2)
984{
985#if CHAR_MAX == SCHAR_MAX
986 return std::memcmp(start1, start2, (end1 - start1));
987#else
988 return lexicographical<const char *>(start1, end1, start2, 0);
989#endif
990}
991
992inline
993int RangeCompare_Imp::lexicographical(const wchar_t *start1,
994 const wchar_t *end1,
995 const wchar_t *start2)
996{
997 return std::wmemcmp(start1, start2, end1 - start1);
998}
999
1000template <class INPUT_ITER>
1002 INPUT_ITER end1,
1003 INPUT_ITER start2,
1005{
1006 for ( ; start1 != end1; ++start1, ++start2) {
1007 if (*start1 < *start2) {
1008 return -1; // RETURN
1009 }
1010 else if (*start2 < *start1) {
1011 return 1; // RETURN
1012 }
1013 }
1014 return 0;
1015}
1016
1017template <class INPUT_ITER>
1018inline
1020 INPUT_ITER end1,
1021 INPUT_ITER start2)
1022{
1023 if (start1 != end1) {
1024 return lexicographical(start1, end1, start2, *start1); // RETURN
1025 }
1026 return 0;
1027}
1028
1029} // close package namespace
1030
1031#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
1032// ============================================================================
1033// BACKWARD COMPATIBILITY
1034// ============================================================================
1035
1036/// This alias is defined for backward compatibility.
1038#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
1039
1040
1041
1042#endif
1043
1044// ----------------------------------------------------------------------------
1045// Copyright 2013 Bloomberg Finance L.P.
1046//
1047// Licensed under the Apache License, Version 2.0 (the "License");
1048// you may not use this file except in compliance with the License.
1049// You may obtain a copy of the License at
1050//
1051// http://www.apache.org/licenses/LICENSE-2.0
1052//
1053// Unless required by applicable law or agreed to in writing, software
1054// distributed under the License is distributed on an "AS IS" BASIS,
1055// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1056// See the License for the specific language governing permissions and
1057// limitations under the License.
1058// ----------------------------- END-OF-FILE ----------------------------------
1059
1060/** @} */
1061/** @} */
1062/** @} */
bslalg::RangeCompare bslalg_RangeCompare
This alias is defined for backward compatibility.
Definition bslalg_rangecompare.h:1037
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdlc_flathashmap.h:2218
Definition bslmf_isconvertible.h:875
Definition bslalg_rangecompare.h:495
static int lexicographical(const VALUE_TYPE *start1, const VALUE_TYPE *end1, const VALUE_TYPE *start2, const VALUE_TYPE *end2, const VALUE_TYPE &, bsl::true_type)
Definition bslalg_rangecompare.h:914
static bool equal(const VALUE_TYPE *start1, const VALUE_TYPE *end1, const VALUE_TYPE *start2, const VALUE_TYPE *end2, const VALUE_TYPE &, bsl::true_type)
Definition bslalg_rangecompare.h:781
static bool equalBitwiseEqualityComparable(const VALUE_TYPE *start1, const VALUE_TYPE *end1, const VALUE_TYPE *start2, bsl::true_type)
Definition bslalg_rangecompare.h:884
Definition bslalg_rangecompare.h:400
static bool equal(INPUT_ITER start1, INPUT_ITER end1, INPUT_ITER start2)
Definition bslalg_rangecompare.h:683
std::size_t size_type
Definition bslalg_rangecompare.h:406
static int lexicographical(INPUT_ITER start1, INPUT_ITER end1, INPUT_ITER start2, INPUT_ITER end2)
Definition bslalg_rangecompare.h:725
Definition bslmf_isbitwiseequalitycomparable.h:500
Definition bslmf_matchanytype.h:152