// bdlb_bitmaskutil.h -*-C++-*- #ifndef INCLUDED_BDLB_BITMASKUTIL #define INCLUDED_BDLB_BITMASKUTIL #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide simple mask values of 'uint32_t' and 'uint64_t' types. // //@CLASSES: // bdlb::BitMaskUtil: namespace for bit-level mask operations // //@DESCRIPTION: This component provides a utility 'struct', // 'bdlb::BitMaskUtil', that serves as a namespace for a collection of // functions that provide simple binary masks. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Creation of Simple Bit Masks ///- - - - - - - - - - - - - - - - - - - - // The following usage examples illustrate how some of the methods provided by // this component are used. Note that, in all of these examples, the low-order // bit is considered bit 0 and resides on the right edge of the bit string. // // First, the 'ge' function takes a single argument, 'index', and returns a bit // mask with all bits below the specified 'index' cleared and all bits at or // above the 'index' set: //.. // +-------------------------------------------------------------------------+ // | 'bdlb::BitMaskUtil::ge(16)' in binary: | // | | // | 'index': bit 16: * | // | All bits at and above bit 16 are set: 11111111111111110000000000000000 | // +-------------------------------------------------------------------------+ // // const uint32_t expGe = 0xffff0000; // assert(expGe == bdlb::BitMaskUtil::ge(16)); //.. // Next, the 'lt' function returns a bit mask with all bits at or above the // specified 'index' cleared, and all bits below 'index' set. 'lt' and 'ge' // return the complement of each other if passed the same 'index': //.. // +-------------------------------------------------------------------------+ // | 'bdlb::BitMaskUtil::lt(16)' in binary: | // | | // | 'index': bit 16: * | // | All bits below bit 16 are set: 00000000000000001111111111111111 | // +-------------------------------------------------------------------------+ // // const uint32_t expLt = 0x0000ffff; // assert(expLt == bdlb::BitMaskUtil::lt(16)); // // assert(expGe == ~expLt); //.. // Then, the 'eq' function returns a bit mask with only the bit at the // specified 'index' set: //.. // +-------------------------------------------------------------------------+ // | 'bdlb::BitMaskUtil::eq(23)' in binary: | // | | // | 'index': bit 23: * | // | Only bit 23 is set: 00000000100000000000000000000000 | // +-------------------------------------------------------------------------+ // // const uint32_t expEq = 0x00800000; // assert(expEq == bdlb::BitMaskUtil::eq(23)); //.. // Now, the 'ne' function returns a bit mask with only the bit at the specified // 'index' cleared. 'ne' and 'eq' return the complement of each other for a // given 'index': //.. // +-------------------------------------------------------------------------+ // | 'bdlb::BitMaskUtil::ne(23)' in binary: | // | | // | 'index': bit 23: * | // | All bits other than bit 16 are set: 11111111011111111111111111111111 | // +-------------------------------------------------------------------------+ // // const uint32_t expNe = 0xff7fffff; // assert(expNe == bdlb::BitMaskUtil::ne(23)); // // assert(expEq == ~expNe); //.. // Finally, 'one' and 'zero' return a bit mask with all bits within a specified // range starting from a specified 'index' either set or cleared, respectively. // For the same arguments, 'one' and 'zero' return the complement of each // other: //.. // +-------------------------------------------------------------------------+ // | 'bdlb::BitMaskUtil::one(16, 4)' in binary: | // | | // | bit 16: * | // | 4 bits starting at bit 16: **** | // | Result: only those bits set: 00000000000011110000000000000000 | // +-------------------------------------------------------------------------+ // // const uint32_t expOne = 0x000f0000; // assert(expOne == bdlb::BitMaskUtil::one(16, 4)); // // +-------------------------------------------------------------------------+ // | 'bdlb::BitMaskUtil::zero(16, 4)' in binary: | // | | // | bit 16: * | // | 4 bits starting at bit 16: **** | // | Result: only those bits cleared: 11111111111100001111111111111111 | // +-------------------------------------------------------------------------+ // // const uint32_t expZero = 0xfff0ffff; // assert(expZero == bdlb::BitMaskUtil::zero(16, 4)); // // assert(expZero == ~expOne); //.. #include <bdlscm_version.h> #include <bdlb_bitutil.h> #include <bsls_assert.h> #include <bsls_performancehint.h> #include <bsls_review.h> #include <bsl_cstdint.h> namespace BloombergLP { namespace bdlb { // ================== // struct BitMaskUtil // ================== struct BitMaskUtil { // This utility 'struct' provides a namespace for a set of bit-level, // stateless functions that take one or two 'int' arguments and return // masks of the built-in 32- and 64-bit integer types 'uint32_t' and // 'uint64_t', respectively. // PUBLIC TYPES enum { k_BITS_PER_UINT32 = 32, // number of bits in type 'uint32_t' k_BITS_PER_UINT64 = 64 // number of bits in type 'uint64_t' }; // CLASS METHODS static bsl::uint32_t eq(int index); static bsl::uint64_t eq64(int index); // Return the unsigned integral value having the bit at the specified // 'index' position set to 1, and all other bits set to 0. The // behavior is undefined unless '0 <= index <= # of bits in result'. static bsl::uint32_t ge(int index); static bsl::uint64_t ge64(int index); // Return the unsigned integral value having all bits at positions // greater than or equal to the specified 'index' set to 1, and all // other bits set to 0. The behavior is undefined unless // '0 <= index <= # of bits in result'. static bsl::uint32_t gt(int index); static bsl::uint64_t gt64(int index); // Return the unsigned integral value having all bits at positions // greater than the specified 'index' set to 1, and all other bits set // to 0. The behavior is undefined unless // '0 <= index <= # of bits in result'. static bsl::uint32_t le(int index); static bsl::uint64_t le64(int index); // Return the unsigned integral value having all bits at positions less // than or equal to the specified 'index' set to 1, and all other bits // set to 0. The behavior is undefined unless // '0 <= index <= # of bits in result'. static bsl::uint32_t lt(int index); static bsl::uint64_t lt64(int index); // Return the unsigned integral value having all bits at positions less // than the specified 'index' set to 1, and all other bits set to 0. // The behavior is undefined unless // '0 <= index <= # of bits in result'. static bsl::uint32_t ne(int index); static bsl::uint64_t ne64(int index); // Return the unsigned integral value having the bit at the specified // 'index' position set to 0, and all other bits set to 1. The // behavior is undefined unless '0 <= index <= # of bits in result'. static bsl::uint32_t one(int index, int numBits); static bsl::uint64_t one64(int index, int numBits); // Return the unsigned integral value having the specified 'numBits' // starting at the specified 'index' set to 1, and all other bits set // to 0. The behavior is undefined unless '0 <= index', // '0 <= numBits', and 'index + numBits <= # of bits in result'. static bsl::uint32_t zero(int index, int numBits); static bsl::uint64_t zero64(int index, int numBits); // Return the unsigned integral value having the specified 'numBits' // starting at the specified 'index' set to 0, and all other bits set // to 1. The behavior is undefined unless '0 <= index', // '0 <= numBits', and 'index + numBits <= # of bits in result'. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // ------------------ // struct BitMaskUtil // ------------------ // CLASS METHODS inline bsl::uint32_t BitMaskUtil::eq(int index) { BSLS_ASSERT(0 <= index); BSLS_ASSERT( index <= static_cast<int>(k_BITS_PER_UINT32)); return BSLS_PERFORMANCEHINT_PREDICT_LIKELY( index < static_cast<int>(k_BITS_PER_UINT32)) ? 1u << index : 0; } inline bsl::uint64_t BitMaskUtil::eq64(int index) { BSLS_ASSERT(0 <= index); BSLS_ASSERT( index <= static_cast<int>(k_BITS_PER_UINT64)); return BSLS_PERFORMANCEHINT_PREDICT_LIKELY( index < static_cast<int>(k_BITS_PER_UINT64)) ? 1LL << index : 0; } inline bsl::uint32_t BitMaskUtil::ge(int index) { BSLS_ASSERT(0 <= index); BSLS_ASSERT( index <= static_cast<int>(k_BITS_PER_UINT32)); return BSLS_PERFORMANCEHINT_PREDICT_LIKELY( index < static_cast<int>(k_BITS_PER_UINT32)) ? (~static_cast<bsl::uint32_t>(0) << index) : 0; } inline bsl::uint64_t BitMaskUtil::ge64(int index) { BSLS_ASSERT(0 <= index); BSLS_ASSERT( index <= static_cast<int>(k_BITS_PER_UINT64)); return BSLS_PERFORMANCEHINT_PREDICT_LIKELY( index < static_cast<int>(k_BITS_PER_UINT64)) ? (~0ULL << index) : 0; } inline bsl::uint32_t BitMaskUtil::gt(int index) { BSLS_ASSERT(0 <= index); BSLS_ASSERT( index <= static_cast<int>(k_BITS_PER_UINT32)); ++index; return BSLS_PERFORMANCEHINT_PREDICT_LIKELY( index < static_cast<int>(k_BITS_PER_UINT32)) ? ~((1u << index) - 1) : 0; } inline bsl::uint64_t BitMaskUtil::gt64(int index) { BSLS_ASSERT(0 <= index); BSLS_ASSERT( index <= static_cast<int>(k_BITS_PER_UINT64)); ++index; return BSLS_PERFORMANCEHINT_PREDICT_LIKELY( index < static_cast<int>(k_BITS_PER_UINT64)) ? ~((1LL << index) - 1) : 0; } inline bsl::uint32_t BitMaskUtil::le(int index) { BSLS_ASSERT(0 <= index); BSLS_ASSERT( index <= static_cast<int>(k_BITS_PER_UINT32)); ++index; return BSLS_PERFORMANCEHINT_PREDICT_LIKELY( index < static_cast<int>(k_BITS_PER_UINT32)) ? (1u << index) - 1 : -1; } inline bsl::uint64_t BitMaskUtil::le64(int index) { BSLS_ASSERT(0 <= index); BSLS_ASSERT( index <= static_cast<int>(k_BITS_PER_UINT64)); ++index; return BSLS_PERFORMANCEHINT_PREDICT_LIKELY( index < static_cast<int>(k_BITS_PER_UINT64)) ? (1LL << index) - 1 : -1LL; } inline bsl::uint32_t BitMaskUtil::lt(int index) { BSLS_ASSERT(0 <= index); BSLS_ASSERT( index <= static_cast<int>(k_BITS_PER_UINT32)); return BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( index >= static_cast<int>(k_BITS_PER_UINT32)) ? -1 : (1u << index) - 1; } inline bsl::uint64_t BitMaskUtil::lt64(int index) { BSLS_ASSERT(0 <= index); BSLS_ASSERT( index <= static_cast<int>(k_BITS_PER_UINT64)); return BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( index >= static_cast<int>(k_BITS_PER_UINT64)) ? -1LL : (1LL << index) - 1; } inline bsl::uint32_t BitMaskUtil::ne(int index) { BSLS_ASSERT(0 <= index); BSLS_ASSERT( index <= static_cast<int>(k_BITS_PER_UINT32)); return BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( index >= static_cast<int>(k_BITS_PER_UINT32)) ? -1 : ~(1u << index); } inline bsl::uint64_t BitMaskUtil::ne64(int index) { BSLS_ASSERT(0 <= index); BSLS_ASSERT( index <= static_cast<int>(k_BITS_PER_UINT64)); return BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( index >= static_cast<int>(k_BITS_PER_UINT64)) ? -1LL : ~(1LL << index); } inline bsl::uint32_t BitMaskUtil::one(int index, int numBits) { BSLS_ASSERT(0 <= index); BSLS_ASSERT(0 <= numBits); BSLS_ASSERT(index + numBits <= static_cast<int>(k_BITS_PER_UINT32)); return lt(index + numBits) & ge(index); } inline bsl::uint64_t BitMaskUtil::one64(int index, int numBits) { BSLS_ASSERT(0 <= index); BSLS_ASSERT(0 <= numBits); BSLS_ASSERT(index + numBits <= static_cast<int>(k_BITS_PER_UINT64)); return lt64(index + numBits) & ge64(index); } inline bsl::uint32_t BitMaskUtil::zero(int index, int numBits) { BSLS_ASSERT(0 <= index); BSLS_ASSERT(0 <= numBits); BSLS_ASSERT(index + numBits <= static_cast<int>(k_BITS_PER_UINT32)); return lt(index) | ge(index + numBits); } inline bsl::uint64_t BitMaskUtil::zero64(int index, int numBits) { BSLS_ASSERT(0 <= index); BSLS_ASSERT(0 <= numBits); BSLS_ASSERT(index + numBits <= static_cast<int>(k_BITS_PER_UINT64)); return lt64(index) | ge64(index + numBits); } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2015 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------