SHOW:
|
|
- or go back to the newest paste.
| 1 | #include <climits> | |
| 2 | #include <cstring> | |
| 3 | #include <cstddef> | |
| 4 | ||
| 5 | #define PREPARE_FIRST_COPY() \ | |
| 6 | do { \
| |
| 7 | if (src_len >= (CHAR_BIT - dst_offset_modulo)) { \
| |
| 8 | *dst &= reverse_mask[dst_offset_modulo]; \ | |
| 9 | src_len -= CHAR_BIT - dst_offset_modulo; \ | |
| 10 | } else { \
| |
| 11 | *dst &= reverse_mask[dst_offset_modulo] \ | |
| 12 | | reverse_mask_xor[dst_offset_modulo + src_len + 1]; \ | |
| 13 | c &= reverse_mask[dst_offset_modulo + src_len ]; \ | |
| 14 | src_len = 0; \ | |
| 15 | } } while (0) | |
| 16 | ||
| 17 | /* | |
| 18 | Copy of unaligned arrays. | |
| 19 | http://stackoverflow.com/a/3535337/1454243 | |
| 20 | */ | |
| 21 | static int bitarray_copy(const unsigned char *src_org, int src_offset, int src_len, unsigned char *dst_org, int dst_offset) | |
| 22 | {
| |
| 23 | static const unsigned char mask[] = | |
| 24 | { 0x55, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
| |
| 25 | static const unsigned char mask_xor[] = | |
| 26 | { 0x55, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00 };
| |
| 27 | static const unsigned char reverse_mask[] = | |
| 28 | { 0x55, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
| |
| 29 | static const unsigned char reverse_mask_xor[] = | |
| 30 | { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00 };
| |
| 31 | ||
| 32 | if (src_len) {
| |
| 33 | const unsigned char *src; | |
| 34 | unsigned char *dst; | |
| 35 | int src_offset_modulo, | |
| 36 | dst_offset_modulo; | |
| 37 | ||
| 38 | src = src_org + (src_offset / CHAR_BIT); | |
| 39 | dst = dst_org + (dst_offset / CHAR_BIT); | |
| 40 | ||
| 41 | src_offset_modulo = src_offset % CHAR_BIT; | |
| 42 | dst_offset_modulo = dst_offset % CHAR_BIT; | |
| 43 | ||
| 44 | if (src_offset_modulo == dst_offset_modulo) {
| |
| 45 | int byte_len; | |
| 46 | int src_len_modulo; | |
| 47 | if (src_offset_modulo) {
| |
| 48 | unsigned char c; | |
| 49 | ||
| 50 | c = reverse_mask_xor[dst_offset_modulo] & *src++; | |
| 51 | ||
| 52 | PREPARE_FIRST_COPY(); | |
| 53 | *dst++ |= c; | |
| 54 | } | |
| 55 | ||
| 56 | byte_len = src_len / CHAR_BIT; | |
| 57 | src_len_modulo = src_len % CHAR_BIT; | |
| 58 | ||
| 59 | if (byte_len) {
| |
| 60 | memcpy(dst, src, byte_len); | |
| 61 | src += byte_len; | |
| 62 | dst += byte_len; | |
| 63 | } | |
| 64 | if (src_len_modulo) {
| |
| 65 | *dst &= reverse_mask_xor[src_len_modulo]; | |
| 66 | *dst |= reverse_mask[src_len_modulo] & *src; | |
| 67 | } | |
| 68 | } else {
| |
| 69 | int bit_diff_ls, | |
| 70 | bit_diff_rs; | |
| 71 | int byte_len; | |
| 72 | int src_len_modulo; | |
| 73 | unsigned char c; | |
| 74 | /* | |
| 75 | * Begin: Line things up on destination. | |
| 76 | */ | |
| 77 | if (src_offset_modulo > dst_offset_modulo) {
| |
| 78 | bit_diff_ls = src_offset_modulo - dst_offset_modulo; | |
| 79 | bit_diff_rs = CHAR_BIT - bit_diff_ls; | |
| 80 | ||
| 81 | c = *src++ << bit_diff_ls; | |
| 82 | c |= *src >> bit_diff_rs; | |
| 83 | c &= reverse_mask_xor[dst_offset_modulo]; | |
| 84 | } else {
| |
| 85 | bit_diff_rs = dst_offset_modulo - src_offset_modulo; | |
| 86 | bit_diff_ls = CHAR_BIT - bit_diff_rs; | |
| 87 | ||
| 88 | c = *src >> bit_diff_rs & | |
| 89 | reverse_mask_xor[dst_offset_modulo]; | |
| 90 | } | |
| 91 | PREPARE_FIRST_COPY(); | |
| 92 | *dst++ |= c; | |
| 93 | ||
| 94 | /* | |
| 95 | * Middle: copy with only shifting the source. | |
| 96 | */ | |
| 97 | byte_len = src_len / CHAR_BIT; | |
| 98 | ||
| 99 | while (--byte_len >= 0) {
| |
| 100 | c = *src++ << bit_diff_ls; | |
| 101 | c |= *src >> bit_diff_rs; | |
| 102 | *dst++ = c; | |
| 103 | } | |
| 104 | ||
| 105 | /* | |
| 106 | * End: copy the remaing bits; | |
| 107 | */ | |
| 108 | src_len_modulo = src_len % CHAR_BIT; | |
| 109 | if (src_len_modulo) {
| |
| 110 | c = *src++ << bit_diff_ls; | |
| 111 | c |= *src >> bit_diff_rs; | |
| 112 | c &= reverse_mask[src_len_modulo]; | |
| 113 | ||
| 114 | *dst &= reverse_mask_xor[src_len_modulo]; | |
| 115 | *dst |= c; | |
| 116 | } | |
| 117 | } | |
| 118 | } | |
| 119 | } | |
| 120 | ||
| 121 | /** | |
| 122 | * Copy a block of boolean values from a given valueIndex in a source buffer to a given valueIndex in a dst buffer. | |
| 123 | * In each buffer, every byte stores up to eight boolean values. | |
| 124 | * A valueIndex has a byte address = (valueIndex >> 3), and a bit address = (valueIndex & 7). | |
| 125 | * For instance, the bit with valueIndex = 0 is stored at bit 0 of byte 0; | |
| 126 | * the bit with valueIndex = 10 is stored at bit 2 of byte 1, and so on. | |
| 127 | * | |
| 128 | * @param[inout] dstData the beginning of dst data buffer | |
| 129 | * @param[in] srcData the beginning of the src data buffer | |
| 130 | * @param[in] valueIndexInDst the valueIndex in dst | |
| 131 | * @param[in] valueIndexInSrc the valueIndex in src | |
| 132 | * @param[in] length how many bits to copy | |
| 133 | */ | |
| 134 | void copyRLEBoolValues(char* dstData, char* srcData, uint32_t valueIndexInDst, uint32_t valueIndexInSrc, position_t length) | |
| 135 | {
| |
| 136 | - | if (valueIndexInDst > 8 || valueIndexInSrc > 8) {
|
| 136 | + | if (valueIndexInDst > 7 || valueIndexInSrc > 7) {
|
| 137 | copyRLEBoolValues(dstData + (valueIndexInDst / 8), | |
| 138 | srcData + (valueIndexInSrc / 8), | |
| 139 | valueIndexInSrc % 8, | |
| 140 | valueIndexInDst % 8, | |
| 141 | length); | |
| 142 | } else {
| |
| 143 | bitarray_copy(srcData, valueIndexInSrc, length, dstData, valueIndexInDst); | |
| 144 | } | |
| 145 | } |