Write a bit field starting at specified byte and bit, each numbered from 0
| 433 | |
| 434 | // Write a bit field starting at specified byte and bit, each numbered from 0 |
| 435 | void ByteVector::setField2(size_t byteIndex, size_t bitIndex, uint64_t value,unsigned lengthBits) |
| 436 | { |
| 437 | BVASSERT(bitIndex >= 0 && bitIndex <= 7); |
| 438 | // Example: bitIndex = 2, length = 2; |
| 439 | // 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 440 | // 0 0 X X 0 0 0 0 |
| 441 | // endpos = 4; nbytes = 0; lastbit = 4; nbits = 2; mask = 3; shift = 4; |
| 442 | |
| 443 | unsigned endpos = bitIndex + lengthBits; // 1 past the 0-based index of the last bit. |
| 444 | unsigned nbytes = (endpos-1) / 8; // number of bytes that will be modified, minus 1. |
| 445 | ByteType *dp = mStart + byteIndex + nbytes; |
| 446 | |
| 447 | unsigned lastbit = endpos % 8; // index of first bit not to be replaced, or 0. |
| 448 | // Number of bits to modify in the current byte, starting at the last byte. |
| 449 | unsigned nbits = lastbit ? MIN(lengthBits,lastbit) : MIN(lengthBits,8); |
| 450 | |
| 451 | for (int len = lengthBits; len > 0; dp--) { |
| 452 | // Mask of number of bits to be modified in this byte, starting from LSB. |
| 453 | unsigned mask = (1 << nbits) - 1; |
| 454 | ByteType val = value & mask; |
| 455 | value >>= nbits; |
| 456 | if (lastbit) { |
| 457 | // Shift val and mask so they are aligned with the bits to modify in the last byte, |
| 458 | // noting that we modify the last byte first, since we work backwards. |
| 459 | int shift = 8 - lastbit; |
| 460 | mask <<= shift; |
| 461 | val <<= shift; |
| 462 | } |
| 463 | *dp = (*dp & ~mask) | (val & mask); |
| 464 | len -= nbits; |
| 465 | nbits = MIN(len,8); |
| 466 | |
| 467 | lastbit = 0; |
| 468 | } |
| 469 | } |
| 470 | |
| 471 | void ByteVector::appendField(uint64_t value,unsigned lengthBits) |
| 472 | { |