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 $
14 #include <stdlib.h> /* tr_renew() -> realloc() */
15 #include <string.h> /* memmove */
22 const tr_ptrArray TR_PTR_ARRAY_INIT
= { NULL
, 0, 0 };
25 tr_ptrArrayDestruct( tr_ptrArray
* p
, PtrArrayForeachFunc func
)
28 assert( p
->items
|| !p
->n_items
);
31 tr_ptrArrayForeach( p
, func
);
35 memset( p
, ~0, sizeof( tr_ptrArray
) );
39 tr_ptrArrayForeach( tr_ptrArray
* t
,
40 PtrArrayForeachFunc func
)
45 assert( t
->items
|| !t
->n_items
);
48 for( i
= 0; i
< t
->n_items
; ++i
)
53 tr_ptrArrayPeek( tr_ptrArray
* t
,
61 tr_ptrArrayInsert( tr_ptrArray
* t
,
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
)
74 memmove( t
->items
+ pos
+ 1,
76 sizeof( void* ) * ( t
->n_items
- pos
) );
84 tr_ptrArrayPop( tr_ptrArray
* t
)
89 ret
= t
->items
[--t
->n_items
];
95 tr_ptrArrayErase( tr_ptrArray
* t
,
100 if( end
< 0 ) end
= t
->n_items
;
101 assert( begin
< end
);
102 assert( end
<= t
->n_items
);
104 memmove( t
->items
+ begin
,
106 sizeof( void* ) * ( t
->n_items
- end
) );
108 t
->n_items
-= ( end
- begin
);
117 lowerBound2( const tr_ptrArray
* t
,
119 int compare( const void *, const void * ),
123 const int len
= t
->n_items
;
125 for( i
=0; i
<len
; ++i
)
127 const int c
= compare( t
->items
[i
], ptr
);
137 *exact_match
= false;
141 *exact_match
= false;
147 tr_ptrArrayLowerBound( const tr_ptrArray
* t
,
149 int compare( const void *, const void * ),
158 if( t
->n_items
== 0 )
165 int last
= t
->n_items
- 1;
169 const int half
= (last
- first
) / 2;
170 const int c
= compare( t
->items
[first
+ half
], ptr
);
173 const int new_first
= first
+ half
+ 1;
174 if( new_first
> last
) {
181 const int new_last
= first
+ half
- 1;
182 if( new_last
< first
) {
196 assert( pos
== lowerBound2( t
, ptr
, compare
, &match_2
) );
197 assert( match
== match_2
);
200 *exact_match
= match
;
205 assertSortedAndUnique( const tr_ptrArray
* t UNUSED
,
206 int compare(const void*, const void*) UNUSED
)
211 for( i
= 0; i
< t
->n_items
- 2; ++i
)
212 assert( compare( t
->items
[i
], t
->items
[i
+ 1] ) < 0 );
217 tr_ptrArrayInsertSorted( tr_ptrArray
* t
,
219 int compare(const void*, const void*) )
224 assertSortedAndUnique( t
, compare
);
226 pos
= tr_ptrArrayLowerBound( t
, ptr
, compare
, NULL
);
227 ret
= tr_ptrArrayInsert( t
, ptr
, pos
);
229 assertSortedAndUnique( t
, compare
);
234 tr_ptrArrayFindSorted( tr_ptrArray
* t
,
236 int compare(const void*, const void*) )
239 const int pos
= tr_ptrArrayLowerBound( t
, ptr
, compare
, &match
);
240 return match
? t
->items
[pos
] : NULL
;
244 tr_ptrArrayRemoveSorted( tr_ptrArray
* t
,
246 int compare(const void*, const void*) )
250 const int pos
= tr_ptrArrayLowerBound( t
, ptr
, compare
, &match
);
251 assertSortedAndUnique( t
, compare
);
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 ) );