1 | /* |
---|
2 | * This file Copyright (C) Mnemosyne LLC |
---|
3 | * |
---|
4 | * This file is licensed by the GPL version 2. Works owned by the |
---|
5 | * Transmission project are granted a special exemption to clause 2(b) |
---|
6 | * so that the bulk of its code can remain under the MIT license. |
---|
7 | * This exemption does not extend to derived works not owned by |
---|
8 | * the Transmission project. |
---|
9 | * |
---|
10 | * $Id: bitfield.c 12927 2011-09-27 02:44:07Z jordan $ |
---|
11 | */ |
---|
12 | |
---|
13 | #include <assert.h> |
---|
14 | #include <stdlib.h> /* realloc() */ |
---|
15 | #include <string.h> /* memset */ |
---|
16 | |
---|
17 | #include "transmission.h" |
---|
18 | #include "bitfield.h" |
---|
19 | #include "utils.h" /* tr_new0() */ |
---|
20 | |
---|
21 | const tr_bitfield TR_BITFIELD_INIT = { NULL, 0, 0, 0, false, false }; |
---|
22 | |
---|
23 | /**** |
---|
24 | ***** |
---|
25 | ****/ |
---|
26 | |
---|
27 | static const int8_t trueBitCount[256] = |
---|
28 | { |
---|
29 | 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, |
---|
30 | 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, |
---|
31 | 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, |
---|
32 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
---|
33 | 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, |
---|
34 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
---|
35 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
---|
36 | 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, |
---|
37 | 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, |
---|
38 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
---|
39 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
---|
40 | 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, |
---|
41 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
---|
42 | 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, |
---|
43 | 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, |
---|
44 | 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 |
---|
45 | }; |
---|
46 | |
---|
47 | static size_t |
---|
48 | countArray( const tr_bitfield * b ) |
---|
49 | { |
---|
50 | size_t i; |
---|
51 | size_t ret = 0; |
---|
52 | |
---|
53 | for( i=0; i<b->alloc_count; ++i ) |
---|
54 | ret += trueBitCount[b->bits[i]]; |
---|
55 | |
---|
56 | return ret; |
---|
57 | } |
---|
58 | |
---|
59 | static size_t |
---|
60 | countRange( const tr_bitfield * b, size_t begin, size_t end ) |
---|
61 | { |
---|
62 | size_t ret = 0; |
---|
63 | const size_t first_byte = begin >> 3u; |
---|
64 | const size_t last_byte = ( end - 1 ) >> 3u; |
---|
65 | |
---|
66 | if( !b->bit_count ) |
---|
67 | return 0; |
---|
68 | if( first_byte >= b->alloc_count ) |
---|
69 | return 0; |
---|
70 | |
---|
71 | assert( begin < end ); |
---|
72 | assert( b->bits != NULL ); |
---|
73 | |
---|
74 | if( first_byte == last_byte ) |
---|
75 | { |
---|
76 | int i; |
---|
77 | uint8_t val = b->bits[first_byte]; |
---|
78 | |
---|
79 | i = begin - (first_byte * 8); |
---|
80 | val <<= i; |
---|
81 | val >>= i; |
---|
82 | i = (last_byte+1)*8 - end; |
---|
83 | val >>= i; |
---|
84 | val <<= i; |
---|
85 | |
---|
86 | ret += trueBitCount[val]; |
---|
87 | } |
---|
88 | else |
---|
89 | { |
---|
90 | size_t i; |
---|
91 | uint8_t val; |
---|
92 | |
---|
93 | /* first byte */ |
---|
94 | i = begin - (first_byte * 8); |
---|
95 | val = b->bits[first_byte]; |
---|
96 | val <<= i; |
---|
97 | val >>= i; |
---|
98 | ret += trueBitCount[val]; |
---|
99 | |
---|
100 | /* middle bytes */ |
---|
101 | for( i=first_byte+1; i<b->alloc_count && i<last_byte; ++i ) |
---|
102 | ret += trueBitCount[b->bits[i]]; |
---|
103 | |
---|
104 | /* last byte */ |
---|
105 | if( last_byte < b->alloc_count ) { |
---|
106 | i = (last_byte+1)*8 - end; |
---|
107 | val = b->bits[last_byte]; |
---|
108 | val >>= i; |
---|
109 | val <<= i; |
---|
110 | ret += trueBitCount[val]; |
---|
111 | } |
---|
112 | } |
---|
113 | |
---|
114 | assert( ret <= ( begin - end ) ); |
---|
115 | return ret; |
---|
116 | } |
---|
117 | |
---|
118 | size_t |
---|
119 | tr_bitfieldCountRange( const tr_bitfield * b, size_t begin, size_t end ) |
---|
120 | { |
---|
121 | if( tr_bitfieldHasAll( b ) ) |
---|
122 | return end - begin; |
---|
123 | |
---|
124 | if( tr_bitfieldHasNone( b ) ) |
---|
125 | return 0; |
---|
126 | |
---|
127 | return countRange( b, begin, end ); |
---|
128 | } |
---|
129 | |
---|
130 | /*** |
---|
131 | **** |
---|
132 | ***/ |
---|
133 | |
---|
134 | static bool |
---|
135 | tr_bitfieldIsValid( const tr_bitfield * b UNUSED ) |
---|
136 | { |
---|
137 | assert( b != NULL ); |
---|
138 | assert( ( b->alloc_count == 0 ) == ( b->bits == 0 ) ); |
---|
139 | assert( !b->bits || ( b->true_count == countArray ( b ) ) ); |
---|
140 | return true; |
---|
141 | } |
---|
142 | |
---|
143 | size_t |
---|
144 | tr_bitfieldCountTrueBits( const tr_bitfield * b ) |
---|
145 | { |
---|
146 | tr_bitfieldIsValid( b ); |
---|
147 | return b->true_count; |
---|
148 | } |
---|
149 | |
---|
150 | static size_t |
---|
151 | get_bytes_needed( size_t bit_count ) |
---|
152 | { |
---|
153 | return ( bit_count + 7u ) / 8u; |
---|
154 | } |
---|
155 | |
---|
156 | static void |
---|
157 | set_all_true( uint8_t * array, size_t bit_count ) |
---|
158 | { |
---|
159 | const uint8_t val = 0xFF; |
---|
160 | const size_t n = get_bytes_needed( bit_count ); |
---|
161 | memset( array, val, n-1 ); |
---|
162 | array[n-1] = val << (n*8 - bit_count); |
---|
163 | } |
---|
164 | |
---|
165 | void* |
---|
166 | tr_bitfieldGetRaw( const tr_bitfield * b, size_t * byte_count ) |
---|
167 | { |
---|
168 | const size_t n = get_bytes_needed( b->bit_count ); |
---|
169 | uint8_t * bits = tr_new0( uint8_t, n ); |
---|
170 | |
---|
171 | assert( b->bit_count > 0 ); |
---|
172 | |
---|
173 | if( b->alloc_count ) |
---|
174 | memcpy( bits, b->bits, b->alloc_count ); |
---|
175 | else if( tr_bitfieldHasAll( b ) ) |
---|
176 | set_all_true( bits, b->bit_count ); |
---|
177 | |
---|
178 | *byte_count = n; |
---|
179 | return bits; |
---|
180 | } |
---|
181 | |
---|
182 | static void |
---|
183 | tr_bitfieldEnsureBitsAlloced( tr_bitfield * b, size_t nth ) |
---|
184 | { |
---|
185 | size_t bytes_needed; |
---|
186 | const bool has_all = tr_bitfieldHasAll( b ); |
---|
187 | |
---|
188 | if( has_all ) |
---|
189 | bytes_needed = get_bytes_needed( MAX( nth, b->true_count ) + 1 ); |
---|
190 | else |
---|
191 | bytes_needed = get_bytes_needed( nth + 1 ); |
---|
192 | |
---|
193 | if( b->alloc_count < bytes_needed ) |
---|
194 | { |
---|
195 | b->bits = tr_renew( uint8_t, b->bits, bytes_needed ); |
---|
196 | memset( b->bits + b->alloc_count, 0, bytes_needed - b->alloc_count ); |
---|
197 | b->alloc_count = bytes_needed; |
---|
198 | |
---|
199 | if( has_all ) |
---|
200 | set_all_true( b->bits, b->true_count ); |
---|
201 | } |
---|
202 | } |
---|
203 | |
---|
204 | static void |
---|
205 | tr_bitfieldFreeArray( tr_bitfield * b ) |
---|
206 | { |
---|
207 | tr_free( b->bits ); |
---|
208 | b->bits = NULL; |
---|
209 | b->alloc_count = 0; |
---|
210 | } |
---|
211 | |
---|
212 | static void |
---|
213 | tr_bitfieldSetTrueCount( tr_bitfield * b, size_t n ) |
---|
214 | { |
---|
215 | b->true_count = n; |
---|
216 | |
---|
217 | if( tr_bitfieldHasAll( b ) || tr_bitfieldHasNone( b ) ) |
---|
218 | tr_bitfieldFreeArray( b ); |
---|
219 | |
---|
220 | assert( tr_bitfieldIsValid( b ) ); |
---|
221 | } |
---|
222 | |
---|
223 | static void |
---|
224 | tr_bitfieldRebuildTrueCount( tr_bitfield * b ) |
---|
225 | { |
---|
226 | tr_bitfieldSetTrueCount( b, countArray( b ) ); |
---|
227 | } |
---|
228 | |
---|
229 | static void |
---|
230 | tr_bitfieldIncTrueCount( tr_bitfield * b, int i ) |
---|
231 | { |
---|
232 | tr_bitfieldSetTrueCount( b, b->true_count + i ); |
---|
233 | } |
---|
234 | |
---|
235 | /**** |
---|
236 | ***** |
---|
237 | ****/ |
---|
238 | |
---|
239 | void |
---|
240 | tr_bitfieldConstruct( tr_bitfield * b, size_t bit_count ) |
---|
241 | { |
---|
242 | b->bit_count = bit_count; |
---|
243 | b->true_count = 0; |
---|
244 | b->bits = NULL; |
---|
245 | b->alloc_count = 0; |
---|
246 | b->have_all_hint = false; |
---|
247 | b->have_none_hint = false; |
---|
248 | |
---|
249 | assert( tr_bitfieldIsValid( b ) ); |
---|
250 | } |
---|
251 | |
---|
252 | void |
---|
253 | tr_bitfieldSetHasNone( tr_bitfield * b ) |
---|
254 | { |
---|
255 | tr_bitfieldFreeArray( b ); |
---|
256 | b->true_count = 0; |
---|
257 | b->have_all_hint = false; |
---|
258 | b->have_none_hint = true; |
---|
259 | |
---|
260 | assert( tr_bitfieldIsValid( b ) ); |
---|
261 | } |
---|
262 | |
---|
263 | void |
---|
264 | tr_bitfieldSetHasAll( tr_bitfield * b ) |
---|
265 | { |
---|
266 | tr_bitfieldFreeArray( b ); |
---|
267 | b->true_count = b->bit_count; |
---|
268 | b->have_all_hint = true; |
---|
269 | b->have_none_hint = false; |
---|
270 | |
---|
271 | assert( tr_bitfieldIsValid( b ) ); |
---|
272 | } |
---|
273 | |
---|
274 | void |
---|
275 | tr_bitfieldSetFromBitfield( tr_bitfield * b, const tr_bitfield * src ) |
---|
276 | { |
---|
277 | if( tr_bitfieldHasAll( src ) ) |
---|
278 | tr_bitfieldSetHasAll( b ); |
---|
279 | else if( tr_bitfieldHasNone( src ) ) |
---|
280 | tr_bitfieldSetHasNone( b ); |
---|
281 | else |
---|
282 | tr_bitfieldSetRaw( b, src->bits, src->alloc_count, true ); |
---|
283 | } |
---|
284 | |
---|
285 | void |
---|
286 | tr_bitfieldSetRaw( tr_bitfield * b, const void * bits, size_t byte_count, bool bounded ) |
---|
287 | { |
---|
288 | tr_bitfieldFreeArray( b ); |
---|
289 | b->true_count = 0; |
---|
290 | |
---|
291 | if( bounded ) |
---|
292 | byte_count = MIN( byte_count, get_bytes_needed( b->bit_count ) ); |
---|
293 | |
---|
294 | b->bits = tr_memdup( bits, byte_count ); |
---|
295 | b->alloc_count = byte_count; |
---|
296 | |
---|
297 | if( bounded ) { |
---|
298 | /* ensure the excess bits are set to '0' */ |
---|
299 | const int excess_bit_count = byte_count*8 - b->bit_count; |
---|
300 | assert( excess_bit_count >= 0 ); |
---|
301 | assert( excess_bit_count <= 7 ); |
---|
302 | if( excess_bit_count ) |
---|
303 | b->bits[b->alloc_count-1] &= ((0xff) << excess_bit_count); |
---|
304 | } |
---|
305 | |
---|
306 | tr_bitfieldRebuildTrueCount( b ); |
---|
307 | } |
---|
308 | |
---|
309 | void |
---|
310 | tr_bitfieldSetFromFlags( tr_bitfield * b, const bool * flags, size_t n ) |
---|
311 | { |
---|
312 | size_t i; |
---|
313 | size_t trueCount = 0; |
---|
314 | |
---|
315 | tr_bitfieldFreeArray( b ); |
---|
316 | tr_bitfieldEnsureBitsAlloced( b, n ); |
---|
317 | |
---|
318 | for( i=0; i<n; ++i ) |
---|
319 | { |
---|
320 | if( flags[i] ) |
---|
321 | { |
---|
322 | ++trueCount; |
---|
323 | b->bits[i >> 3u] |= ( 0x80 >> ( i & 7u ) ); |
---|
324 | } |
---|
325 | } |
---|
326 | |
---|
327 | tr_bitfieldSetTrueCount( b, trueCount ); |
---|
328 | } |
---|
329 | |
---|
330 | void |
---|
331 | tr_bitfieldAdd( tr_bitfield * b, size_t nth ) |
---|
332 | { |
---|
333 | if( !tr_bitfieldHas( b, nth ) ) |
---|
334 | { |
---|
335 | tr_bitfieldEnsureBitsAlloced( b, nth ); |
---|
336 | b->bits[nth >> 3u] |= ( 0x80 >> ( nth & 7u ) ); |
---|
337 | tr_bitfieldIncTrueCount( b, 1 ); |
---|
338 | } |
---|
339 | } |
---|
340 | |
---|
341 | /* Sets bit range [begin, end) to 1 */ |
---|
342 | void |
---|
343 | tr_bitfieldAddRange( tr_bitfield * b, size_t begin, size_t end ) |
---|
344 | { |
---|
345 | size_t sb, eb; |
---|
346 | unsigned char sm, em; |
---|
347 | const size_t diff = (end-begin) - tr_bitfieldCountRange( b, begin, end ); |
---|
348 | |
---|
349 | if( diff == 0 ) |
---|
350 | return; |
---|
351 | |
---|
352 | end--; |
---|
353 | if( ( end >= b->bit_count ) || ( begin > end ) ) |
---|
354 | return; |
---|
355 | |
---|
356 | sb = begin >> 3; |
---|
357 | sm = ~( 0xff << ( 8 - ( begin & 7 ) ) ); |
---|
358 | eb = end >> 3; |
---|
359 | em = 0xff << ( 7 - ( end & 7 ) ); |
---|
360 | |
---|
361 | tr_bitfieldEnsureBitsAlloced( b, end ); |
---|
362 | if( sb == eb ) |
---|
363 | { |
---|
364 | b->bits[sb] |= ( sm & em ); |
---|
365 | } |
---|
366 | else |
---|
367 | { |
---|
368 | b->bits[sb] |= sm; |
---|
369 | b->bits[eb] |= em; |
---|
370 | if( ++sb < eb ) |
---|
371 | memset ( b->bits + sb, 0xff, eb - sb ); |
---|
372 | } |
---|
373 | |
---|
374 | tr_bitfieldIncTrueCount( b, diff ); |
---|
375 | } |
---|
376 | |
---|
377 | void |
---|
378 | tr_bitfieldRem( tr_bitfield * b, size_t nth ) |
---|
379 | { |
---|
380 | assert( tr_bitfieldIsValid( b ) ); |
---|
381 | |
---|
382 | if( !tr_bitfieldHas( b, nth ) ) |
---|
383 | { |
---|
384 | tr_bitfieldEnsureBitsAlloced( b, nth ); |
---|
385 | b->bits[nth >> 3u] &= ( 0xff7f >> ( nth & 7u ) ); |
---|
386 | tr_bitfieldIncTrueCount( b, -1 ); |
---|
387 | } |
---|
388 | } |
---|
389 | |
---|
390 | /* Clears bit range [begin, end) to 0 */ |
---|
391 | void |
---|
392 | tr_bitfieldRemRange( tr_bitfield * b, size_t begin, size_t end ) |
---|
393 | { |
---|
394 | size_t sb, eb; |
---|
395 | unsigned char sm, em; |
---|
396 | const size_t diff = tr_bitfieldCountRange( b, begin, end ); |
---|
397 | |
---|
398 | if( !diff ) |
---|
399 | return; |
---|
400 | |
---|
401 | end--; |
---|
402 | |
---|
403 | if( ( end >= b->bit_count ) || ( begin > end ) ) |
---|
404 | return; |
---|
405 | |
---|
406 | sb = begin >> 3; |
---|
407 | sm = 0xff << ( 8 - ( begin & 7 ) ); |
---|
408 | eb = end >> 3; |
---|
409 | em = ~( 0xff << ( 7 - ( end & 7 ) ) ); |
---|
410 | |
---|
411 | tr_bitfieldEnsureBitsAlloced( b, end ); |
---|
412 | if( sb == eb ) |
---|
413 | { |
---|
414 | b->bits[sb] &= ( sm | em ); |
---|
415 | } |
---|
416 | else |
---|
417 | { |
---|
418 | b->bits[sb] &= sm; |
---|
419 | b->bits[eb] &= em; |
---|
420 | if( ++sb < eb ) |
---|
421 | memset ( b->bits + sb, 0, eb - sb ); |
---|
422 | } |
---|
423 | |
---|
424 | tr_bitfieldIncTrueCount( b, -diff ); |
---|
425 | } |
---|