BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlb_bitstringutil.h
Go to the documentation of this file.
1/// @file bdlb_bitstringutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlb_bitstringutil.h -*-C++-*-
8#ifndef INCLUDED_BDLB_BITSTRINGUTIL
9#define INCLUDED_BDLB_BITSTRINGUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlb_bitstringutil bdlb_bitstringutil
15/// @brief Provide efficient operations on a multi-word sequence of bits.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlb
19/// @{
20/// @addtogroup bdlb_bitstringutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlb_bitstringutil-purpose"> Purpose</a>
25/// * <a href="#bdlb_bitstringutil-classes"> Classes </a>
26/// * <a href="#bdlb_bitstringutil-description"> Description </a>
27/// * <a href="#bdlb_bitstringutil-the-bit-string-pseudo-type"> The "Bit String" Pseudo-Type </a>
28/// * <a href="#bdlb_bitstringutil-manipulator-functions"> Manipulator Functions </a>
29/// * <a href="#bdlb_bitstringutil-accessor-functions"> Accessor Functions </a>
30/// * <a href="#bdlb_bitstringutil-usage"> Usage </a>
31/// * <a href="#bdlb_bitstringutil-example-1-maintaining-a-calendar-of-business-days"> Example 1: Maintaining a Calendar of Business Days </a>
32///
33/// # Purpose {#bdlb_bitstringutil-purpose}
34/// Provide efficient operations on a multi-word sequence of bits.
35///
36/// # Classes {#bdlb_bitstringutil-classes}
37///
38/// - bdlb::BitStringUtil: namespace for common bit-manipulation procedures
39///
40/// @see bdlb_bitutil, bdlb_bitmaskutil, bdlb_bitstringimputil,
41/// bdlc_bitarray
42///
43/// # Description {#bdlb_bitstringutil-description}
44/// This component provides a utility `struct`,
45/// `bdlb::BitStringUtil`, that serves as a namespace for a collection of
46/// efficient, bit-level procedures on "bit strings", sequences of bits stored
47/// in arrays of 64-bit `uint64_t` values. A number of operations of various
48/// types are provided: bitwise-logical, copy, assignment, read, insert/remove,
49/// compare, find, count, and print operations are offered, among others.
50///
51/// ## The "Bit String" Pseudo-Type {#bdlb_bitstringutil-the-bit-string-pseudo-type}
52///
53///
54/// A contiguous sequence of bits that occupy a positive integral number of
55/// sequential `uint64_t` values can be viewed as a string of bits. This
56/// component supports operations on such sequences. The notion of "bit
57/// string", a pseudo-type, is used to document those operations.
58/// Correspondingly, `BitStringUtil` operations are categorized as either
59/// "manipulators", operations that modify bit strings; or "accessors",
60/// operations that return information and guarantee that no change to bit
61/// strings occurs.
62///
63/// A bit string has two "structural" attributes:
64/// @code
65/// Capacity - The capacity, in bits, of a bit string is the number of
66/// 'uint64_t' values in the array multiplied by
67/// 'BitStringUtil::k_BITS_PER_UINT64'. Note that the capacity of a
68/// bit string is analogous to the capacity of a 'bsl::vector'.
69///
70/// Length - The number of significant bits stored in the bit string. The
71/// length can never exceed the capacity, and the length is
72/// analogous to the length of a 'bsl::vector'.
73/// @endcode
74/// Since the bit string is a pseudo-type, there is no language support for
75/// managing these values; the user must do so explicitly.
76///
77/// Many operations on a bit string refer to a "position" within a bit string,
78/// or a range of positions within a bit string:
79/// @code
80/// Position - The offset (in bits) of a bit value from the beginning of a
81/// bit string (also called the "index" of a bit).
82/// @endcode
83/// The notion of "position" used in this component is a generalization of the
84/// notion of a bit's position in a single integer value.
85///
86/// Bits within a 64-bit `uint64_t` (irrespective of the endian-ness of a
87/// platform) are here numbered, starting at 0, from the least-significant bit
88/// to the most-significant bit. In illustrations, we typically show the
89/// high-order bits on the left:
90/// @code
91/// 63 62 . . . . . 5 4 3 2 1 0
92/// +-----------------------------------+
93/// | 1| 0| . . . . . | 1| 1| 0| 0| 1| 0|
94/// +-----------------------------------+
95/// @endcode
96/// Thus, left-shifting (e.g., caused by `insert`ing low-order bits) causes bits
97/// to move up in bit-position (to positions of higher significance) and
98/// right-shifting (e.g., caused by `remove`ing low-order bits) causes bits to
99/// move into positions of less significance.
100///
101/// This component extends this representation to an arbitrary sequence of bits
102/// represented using an array of 64-bit `uint64_t` values. For example, the
103/// bit string shown below is built on an array of three `uint64_t` values.
104/// Thus, it has a capacity of 192 (i.e.,
105/// `3 * BitStringUtil::k_BITS_PER_UINT64`). Note that words are ordered
106/// right-to-left, so the lowest-order bits are to the right. This is also how
107/// the `bdlb::BitStringUtil::print` function orders the words it outputs:
108/// @code
109/// |<------ word 2 ------>|<------ word 1 ------>|<------ word 0 ------>|
110/// | 191 190 . . 129 128 | 127 126 . . . 65 64 | 63 62 . . . . . 1 0 |
111/// +----------------------+----------------------+----------------------+
112/// @endcode
113///
114/// ## Manipulator Functions {#bdlb_bitstringutil-manipulator-functions}
115///
116///
117/// Manipulator functions return `void`, and take the address of an integer as
118/// the first argument in order to modify it in place.
119/// @code
120///
121///
122/// Assignment
123/// +--------------------------------------------------------------------------+
124/// | assign | Overloaded; assign 0 or more contiguous bits to a specified |
125/// | | 'bool' value. |
126/// +--------------------------------------------------------------------------+
127/// | assign0 | Overloaded; assign 0 or more contiguous bits to 'false'. |
128/// +--------------------------------------------------------------------------+
129/// | assign1 | Overloaded; assign 0 or more contiguous bits to 'true'. |
130/// +--------------------------------------------------------------------------+
131/// | assignBits | Assign up to one word of contiguous bits, taken from a |
132/// | | 'uint64_t' argument. |
133/// +--------------------------------------------------------------------------+
134///
135///
136/// Bitwise-Logical
137/// +--------------------------------------------------------------------------+
138/// | andEqual | Bitwise-AND ranges of equal length from two bit strings, a |
139/// | | 'dstBitString' and a 'srcBitString', writing the result |
140/// | | over the range from 'dstBitString'. |
141/// +--------------------------------------------------------------------------+
142/// | minusEqual | Bitwise-MINUS ranges of equal length from two bit strings, |
143/// | | a 'srcBitString' from a 'dstBitString', writing the result |
144/// | | over the range from 'dstBitString'. |
145/// +--------------------------------------------------------------------------+
146/// | orEqual | Bitwise-OR ranges of equal length from two bit strings, a |
147/// | | 'dstBitString' and a 'srcBitString', writing the result |
148/// | | over the range from 'dstBitString'. |
149/// +--------------------------------------------------------------------------+
150/// | xorEqual | Bitwise-XOR ranges of equal length from two bit strings, a |
151/// | | 'dstBitString' and a 'srcBitString', writing the result |
152/// | | over the range from 'dstBitString'. |
153/// +--------------------------------------------------------------------------+
154///
155///
156/// Copy
157/// +--------------------------------------------------------------------------+
158/// | copyRaw | Copy a range from one bit string to another range, with some |
159/// | | restrictions on overlap between the two ranges. |
160/// +--------------------------------------------------------------------------+
161/// | copy | Copy a range from one bit string to another range, with no |
162/// | | restrictions on overlap between the two ranges. |
163/// +--------------------------------------------------------------------------+
164///
165///
166/// Insert / Remove
167/// +--------------------------------------------------------------------------+
168/// | insert | Overloaded; insert 0 or more bits of a specified 'bool' |
169/// | | value. |
170/// +--------------------------------------------------------------------------+
171/// | insert0 | Overloaded; insert 0 or more 'false' bits. |
172/// +--------------------------------------------------------------------------+
173/// | insert1 | Overloaded; insert 0 or more 'true' bits. |
174/// +--------------------------------------------------------------------------+
175/// | insertRaw | Make room for additional bits in a bit string by moving all |
176/// | | bits above a given index up, leaving the values of the |
177/// | | newly-inserted bits undefined. |
178/// +--------------------------------------------------------------------------+
179/// | remove | Remove 0 or more bits from a bit string. |
180/// +--------------------------------------------------------------------------+
181/// | removeAndFill0 | Remove 0 or more bits from a bit string and assign |
182/// | | 'false' to vacated higher-order bits. |
183/// +--------------------------------------------------------------------------+
184/// | removeAndFill1 | Remove 0 or more bits from a bit string and assign |
185/// | | 'true' to vacated higher-order bits. |
186/// +--------------------------------------------------------------------------+
187///
188///
189/// Other Manipulators
190/// +--------------------------------------------------------------------------+
191/// | swapRaw | Swap two ranges of bit strings, which must not overlap. |
192/// +--------------------------------------------------------------------------+
193/// | toggle | Negate all the bits in a range of a bit string. |
194/// +--------------------------------------------------------------------------+
195///
196/// @endcode
197///
198/// ## Accessor Functions {#bdlb_bitstringutil-accessor-functions}
199///
200///
201/// Accessor function return a value but do not modify a bit string.
202/// @code
203///
204/// Compare
205/// +--------------------------------------------------------------------------+
206/// | areEqual | Compare two ranges of bits for equality. |
207/// +--------------------------------------------------------------------------+
208///
209///
210/// Read
211/// +--------------------------------------------------------------------------+
212/// | bit | Return the boolean value of a single bit from a bit string. |
213/// +--------------------------------------------------------------------------+
214/// | bits | Return a 'uint64_t' containing at most 'k_BITS_PER_UINT64' |
215/// | | adjacent bits from a bit string. |
216/// +--------------------------------------------------------------------------+
217///
218///
219/// Find
220/// +--------------------------------------------------------------------------+
221/// | find0AtMaxIndex | Locate the highest-order 0 bit in a range. |
222/// +--------------------------------------------------------------------------+
223/// | find0AtMinIndex | Locate the lowest-order 0 bit in a range. |
224/// +--------------------------------------------------------------------------+
225/// | find1AtMaxIndex | Locate the highest-order 1 bit in a range. |
226/// +--------------------------------------------------------------------------+
227/// | find1AtMinIndex | Locate the lowest-order 1 bit in a range. |
228/// +--------------------------------------------------------------------------+
229///
230///
231/// Count
232/// +--------------------------------------------------------------------------+
233/// | isAny0 | Return 'true' if any bit in a range is 0, and 'false' |
234/// | | otherwise. |
235/// +--------------------------------------------------------------------------+
236/// | isAny1 | Return 'true' if any bit in a range is 1, and 'false' |
237/// | | otherwise. |
238/// +--------------------------------------------------------------------------+
239/// | num0 | Return the number of 0 bits in a range. |
240/// +--------------------------------------------------------------------------+
241/// | num1 | Return the number of 1 bits in a range. |
242/// +--------------------------------------------------------------------------+
243///
244///
245/// Output
246/// +--------------------------------------------------------------------------+
247/// | print | Output a bit string in hex. |
248/// +--------------------------------------------------------------------------+
249///
250/// @endcode
251///
252/// ## Usage {#bdlb_bitstringutil-usage}
253///
254///
255/// This section illustrates intended use of this component.
256///
257/// ### Example 1: Maintaining a Calendar of Business Days {#bdlb_bitstringutil-example-1-maintaining-a-calendar-of-business-days}
258///
259///
260/// Bit strings can be used to represent business calendars and facilitate
261/// efficient operations on such calendars. We will use bit strings to mark
262/// properties of days of the year 2013.
263///
264/// First, create an enumeration showing the number of days in the year 2013
265/// before the beginning of each month, so that:
266/// @code
267/// <constant for month> + <day of month> == <day of year>
268///
269/// enum {
270/// JAN = 0, // Note: First DOY is 'JAN + 1'.
271/// FEB = JAN + 31,
272/// MAR = FEB + 28, // 2013 was not a leap year.
273/// APR = MAR + 31,
274/// MAY = APR + 30,
275/// JUN = MAY + 31,
276/// JUL = JUN + 30,
277/// AUG = JUL + 31,
278/// SEP = AUG + 31,
279/// OCT = SEP + 30,
280/// NOV = OCT + 31,
281/// DEC = NOV + 30
282/// };
283/// @endcode
284/// Then, create a bit string with sufficient capacity to represent every day
285/// of a year (note that 64 * 6 = 384) and set a 1-bit in the indices
286/// corresponding to the day-of-year (DOY) for each weekend day. For
287/// convenience in date calculations, the 0 index is not used; the 365 days of
288/// the year are at indices `[1 .. 365]`. Further note that the values set
289/// below correspond to the year 2013:
290/// @code
291/// uint64_t weekends[6] = { 0 };
292///
293/// // We are marking only weekend days, so start with the first weekend day
294/// // of the year: Saturday, January 5, 2013.
295///
296/// for (int i = 5; i < 366; i += 7) {
297/// bdlb::BitStringUtil::assign(weekends, i, 1);
298/// if (i + 1 < 366) {
299/// bdlb::BitStringUtil::assign(weekends, i + 1, 1);
300/// }
301/// }
302/// @endcode
303/// Next, we can easily use `bdlb::BitStringUtil` methods to find days of
304/// interest. For example, we can find the first and last weekend days of the
305/// year:
306/// @code
307/// const int firstWeekendDay = bdlb::BitStringUtil::find1AtMinIndex(weekends,
308/// 365 + 1);
309/// const int lastWeekendDay = bdlb::BitStringUtil::find1AtMaxIndex(weekends,
310/// 365 + 1);
311///
312/// assert(JAN + 5 == firstWeekendDay);
313/// assert(DEC + 29 == lastWeekendDay);
314/// @endcode
315/// Then, we define the following enumeration that allows us to easily represent
316/// the US holidays of the year:
317/// @code
318/// uint64_t holidays[6] = { 0 };
319///
320/// enum USHolidays2013 {
321/// NEW_YEARS_DAY = JAN + 1,
322/// MARTIN_LUTHER_KING_JR_DAY = JAN + 21,
323/// PRESIDENTS_DAY = FEB + 18,
324/// GOOD_FRIDAY = MAR + 29,
325/// MEMORIAL_DAY = MAY + 27,
326/// INDEPENDENCE_DAY = JUL + 4,
327/// LABOR_DAY = SEP + 2,
328/// THANKSGIVING = NOV + 28,
329/// CHRISTMAS = DEC + 25
330/// };
331///
332/// bdlb::BitStringUtil::assign(holidays, NEW_YEARS_DAY, true);
333/// bdlb::BitStringUtil::assign(holidays, MARTIN_LUTHER_KING_JR_DAY, true);
334/// bdlb::BitStringUtil::assign(holidays, PRESIDENTS_DAY, true);
335/// bdlb::BitStringUtil::assign(holidays, GOOD_FRIDAY, true);
336/// bdlb::BitStringUtil::assign(holidays, MEMORIAL_DAY, true);
337/// bdlb::BitStringUtil::assign(holidays, INDEPENDENCE_DAY, true);
338/// bdlb::BitStringUtil::assign(holidays, LABOR_DAY, true);
339/// bdlb::BitStringUtil::assign(holidays, THANKSGIVING, true);
340/// bdlb::BitStringUtil::assign(holidays, CHRISTMAS, true);
341/// @endcode
342/// Next, the following enumeration indicates the beginning of fiscal quarters:
343/// @code
344/// enum {
345/// Q1 = JAN + 1,
346/// Q2 = APR + 1,
347/// Q3 = JUN + 1,
348/// Q4 = OCT + 1
349/// };
350/// @endcode
351/// Now, we can query our calendar for the first holiday in the third quarter,
352/// if any:
353/// @code
354/// const bsl::size_t firstHolidayOfQ3 = bdlb::BitStringUtil::find1AtMinIndex(
355/// holidays,
356/// Q3,
357/// Q4);
358/// assert(INDEPENDENCE_DAY == firstHolidayOfQ3);
359/// @endcode
360/// Finally, our weekend and holiday calendars are readily combined to represent
361/// days off for either reason (i.e., holiday or weekend):
362/// @code
363/// uint64_t allDaysOff[6] = { 0 };
364/// bdlb::BitStringUtil::orEqual(allDaysOff, 1, weekends, 1, 365);
365/// bdlb::BitStringUtil::orEqual(allDaysOff, 1, holidays, 1, 365);
366///
367/// bool isOffMay24 = bdlb::BitStringUtil::bit(allDaysOff, MAY + 24);
368/// bool isOffMay25 = bdlb::BitStringUtil::bit(allDaysOff, MAY + 25);
369/// bool isOffMay26 = bdlb::BitStringUtil::bit(allDaysOff, MAY + 26);
370/// bool isOffMay27 = bdlb::BitStringUtil::bit(allDaysOff, MAY + 27);
371/// bool isOffMay28 = bdlb::BitStringUtil::bit(allDaysOff, MAY + 28);
372///
373/// assert(false == isOffMay24);
374/// assert(true == isOffMay25); // Saturday
375/// assert(true == isOffMay26); // Sunday
376/// assert(true == isOffMay27); // Note May 27, 2013 is Memorial Day.
377/// assert(false == isOffMay28);
378/// @endcode
379/// @}
380/** @} */
381/** @} */
382
383/** @addtogroup bdl
384 * @{
385 */
386/** @addtogroup bdlb
387 * @{
388 */
389/** @addtogroup bdlb_bitstringutil
390 * @{
391 */
392
393#include <bdlscm_version.h>
394
395#include <bdlb_bitutil.h>
396
397#include <bsls_assert.h>
398#include <bsls_review.h>
399
400#include <bsl_cstddef.h>
401#include <bsl_cstdint.h>
402#include <bsl_iosfwd.h>
403
404
405namespace bdlb {
406
407 // ====================
408 // struct BitStringUtil
409 // ====================
410
411/// This `struct` provides a namespace for a suite of static functions to
412/// manipulate and access sequences of bits stored in an array of `uint64_t`
413/// (also known as a "bit string"; see {The "Bit String" Pseudo-Type}).
414///
415/// See @ref bdlb_bitstringutil
417
418 // PUBLIC TYPES
419 enum { k_BITS_PER_UINT64 = 64 }; // number of bits in a 'uint64_t'
420
421 // PUBLIC CLASS CONSTANTS
422 static const bsl::size_t k_INVALID_INDEX = ~static_cast<bsl::size_t>(0);
423
424 // CLASS METHODS
425
426 // Assign
427
428 /// Set the bit at the specified `index` in the specified `bitString` to the specified `value`.
429 ///
430 /// \pre The behavior is undefined unless `index` is
431 /// less than the capacity of `bitString`.
432 static void assign(bsl::uint64_t *bitString,
433 bsl::size_t index,
434 bool value);
435
436 /// Set the specified `numBits` beginning at the specified `index` in
437 /// the specified `bitString` to the specified `value`.
438 ///
439 /// \pre The behavior is undefined unless `bitString` has a capacity of at least
440 /// `index + numBits`.
441 static void assign(bsl::uint64_t *bitString,
442 bsl::size_t index,
443 bool value,
444 bsl::size_t numBits);
445
446 /// Set the bit at the specified `index` in the specified `bitString` to `false`.
447 ///
448 /// \pre The behavior is undefined unless `index` is less than the
449 /// capacity of `bitString`.
450 static void assign0(bsl::uint64_t *bitString, bsl::size_t index);
451
452 /// Set the specified `numBits` beginning at the specified `index` in
453 /// the specified `bitString` to `false`.
454 ///
455 /// \pre The behavior is undefined unless `bitString` has a capacity of at least `index + numBits`.
456 static void assign0(bsl::uint64_t *bitString,
457 bsl::size_t index,
458 bsl::size_t numBits);
459
460 /// Set the bit at the specified `index` in the specified `bitString` to `true`.
461 ///
462 /// \pre The behavior is undefined unless `index` is less than the
463 /// capacity of `bitString`.
464 static void assign1(bsl::uint64_t *bitString, bsl::size_t index);
465
466 /// Set the specified `numBits` beginning at the specified `index` in
467 /// the specified `bitString` to `true`.
468 ///
469 /// \pre The behavior is undefined unless `bitString` has a capacity of at least `index + numBits`.
470 static void assign1(bsl::uint64_t *bitString,
471 bsl::size_t index,
472 bsl::size_t numBits);
473
474 /// Assign the low-order specified `numBits` from the specified
475 /// `srcValue` to the `numBits` starting at the specified `index` in the specified `bitString`.
476 ///
477 /// \pre The behavior is undefined unless
478 /// `numBits <= k_BITS_PER_UINT64` and `bitString` has a capacity of at
479 /// least `index + numBits`.
480 static void assignBits(bsl::uint64_t *bitString,
481 bsl::size_t index,
482 bsl::uint64_t srcValue,
483 bsl::size_t numBits);
484
485 // Bitwise-Logical
486
487 /// Bitwise AND the specified `numBits` of the specified `dstBitString`
488 /// starting at the specified `dstIndex` with the `numBits` of the
489 /// specified `srcBitString` starting at the specified `srcIndex`, and
490 /// write the result over the bits that were read from `dstBitString`.
491 ///
492 /// \pre The behavior is undefined unless `dstBitString` has a length of at
493 /// least `dstIndex + numBits` and `srcBitString` has a length of at
494 /// least `srcIndex + numBits`.
495 static void andEqual(bsl::uint64_t *dstBitString,
496 bsl::size_t dstIndex,
497 const bsl::uint64_t *srcBitString,
498 bsl::size_t srcIndex,
499 bsl::size_t numBits);
500
501 /// Bitwise MINUS the specified `numBits` of the specified
502 /// `srcBitString` starting at the specified `srcIndex` from the
503 /// `numBits` of the specified `dstBitString` starting at the specified
504 /// `dstIndex`, and write the result over the bits that were read from `dstBitString`.
505 ///
506 /// \pre The behavior is undefined unless `dstBitString` has
507 /// a length of at least `dstIndex + numBits` and `srcBitString` has a length of at least `srcIndex + numBits`.
508 ///
509 /// \note Note that the logical
510 /// difference `A - B` is defined to be `A & !B`.
511 static void minusEqual(bsl::uint64_t *dstBitString,
512 bsl::size_t dstIndex,
513 const bsl::uint64_t *srcBitString,
514 bsl::size_t srcIndex,
515 bsl::size_t numBits);
516
517 /// Bitwise OR the specified `numBits` of the specified `dstBitString`
518 /// starting at the specified `dstIndex` with the `numBits` of the
519 /// specified `srcBitString` starting at the specified `srcIndex`, and
520 /// write the result over the bits that were read from `dstBitString`.
521 ///
522 /// \pre The behavior is undefined unless `dstBitString` has a length of at
523 /// least `dstIndex + numBits` and `srcBitString` has a length of at
524 /// least `srcIndex + numBits`.
525 static void orEqual(bsl::uint64_t *dstBitString,
526 bsl::size_t dstIndex,
527 const bsl::uint64_t *srcBitString,
528 bsl::size_t srcIndex,
529 bsl::size_t numBits);
530
531 /// Bitwise XOR the specified `numBits` of the specified `dstBitString`
532 /// starting at the specified `dstIndex` with the `numBits` of the
533 /// specified `srcBitString` starting at the specified `srcIndex`, and
534 /// write the result over the bits that were read from `dstBitString`.
535 ///
536 /// \pre The behavior is undefined unless `dstBitString` has a length of at
537 /// least `dstIndex + numBits` and `srcBitString` has a length of at
538 /// least `srcIndex + numBits`.
539 static void xorEqual(bsl::uint64_t *dstBitString,
540 bsl::size_t dstIndex,
541 const bsl::uint64_t *srcBitString,
542 bsl::size_t srcIndex,
543 bsl::size_t numBits);
544
545 // Copy
546
547 /// Copy to the specified `dstBitString`, beginning at the specified
548 /// `dstIndex`, the specified `numBits` beginning at the specified
549 /// `srcIndex` in the specified `srcBitString`. This function works
550 /// correctly regardless of whether the source and destination ranges overlap.
551 ///
552 /// \pre The behavior is undefined unless `dstBitString` has a
553 /// capacity of at least `dstIndex + numBits` and `srcBitString` has a
554 /// length of at least `srcIndex + numBits`.
555 static void copy(bsl::uint64_t *dstBitString,
556 bsl::size_t dstIndex,
557 const bsl::uint64_t *srcBitString,
558 bsl::size_t srcIndex,
559 bsl::size_t numBits);
560
561 /// Copy to the specified `dstBitString`, beginning at the specified
562 /// `dstIndex`, the specified `numBits` beginning at the specified
563 /// `srcIndex` in the specified `srcBitString`.
564 ///
565 /// \pre The behavior is undefined unless `dstBitString` has a capacity of at least
566 /// `dstIndex + numBits`, `srcBitString` has a length of at least
567 /// `srcIndex + numBits`, and the source and destination ranges either
568 /// do not overlap, or the destination range is equal to the source
569 /// range, or the start of the destination range is below the start of
570 /// the source range.
571 static void copyRaw(bsl::uint64_t *dstBitString,
572 bsl::size_t dstIndex,
573 const bsl::uint64_t *srcBitString,
574 bsl::size_t srcIndex,
575 bsl::size_t numBits);
576
577 // Insert / Remove
578
579 /// Insert the specified `numBits`, each having the specified `value`,
580 /// into the specified `bitString` having the specified `initialLength`,
581 /// beginning at the specified `dstIndex`. Bits at or above `dstIndex`
582 /// are shifted up by `numBits` index positions and the length of
583 /// `bitString` is increased by `numBits`.
584 ///
585 /// \pre The behavior is undefined unless `dstIndex <= initialLength` and `bitString` has a capacity of
586 /// at least `initialLength + numBits`.
587 static void insert(bsl::uint64_t *bitString,
588 bsl::size_t initialLength,
589 bsl::size_t dstIndex,
590 bool value,
591 bsl::size_t numBits);
592
593 /// Insert the specified `numBits` 0 bits into the specified `bitString`
594 /// having the specified `initialLength` beginning at the specified
595 /// `dstIndex`. Bits at or above `dstIndex` are shifted up by `numBits`
596 /// index positions and the length of `bitString` is increased by `numBits`.
597 ///
598 /// \pre The behavior is undefined unless
599 /// `dstIndex <= initialLength` and `bitString` has a capacity of at
600 /// least `initialLength + numBits`.
601 static void insert0(bsl::uint64_t *bitString,
602 bsl::size_t initialLength,
603 bsl::size_t dstIndex,
604 bsl::size_t numBits);
605
606 /// Insert the specified `numBits` 1 bits into the specified `bitString`
607 /// having the specified `initialLength` beginning at the specified
608 /// `dstIndex`. Bits at or above `dstIndex` are shifted up by `numBits`
609 /// index positions and the length of `bitString` is increased by `numBits`.
610 ///
611 /// \pre The behavior is undefined unless
612 /// `dstIndex <= initialLength` and `bitString` has a capacity of at
613 /// least `initialLength + numBits`.
614 static void insert1(bsl::uint64_t *bitString,
615 bsl::size_t initialLength,
616 bsl::size_t dstIndex,
617 bsl::size_t numBits);
618
619 /// Insert the specified `numBits` into the specified `bitString` having
620 /// the specified `initialLength` beginning at the specified `dstIndex`.
621 /// Bits at or above `dstIndex` are shifted up by `numBits` index
622 /// positions and the length of `bitString` is increased by `numBits`.
623 /// The values of the inserted bits are undefined.
624 ///
625 /// \pre The behavior is undefined unless `dstIndex <= initialLength` and `bitString` has a capacity of at least `initialLength + numBits`.
626 ///
627 /// \note Note that the
628 /// inserted bits are not assigned any value.
629 static void insertRaw(bsl::uint64_t *bitString,
630 bsl::size_t initialLength,
631 bsl::size_t dstIndex,
632 bsl::size_t numBits);
633
634 /// Remove the specified `numBits` from the specified `bitString` of the
635 /// specified `length` beginning at the specified `index`. Bits above
636 /// `index + numBits` are shifted down by `numBits` index positions and
637 /// the length of `bitString` is reduced by `numBits`. The values of
638 /// the vacated high-order bits are not modified.
639 ///
640 /// \pre The behavior is undefined unless `index + numBits <= length`.
641 static void remove(bsl::uint64_t *bitString,
642 bsl::size_t length,
643 bsl::size_t index,
644 bsl::size_t numBits);
645
646 /// Remove the specified `numBits` from the specified `bitString` having
647 /// the specified `length` beginning at the specified `index`. Bits
648 /// above `index + numBits` are shifted down by `numBits` index
649 /// positions and the last `numBits` of `bitString` are set to 0. The
650 /// length of `bitString` is not changed.
651 ///
652 /// \pre The behavior is undefined unless `index + numBits <= length`.
653 static void removeAndFill0(bsl::uint64_t *bitString,
654 bsl::size_t length,
655 bsl::size_t index,
656 bsl::size_t numBits);
657
658 /// Remove the specified `numBits` from the specified `bitString` having
659 /// the specified `length` beginning at the specified `index`. Bits
660 /// above `index + numBits` are shifted down by `numBits` index
661 /// positions and the last `numBits` of `bitString` are set to 1. The
662 /// length of `bitString` is not changed.
663 ///
664 /// \pre The behavior is undefined unless `index + numBits <= length`.
665 static void removeAndFill1(bsl::uint64_t *bitString,
666 bsl::size_t length,
667 bsl::size_t index,
668 bsl::size_t numBits);
669
670 // Other Manipulators
671
672 /// Exchange the specified `numBits` beginning at the specified `index1`
673 /// in the specified `bitString1` with the `numBits` beginning at the
674 /// specified `index2` in the specified `bitString2`.
675 ///
676 /// \pre The behavior is undefined unless `bitString1` has a length of at least
677 /// `index1 + numBits`, `bitString2` has a length of at least
678 /// `index2 + numBits`, and there is *no* overlap between the swapped
679 /// ranges of bits.
680 static void swapRaw(bsl::uint64_t *bitString1,
681 bsl::size_t index1,
682 bsl::uint64_t *bitString2,
683 bsl::size_t index2,
684 bsl::size_t numBits);
685
686 /// Invert the values of the specified `numBits` in the specified
687 /// `bitString` beginning at the specified `index`.
688 ///
689 /// \pre The behavior is undefined unless `bitString` has a length of at least
690 /// `index + numBits`.
691 static void toggle(bsl::uint64_t *bitString,
692 bsl::size_t index,
693 bsl::size_t numBits);
694
695 // Compare
696
697 /// Return `true` if the specified low-order `numBits` in the specified
698 /// `bitString1` are bitwise equal to the corresponding bits in the
699 /// specified `bitString2`, and `false` otherwise.
700 ///
701 /// \pre The behavior is undefined unless both `bitString1` and `bitString2` have a length of
702 /// at least `numBits`.
703 static bool areEqual(const bsl::uint64_t *bitString1,
704 const bsl::uint64_t *bitString2,
705 bsl::size_t numBits);
706
707 /// Return `true` if the specified `numBits` beginning at the specified
708 /// `index1` in the specified `bitString1` are bitwise equal to the
709 /// `numBits` beginning at the specified `index2` in the specified
710 /// `bitString2`, and `false` otherwise.
711 ///
712 /// \pre The behavior is undefined unless `bitString1` has a length of at least `index1 + numBits` and
713 /// `bitString2` has a length of at least `index2 + numBits`.
714 static bool areEqual(const bsl::uint64_t *bitString1,
715 bsl::size_t index1,
716 const bsl::uint64_t *bitString2,
717 bsl::size_t index2,
718 bsl::size_t numBits);
719
720 // Read
721
722 /// Return the bit value at the specified `index` in the specified `bitString`.
723 ///
724 /// \pre The behavior is undefined unless `index` is less than
725 /// the length of `bitString`.
726 static bool bit(const bsl::uint64_t *bitString, bsl::size_t index);
727
728 /// Return the specified `numBits` beginning at the specified `index` in
729 /// the specified `bitString` as the low-order bits of the returned value.
730 ///
731 /// \pre The behavior is undefined unless
732 /// `numBits <= k_BITS_PER_UINT64` and `bitString` has a length of at
733 /// least `index + numBits`.
734 static bsl::uint64_t bits(const bsl::uint64_t *bitString,
735 bsl::size_t index,
736 bsl::size_t numBits);
737
738 // Find
739
740 /// Return the index of the most-significant 0 bit in the specified
741 /// `bitString` having the specified `length`, if such a bit exists, and
742 /// `k_INVALID_INDEX` otherwise.
743 static bsl::size_t find0AtMaxIndex(const bsl::uint64_t *bitString,
744 bsl::size_t length);
745
746 /// Return the index of the most-significant 0 bit in the specified
747 /// `bitString` in the specified range `[begin .. end)`, if such a bit
748 /// exists, and `k_INVALID_INDEX` otherwise.
749 ///
750 /// \pre The behavior is undefined unless `begin <= end` and `end` is less than or equal to the length
751 /// of `bitString`.
752 static bsl::size_t find0AtMaxIndex(const bsl::uint64_t *bitString,
753 bsl::size_t begin,
754 bsl::size_t end);
755
756 /// Return the index of the least-significant 0 bit in the specified
757 /// `bitString` having the specified `length`, if such a bit exists, and
758 /// `k_INVALID_INDEX` otherwise.
759 static bsl::size_t find0AtMinIndex(const bsl::uint64_t *bitString,
760 bsl::size_t length);
761
762 /// Return the index of the least-significant 0 bit in the specified
763 /// `bitString` in the specified range `[begin .. end)`, if such a bit
764 /// exists, and `k_INVALID_INDEX` otherwise.
765 ///
766 /// \pre The behavior is undefined unless `begin <= end` and `end` is less than or equal to the length
767 /// of `bitString`.
768 static bsl::size_t find0AtMinIndex(const bsl::uint64_t *bitString,
769 bsl::size_t begin,
770 bsl::size_t end);
771
772 /// Return the index of the most-significant 1 bit in the specified
773 /// `bitString` having the specified `length`, if such a bit exists, and
774 /// `k_INVALID_INDEX` otherwise.
775 static bsl::size_t find1AtMaxIndex(const bsl::uint64_t *bitString,
776 bsl::size_t length);
777
778 /// Return the index of the most-significant 1 bit in the specified
779 /// `bitString` in the specified range `[begin .. end)`, if such a bit
780 /// exists, and `k_INVALID_INDEX` otherwise.
781 ///
782 /// \pre The behavior is undefined unless `begin <= end` and `end` is less than or equal to the length
783 /// of `bitString`.
784 static bsl::size_t find1AtMaxIndex(const bsl::uint64_t *bitString,
785 bsl::size_t begin,
786 bsl::size_t end);
787
788 /// Return the index of the least-significant 1 bit in the specified
789 /// `bitString` having the specified `length`, if such a bit exists, and
790 /// `k_INVALID_INDEX` otherwise.
791 static bsl::size_t find1AtMinIndex(const bsl::uint64_t *bitString,
792 bsl::size_t length);
793
794 /// Return the index of the least-significant 1 bit in the specified
795 /// `bitString` in the specified range `[begin .. end)`, if such a bit
796 /// exists, and `k_INVALID_INDEX` otherwise.
797 ///
798 /// \pre The behavior is undefined unless `begin <= end` and `end` is less than or equal to the length
799 /// of `bitString`.
800 static bsl::size_t find1AtMinIndex(const bsl::uint64_t *bitString,
801 bsl::size_t begin,
802 bsl::size_t end);
803
804 // Count
805
806 /// Return `true` if any of the specified `numBits` beginning at the
807 /// specified `index` in the specified `bitString` are 0, and `false` otherwise.
808 ///
809 /// \pre The behavior is undefined unless `bitString` has a
810 /// length of at least `index + numBits`.
811 static bool isAny0(const bsl::uint64_t *bitString,
812 bsl::size_t index,
813 bsl::size_t numBits);
814
815 /// Return `true` if any of the specified `numBits` beginning at the
816 /// specified `index` in the specified `bitString` are 1, and `false` otherwise.
817 ///
818 /// \pre The behavior is undefined unless `bitString` has a
819 /// length of at least `index + numBits`.
820 static bool isAny1(const bsl::uint64_t *bitString,
821 bsl::size_t index,
822 bsl::size_t numBits);
823
824 /// Return the number of 0 bits in the specified `numBits` beginning at
825 /// the specified `index` in the specified `bitString`.
826 ///
827 /// \pre The behavior is undefined unless `bitString` has a length of at least
828 /// `index + numBits`.
829 static bsl::size_t num0(const bsl::uint64_t *bitString,
830 bsl::size_t index,
831 bsl::size_t numBits);
832
833 /// Return the number of 1 bits in the specified `numBits` beginning at
834 /// the specified `index` in the specified `bitString`.
835 ///
836 /// \pre The behavior is undefined unless `bitString` has a length of at least
837 /// `index + numBits`.
838 static bsl::size_t num1(const bsl::uint64_t *bitString,
839 bsl::size_t index,
840 bsl::size_t numBits);
841
842 // Printing
843
844 /// Format to the specified output `stream` the specified low-order
845 /// `numBits` in the specified `bitString` in hexadecimal, and return a
846 /// reference to `stream`. The highest order bits are printed first, in
847 /// groups of 16 nibbles, 64 nibbles per line (in the case of multi-line
848 /// output). Optionally specify `level`, the indentation level for each
849 /// line output. Optionally specify `spacesPerLevel`, the number of
850 /// spaces per indentation level. Each line is indented by the absolute
851 /// value of `level * spacesPerLevel`. If `spacesPerLevel` is negative,
852 /// suppress line breaks and format the entire output on one line. If
853 /// `stream` is initially invalid, this operation has no effect.
854 ///
855 /// \note Note that a trailing newline is provided in multiline mode only.
856 static bsl::ostream& print(bsl::ostream& stream,
857 const bsl::uint64_t *bitString,
858 bsl::size_t numBits,
859 int level = 1,
860 int spacesPerLevel = 4);
861};
862
863// ============================================================================
864// INLINE DEFINITIONS
865// ============================================================================
866
867 // --------------------
868 // struct BitStringUtil
869 // --------------------
870
871// CLASS METHODS
872
873 // Manipulators
874
875 // Assign
876
877inline
878void BitStringUtil::assign(bsl::uint64_t *bitString,
879 bsl::size_t index,
880 bool value)
881{
882 BSLS_ASSERT(bitString);
883
884 const bsl::size_t idx = index / k_BITS_PER_UINT64;
885 const int pos = static_cast<unsigned>(index) % k_BITS_PER_UINT64;
886
887 if (value) {
888 bitString[idx] |= (1ULL << pos);
889 }
890 else {
891 bitString[idx] &= ~(1ULL << pos);
892 }
893}
894
895inline
896void BitStringUtil::assign0(bsl::uint64_t *bitString, bsl::size_t index)
897{
898 BSLS_ASSERT(bitString);
899
900 const bsl::size_t idx = index / k_BITS_PER_UINT64;
901 const int pos = static_cast<unsigned>(index) % k_BITS_PER_UINT64;
902
903 bitString[idx] &= ~(1ULL << pos);
904}
905
906inline
907void BitStringUtil::assign1(bsl::uint64_t *bitString, bsl::size_t index)
908{
909 BSLS_ASSERT(bitString);
910
911 const bsl::size_t idx = index / k_BITS_PER_UINT64;
912 const int pos = static_cast<unsigned>(index) % k_BITS_PER_UINT64;
913
914 bitString[idx] |= 1ULL << pos;
915}
916
917 // Insert / Remove
918
919inline
920void BitStringUtil::insert(bsl::uint64_t *bitString,
921 bsl::size_t initialLength,
922 bsl::size_t dstIndex,
923 bool value,
924 bsl::size_t numBits)
925{
926 BSLS_ASSERT(bitString);
927
928 insertRaw(bitString, initialLength, dstIndex, numBits);
929 assign(bitString, dstIndex, value, numBits);
930}
931
932inline
933void BitStringUtil::insert0(bsl::uint64_t *bitString,
934 bsl::size_t initialLength,
935 bsl::size_t dstIndex,
936 bsl::size_t numBits)
937{
938 BSLS_ASSERT(bitString);
939
940 insertRaw(bitString, initialLength, dstIndex, numBits);
941 assign0(bitString, dstIndex, numBits);
942}
943
944inline
945void BitStringUtil::insert1(bsl::uint64_t *bitString,
946 bsl::size_t initialLength,
947 bsl::size_t dstIndex,
948 bsl::size_t numBits)
949{
950 BSLS_ASSERT(bitString);
951
952 insertRaw(bitString, initialLength, dstIndex, numBits);
953 assign1(bitString, dstIndex, numBits);
954}
955
956inline
957void BitStringUtil::removeAndFill0(bsl::uint64_t *bitString,
958 bsl::size_t length,
959 bsl::size_t index,
960 bsl::size_t numBits)
961{
962 BSLS_ASSERT(bitString);
963
964 remove(bitString, length, index, numBits);
965 assign0(bitString, length - numBits, numBits);
966}
967
968inline
969void BitStringUtil::removeAndFill1(bsl::uint64_t *bitString,
970 bsl::size_t length,
971 bsl::size_t index,
972 bsl::size_t numBits)
973{
974 BSLS_ASSERT(bitString);
975
976 remove(bitString, length, index, numBits);
977 assign1(bitString, length - numBits, numBits);
978}
979
980 // Accessors
981
982 // Read
983inline
984bool BitStringUtil::bit(const bsl::uint64_t *bitString, bsl::size_t index)
985{
986 BSLS_ASSERT(bitString);
987
988 const bsl::size_t idx = index / k_BITS_PER_UINT64;
989 const int pos = static_cast<unsigned>(index) % k_BITS_PER_UINT64;
990
991 return bitString[idx] & (1ULL << pos);
992}
993
994 // Count
995
996inline
997bsl::size_t BitStringUtil::num0(const bsl::uint64_t *bitString,
998 bsl::size_t index,
999 bsl::size_t numBits)
1000{
1001 BSLS_ASSERT(bitString);
1002
1003 return numBits - num1(bitString, index, numBits);
1004}
1005
1006} // close package namespace
1007
1008
1009#endif
1010
1011// ----------------------------------------------------------------------------
1012// Copyright 2015 Bloomberg Finance L.P.
1013//
1014// Licensed under the Apache License, Version 2.0 (the "License");
1015// you may not use this file except in compliance with the License.
1016// You may obtain a copy of the License at
1017//
1018// http://www.apache.org/licenses/LICENSE-2.0
1019//
1020// Unless required by applicable law or agreed to in writing, software
1021// distributed under the License is distributed on an "AS IS" BASIS,
1022// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1023// See the License for the specific language governing permissions and
1024// limitations under the License.
1025// ----------------------------- END-OF-FILE ----------------------------------
1026
1027/** @} */
1028/** @} */
1029/** @} */
#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
Definition bdlb_bitstringutil.h:416
static bsl::size_t find0AtMinIndex(const bsl::uint64_t *bitString, bsl::size_t length)
static void insertRaw(bsl::uint64_t *bitString, bsl::size_t initialLength, bsl::size_t dstIndex, bsl::size_t numBits)
static void assign(bsl::uint64_t *bitString, bsl::size_t index, bool value)
Definition bdlb_bitstringutil.h:878
static void toggle(bsl::uint64_t *bitString, bsl::size_t index, bsl::size_t numBits)
static void assignBits(bsl::uint64_t *bitString, bsl::size_t index, bsl::uint64_t srcValue, bsl::size_t numBits)
static void assign0(bsl::uint64_t *bitString, bsl::size_t index)
Definition bdlb_bitstringutil.h:896
static bool areEqual(const bsl::uint64_t *bitString1, bsl::size_t index1, const bsl::uint64_t *bitString2, bsl::size_t index2, bsl::size_t numBits)
static bool bit(const bsl::uint64_t *bitString, bsl::size_t index)
Definition bdlb_bitstringutil.h:984
static void orEqual(bsl::uint64_t *dstBitString, bsl::size_t dstIndex, const bsl::uint64_t *srcBitString, bsl::size_t srcIndex, bsl::size_t numBits)
static const bsl::size_t k_INVALID_INDEX
Definition bdlb_bitstringutil.h:422
static bsl::size_t find1AtMinIndex(const bsl::uint64_t *bitString, bsl::size_t begin, bsl::size_t end)
static bsl::uint64_t bits(const bsl::uint64_t *bitString, bsl::size_t index, bsl::size_t numBits)
static bool areEqual(const bsl::uint64_t *bitString1, const bsl::uint64_t *bitString2, bsl::size_t numBits)
static void insert1(bsl::uint64_t *bitString, bsl::size_t initialLength, bsl::size_t dstIndex, bsl::size_t numBits)
Definition bdlb_bitstringutil.h:945
static void copyRaw(bsl::uint64_t *dstBitString, bsl::size_t dstIndex, const bsl::uint64_t *srcBitString, bsl::size_t srcIndex, bsl::size_t numBits)
static bsl::size_t find0AtMaxIndex(const bsl::uint64_t *bitString, bsl::size_t begin, bsl::size_t end)
static void assign1(bsl::uint64_t *bitString, bsl::size_t index, bsl::size_t numBits)
static bsl::size_t find0AtMaxIndex(const bsl::uint64_t *bitString, bsl::size_t length)
static bsl::size_t find1AtMaxIndex(const bsl::uint64_t *bitString, bsl::size_t length)
static void assign1(bsl::uint64_t *bitString, bsl::size_t index)
Definition bdlb_bitstringutil.h:907
static void remove(bsl::uint64_t *bitString, bsl::size_t length, bsl::size_t index, bsl::size_t numBits)
static void insert0(bsl::uint64_t *bitString, bsl::size_t initialLength, bsl::size_t dstIndex, bsl::size_t numBits)
Definition bdlb_bitstringutil.h:933
static bool isAny0(const bsl::uint64_t *bitString, bsl::size_t index, bsl::size_t numBits)
static void assign0(bsl::uint64_t *bitString, bsl::size_t index, bsl::size_t numBits)
static void assign(bsl::uint64_t *bitString, bsl::size_t index, bool value, bsl::size_t numBits)
static void andEqual(bsl::uint64_t *dstBitString, bsl::size_t dstIndex, const bsl::uint64_t *srcBitString, bsl::size_t srcIndex, bsl::size_t numBits)
static void minusEqual(bsl::uint64_t *dstBitString, bsl::size_t dstIndex, const bsl::uint64_t *srcBitString, bsl::size_t srcIndex, bsl::size_t numBits)
static bsl::size_t find1AtMinIndex(const bsl::uint64_t *bitString, bsl::size_t length)
static bsl::size_t num0(const bsl::uint64_t *bitString, bsl::size_t index, bsl::size_t numBits)
Definition bdlb_bitstringutil.h:997
static bool isAny1(const bsl::uint64_t *bitString, bsl::size_t index, bsl::size_t numBits)
static bsl::size_t find0AtMinIndex(const bsl::uint64_t *bitString, bsl::size_t begin, bsl::size_t end)
static void copy(bsl::uint64_t *dstBitString, bsl::size_t dstIndex, const bsl::uint64_t *srcBitString, bsl::size_t srcIndex, bsl::size_t numBits)
static bsl::ostream & print(bsl::ostream &stream, const bsl::uint64_t *bitString, bsl::size_t numBits, int level=1, int spacesPerLevel=4)
static bsl::size_t find1AtMaxIndex(const bsl::uint64_t *bitString, bsl::size_t begin, bsl::size_t end)
static void removeAndFill1(bsl::uint64_t *bitString, bsl::size_t length, bsl::size_t index, bsl::size_t numBits)
Definition bdlb_bitstringutil.h:969
static void swapRaw(bsl::uint64_t *bitString1, bsl::size_t index1, bsl::uint64_t *bitString2, bsl::size_t index2, bsl::size_t numBits)
static void insert(bsl::uint64_t *bitString, bsl::size_t initialLength, bsl::size_t dstIndex, bool value, bsl::size_t numBits)
Definition bdlb_bitstringutil.h:920
static void removeAndFill0(bsl::uint64_t *bitString, bsl::size_t length, bsl::size_t index, bsl::size_t numBits)
Definition bdlb_bitstringutil.h:957
static void xorEqual(bsl::uint64_t *dstBitString, bsl::size_t dstIndex, const bsl::uint64_t *srcBitString, bsl::size_t srcIndex, bsl::size_t numBits)
static bsl::size_t num1(const bsl::uint64_t *bitString, bsl::size_t index, bsl::size_t numBits)
@ k_BITS_PER_UINT64
Definition bdlb_bitstringutil.h:419