View difference between Paste ID: tN9YXqjw and uZqMdEP9
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
}