2 * This file Copyright (C) Mnemosyne LLC
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.
10 * $Id: bitfield.c 12554 2011-07-17 14:34:33Z jordan $
14 #include <stdlib.h> /* realloc() */
15 #include <string.h> /* memset */
17 #include "transmission.h"
19 #include "utils.h" /* tr_new0() */
21 const tr_bitfield TR_BITFIELD_INIT
= { NULL
, 0, 0, 0, false, false };
27 static const int8_t trueBitCount
[256] =
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
48 countArray( const tr_bitfield
* b
)
53 for( i
=0; i
<b
->alloc_count
; ++i
)
54 ret
+= trueBitCount
[b
->bits
[i
]];
60 countRange( const tr_bitfield
* b
, size_t begin
, size_t end
)
63 const size_t first_byte
= begin
>> 3u;
64 const size_t last_byte
= ( end
- 1 ) >> 3u;
68 if( first_byte
>= b
->alloc_count
)
71 assert( begin
< end
);
72 assert( b
->bits
!= NULL
);
74 if( first_byte
== last_byte
)
77 uint8_t val
= b
->bits
[first_byte
];
79 i
= begin
- (first_byte
* 8);
82 i
= (last_byte
+1)*8 - end
;
86 ret
+= trueBitCount
[val
];
94 i
= begin
- (first_byte
* 8);
95 val
= b
->bits
[first_byte
];
98 ret
+= trueBitCount
[val
];
101 for( i
=first_byte
+1; i
<b
->alloc_count
&& i
<last_byte
; ++i
)
102 ret
+= trueBitCount
[b
->bits
[i
]];
105 if( last_byte
< b
->alloc_count
) {
106 i
= (last_byte
+1)*8 - end
;
107 val
= b
->bits
[last_byte
];
110 ret
+= trueBitCount
[val
];
114 assert( ret
<= ( begin
- end
) );
119 tr_bitfieldCountRange( const tr_bitfield
* b
, size_t begin
, size_t end
)
121 if( tr_bitfieldHasAll( b
) )
124 if( tr_bitfieldHasNone( b
) )
127 return countRange( b
, begin
, end
);
135 tr_bitfieldIsValid( const tr_bitfield
* b UNUSED
)
138 assert( ( b
->alloc_count
== 0 ) == ( b
->bits
== 0 ) );
139 assert( !b
->bits
|| ( b
->true_count
== countArray ( b
) ) );
144 tr_bitfieldCountTrueBits( const tr_bitfield
* b
)
146 tr_bitfieldIsValid( b
);
147 return b
->true_count
;
151 get_bytes_needed( size_t bit_count
)
153 return ( bit_count
+ 7u ) / 8u;
157 set_all_true( uint8_t * array
, size_t bit_count
)
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
);
166 tr_bitfieldGetRaw( const tr_bitfield
* b
, size_t * byte_count
)
168 const size_t n
= get_bytes_needed( b
->bit_count
);
169 uint8_t * bits
= tr_new0( uint8_t, n
);
171 assert( b
->bit_count
> 0 );
174 memcpy( bits
, b
->bits
, b
->alloc_count
);
175 else if( tr_bitfieldHasAll( b
) )
176 set_all_true( bits
, b
->bit_count
);
183 tr_bitfieldEnsureBitsAlloced( tr_bitfield
* b
, size_t nth
)
186 const bool has_all
= tr_bitfieldHasAll( b
);
188 assert( tr_bitfieldIsValid( b
) );
191 bytes_needed
= get_bytes_needed( MAX( nth
, b
->true_count
) + 1 );
193 bytes_needed
= get_bytes_needed( nth
+ 1 );
195 if( b
->alloc_count
< bytes_needed
)
198 const size_t old_count
= countArray( b
);
200 b
->bits
= tr_renew( uint8_t, b
->bits
, bytes_needed
);
201 memset( b
->bits
+ b
->alloc_count
, 0, bytes_needed
- b
->alloc_count
);
202 b
->alloc_count
= bytes_needed
;
203 assert( old_count
== countArray( b
) );
206 set_all_true( b
->bits
, b
->true_count
);
209 assert( tr_bitfieldIsValid( b
) );
213 tr_bitfieldFreeArray( tr_bitfield
* b
)
221 tr_bitfieldSetTrueCount( tr_bitfield
* b
, size_t n
)
225 if( tr_bitfieldHasAll( b
) || tr_bitfieldHasNone( b
) )
226 tr_bitfieldFreeArray( b
);
228 assert( tr_bitfieldIsValid( b
) );
232 tr_bitfieldRebuildTrueCount( tr_bitfield
* b
)
234 tr_bitfieldSetTrueCount( b
, countArray( b
) );
238 tr_bitfieldIncTrueCount( tr_bitfield
* b
, int i
)
240 tr_bitfieldSetTrueCount( b
, b
->true_count
+ i
);
248 tr_bitfieldConstruct( tr_bitfield
* b
, size_t bit_count
)
250 b
->bit_count
= bit_count
;
254 b
->have_all_hint
= false;
255 b
->have_none_hint
= false;
257 assert( tr_bitfieldIsValid( b
) );
261 tr_bitfieldSetHasNone( tr_bitfield
* b
)
263 tr_bitfieldFreeArray( b
);
265 b
->have_all_hint
= false;
266 b
->have_none_hint
= true;
268 assert( tr_bitfieldIsValid( b
) );
272 tr_bitfieldSetHasAll( tr_bitfield
* b
)
274 tr_bitfieldFreeArray( b
);
275 b
->true_count
= b
->bit_count
;
276 b
->have_all_hint
= true;
277 b
->have_none_hint
= false;
279 assert( tr_bitfieldIsValid( b
) );
283 tr_bitfieldSetFromBitfield( tr_bitfield
* b
, const tr_bitfield
* src
)
285 if( tr_bitfieldHasAll( src
) )
286 tr_bitfieldSetHasAll( b
);
287 else if( tr_bitfieldHasNone( src
) )
288 tr_bitfieldSetHasNone( b
);
290 tr_bitfieldSetRaw( b
, src
->bits
, src
->alloc_count
);
294 tr_bitfieldSetRaw( tr_bitfield
* b
, const void * bits
, size_t byte_count
)
296 tr_bitfieldFreeArray( b
);
298 b
->bits
= tr_memdup( bits
, byte_count
);
299 b
->alloc_count
= byte_count
;
300 tr_bitfieldRebuildTrueCount( b
);
304 tr_bitfieldAdd( tr_bitfield
* b
, size_t nth
)
306 if( !tr_bitfieldHas( b
, nth
) )
308 tr_bitfieldEnsureBitsAlloced( b
, nth
);
309 b
->bits
[nth
>> 3u] |= ( 0x80 >> ( nth
& 7u ) );
310 tr_bitfieldIncTrueCount( b
, 1 );
314 /* Sets bit range [begin, end) to 1 */
316 tr_bitfieldAddRange( tr_bitfield
* b
, size_t begin
, size_t end
)
319 unsigned char sm
, em
;
320 const size_t diff
= (end
-begin
) - tr_bitfieldCountRange( b
, begin
, end
);
326 if( ( end
>= b
->bit_count
) || ( begin
> end
) )
330 sm
= ~( 0xff << ( 8 - ( begin
& 7 ) ) );
332 em
= 0xff << ( 7 - ( end
& 7 ) );
334 tr_bitfieldEnsureBitsAlloced( b
, end
);
337 b
->bits
[sb
] |= ( sm
& em
);
344 memset ( b
->bits
+ sb
, 0xff, eb
- sb
);
347 tr_bitfieldIncTrueCount( b
, diff
);
351 tr_bitfieldRem( tr_bitfield
* b
, size_t nth
)
353 assert( tr_bitfieldIsValid( b
) );
355 if( !tr_bitfieldHas( b
, nth
) )
357 tr_bitfieldEnsureBitsAlloced( b
, nth
);
358 b
->bits
[nth
>> 3u] &= ( 0xff7f >> ( nth
& 7u ) );
359 tr_bitfieldIncTrueCount( b
, -1 );
363 /* Clears bit range [begin, end) to 0 */
365 tr_bitfieldRemRange( tr_bitfield
* b
, size_t begin
, size_t end
)
368 unsigned char sm
, em
;
369 const size_t diff
= tr_bitfieldCountRange( b
, begin
, end
);
376 if( ( end
>= b
->bit_count
) || ( begin
> end
) )
380 sm
= 0xff << ( 8 - ( begin
& 7 ) );
382 em
= ~( 0xff << ( 7 - ( end
& 7 ) ) );
384 tr_bitfieldEnsureBitsAlloced( b
, end
);
387 b
->bits
[sb
] &= ( sm
| em
);
394 memset ( b
->bits
+ sb
, 0, eb
- sb
);
397 tr_bitfieldIncTrueCount( b
, -diff
);