source: trunk/libtransmission/bitset.c @ 12204

Last change on this file since 12204 was 12204, checked in by jordan, 11 years ago

(trunk) #4138 "use stdbool.h instead of tr_bool" -- done.

  • Property svn:keywords set to Date Rev Author Id
File size: 5.3 KB
Line 
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: bitset.c 12204 2011-03-22 15:19:54Z jordan $
11 */
12
13#include <string.h> /* memset() */
14#include <stdlib.h> /* realloc() */
15
16#include "transmission.h"
17#include "bencode.h"
18#include "bitset.h"
19#include "utils.h"
20
21const tr_bitset TR_BITSET_INIT = { false, false, { NULL, 0, 0 } };
22
23void
24tr_bitsetConstruct( tr_bitset * b, size_t bitCount )
25{
26    *b = TR_BITSET_INIT;
27    b->bitfield.bitCount = bitCount;
28}
29
30void
31tr_bitsetDestruct( tr_bitset * b )
32{
33    tr_free( b->bitfield.bits );
34    *b = TR_BITSET_INIT;
35}
36
37static void
38tr_bitsetClear( tr_bitset * b )
39{
40    tr_free( b->bitfield.bits );
41    b->bitfield.bits = NULL;
42    b->haveAll = false;
43    b->haveNone = false;
44}
45
46void
47tr_bitsetSetHaveAll( tr_bitset * b )
48{
49    tr_bitsetClear( b );
50    b->haveAll = true;
51}
52
53void
54tr_bitsetSetHaveNone( tr_bitset * b )
55{
56    tr_bitsetClear( b );
57    b->haveNone = true;
58}
59
60void
61tr_bitsetSetBitfield( tr_bitset * b, const tr_bitfield * bitfield )
62{
63    const size_t n = tr_bitfieldCountTrueBits( bitfield );
64
65    if( n == 0 )
66    {
67        tr_bitsetSetHaveNone( b );
68    }
69    else if( n == bitfield->bitCount )
70    {
71        tr_bitsetSetHaveAll( b );
72    }
73    else
74    {
75        tr_bitsetDestruct( b );
76        b->bitfield.bits = tr_memdup( bitfield->bits, bitfield->byteCount );
77        b->bitfield.bitCount = bitfield->bitCount;
78        b->bitfield.byteCount = bitfield->byteCount;
79    }
80}
81
82/***
83****
84***/
85
86void
87tr_bitsetAdd( tr_bitset * b, size_t i )
88{
89    tr_bitfield * bf = &b->bitfield;
90
91    if( b->haveAll )
92        return;
93
94    b->haveNone = false;
95
96    /* do we need to resize the bitfield to accomodate this bit? */
97    if( !bf->bits || ( bf->bitCount < i+1 ) )
98    {
99        const size_t oldByteCount = bf->byteCount;
100        if( bf->bitCount < i + 1 )
101            bf->bitCount = i + 1;
102        bf->byteCount = ( bf->bitCount + 7u ) / 8u;
103        bf->bits = tr_renew( uint8_t, bf->bits, bf->byteCount );
104        if( bf->byteCount > oldByteCount )
105            memset( bf->bits + oldByteCount, 0, bf->byteCount - oldByteCount );
106    }
107
108    tr_bitfieldAdd( bf, i );
109}
110
111void
112tr_bitsetRem( tr_bitset * b, size_t i )
113{
114    if( b->haveNone )
115        return;
116
117    b->haveAll = false;
118
119    if( !b->bitfield.bits )
120    {
121        tr_bitfieldConstruct( &b->bitfield, b->bitfield.bitCount );
122        tr_bitfieldAddRange( &b->bitfield, 0, b->bitfield.bitCount );
123    }
124
125    tr_bitfieldRem( &b->bitfield, i );
126}
127
128void
129tr_bitsetRemRange( tr_bitset * b, size_t begin, size_t end )
130{
131    if( b->haveNone )
132        return;
133
134    b->haveAll = false;
135    if( !b->bitfield.bits )
136    {
137        tr_bitfieldConstruct( &b->bitfield, b->bitfield.bitCount );
138        tr_bitfieldAddRange( &b->bitfield, 0, b->bitfield.bitCount );
139    }
140
141    tr_bitfieldRemRange( &b->bitfield, begin, end );
142}
143
144/***
145****
146***/
147
148bool
149tr_bitsetHas( const tr_bitset * b, const size_t nth )
150{
151    if( b->haveAll ) return true;
152    if( b->haveNone ) return false;
153    if( nth >= b->bitfield.bitCount ) return false;
154    return tr_bitfieldHas( &b->bitfield, nth );
155}
156
157size_t
158tr_bitsetCountRange( const tr_bitset * b, const size_t begin, const size_t end )
159{
160    if( b->haveAll ) return end - begin;
161    if( b->haveNone ) return 0;
162    return tr_bitfieldCountRange( &b->bitfield, begin, end );
163}
164
165double
166tr_bitsetPercent( const tr_bitset * b )
167{
168    if( b->haveAll ) return 1.0;
169    if( b->haveNone ) return 0.0;
170    if( b->bitfield.bitCount == 0 ) return 0.0;
171    return tr_bitfieldCountTrueBits( &b->bitfield ) / (double)b->bitfield.bitCount;
172}
173
174void
175tr_bitsetOr( tr_bitfield * a, const tr_bitset * b )
176{
177    if( b->haveAll )
178        tr_bitfieldAddRange( a, 0, a->bitCount );
179    else if( !b->haveNone )
180        tr_bitfieldOr( a, &b->bitfield );
181}
182
183/***
184****
185***/
186
187bool
188tr_bitsetFromBenc( tr_bitset * b, tr_benc * benc )
189{
190    size_t buflen;
191    const uint8_t * buf;
192    bool handled = false;
193
194    if( tr_bencGetRaw( benc, &buf, &buflen ) )
195    {
196        if( ( buflen == 3 ) && !memcmp( buf, "all", 3 ) )
197        {
198            tr_bitsetSetHaveAll( b );
199            handled = true;
200        }
201        else if( ( buflen == 4 ) && !memcmp( buf, "none", 4 ) )
202        {
203            tr_bitsetSetHaveNone( b );
204            handled = true;
205        }
206        else
207        {
208            b->haveAll = false;
209            b->haveNone = false;
210            tr_free( b->bitfield.bits );
211            b->bitfield.bits = tr_memdup( buf, buflen );
212            b->bitfield.byteCount = buflen;
213            b->bitfield.bitCount = buflen * 8;
214            handled = true;
215        }
216    }
217
218    return handled;
219}
220
221void
222tr_bitsetToBenc( const tr_bitset * b, tr_benc * benc )
223{
224    if( b->haveAll )
225    {
226        tr_bencInitStr( benc, "all", 3 );
227    }
228    else if( b->haveNone )
229    {
230        tr_bencInitStr( benc, "none", 4 );
231    }
232    else
233    {
234        const tr_bitfield * bf = &b->bitfield;
235        const size_t n = tr_bitfieldCountTrueBits( bf );
236
237        if( n == bf->bitCount )
238        {
239            tr_bencInitStr( benc, "all", 3 );
240        }
241        else if( n == 0 )
242        {
243            tr_bencInitStr( benc, "none", 4 );
244        }
245        else
246        {
247            tr_bencInitRaw( benc, bf->bits, bf->byteCount );
248        }
249    }
250}
Note: See TracBrowser for help on using the repository browser.