mirror of
https://github.com/moses-smt/mosesdecoder.git
synced 2024-12-27 05:55:02 +03:00
476 lines
9.9 KiB
C
476 lines
9.9 KiB
C
/*
|
|
* 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 <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 ) )
|
|
{
|
|
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 );
|
|
unsigned int i;
|
|
|
|
if ( DEBUG_LISTS )
|
|
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;
|
|
int ii;
|
|
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 )
|
|
{
|
|
printf( "%s", object_str( list_item( iter ) ) );
|
|
iter = list_next( iter );
|
|
for ( ; iter != end; iter = list_next( iter ) )
|
|
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()
|
|
{
|
|
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 )
|
|
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
|