mirror of
https://github.com/moses-smt/mosesdecoder.git
synced 2024-12-28 14:32:38 +03:00
224 lines
5.3 KiB
C
224 lines
5.3 KiB
C
/* Copyright David Abrahams 2004. Distributed under the Boost */
|
|
/* Software License, Version 1.0. (See accompanying */
|
|
/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
|
|
|
|
#include "jam.h"
|
|
#include "strings.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
|
|
#ifndef NDEBUG
|
|
# define JAM_STRING_MAGIC ((char)0xcf)
|
|
# define JAM_STRING_MAGIC_SIZE 4
|
|
static void assert_invariants( string * self )
|
|
{
|
|
int i;
|
|
|
|
if ( self->value == 0 )
|
|
{
|
|
assert( self->size == 0 );
|
|
assert( self->capacity == 0 );
|
|
assert( self->opt[ 0 ] == 0 );
|
|
return;
|
|
}
|
|
|
|
assert( self->size < self->capacity );
|
|
assert( ( self->capacity <= sizeof( self->opt ) ) == ( self->value == self->opt ) );
|
|
assert( self->value[ self->size ] == 0 );
|
|
/* String objects modified manually after construction to contain embedded
|
|
* '\0' characters are considered structurally valid.
|
|
*/
|
|
assert( strlen( self->value ) <= self->size );
|
|
|
|
for ( i = 0; i < 4; ++i )
|
|
{
|
|
assert( self->magic[ i ] == JAM_STRING_MAGIC );
|
|
assert( self->value[ self->capacity + i ] == JAM_STRING_MAGIC );
|
|
}
|
|
}
|
|
#else
|
|
# define JAM_STRING_MAGIC_SIZE 0
|
|
# define assert_invariants(x) do {} while (0)
|
|
#endif
|
|
|
|
|
|
void string_new( string * s )
|
|
{
|
|
s->value = s->opt;
|
|
s->size = 0;
|
|
s->capacity = sizeof( s->opt );
|
|
s->opt[ 0 ] = 0;
|
|
#ifndef NDEBUG
|
|
memset( s->magic, JAM_STRING_MAGIC, sizeof( s->magic ) );
|
|
#endif
|
|
assert_invariants( s );
|
|
}
|
|
|
|
|
|
void string_free( string * s )
|
|
{
|
|
assert_invariants( s );
|
|
if ( s->value != s->opt )
|
|
BJAM_FREE( s->value );
|
|
string_new( s );
|
|
}
|
|
|
|
|
|
static void string_reserve_internal( string * self, size_t capacity )
|
|
{
|
|
if ( self->value == self->opt )
|
|
{
|
|
self->value = (char *)BJAM_MALLOC_ATOMIC( capacity +
|
|
JAM_STRING_MAGIC_SIZE );
|
|
self->value[ 0 ] = 0;
|
|
strncat( self->value, self->opt, sizeof(self->opt) );
|
|
assert( strlen( self->value ) <= self->capacity && "Regression test" );
|
|
}
|
|
else
|
|
{
|
|
self->value = (char *)BJAM_REALLOC( self->value, capacity +
|
|
JAM_STRING_MAGIC_SIZE );
|
|
}
|
|
#ifndef NDEBUG
|
|
memcpy( self->value + capacity, self->magic, JAM_STRING_MAGIC_SIZE );
|
|
#endif
|
|
self->capacity = capacity;
|
|
}
|
|
|
|
|
|
void string_reserve( string * self, size_t capacity )
|
|
{
|
|
assert_invariants( self );
|
|
if ( capacity <= self->capacity )
|
|
return;
|
|
string_reserve_internal( self, capacity );
|
|
assert_invariants( self );
|
|
}
|
|
|
|
|
|
static void extend_full( string * self, char const * start, char const * finish )
|
|
{
|
|
size_t new_size = self->capacity + ( finish - start );
|
|
size_t new_capacity = self->capacity;
|
|
size_t old_size = self->capacity;
|
|
while ( new_capacity < new_size + 1)
|
|
new_capacity <<= 1;
|
|
string_reserve_internal( self, new_capacity );
|
|
memcpy( self->value + old_size, start, new_size - old_size );
|
|
self->value[ new_size ] = 0;
|
|
self->size = new_size;
|
|
}
|
|
|
|
static void maybe_reserve( string * self, size_t new_size )
|
|
{
|
|
size_t capacity = self->capacity;
|
|
if ( capacity <= new_size )
|
|
{
|
|
size_t new_capacity = capacity;
|
|
while ( new_capacity <= new_size )
|
|
new_capacity <<= 1;
|
|
string_reserve_internal( self, new_capacity );
|
|
}
|
|
}
|
|
|
|
|
|
void string_append( string * self, char const * rhs )
|
|
{
|
|
size_t rhs_size = strlen( rhs );
|
|
size_t new_size = self->size + rhs_size;
|
|
assert_invariants( self );
|
|
|
|
maybe_reserve( self, new_size );
|
|
|
|
memcpy( self->value + self->size, rhs, rhs_size + 1 );
|
|
self->size = new_size;
|
|
|
|
assert_invariants( self );
|
|
}
|
|
|
|
|
|
void string_append_range( string * self, char const * start, char const * finish )
|
|
{
|
|
size_t rhs_size = finish - start;
|
|
size_t new_size = self->size + rhs_size;
|
|
assert_invariants( self );
|
|
|
|
maybe_reserve( self, new_size );
|
|
|
|
memcpy( self->value + self->size, start, rhs_size );
|
|
self->size = new_size;
|
|
self->value[ new_size ] = 0;
|
|
|
|
assert_invariants( self );
|
|
}
|
|
|
|
|
|
void string_copy( string * s, char const * rhs )
|
|
{
|
|
string_new( s );
|
|
string_append( s, rhs );
|
|
}
|
|
|
|
void string_truncate( string * self, size_t n )
|
|
{
|
|
assert_invariants( self );
|
|
assert( n <= self->capacity );
|
|
self->value[ self->size = n ] = 0;
|
|
assert_invariants( self );
|
|
}
|
|
|
|
|
|
void string_pop_back( string * self )
|
|
{
|
|
string_truncate( self, self->size - 1 );
|
|
}
|
|
|
|
|
|
void string_push_back( string * self, char x )
|
|
{
|
|
string_append_range( self, &x, &x + 1 );
|
|
}
|
|
|
|
|
|
char string_back( string * self )
|
|
{
|
|
assert_invariants( self );
|
|
return self->value[ self->size - 1 ];
|
|
}
|
|
|
|
|
|
#ifndef NDEBUG
|
|
void string_unit_test()
|
|
{
|
|
{
|
|
string s[ 1 ];
|
|
int i;
|
|
int const limit = sizeof( s->opt ) * 2 + 2;
|
|
string_new( s );
|
|
assert( s->value == s->opt );
|
|
for ( i = 0; i < limit; ++i )
|
|
{
|
|
string_push_back( s, (char)( i + 1 ) );
|
|
assert( s->size == i + 1 );
|
|
}
|
|
assert( s->size == limit );
|
|
assert( s->value != s->opt );
|
|
for ( i = 0; i < limit; ++i )
|
|
assert( s->value[ i ] == (char)( i + 1 ) );
|
|
string_free( s );
|
|
}
|
|
|
|
{
|
|
char * const original = " \n\t\v Foo \r\n\v \tBar\n\n\r\r\t\n\v\t \t";
|
|
string copy[ 1 ];
|
|
string_copy( copy, original );
|
|
assert( !strcmp( copy->value, original ) );
|
|
assert( copy->size == strlen( original ) );
|
|
string_free( copy );
|
|
}
|
|
}
|
|
#endif
|