Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 1 | /** @file hei_bit_string.cpp |
| 2 | * @brief BitString and BitStringBuffer class definitions |
| 3 | */ |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 4 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 5 | #include <util/hei_bit_string.hpp> |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 6 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 7 | #include <hei_user_defines.hpp> |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 8 | |
| 9 | #include <algorithm> |
| 10 | |
Zane Shelley | 871adec | 2019-07-30 11:01:39 -0500 | [diff] [blame] | 11 | namespace libhei |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 12 | { |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 13 | |
| 14 | //############################################################################## |
| 15 | // BitString class |
| 16 | //############################################################################## |
| 17 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 18 | // number of bits in a uint64_t |
| 19 | constexpr uint32_t BitString::UINT64_BIT_LEN = sizeof(uint64_t) * 8; |
| 20 | // number of bits in a uint8_t |
| 21 | constexpr uint32_t BitString::UINT8_BIT_LEN = sizeof(uint8_t) * 8; |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 22 | |
| 23 | //------------------------------------------------------------------------------ |
| 24 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 25 | uint64_t BitString::getFieldRight( uint32_t i_pos, uint32_t i_len ) const |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 26 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 27 | HEI_ASSERT( nullptr != getBufAddr() ); // must to have a valid address |
| 28 | HEI_ASSERT( 0 < i_len ); // must have at least one bit |
| 29 | HEI_ASSERT( i_len <= UINT64_BIT_LEN ); // i_len length must be valid |
| 30 | HEI_ASSERT( i_pos + i_len <= getBitLen() ); // field must be within range |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 31 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 32 | // Get the relative address of this byte and the relative starting position |
| 33 | // within the byte. |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 34 | uint32_t relPos = 0; |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 35 | uint8_t * relAddr = getRelativePosition( relPos, i_pos ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 36 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 37 | // Get the length of the target bit field within this byte and the length of |
| 38 | // the bit field for any remaining bits. |
| 39 | uint32_t bf_len = i_len; |
| 40 | uint32_t remain_len = 0; |
| 41 | if ( UINT8_BIT_LEN < relPos + i_len ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 42 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 43 | // The target bit field crosses a byte boundary. So truncate the bit |
| 44 | // length for this byte and update the remaining length. |
| 45 | bf_len = UINT8_BIT_LEN - relPos; |
| 46 | remain_len = i_len - bf_len; |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 47 | } |
| 48 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 49 | // Get the target bit field within this byte (right justified). |
| 50 | uint8_t bf = *relAddr; |
| 51 | bf <<= relPos; // Mask off uneeded bits on the left side. |
| 52 | bf >>= UINT8_BIT_LEN - bf_len; // Right justify the value. |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 53 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 54 | // Check for any remaining bits after this target byte. |
| 55 | if ( 0 != remain_len ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 56 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 57 | // Recursively call this function on the remaining bits and push them |
| 58 | // into the right side of the return value. |
| 59 | uint64_t val = static_cast<uint64_t>(bf) << remain_len; |
| 60 | return val | getFieldRight( i_pos + bf_len, remain_len ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 61 | } |
| 62 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 63 | // Nothing more to do. Simply return this bit field. |
| 64 | return bf; |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 65 | } |
| 66 | |
| 67 | //------------------------------------------------------------------------------ |
| 68 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 69 | void BitString::setFieldLeft( uint32_t i_pos, uint32_t i_len, uint64_t i_val ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 70 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 71 | HEI_ASSERT( nullptr != getBufAddr() ); // must to have a valid address |
| 72 | HEI_ASSERT( 0 < i_len ); // must have at least one bit |
| 73 | HEI_ASSERT( i_len <= UINT64_BIT_LEN ); // i_len length must be valid |
| 74 | HEI_ASSERT( i_pos + i_len <= getBitLen() ); // field must be within range |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 75 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 76 | // Get the relative address of this byte and the relative starting position |
| 77 | // within the byte. |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 78 | uint32_t relPos = 0; |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 79 | uint8_t * relAddr = getRelativePosition( relPos, i_pos ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 80 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 81 | // Get the length of the target bit field within this byte and the length of |
| 82 | // the bit field for any remaining bits. |
| 83 | uint32_t bf_len = i_len; |
| 84 | uint32_t remain_len = 0; |
| 85 | if ( UINT8_BIT_LEN < relPos + i_len ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 86 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 87 | // The target bit field crosses a byte boundary. So truncate the bit |
| 88 | // length for this byte and update the remaining length. |
| 89 | bf_len = UINT8_BIT_LEN - relPos; |
| 90 | remain_len = i_len - bf_len; |
| 91 | } |
| 92 | |
| 93 | // It is possible there are bits in this byte on either side of the target |
| 94 | // bit field that must be preserved. Get the length of each of those bit |
| 95 | // fields. |
| 96 | uint32_t bf_l_len = relPos; |
| 97 | uint32_t bf_r_len = UINT8_BIT_LEN - (bf_l_len + bf_len); |
| 98 | |
| 99 | // Get the target bit field from the left justified inputed value. |
| 100 | uint8_t bf = (i_val >> (UINT64_BIT_LEN - bf_len)) << bf_r_len; |
| 101 | |
| 102 | // Get the bit fields on either side of the target bit field. |
| 103 | uint32_t bf_l_shift = UINT8_BIT_LEN - bf_l_len; |
| 104 | uint32_t bf_r_shift = UINT8_BIT_LEN - bf_r_len; |
| 105 | uint8_t bf_l = *relAddr; bf_l >>= bf_l_shift; bf_l <<= bf_l_shift; |
| 106 | uint8_t bf_r = *relAddr; bf_r <<= bf_r_shift; bf_r >>= bf_r_shift; |
| 107 | |
| 108 | // Combine all three parts of the byte and write it out to memory. |
| 109 | *relAddr = bf_l | bf | bf_r; |
| 110 | |
| 111 | // Check for any remaining bits after this target byte. |
| 112 | if ( 0 != remain_len ) |
| 113 | { |
| 114 | // Recursively call this function on the remaining bits. |
| 115 | setFieldLeft( i_pos + bf_len, remain_len, i_val << bf_len ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 116 | } |
| 117 | } |
| 118 | |
| 119 | //------------------------------------------------------------------------------ |
| 120 | |
| 121 | void BitString::setPattern( uint32_t i_sPos, uint32_t i_sLen, |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 122 | uint64_t i_pattern, uint32_t i_pLen ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 123 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 124 | |
| 125 | HEI_ASSERT(nullptr != getBufAddr()); // must to have a valid address |
| 126 | HEI_ASSERT(0 < i_sLen); // must have at least one bit |
| 127 | HEI_ASSERT(i_sPos + i_sLen <= getBitLen()); // field must be within range |
| 128 | HEI_ASSERT(0 < i_pLen); // must have at least one bit |
| 129 | HEI_ASSERT(i_pLen <= UINT64_BIT_LEN); // i_pLen length must be valid |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 130 | |
| 131 | // Get a bit string for the pattern subset (right justified). |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 132 | // Note that we cannot use a BitStringBuffer here because this function |
| 133 | // could be used in the constructor of BitStringBuffer, which could causes |
| 134 | // an infinite loop. |
| 135 | uint8_t a[sizeof(i_pattern)] = {}; |
| 136 | BitString bs { sizeof(i_pattern)*8, a }; |
| 137 | bs.setFieldRight(0, i_pLen, i_pattern); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 138 | |
| 139 | // Iterate the range in chunks the size of i_pLen. |
| 140 | uint32_t endPos = i_sPos + i_sLen; |
| 141 | for ( uint32_t pos = i_sPos; pos < endPos; pos += i_pLen ) |
| 142 | { |
| 143 | // The true chunk size is either i_pLen or the leftovers at the end. |
| 144 | uint32_t len = std::min( i_pLen, endPos - pos ); |
| 145 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 146 | // Get this chunk's pattern value, truncate (right justified) if needed. |
| 147 | uint64_t pattern = bs.getFieldRight( 0, len ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 148 | |
| 149 | // Set the pattern in this string. |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 150 | setFieldRight( pos, len, pattern ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 151 | } |
| 152 | } |
| 153 | |
| 154 | //------------------------------------------------------------------------------ |
| 155 | |
| 156 | void BitString::setString( const BitString & i_sStr, uint32_t i_sPos, |
| 157 | uint32_t i_sLen, uint32_t i_dPos ) |
| 158 | { |
| 159 | // Ensure the source parameters are valid. |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 160 | HEI_ASSERT( nullptr != i_sStr.getBufAddr() ); |
| 161 | HEI_ASSERT( 0 < i_sLen ); // at least one bit to copy |
| 162 | HEI_ASSERT( i_sPos + i_sLen <= i_sStr.getBitLen() ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 163 | |
| 164 | // Ensure the destination has at least one bit available to copy. |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 165 | HEI_ASSERT( nullptr != getBufAddr() ); |
| 166 | HEI_ASSERT( i_dPos < getBitLen() ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 167 | |
| 168 | // If the source length is greater than the destination length than the |
| 169 | // extra source bits are ignored. |
| 170 | uint32_t actLen = std::min( i_sLen, getBitLen() - i_dPos ); |
| 171 | |
| 172 | // The bit strings may be in overlapping memory spaces. So we need to copy |
| 173 | // the data in the correct direction to prevent overlapping. |
| 174 | uint32_t sRelOffset = 0, dRelOffset = 0; |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 175 | uint8_t * sRelAddr = i_sStr.getRelativePosition( sRelOffset, i_sPos ); |
| 176 | uint8_t * dRelAddr = getRelativePosition( dRelOffset, i_dPos ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 177 | |
| 178 | // Copy the data. |
| 179 | if ( (dRelAddr == sRelAddr) && (dRelOffset == sRelOffset) ) |
| 180 | { |
| 181 | // Do nothing. The source and destination are the same. |
| 182 | } |
| 183 | else if ( (dRelAddr < sRelAddr) || |
| 184 | ((dRelAddr == sRelAddr) && (dRelOffset < sRelOffset)) ) |
| 185 | { |
| 186 | // Copy the data forward. |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 187 | for ( uint32_t pos = 0; pos < actLen; pos += UINT64_BIT_LEN ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 188 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 189 | uint32_t len = std::min( actLen - pos, UINT64_BIT_LEN ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 190 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 191 | uint64_t value = i_sStr.getFieldRight( i_sPos + pos, len ); |
| 192 | setFieldRight( i_dPos + pos, len, value ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 193 | } |
| 194 | } |
| 195 | else // Copy the data backwards. |
| 196 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 197 | // Get the first position of the last chunk (byte aligned). |
| 198 | uint32_t lastPos = ((actLen-1) / UINT64_BIT_LEN) * UINT64_BIT_LEN; |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 199 | |
| 200 | // Start with the last chunk and work backwards. |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 201 | for ( int32_t pos = lastPos; 0 <= pos; pos -= UINT64_BIT_LEN ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 202 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 203 | uint32_t len = std::min( actLen - pos, UINT64_BIT_LEN ); |
| 204 | uint64_t value = i_sStr.getFieldRight( i_sPos + pos, len ); |
| 205 | setFieldRight( i_dPos + pos, len, value ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 206 | } |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | //------------------------------------------------------------------------------ |
| 211 | |
| 212 | void BitString::maskString( const BitString & i_mask ) |
| 213 | { |
| 214 | // Get the length of the smallest string. |
| 215 | uint32_t actLen = std::min( getBitLen(), i_mask.getBitLen() ); |
| 216 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 217 | for ( uint32_t pos = 0; pos < actLen; pos += UINT64_BIT_LEN ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 218 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 219 | uint32_t len = std::min( actLen - pos, UINT64_BIT_LEN ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 220 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 221 | uint64_t dVal = getFieldRight( pos, len ); |
| 222 | uint64_t sVal = i_mask.getFieldRight( pos, len ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 223 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 224 | setFieldRight( pos, len, dVal & ~sVal ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 225 | } |
| 226 | } |
| 227 | |
| 228 | //------------------------------------------------------------------------------ |
| 229 | |
| 230 | bool BitString::isEqual( const BitString & i_str ) const |
| 231 | { |
| 232 | if ( getBitLen() != i_str.getBitLen() ) |
| 233 | return false; // size not equal |
| 234 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 235 | for ( uint32_t pos = 0; pos < getBitLen(); pos += UINT64_BIT_LEN ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 236 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 237 | uint32_t len = std::min( getBitLen() - pos, UINT64_BIT_LEN ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 238 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 239 | if ( getFieldRight(pos, len) != i_str.getFieldRight(pos, len) ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 240 | return false; // bit strings do not match |
| 241 | } |
| 242 | |
| 243 | return true; // bit strings match |
| 244 | } |
| 245 | |
| 246 | //------------------------------------------------------------------------------ |
| 247 | |
| 248 | bool BitString::isZero() const |
| 249 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 250 | for ( uint32_t pos = 0; pos < getBitLen(); pos += UINT64_BIT_LEN ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 251 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 252 | uint32_t len = std::min( getBitLen() - pos, UINT64_BIT_LEN ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 253 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 254 | if ( 0 != getFieldRight(pos, len) ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 255 | return false; // something is non-zero |
| 256 | } |
| 257 | |
| 258 | return true; // everything was zero |
| 259 | } |
| 260 | |
| 261 | //------------------------------------------------------------------------------ |
| 262 | |
| 263 | uint32_t BitString::getSetCount( uint32_t i_pos, uint32_t i_len ) const |
| 264 | { |
| 265 | uint32_t endPos = i_pos + i_len; |
| 266 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 267 | HEI_ASSERT( endPos <= getBitLen() ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 268 | |
| 269 | uint32_t count = 0; |
| 270 | |
| 271 | for ( uint32_t i = i_pos; i < endPos; i++ ) |
| 272 | { |
| 273 | if ( isBitSet(i) ) count++; |
| 274 | } |
| 275 | |
| 276 | return count; |
| 277 | } |
| 278 | |
| 279 | //------------------------------------------------------------------------------ |
| 280 | |
| 281 | BitStringBuffer BitString::operator~() const |
| 282 | { |
| 283 | BitStringBuffer bsb( getBitLen() ); |
| 284 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 285 | for ( uint32_t pos = 0; pos < getBitLen(); pos += UINT64_BIT_LEN ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 286 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 287 | uint32_t len = std::min( getBitLen() - pos, UINT64_BIT_LEN ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 288 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 289 | uint64_t dVal = getFieldRight( pos, len ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 290 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 291 | bsb.setFieldRight( pos, len, ~dVal ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 292 | } |
| 293 | |
| 294 | return bsb; |
| 295 | } |
| 296 | |
| 297 | //------------------------------------------------------------------------------ |
| 298 | |
| 299 | BitStringBuffer BitString::operator&( const BitString & i_bs ) const |
| 300 | { |
| 301 | // Get the length of the smallest string. |
| 302 | uint32_t actLen = std::min( getBitLen(), i_bs.getBitLen() ); |
| 303 | |
| 304 | BitStringBuffer bsb( actLen ); |
| 305 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 306 | for ( uint32_t pos = 0; pos < actLen; pos += UINT64_BIT_LEN ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 307 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 308 | uint32_t len = std::min( actLen - pos, UINT64_BIT_LEN ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 309 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 310 | uint64_t dVal = getFieldRight( pos, len ); |
| 311 | uint64_t sVal = i_bs.getFieldRight( pos, len ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 312 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 313 | bsb.setFieldRight( pos, len, dVal & sVal ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 314 | } |
| 315 | |
| 316 | return bsb; |
| 317 | } |
| 318 | |
| 319 | //------------------------------------------------------------------------------ |
| 320 | |
| 321 | BitStringBuffer BitString::operator|( const BitString & i_bs ) const |
| 322 | { |
| 323 | // Get the length of the smallest string. |
| 324 | uint32_t actLen = std::min( getBitLen(), i_bs.getBitLen() ); |
| 325 | |
| 326 | BitStringBuffer bsb( actLen ); |
| 327 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 328 | for ( uint32_t pos = 0; pos < actLen; pos += UINT64_BIT_LEN ) |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 329 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 330 | uint32_t len = std::min( actLen - pos, UINT64_BIT_LEN ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 331 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 332 | uint64_t dVal = getFieldRight( pos, len ); |
| 333 | uint64_t sVal = i_bs.getFieldRight( pos, len ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 334 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 335 | bsb.setFieldRight( pos, len, dVal | sVal ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 336 | } |
| 337 | |
| 338 | return bsb; |
| 339 | } |
| 340 | |
| 341 | //------------------------------------------------------------------------------ |
| 342 | |
| 343 | BitStringBuffer BitString::operator>>( uint32_t i_shift ) const |
| 344 | { |
| 345 | BitStringBuffer bsb( getBitLen() ); // default all zeros |
| 346 | |
| 347 | if ( i_shift < getBitLen() ) |
| 348 | { |
| 349 | // bso overlays bsb, containing the shifted offset. |
| 350 | BitString bso ( bsb.getBitLen() - i_shift, bsb.getBufAddr(), i_shift ); |
| 351 | |
| 352 | // Copy this into bso. |
| 353 | bso.setString( *this ); |
| 354 | } |
| 355 | |
| 356 | return bsb; |
| 357 | } |
| 358 | |
| 359 | //------------------------------------------------------------------------------ |
| 360 | |
| 361 | BitStringBuffer BitString::operator<<( uint32_t i_shift ) const |
| 362 | { |
| 363 | BitStringBuffer bsb( getBitLen() ); // default all zeros |
| 364 | |
| 365 | if ( i_shift < getBitLen() ) |
| 366 | { |
| 367 | // bso overlays *this, containing the shifted offset. |
| 368 | BitString bso ( this->getBitLen() - i_shift, this->getBufAddr(), |
| 369 | i_shift ); |
| 370 | |
| 371 | // Copy bso into bsb. |
| 372 | bsb.setString( bso ); |
| 373 | } |
| 374 | |
| 375 | return bsb; |
| 376 | } |
| 377 | |
| 378 | //------------------------------------------------------------------------------ |
| 379 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 380 | uint8_t * BitString::getRelativePosition( uint32_t & o_relPos, |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 381 | uint32_t i_absPos ) const |
| 382 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 383 | HEI_ASSERT( nullptr != getBufAddr() ); // must to have a valid address |
| 384 | HEI_ASSERT( i_absPos < getBitLen() ); // must be a valid position |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 385 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 386 | o_relPos = (i_absPos + iv_offset) % UINT8_BIT_LEN; |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 387 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 388 | return ((uint8_t *)iv_bufAddr + ((i_absPos + iv_offset) / UINT8_BIT_LEN)); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 389 | } |
| 390 | |
| 391 | //############################################################################## |
| 392 | // BitStringBuffer class |
| 393 | //############################################################################## |
| 394 | |
| 395 | BitStringBuffer::BitStringBuffer( uint32_t i_bitLen ) : |
| 396 | BitString( i_bitLen, nullptr ) |
| 397 | { |
| 398 | initBuffer(); |
| 399 | } |
| 400 | |
| 401 | //------------------------------------------------------------------------------ |
| 402 | |
| 403 | BitStringBuffer::~BitStringBuffer() |
| 404 | { |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 405 | delete [] (uint8_t *)getBufAddr(); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 406 | } |
| 407 | |
| 408 | //------------------------------------------------------------------------------ |
| 409 | |
| 410 | BitStringBuffer::BitStringBuffer( const BitString & i_bs ) : |
| 411 | BitString( i_bs.getBitLen(), nullptr ) |
| 412 | { |
| 413 | initBuffer(); |
| 414 | if ( !i_bs.isZero() ) setString( i_bs ); |
| 415 | } |
| 416 | |
| 417 | //------------------------------------------------------------------------------ |
| 418 | |
| 419 | BitStringBuffer::BitStringBuffer( const BitStringBuffer & i_bsb ) : |
| 420 | BitString( i_bsb.getBitLen(), nullptr ) |
| 421 | { |
| 422 | initBuffer(); |
| 423 | if ( !i_bsb.isZero() ) setString( i_bsb ); |
| 424 | } |
| 425 | |
| 426 | //------------------------------------------------------------------------------ |
| 427 | |
| 428 | BitStringBuffer & BitStringBuffer::operator=( const BitString & i_bs ) |
| 429 | { |
| 430 | // The initBuffer() function will deallocate the buffer as well, however we |
| 431 | // also need to deallocate the buffer here before we set the length. |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 432 | delete [] (uint8_t *)getBufAddr(); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 433 | setBufAddr( nullptr ); |
| 434 | |
| 435 | setBitLen( i_bs.getBitLen() ); |
| 436 | initBuffer(); |
| 437 | if ( !i_bs.isZero() ) setString( i_bs ); |
| 438 | |
| 439 | return *this; |
| 440 | } |
| 441 | |
| 442 | //------------------------------------------------------------------------------ |
| 443 | |
| 444 | BitStringBuffer & BitStringBuffer::operator=( const BitStringBuffer & i_bsb ) |
| 445 | { |
| 446 | if ( this != &i_bsb ) // Check for assignment to self |
| 447 | { |
| 448 | // The initBuffer() function will deallocate the buffer as well, however |
| 449 | // we also need to deallocate the buffer here before we set the length. |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 450 | delete [] (uint8_t *)getBufAddr(); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 451 | setBufAddr( nullptr ); |
| 452 | |
| 453 | setBitLen( i_bsb.getBitLen() ); |
| 454 | initBuffer(); |
| 455 | if ( !i_bsb.isZero() ) setString( i_bsb ); |
| 456 | } |
| 457 | |
| 458 | return *this; |
| 459 | } |
| 460 | |
| 461 | //------------------------------------------------------------------------------ |
| 462 | |
| 463 | void BitStringBuffer::initBuffer() |
| 464 | { |
| 465 | // Deallocate the current buffer. |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 466 | delete [] (uint8_t *)getBufAddr(); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 467 | |
Ben Tyner | a8126fd | 2019-08-01 19:40:07 -0500 | [diff] [blame] | 468 | // create new buffer, initialized to 0's |
| 469 | setBufAddr( new uint8_t[ getMinBytes(getBitLen()) ]() ); |
Zane Shelley | fd3f9cc | 2019-07-29 15:02:24 -0500 | [diff] [blame] | 470 | } |
| 471 | |
Zane Shelley | 871adec | 2019-07-30 11:01:39 -0500 | [diff] [blame] | 472 | } // end namespace libhei |