BDE 4.14.0 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}).
415
416 // PUBLIC TYPES
417 enum { k_BITS_PER_UINT64 = 64 }; // number of bits in a 'uint64_t'
418
419 // PUBLIC CLASS CONSTANTS
420 static const bsl::size_t k_INVALID_INDEX = ~static_cast<bsl::size_t>(0);
421
422 // CLASS METHODS
423
424 // Assign
425
426 /// Set the bit at the specified `index` in the specified `bitString` to
427 /// the specified `value`. The behavior is undefined unless `index` is
428 /// less than the capacity of `bitString`.
429 static void assign(bsl::uint64_t *bitString,
430 bsl::size_t index,
431 bool value);
432
433 /// Set the specified `numBits` beginning at the specified `index` in
434 /// the specified `bitString` to the specified `value`. The behavior is
435 /// undefined unless `bitString` has a capacity of at least
436 /// `index + numBits`.
437 static void assign(bsl::uint64_t *bitString,
438 bsl::size_t index,
439 bool value,
440 bsl::size_t numBits);
441
442 /// Set the bit at the specified `index` in the specified `bitString` to
443 /// `false`. The behavior is undefined unless `index` is less than the
444 /// capacity of `bitString`.
445 static void assign0(bsl::uint64_t *bitString, bsl::size_t index);
446
447 /// Set the specified `numBits` beginning at the specified `index` in
448 /// the specified `bitString` to `false`. The behavior is undefined
449 /// unless `bitString` has a capacity of at least `index + numBits`.
450 static void assign0(bsl::uint64_t *bitString,
451 bsl::size_t index,
452 bsl::size_t numBits);
453
454 /// Set the bit at the specified `index` in the specified `bitString` to
455 /// `true`. The behavior is undefined unless `index` is less than the
456 /// capacity of `bitString`.
457 static void assign1(bsl::uint64_t *bitString, bsl::size_t index);
458
459 /// Set the specified `numBits` beginning at the specified `index` in
460 /// the specified `bitString` to `true`. The behavior is undefined
461 /// unless `bitString` has a capacity of at least `index + numBits`.
462 static void assign1(bsl::uint64_t *bitString,
463 bsl::size_t index,
464 bsl::size_t numBits);
465
466 /// Assign the low-order specified `numBits` from the specified
467 /// `srcValue` to the `numBits` starting at the specified `index` in the
468 /// specified `bitString`. The behavior is undefined unless
469 /// `numBits <= k_BITS_PER_UINT64` and `bitString` has a capacity of at
470 /// least `index + numBits`.
471 static void assignBits(bsl::uint64_t *bitString,
472 bsl::size_t index,
473 bsl::uint64_t srcValue,
474 bsl::size_t numBits);
475
476 // Bitwise-Logical
477
478 /// Bitwise AND the specified `numBits` of the specified `dstBitString`
479 /// starting at the specified `dstIndex` with the `numBits` of the
480 /// specified `srcBitString` starting at the specified `srcIndex`, and
481 /// write the result over the bits that were read from `dstBitString`.
482 /// The behavior is undefined unless `dstBitString` has a length of at
483 /// least `dstIndex + numBits` and `srcBitString` has a length of at
484 /// least `srcIndex + numBits`.
485 static void andEqual(bsl::uint64_t *dstBitString,
486 bsl::size_t dstIndex,
487 const bsl::uint64_t *srcBitString,
488 bsl::size_t srcIndex,
489 bsl::size_t numBits);
490
491 /// Bitwise MINUS the specified `numBits` of the specified
492 /// `srcBitString` starting at the specified `srcIndex` from the
493 /// `numBits` of the specified `dstBitString` starting at the specified
494 /// `dstIndex`, and write the result over the bits that were read from
495 /// `dstBitString`. The behavior is undefined unless `dstBitString` has
496 /// a length of at least `dstIndex + numBits` and `srcBitString` has a
497 /// length of at least `srcIndex + numBits`. Note that the logical
498 /// difference `A - B` is defined to be `A & !B`.
499 static void minusEqual(bsl::uint64_t *dstBitString,
500 bsl::size_t dstIndex,
501 const bsl::uint64_t *srcBitString,
502 bsl::size_t srcIndex,
503 bsl::size_t numBits);
504
505 /// Bitwise OR the specified `numBits` of the specified `dstBitString`
506 /// starting at the specified `dstIndex` with the `numBits` of the
507 /// specified `srcBitString` starting at the specified `srcIndex`, and
508 /// write the result over the bits that were read from `dstBitString`.
509 /// The behavior is undefined unless `dstBitString` has a length of at
510 /// least `dstIndex + numBits` and `srcBitString` has a length of at
511 /// least `srcIndex + numBits`.
512 static void orEqual(bsl::uint64_t *dstBitString,
513 bsl::size_t dstIndex,
514 const bsl::uint64_t *srcBitString,
515 bsl::size_t srcIndex,
516 bsl::size_t numBits);
517
518 /// Bitwise XOR the specified `numBits` of the specified `dstBitString`
519 /// starting at the specified `dstIndex` with the `numBits` of the
520 /// specified `srcBitString` starting at the specified `srcIndex`, and
521 /// write the result over the bits that were read from `dstBitString`.
522 /// 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 xorEqual(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 // Copy
532
533 /// Copy to the specified `dstBitString`, beginning at the specified
534 /// `dstIndex`, the specified `numBits` beginning at the specified
535 /// `srcIndex` in the specified `srcBitString`. This function works
536 /// correctly regardless of whether the source and destination ranges
537 /// overlap. The behavior is undefined unless `dstBitString` has a
538 /// capacity of at least `dstIndex + numBits` and `srcBitString` has a
539 /// length of at least `srcIndex + numBits`.
540 static void copy(bsl::uint64_t *dstBitString,
541 bsl::size_t dstIndex,
542 const bsl::uint64_t *srcBitString,
543 bsl::size_t srcIndex,
544 bsl::size_t numBits);
545
546 /// Copy to the specified `dstBitString`, beginning at the specified
547 /// `dstIndex`, the specified `numBits` beginning at the specified
548 /// `srcIndex` in the specified `srcBitString`. The behavior is
549 /// undefined unless `dstBitString` has a capacity of at least
550 /// `dstIndex + numBits`, `srcBitString` has a length of at least
551 /// `srcIndex + numBits`, and the source and destination ranges either
552 /// do not overlap, or the destination range is equal to the source
553 /// range, or the start of the destination range is below the start of
554 /// the source range.
555 static void copyRaw(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 // Insert / Remove
562
563 /// Insert the specified `numBits`, each having the specified `value`,
564 /// into the specified `bitString` having the specified `initialLength`,
565 /// beginning at the specified `dstIndex`. Bits at or above `dstIndex`
566 /// are shifted up by `numBits` index positions and the length of
567 /// `bitString` is increased by `numBits`. The behavior is undefined
568 /// unless `dstIndex <= initialLength` and `bitString` has a capacity of
569 /// at least `initialLength + numBits`.
570 static void insert(bsl::uint64_t *bitString,
571 bsl::size_t initialLength,
572 bsl::size_t dstIndex,
573 bool value,
574 bsl::size_t numBits);
575
576 /// Insert the specified `numBits` 0 bits into the specified `bitString`
577 /// having the specified `initialLength` beginning at the specified
578 /// `dstIndex`. Bits at or above `dstIndex` are shifted up by `numBits`
579 /// index positions and the length of `bitString` is increased by
580 /// `numBits`. The behavior is undefined unless
581 /// `dstIndex <= initialLength` and `bitString` has a capacity of at
582 /// least `initialLength + numBits`.
583 static void insert0(bsl::uint64_t *bitString,
584 bsl::size_t initialLength,
585 bsl::size_t dstIndex,
586 bsl::size_t numBits);
587
588 /// Insert the specified `numBits` 1 bits into the specified `bitString`
589 /// having the specified `initialLength` beginning at the specified
590 /// `dstIndex`. Bits at or above `dstIndex` are shifted up by `numBits`
591 /// index positions and the length of `bitString` is increased by
592 /// `numBits`. The behavior is undefined unless
593 /// `dstIndex <= initialLength` and `bitString` has a capacity of at
594 /// least `initialLength + numBits`.
595 static void insert1(bsl::uint64_t *bitString,
596 bsl::size_t initialLength,
597 bsl::size_t dstIndex,
598 bsl::size_t numBits);
599
600 /// Insert the specified `numBits` into the specified `bitString` having
601 /// the specified `initialLength` beginning at the specified `dstIndex`.
602 /// Bits at or above `dstIndex` are shifted up by `numBits` index
603 /// positions and the length of `bitString` is increased by `numBits`.
604 /// The values of the inserted bits are undefined. The behavior is
605 /// undefined unless `dstIndex <= initialLength` and `bitString` has a
606 /// capacity of at least `initialLength + numBits`. Note that the
607 /// inserted bits are not assigned any value.
608 static void insertRaw(bsl::uint64_t *bitString,
609 bsl::size_t initialLength,
610 bsl::size_t dstIndex,
611 bsl::size_t numBits);
612
613 /// Remove the specified `numBits` from the specified `bitString` of the
614 /// specified `length` beginning at the specified `index`. Bits above
615 /// `index + numBits` are shifted down by `numBits` index positions and
616 /// the length of `bitString` is reduced by `numBits`. The values of
617 /// the vacated high-order bits are not modified. The behavior is
618 /// undefined unless `index + numBits <= length`.
619 static void remove(bsl::uint64_t *bitString,
620 bsl::size_t length,
621 bsl::size_t index,
622 bsl::size_t numBits);
623
624 /// Remove the specified `numBits` from the specified `bitString` having
625 /// the specified `length` beginning at the specified `index`. Bits
626 /// above `index + numBits` are shifted down by `numBits` index
627 /// positions and the last `numBits` of `bitString` are set to 0. The
628 /// length of `bitString` is not changed. The behavior is undefined
629 /// unless `index + numBits <= length`.
630 static void removeAndFill0(bsl::uint64_t *bitString,
631 bsl::size_t length,
632 bsl::size_t index,
633 bsl::size_t numBits);
634
635 /// Remove the specified `numBits` from the specified `bitString` having
636 /// the specified `length` beginning at the specified `index`. Bits
637 /// above `index + numBits` are shifted down by `numBits` index
638 /// positions and the last `numBits` of `bitString` are set to 1. The
639 /// length of `bitString` is not changed. The behavior is undefined
640 /// unless `index + numBits <= length`.
641 static void removeAndFill1(bsl::uint64_t *bitString,
642 bsl::size_t length,
643 bsl::size_t index,
644 bsl::size_t numBits);
645
646 // Other Manipulators
647
648 /// Exchange the specified `numBits` beginning at the specified `index1`
649 /// in the specified `bitString1` with the `numBits` beginning at the
650 /// specified `index2` in the specified `bitString2`. The behavior is
651 /// undefined unless `bitString1` has a length of at least
652 /// `index1 + numBits`, `bitString2` has a length of at least
653 /// `index2 + numBits`, and there is *no* overlap between the swapped
654 /// ranges of bits.
655 static void swapRaw(bsl::uint64_t *bitString1,
656 bsl::size_t index1,
657 bsl::uint64_t *bitString2,
658 bsl::size_t index2,
659 bsl::size_t numBits);
660
661 /// Invert the values of the specified `numBits` in the specified
662 /// `bitString` beginning at the specified `index`. The behavior is
663 /// undefined unless `bitString` has a length of at least
664 /// `index + numBits`.
665 static void toggle(bsl::uint64_t *bitString,
666 bsl::size_t index,
667 bsl::size_t numBits);
668
669 // Compare
670
671 /// Return `true` if the specified low-order `numBits` in the specified
672 /// `bitString1` are bitwise equal to the corresponding bits in the
673 /// specified `bitString2`, and `false` otherwise. The behavior is
674 /// undefined unless both `bitString1` and `bitString2` have a length of
675 /// at least `numBits`.
676 static bool areEqual(const bsl::uint64_t *bitString1,
677 const bsl::uint64_t *bitString2,
678 bsl::size_t numBits);
679
680 /// Return `true` if the specified `numBits` beginning at the specified
681 /// `index1` in the specified `bitString1` are bitwise equal to the
682 /// `numBits` beginning at the specified `index2` in the specified
683 /// `bitString2`, and `false` otherwise. The behavior is undefined
684 /// unless `bitString1` has a length of at least `index1 + numBits` and
685 /// `bitString2` has a length of at least `index2 + numBits`.
686 static bool areEqual(const bsl::uint64_t *bitString1,
687 bsl::size_t index1,
688 const bsl::uint64_t *bitString2,
689 bsl::size_t index2,
690 bsl::size_t numBits);
691
692 // Read
693
694 /// Return the bit value at the specified `index` in the specified
695 /// `bitString`. The behavior is undefined unless `index` is less than
696 /// the length of `bitString`.
697 static bool bit(const bsl::uint64_t *bitString, bsl::size_t index);
698
699 /// Return the specified `numBits` beginning at the specified `index` in
700 /// the specified `bitString` as the low-order bits of the returned
701 /// value. The behavior is undefined unless
702 /// `numBits <= k_BITS_PER_UINT64` and `bitString` has a length of at
703 /// least `index + numBits`.
704 static bsl::uint64_t bits(const bsl::uint64_t *bitString,
705 bsl::size_t index,
706 bsl::size_t numBits);
707
708 // Find
709
710 /// Return the index of the most-significant 0 bit in the specified
711 /// `bitString` having the specified `length`, if such a bit exists, and
712 /// `k_INVALID_INDEX` otherwise.
713 static bsl::size_t find0AtMaxIndex(const bsl::uint64_t *bitString,
714 bsl::size_t length);
715
716 /// Return the index of the most-significant 0 bit in the specified
717 /// `bitString` in the specified range `[begin .. end)`, if such a bit
718 /// exists, and `k_INVALID_INDEX` otherwise. The behavior is undefined
719 /// unless `begin <= end` and `end` is less than or equal to the length
720 /// of `bitString`.
721 static bsl::size_t find0AtMaxIndex(const bsl::uint64_t *bitString,
722 bsl::size_t begin,
723 bsl::size_t end);
724
725 /// Return the index of the least-significant 0 bit in the specified
726 /// `bitString` having the specified `length`, if such a bit exists, and
727 /// `k_INVALID_INDEX` otherwise.
728 static bsl::size_t find0AtMinIndex(const bsl::uint64_t *bitString,
729 bsl::size_t length);
730
731 /// Return the index of the least-significant 0 bit in the specified
732 /// `bitString` in the specified range `[begin .. end)`, if such a bit
733 /// exists, and `k_INVALID_INDEX` otherwise. The behavior is undefined
734 /// unless `begin <= end` and `end` is less than or equal to the length
735 /// of `bitString`.
736 static bsl::size_t find0AtMinIndex(const bsl::uint64_t *bitString,
737 bsl::size_t begin,
738 bsl::size_t end);
739
740 /// Return the index of the most-significant 1 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 find1AtMaxIndex(const bsl::uint64_t *bitString,
744 bsl::size_t length);
745
746 /// Return the index of the most-significant 1 bit in the specified
747 /// `bitString` in the specified range `[begin .. end)`, if such a bit
748 /// exists, and `k_INVALID_INDEX` otherwise. The behavior is undefined
749 /// unless `begin <= end` and `end` is less than or equal to the length
750 /// of `bitString`.
751 static bsl::size_t find1AtMaxIndex(const bsl::uint64_t *bitString,
752 bsl::size_t begin,
753 bsl::size_t end);
754
755 /// Return the index of the least-significant 1 bit in the specified
756 /// `bitString` having the specified `length`, if such a bit exists, and
757 /// `k_INVALID_INDEX` otherwise.
758 static bsl::size_t find1AtMinIndex(const bsl::uint64_t *bitString,
759 bsl::size_t length);
760
761 /// Return the index of the least-significant 1 bit in the specified
762 /// `bitString` in the specified range `[begin .. end)`, if such a bit
763 /// exists, and `k_INVALID_INDEX` otherwise. The behavior is undefined
764 /// unless `begin <= end` and `end` is less than or equal to the length
765 /// of `bitString`.
766 static bsl::size_t find1AtMinIndex(const bsl::uint64_t *bitString,
767 bsl::size_t begin,
768 bsl::size_t end);
769
770 // Count
771
772 /// Return `true` if any of the specified `numBits` beginning at the
773 /// specified `index` in the specified `bitString` are 0, and `false`
774 /// otherwise. The behavior is undefined unless `bitString` has a
775 /// length of at least `index + numBits`.
776 static bool isAny0(const bsl::uint64_t *bitString,
777 bsl::size_t index,
778 bsl::size_t numBits);
779
780 /// Return `true` if any of the specified `numBits` beginning at the
781 /// specified `index` in the specified `bitString` are 1, and `false`
782 /// otherwise. The behavior is undefined unless `bitString` has a
783 /// length of at least `index + numBits`.
784 static bool isAny1(const bsl::uint64_t *bitString,
785 bsl::size_t index,
786 bsl::size_t numBits);
787
788 /// Return the number of 0 bits in the specified `numBits` beginning at
789 /// the specified `index` in the specified `bitString`. The behavior is
790 /// undefined unless `bitString` has a length of at least
791 /// `index + numBits`.
792 static bsl::size_t num0(const bsl::uint64_t *bitString,
793 bsl::size_t index,
794 bsl::size_t numBits);
795
796 /// Return the number of 1 bits in the specified `numBits` beginning at
797 /// the specified `index` in the specified `bitString`. The behavior is
798 /// undefined unless `bitString` has a length of at least
799 /// `index + numBits`.
800 static bsl::size_t num1(const bsl::uint64_t *bitString,
801 bsl::size_t index,
802 bsl::size_t numBits);
803
804 // Printing
805
806 /// Format to the specified output `stream` the specified low-order
807 /// `numBits` in the specified `bitString` in hexadecimal, and return a
808 /// reference to `stream`. The highest order bits are printed first, in
809 /// groups of 16 nibbles, 64 nibbles per line (in the case of multi-line
810 /// output). Optionally specify `level`, the indentation level for each
811 /// line output. Optionally specify `spacesPerLevel`, the number of
812 /// spaces per indentation level. Each line is indented by the absolute
813 /// value of `level * spacesPerLevel`. If `spacesPerLevel` is negative,
814 /// suppress line breaks and format the entire output on one line. If
815 /// `stream` is initially invalid, this operation has no effect. Note
816 /// that a trailing newline is provided in multiline mode only.
817 static bsl::ostream& print(bsl::ostream& stream,
818 const bsl::uint64_t *bitString,
819 bsl::size_t numBits,
820 int level = 1,
821 int spacesPerLevel = 4);
822};
823
824// ============================================================================
825// INLINE DEFINITIONS
826// ============================================================================
827
828 // --------------------
829 // struct BitStringUtil
830 // --------------------
831
832// CLASS METHODS
833
834 // Manipulators
835
836 // Assign
837
838inline
839void BitStringUtil::assign(bsl::uint64_t *bitString,
840 bsl::size_t index,
841 bool value)
842{
843 BSLS_ASSERT(bitString);
844
845 const bsl::size_t idx = index / k_BITS_PER_UINT64;
846 const int pos = static_cast<unsigned>(index) % k_BITS_PER_UINT64;
847
848 if (value) {
849 bitString[idx] |= (1ULL << pos);
850 }
851 else {
852 bitString[idx] &= ~(1ULL << pos);
853 }
854}
855
856inline
857void BitStringUtil::assign0(bsl::uint64_t *bitString, bsl::size_t index)
858{
859 BSLS_ASSERT(bitString);
860
861 const bsl::size_t idx = index / k_BITS_PER_UINT64;
862 const int pos = static_cast<unsigned>(index) % k_BITS_PER_UINT64;
863
864 bitString[idx] &= ~(1ULL << pos);
865}
866
867inline
868void BitStringUtil::assign1(bsl::uint64_t *bitString, bsl::size_t index)
869{
870 BSLS_ASSERT(bitString);
871
872 const bsl::size_t idx = index / k_BITS_PER_UINT64;
873 const int pos = static_cast<unsigned>(index) % k_BITS_PER_UINT64;
874
875 bitString[idx] |= 1ULL << pos;
876}
877
878 // Insert / Remove
879
880inline
881void BitStringUtil::insert(bsl::uint64_t *bitString,
882 bsl::size_t initialLength,
883 bsl::size_t dstIndex,
884 bool value,
885 bsl::size_t numBits)
886{
887 BSLS_ASSERT(bitString);
888
889 insertRaw(bitString, initialLength, dstIndex, numBits);
890 assign(bitString, dstIndex, value, numBits);
891}
892
893inline
894void BitStringUtil::insert0(bsl::uint64_t *bitString,
895 bsl::size_t initialLength,
896 bsl::size_t dstIndex,
897 bsl::size_t numBits)
898{
899 BSLS_ASSERT(bitString);
900
901 insertRaw(bitString, initialLength, dstIndex, numBits);
902 assign0(bitString, dstIndex, numBits);
903}
904
905inline
906void BitStringUtil::insert1(bsl::uint64_t *bitString,
907 bsl::size_t initialLength,
908 bsl::size_t dstIndex,
909 bsl::size_t numBits)
910{
911 BSLS_ASSERT(bitString);
912
913 insertRaw(bitString, initialLength, dstIndex, numBits);
914 assign1(bitString, dstIndex, numBits);
915}
916
917inline
918void BitStringUtil::removeAndFill0(bsl::uint64_t *bitString,
919 bsl::size_t length,
920 bsl::size_t index,
921 bsl::size_t numBits)
922{
923 BSLS_ASSERT(bitString);
924
925 remove(bitString, length, index, numBits);
926 assign0(bitString, length - numBits, numBits);
927}
928
929inline
930void BitStringUtil::removeAndFill1(bsl::uint64_t *bitString,
931 bsl::size_t length,
932 bsl::size_t index,
933 bsl::size_t numBits)
934{
935 BSLS_ASSERT(bitString);
936
937 remove(bitString, length, index, numBits);
938 assign1(bitString, length - numBits, numBits);
939}
940
941 // Accessors
942
943 // Read
944inline
945bool BitStringUtil::bit(const bsl::uint64_t *bitString, bsl::size_t index)
946{
947 BSLS_ASSERT(bitString);
948
949 const bsl::size_t idx = index / k_BITS_PER_UINT64;
950 const int pos = static_cast<unsigned>(index) % k_BITS_PER_UINT64;
951
952 return bitString[idx] & (1ULL << pos);
953}
954
955 // Count
956
957inline
958bsl::size_t BitStringUtil::num0(const bsl::uint64_t *bitString,
959 bsl::size_t index,
960 bsl::size_t numBits)
961{
962 BSLS_ASSERT(bitString);
963
964 return numBits - num1(bitString, index, numBits);
965}
966
967} // close package namespace
968
969
970#endif
971
972// ----------------------------------------------------------------------------
973// Copyright 2015 Bloomberg Finance L.P.
974//
975// Licensed under the Apache License, Version 2.0 (the "License");
976// you may not use this file except in compliance with the License.
977// You may obtain a copy of the License at
978//
979// http://www.apache.org/licenses/LICENSE-2.0
980//
981// Unless required by applicable law or agreed to in writing, software
982// distributed under the License is distributed on an "AS IS" BASIS,
983// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
984// See the License for the specific language governing permissions and
985// limitations under the License.
986// ----------------------------- END-OF-FILE ----------------------------------
987
988/** @} */
989/** @} */
990/** @} */
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlb_algorithmworkaroundutil.h:74
Definition bdlb_bitstringutil.h:414
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:839
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:857
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:945
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:420
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:906
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:868
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:894
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:958
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:930
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:881
static void removeAndFill0(bsl::uint64_t *bitString, bsl::size_t length, bsl::size_t index, bsl::size_t numBits)
Definition bdlb_bitstringutil.h:918
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:417