2 * Copyright 1993, 1995 Christopher Seiwald.
4 * This file is part of Jam - see jam.c for Copyright information.
8 * lists.c - maintain lists of objects
16 static LIST * freelist[ 32 ]; /* junkpile for list_dealloc() */
18 static unsigned get_bucket( unsigned size )
21 while ( size > ( 1u << bucket ) ) ++bucket;
25 static LIST * list_alloc( unsigned const size )
27 unsigned const bucket = get_bucket( size );
28 if ( freelist[ bucket ] )
30 LIST * result = freelist[ bucket ];
31 freelist[ bucket ] = result->impl.next;
34 return (LIST *)BJAM_MALLOC( sizeof( LIST ) + ( 1u << bucket ) *
38 static void list_dealloc( LIST * l )
40 unsigned size = list_length( l );
44 if ( size == 0 ) return;
46 bucket = get_bucket( size );;
48 #ifdef BJAM_NO_MEM_CACHE
51 node->impl.next = freelist[ bucket ];
52 freelist[ bucket ] = node;
57 * list_append() - append a list onto another one, returning total
60 LIST * list_append( LIST * l, LIST * nl )
62 if ( list_empty( l ) )
64 if ( !list_empty( nl ) )
66 int const l_size = list_length( l );
67 int const nl_size = list_length( nl );
68 int const size = l_size + nl_size;
69 unsigned const bucket = get_bucket( size );
71 /* Do we need to reallocate? */
72 if ( l_size <= ( 1u << ( bucket - 1 ) ) )
74 LIST * result = list_alloc( size );
75 memcpy( list_begin( result ), list_begin( l ), l_size * sizeof(
82 memcpy( list_begin( l ) + l_size, list_begin( nl ), nl_size * sizeof(
89 LISTITER list_begin( LIST * l )
91 return l ? (LISTITER)( (char *)l + sizeof( LIST ) ) : 0;
94 LISTITER list_end( LIST * l )
96 return l ? list_begin( l ) + l->impl.size : 0;
99 LIST * list_new( OBJECT * value )
101 LIST * const head = list_alloc( 1 ) ;
103 list_begin( head )[ 0 ] = value;
108 * list_push_back() - tack a string onto the end of a list of strings
111 LIST * list_push_back( LIST * head, OBJECT * value )
113 unsigned int size = list_length( head );
117 printf( "list > %s <\n", object_str( value ) );
119 /* If the size is a power of 2, reallocate. */
122 head = list_alloc( 1 );
124 else if ( ( ( size - 1 ) & size ) == 0 )
126 LIST * l = list_alloc( size + 1 );
127 memcpy( l, head, sizeof( LIST ) + size * sizeof( OBJECT * ) );
128 list_dealloc( head );
132 list_begin( head )[ size ] = value;
133 head->impl.size = size + 1;
140 * list_copy() - copy a whole list of strings (nl) onto end of another (l).
143 LIST * list_copy( LIST * l )
145 int size = list_length( l );
149 if ( size == 0 ) return L0;
151 result = list_alloc( size );
152 result->impl.size = size;
153 for ( i = 0; i < size; ++i )
154 list_begin( result )[ i ] = object_copy( list_begin( l )[ i ] );
159 LIST * list_copy_range( LIST * l, LISTITER first, LISTITER last )
165 int size = last - first;
166 LIST * result = list_alloc( size );
167 LISTITER dest = list_begin( result );
168 result->impl.size = size;
169 for ( ; first != last; ++first, ++dest )
170 *dest = object_copy( *first );
177 * list_sublist() - copy a subset of a list of strings.
180 LIST * list_sublist( LIST * l, int start, int count )
182 int end = start + count;
183 int size = list_length( l );
184 if ( start >= size ) return L0;
185 if ( end > size ) end = size;
186 return list_copy_range( l, list_begin( l ) + start, list_begin( l ) + end );
190 static int str_ptr_compare( void const * va, void const * vb )
192 OBJECT * a = *( (OBJECT * *)va );
193 OBJECT * b = *( (OBJECT * *)vb );
194 return strcmp( object_str( a ), object_str( b ) );
198 LIST * list_sort( LIST * l )
207 len = list_length( l );
208 result = list_copy( l );
210 qsort( list_begin( result ), len, sizeof( OBJECT * ), str_ptr_compare );
217 * list_free() - free a list of strings
220 void list_free( LIST * head )
222 if ( !list_empty( head ) )
224 LISTITER iter = list_begin( head );
225 LISTITER const end = list_end( head );
226 for ( ; iter != end; iter = list_next( iter ) )
227 object_free( list_item( iter ) );
228 list_dealloc( head );
234 * list_pop_front() - remove the front element from a list of strings
237 LIST * list_pop_front( LIST * l )
239 unsigned size = list_length( l );
242 object_free( list_front( l ) );
250 if ( ( ( size - 1 ) & size ) == 0 )
252 LIST * const nl = list_alloc( size );
253 nl->impl.size = size;
254 memcpy( list_begin( nl ), list_begin( l ) + 1, size * sizeof( OBJECT * )
261 memmove( list_begin( l ), list_begin( l ) + 1, size * sizeof( OBJECT * ) );
265 LIST * list_reverse( LIST * l )
267 int size = list_length( l );
268 if ( size == 0 ) return L0;
270 LIST * const result = list_alloc( size );
272 result->impl.size = size;
273 for ( i = 0; i < size; ++i )
274 list_begin( result )[ i ] = object_copy( list_begin( l )[ size - i -
280 int list_cmp( LIST * t, LIST * s )
283 LISTITER t_it = list_begin( t );
284 LISTITER const t_end = list_end( t );
285 LISTITER s_it = list_begin( s );
286 LISTITER const s_end = list_end( s );
288 while ( !status && ( t_it != t_end || s_it != s_end ) )
290 char const * st = t_it != t_end ? object_str( list_item( t_it ) ) : "";
291 char const * ss = s_it != s_end ? object_str( list_item( s_it ) ) : "";
293 status = strcmp( st, ss );
295 t_it = t_it != t_end ? list_next( t_it ) : t_it;
296 s_it = s_it != s_end ? list_next( s_it ) : s_it;
302 int list_is_sublist( LIST * sub, LIST * l )
304 LISTITER iter = list_begin( sub );
305 LISTITER const end = list_end( sub );
306 for ( ; iter != end; iter = list_next( iter ) )
307 if ( !list_in( l, list_item( iter ) ) )
313 * list_print() - print a list of strings to stdout
316 void list_print( LIST * l )
318 LISTITER iter = list_begin( l ), end = list_end( l );
321 printf( "%s", object_str( list_item( iter ) ) );
322 iter = list_next( iter );
323 for ( ; iter != end; iter = list_next( iter ) )
324 printf( " %s", object_str( list_item( iter ) ) );
330 * list_length() - return the number of items in the list
333 int list_length( LIST * l )
335 return l ? l->impl.size : 0;
339 int list_in( LIST * l, OBJECT * value )
341 LISTITER iter = list_begin( l );
342 LISTITER end = list_end( l );
343 for ( ; iter != end; iter = list_next( iter ) )
344 if ( object_equal( list_item( iter ), value ) )
350 LIST * list_unique( LIST * sorted_list )
353 OBJECT * last_added = 0;
355 LISTITER iter = list_begin( sorted_list ), end = list_end( sorted_list );
356 for ( ; iter != end; iter = list_next( iter ) )
358 if ( !last_added || !object_equal( list_item( iter ), last_added ) )
360 result = list_push_back( result, object_copy( list_item( iter ) ) );
361 last_added = list_item( iter );
370 for ( i = 0; i < sizeof( freelist ) / sizeof( freelist[ 0 ] ); ++i )
372 LIST * l = freelist[ i ];
375 LIST * const tmp = l;
384 * lol_init() - initialize a LOL (list of lists).
387 void lol_init( LOL * lol )
394 * lol_add() - append a LIST onto an LOL.
397 void lol_add( LOL * lol, LIST * l )
399 if ( lol->count < LOL_MAX )
400 lol->list[ lol->count++ ] = l;
405 * lol_free() - free the LOL and its LISTs.
408 void lol_free( LOL * lol )
411 for ( i = 0; i < lol->count; ++i )
412 list_free( lol->list[ i ] );
418 * lol_get() - return one of the LISTs in the LOL.
421 LIST * lol_get( LOL * lol, int i )
423 return i < lol->count ? lol->list[ i ] : L0;
428 * lol_print() - debug print LISTS separated by ":".
431 void lol_print( LOL * lol )
434 for ( i = 0; i < lol->count; ++i )
438 list_print( lol->list[ i ] );
444 PyObject * list_to_python( LIST * l )
446 PyObject * result = PyList_New( 0 );
447 LISTITER iter = list_begin( l );
448 LISTITER const end = list_end( l );
449 for ( ; iter != end; iter = list_next( iter ) )
451 PyObject * s = PyString_FromString( object_str( list_item( iter ) ) );
452 PyList_Append( result, s );
459 LIST * list_from_python( PyObject * l )
463 Py_ssize_t n = PySequence_Size( l );
465 for ( i = 0; i < n; ++i )
467 PyObject * v = PySequence_GetItem( l, i );
468 result = list_push_back( result, object_new( PyString_AsString( v ) ) );