Transmission 2.33
[tomato.git] / release / src / router / transmission / libtransmission / ptrarray.c
blob719e4c63289cf71ff7b7b08a35373d6b72f639b8
1 /*
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: ptrarray.c 12553 2011-07-17 14:33:20Z jordan $
13 #include <assert.h>
14 #include <stdlib.h> /* tr_renew() -> realloc() */
15 #include <string.h> /* memmove */
17 #include "ptrarray.h"
18 #include "utils.h"
20 #define FLOOR 32
22 const tr_ptrArray TR_PTR_ARRAY_INIT = { NULL, 0, 0 };
24 void
25 tr_ptrArrayDestruct( tr_ptrArray * p, PtrArrayForeachFunc func )
27 assert( p );
28 assert( p->items || !p->n_items );
30 if( func )
31 tr_ptrArrayForeach( p, func );
33 tr_free( p->items );
35 memset( p, ~0, sizeof( tr_ptrArray ) );
38 void
39 tr_ptrArrayForeach( tr_ptrArray * t,
40 PtrArrayForeachFunc func )
42 int i;
44 assert( t );
45 assert( t->items || !t->n_items );
46 assert( func );
48 for( i = 0; i < t->n_items; ++i )
49 func( t->items[i] );
52 void**
53 tr_ptrArrayPeek( tr_ptrArray * t,
54 int * size )
56 *size = t->n_items;
57 return t->items;
60 int
61 tr_ptrArrayInsert( tr_ptrArray * t,
62 void * ptr,
63 int pos )
65 if( t->n_items >= t->n_alloc )
67 t->n_alloc = MAX( FLOOR, t->n_alloc * 2 );
68 t->items = tr_renew( void*, t->items, t->n_alloc );
71 if( pos < 0 || pos > t->n_items )
72 pos = t->n_items;
73 else
74 memmove( t->items + pos + 1,
75 t->items + pos,
76 sizeof( void* ) * ( t->n_items - pos ) );
78 t->items[pos] = ptr;
79 t->n_items++;
80 return pos;
83 void*
84 tr_ptrArrayPop( tr_ptrArray* t )
86 void * ret = NULL;
88 if( t->n_items )
89 ret = t->items[--t->n_items];
91 return ret;
94 void
95 tr_ptrArrayErase( tr_ptrArray * t,
96 int begin,
97 int end )
99 assert( begin >= 0 );
100 if( end < 0 ) end = t->n_items;
101 assert( begin < end );
102 assert( end <= t->n_items );
104 memmove( t->items + begin,
105 t->items + end,
106 sizeof( void* ) * ( t->n_items - end ) );
108 t->n_items -= ( end - begin );
115 #ifndef NDEBUG
116 static int
117 lowerBound2( const tr_ptrArray * t,
118 const void * ptr,
119 int compare( const void *, const void * ),
120 bool * exact_match )
122 int i;
123 const int len = t->n_items;
125 for( i=0; i<len; ++i )
127 const int c = compare( t->items[i], ptr );
129 if( c == 0 ) {
130 *exact_match = true;
131 return i;
134 if( c < 0 )
135 continue;
137 *exact_match = false;
138 return i;
141 *exact_match = false;
142 return len;
144 #endif
147 tr_ptrArrayLowerBound( const tr_ptrArray * t,
148 const void * ptr,
149 int compare( const void *, const void * ),
150 bool * exact_match )
152 int pos = -1;
153 bool match = false;
154 #ifndef NDEBUG
155 bool match_2;
156 #endif
158 if( t->n_items == 0 )
160 pos = 0;
162 else
164 int first = 0;
165 int last = t->n_items - 1;
167 for( ;; )
169 const int half = (last - first) / 2;
170 const int c = compare( t->items[first + half], ptr );
172 if( c < 0 ) {
173 const int new_first = first + half + 1;
174 if( new_first > last ) {
175 pos = new_first;
176 break;
178 first = new_first;
180 else if( c > 0 ) {
181 const int new_last = first + half - 1;
182 if( new_last < first ) {
183 pos = first;
184 break;
186 last = new_last;
188 else {
189 match = true;
190 pos = first + half;
191 break;
196 assert( pos == lowerBound2( t, ptr, compare, &match_2 ) );
197 assert( match == match_2 );
199 if( exact_match )
200 *exact_match = match;
201 return pos;
204 static void
205 assertSortedAndUnique( const tr_ptrArray * t UNUSED,
206 int compare(const void*, const void*) UNUSED )
208 #if 1
209 int i;
211 for( i = 0; i < t->n_items - 2; ++i )
212 assert( compare( t->items[i], t->items[i + 1] ) < 0 );
213 #endif
217 tr_ptrArrayInsertSorted( tr_ptrArray * t,
218 void * ptr,
219 int compare(const void*, const void*) )
221 int pos;
222 int ret;
224 assertSortedAndUnique( t, compare );
226 pos = tr_ptrArrayLowerBound( t, ptr, compare, NULL );
227 ret = tr_ptrArrayInsert( t, ptr, pos );
229 assertSortedAndUnique( t, compare );
230 return ret;
233 void*
234 tr_ptrArrayFindSorted( tr_ptrArray * t,
235 const void * ptr,
236 int compare(const void*, const void*) )
238 bool match = false;
239 const int pos = tr_ptrArrayLowerBound( t, ptr, compare, &match );
240 return match ? t->items[pos] : NULL;
243 void*
244 tr_ptrArrayRemoveSorted( tr_ptrArray * t,
245 const void * ptr,
246 int compare(const void*, const void*) )
248 bool match;
249 void * ret = NULL;
250 const int pos = tr_ptrArrayLowerBound( t, ptr, compare, &match );
251 assertSortedAndUnique( t, compare );
253 if( match )
255 ret = t->items[pos];
256 assert( compare( ret, ptr ) == 0 );
257 tr_ptrArrayErase( t, pos, pos + 1 );
259 assertSortedAndUnique( t, compare );
260 assert( ( ret == NULL ) || ( compare( ret, ptr ) == 0 ) );
261 return ret;