diff options
Diffstat (limited to 'src/boost/tools/build/src/engine/lists.cpp')
-rw-r--r-- | src/boost/tools/build/src/engine/lists.cpp | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/src/boost/tools/build/src/engine/lists.cpp b/src/boost/tools/build/src/engine/lists.cpp new file mode 100644 index 000000000..af602b504 --- /dev/null +++ b/src/boost/tools/build/src/engine/lists.cpp @@ -0,0 +1,474 @@ +/* + * Copyright 1993, 1995 Christopher Seiwald. + * + * This file is part of Jam - see jam.c for Copyright information. + */ + +/* + * lists.c - maintain lists of objects + */ + +#include "jam.h" +#include "lists.h" +#include "output.h" + +#include <assert.h> + +static LIST * freelist[ 32 ]; /* junkpile for list_dealloc() */ + +static unsigned get_bucket( unsigned size ) +{ + unsigned bucket = 0; + while ( size > ( 1u << bucket ) ) ++bucket; + return bucket; +} + +static LIST * list_alloc( unsigned const size ) +{ + unsigned const bucket = get_bucket( size ); + if ( freelist[ bucket ] ) + { + LIST * result = freelist[ bucket ]; + freelist[ bucket ] = result->impl.next; + return result; + } + return (LIST *)BJAM_MALLOC( sizeof( LIST ) + ( 1u << bucket ) * + sizeof( OBJECT * ) ); +} + +static void list_dealloc( LIST * l ) +{ + unsigned size = list_length( l ); + unsigned bucket; + LIST * node = l; + + if ( size == 0 ) return; + + bucket = get_bucket( size );; + +#ifdef BJAM_NO_MEM_CACHE + BJAM_FREE( node ); +#else + node->impl.next = freelist[ bucket ]; + freelist[ bucket ] = node; +#endif +} + +/* + * list_append() - append a list onto another one, returning total + */ + +LIST * list_append( LIST * l, LIST * nl ) +{ + if ( list_empty( l ) ) + return nl; + if ( !list_empty( nl ) ) + { + unsigned int const l_size = list_length( l ); + int const nl_size = list_length( nl ); + int const size = l_size + nl_size; + unsigned const bucket = get_bucket( size ); + + /* Do we need to reallocate? */ + if ( l_size <= ( 1u << ( bucket - 1 ) ) ) + { + LIST * result = list_alloc( size ); + memcpy( list_begin( result ), list_begin( l ), l_size * sizeof( + OBJECT * ) ); + list_dealloc( l ); + l = result; + } + + l->impl.size = size; + memcpy( list_begin( l ) + l_size, list_begin( nl ), nl_size * sizeof( + OBJECT * ) ); + list_dealloc( nl ); + } + return l; +} + +LISTITER list_begin( LIST * l ) +{ + return l ? (LISTITER)( (char *)l + sizeof( LIST ) ) : 0; +} + +LISTITER list_end( LIST * l ) +{ + return l ? list_begin( l ) + l->impl.size : 0; +} + +LIST * list_new( OBJECT * value ) +{ + LIST * const head = list_alloc( 1 ) ; + head->impl.size = 1; + list_begin( head )[ 0 ] = value; + return head; +} + +/* + * list_push_back() - tack a string onto the end of a list of strings + */ + +LIST * list_push_back( LIST * head, OBJECT * value ) +{ + unsigned int size = list_length( head ); + + if ( DEBUG_LISTS ) + out_printf( "list > %s <\n", object_str( value ) ); + + /* If the size is a power of 2, reallocate. */ + if ( size == 0 ) + { + head = list_alloc( 1 ); + } + else if ( ( ( size - 1 ) & size ) == 0 ) + { + LIST * l = list_alloc( size + 1 ); + memcpy( l, head, sizeof( LIST ) + size * sizeof( OBJECT * ) ); + list_dealloc( head ); + head = l; + } + + list_begin( head )[ size ] = value; + head->impl.size = size + 1; + + return head; +} + + +/* + * list_copy() - copy a whole list of strings (nl) onto end of another (l). + */ + +LIST * list_copy( LIST * l ) +{ + int size = list_length( l ); + int i; + LIST * result; + + if ( size == 0 ) return L0; + + result = list_alloc( size ); + result->impl.size = size; + for ( i = 0; i < size; ++i ) + list_begin( result )[ i ] = object_copy( list_begin( l )[ i ] ); + return result; +} + + +LIST * list_copy_range( LIST * l, LISTITER first, LISTITER last ) +{ + if ( first == last ) + return L0; + else + { + int size = last - first; + LIST * result = list_alloc( size ); + LISTITER dest = list_begin( result ); + result->impl.size = size; + for ( ; first != last; ++first, ++dest ) + *dest = object_copy( *first ); + return result; + } +} + + +/* + * list_sublist() - copy a subset of a list of strings. + */ + +LIST * list_sublist( LIST * l, int start, int count ) +{ + int end = start + count; + int size = list_length( l ); + if ( start >= size ) return L0; + if ( end > size ) end = size; + return list_copy_range( l, list_begin( l ) + start, list_begin( l ) + end ); +} + + +static int str_ptr_compare( void const * va, void const * vb ) +{ + OBJECT * a = *( (OBJECT * *)va ); + OBJECT * b = *( (OBJECT * *)vb ); + return strcmp( object_str( a ), object_str( b ) ); +} + + +LIST * list_sort( LIST * l ) +{ + int len; + LIST * result; + + if ( !l ) + return L0; + + len = list_length( l ); + result = list_copy( l ); + + qsort( list_begin( result ), len, sizeof( OBJECT * ), str_ptr_compare ); + + return result; +} + + +/* + * list_free() - free a list of strings + */ + +void list_free( LIST * head ) +{ + if ( !list_empty( head ) ) + { + LISTITER iter = list_begin( head ); + LISTITER const end = list_end( head ); + for ( ; iter != end; iter = list_next( iter ) ) + object_free( list_item( iter ) ); + list_dealloc( head ); + } +} + + +/* + * list_pop_front() - remove the front element from a list of strings + */ + +LIST * list_pop_front( LIST * l ) +{ + unsigned size = list_length( l ); + assert( size ); + --size; + object_free( list_front( l ) ); + + if ( size == 0 ) + { + list_dealloc( l ); + return L0; + } + + if ( ( ( size - 1 ) & size ) == 0 ) + { + LIST * const nl = list_alloc( size ); + nl->impl.size = size; + memcpy( list_begin( nl ), list_begin( l ) + 1, size * sizeof( OBJECT * ) + ); + list_dealloc( l ); + return nl; + } + + l->impl.size = size; + memmove( list_begin( l ), list_begin( l ) + 1, size * sizeof( OBJECT * ) ); + return l; +} + +LIST * list_reverse( LIST * l ) +{ + int size = list_length( l ); + if ( size == 0 ) return L0; + { + LIST * const result = list_alloc( size ); + int i; + result->impl.size = size; + for ( i = 0; i < size; ++i ) + list_begin( result )[ i ] = object_copy( list_begin( l )[ size - i - + 1 ] ); + return result; + } +} + +int list_cmp( LIST * t, LIST * s ) +{ + int status = 0; + LISTITER t_it = list_begin( t ); + LISTITER const t_end = list_end( t ); + LISTITER s_it = list_begin( s ); + LISTITER const s_end = list_end( s ); + + while ( !status && ( t_it != t_end || s_it != s_end ) ) + { + char const * st = t_it != t_end ? object_str( list_item( t_it ) ) : ""; + char const * ss = s_it != s_end ? object_str( list_item( s_it ) ) : ""; + + status = strcmp( st, ss ); + + t_it = t_it != t_end ? list_next( t_it ) : t_it; + s_it = s_it != s_end ? list_next( s_it ) : s_it; + } + + return status; +} + +int list_is_sublist( LIST * sub, LIST * l ) +{ + LISTITER iter = list_begin( sub ); + LISTITER const end = list_end( sub ); + for ( ; iter != end; iter = list_next( iter ) ) + if ( !list_in( l, list_item( iter ) ) ) + return 0; + return 1; +} + +/* + * list_print() - print a list of strings to stdout + */ + +void list_print( LIST * l ) +{ + LISTITER iter = list_begin( l ), end = list_end( l ); + if ( iter != end ) + { + out_printf( "%s", object_str( list_item( iter ) ) ); + iter = list_next( iter ); + for ( ; iter != end; iter = list_next( iter ) ) + out_printf( " %s", object_str( list_item( iter ) ) ); + } +} + + +/* + * list_length() - return the number of items in the list + */ + +int list_length( LIST * l ) +{ + return l ? l->impl.size : 0; +} + + +int list_in( LIST * l, OBJECT * value ) +{ + LISTITER iter = list_begin( l ); + LISTITER end = list_end( l ); + for ( ; iter != end; iter = list_next( iter ) ) + if ( object_equal( list_item( iter ), value ) ) + return 1; + return 0; +} + + +LIST * list_unique( LIST * sorted_list ) +{ + LIST * result = L0; + OBJECT * last_added = 0; + + LISTITER iter = list_begin( sorted_list ), end = list_end( sorted_list ); + for ( ; iter != end; iter = list_next( iter ) ) + { + if ( !last_added || !object_equal( list_item( iter ), last_added ) ) + { + result = list_push_back( result, object_copy( list_item( iter ) ) ); + last_added = list_item( iter ); + } + } + return result; +} + +void list_done() +{ + unsigned int i; + for ( i = 0; i < sizeof( freelist ) / sizeof( freelist[ 0 ] ); ++i ) + { + LIST * l = freelist[ i ]; + while ( l ) + { + LIST * const tmp = l; + l = l->impl.next; + BJAM_FREE( tmp ); + } + } +} + + +/* + * lol_init() - initialize a LOL (list of lists). + */ + +void lol_init( LOL * lol ) +{ + lol->count = 0; +} + + +/* + * lol_add() - append a LIST onto an LOL. + */ + +void lol_add( LOL * lol, LIST * l ) +{ + if ( lol->count < LOL_MAX ) + lol->list[ lol->count++ ] = l; +} + + +/* + * lol_free() - free the LOL and its LISTs. + */ + +void lol_free( LOL * lol ) +{ + int i; + for ( i = 0; i < lol->count; ++i ) + list_free( lol->list[ i ] ); + lol->count = 0; +} + + +/* + * lol_get() - return one of the LISTs in the LOL. + */ + +LIST * lol_get( LOL * lol, int i ) +{ + return i < lol->count ? lol->list[ i ] : L0; +} + + +/* + * lol_print() - debug print LISTS separated by ":". + */ + +void lol_print( LOL * lol ) +{ + int i; + for ( i = 0; i < lol->count; ++i ) + { + if ( i ) + out_printf( " : " ); + list_print( lol->list[ i ] ); + } +} + +#ifdef HAVE_PYTHON + +PyObject * list_to_python( LIST * l ) +{ + PyObject * result = PyList_New( 0 ); + LISTITER iter = list_begin( l ); + LISTITER const end = list_end( l ); + for ( ; iter != end; iter = list_next( iter ) ) + { + PyObject * s = PyString_FromString( object_str( list_item( iter ) ) ); + PyList_Append( result, s ); + Py_DECREF( s ); + } + + return result; +} + +LIST * list_from_python( PyObject * l ) +{ + LIST * result = L0; + + Py_ssize_t n = PySequence_Size( l ); + Py_ssize_t i; + for ( i = 0; i < n; ++i ) + { + PyObject * v = PySequence_GetItem( l, i ); + result = list_push_back( result, object_new( PyString_AsString( v ) ) ); + Py_DECREF( v ); + } + + return result; +} + +#endif |