diff options
author | Patrick Simianer <simianer@cl.uni-heidelberg.de> | 2012-05-13 03:35:30 +0200 |
---|---|---|
committer | Patrick Simianer <simianer@cl.uni-heidelberg.de> | 2012-05-13 03:35:30 +0200 |
commit | 670a8f984fc6d8342180c59ae9e96b0b76f34d3d (patch) | |
tree | 9f2ce7eec1a77e56b3bb1ad0ad40f212d7a996b0 /jam-files/engine/strings.c | |
parent | eb3ee28dc0eb1d3e5ed01ba0df843be329ae450d (diff) | |
parent | 2f64af3e06a518b93f7ca2c30a9d0aeb2c947031 (diff) |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'jam-files/engine/strings.c')
-rw-r--r-- | jam-files/engine/strings.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/jam-files/engine/strings.c b/jam-files/engine/strings.c new file mode 100644 index 00000000..89561237 --- /dev/null +++ b/jam-files/engine/strings.c @@ -0,0 +1,201 @@ +/* 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 <stdlib.h> +#include <string.h> +#include <assert.h> +#include <stdio.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( 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 ); /* This is a 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; +} + +void string_append( string* self, char const* rhs ) +{ + char* p = self->value + self->size; + char* end = self->value + self->capacity; + assert_invariants( self ); + + while ( *rhs && p != end) + *p++ = *rhs++; + + if ( p != end ) + { + *p = 0; + self->size = p - self->value; + } + else + { + extend_full( self, rhs, rhs + strlen(rhs) ); + } + assert_invariants( self ); +} + +void string_append_range( string* self, char const* start, char const* finish ) +{ + char* p = self->value + self->size; + char* end = self->value + self->capacity; + assert_invariants( self ); + + while ( p != end && start != finish ) + *p++ = *start++; + + if ( p != end ) + { + *p = 0; + self->size = p - self->value; + } + else + { + extend_full( self, start, finish ); + } + 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; + char buffer[sizeof(s->opt) * 2 + 2]; + int limit = sizeof(buffer) > 254 ? 254 : sizeof(buffer); + + string_new(s); + + for (i = 0; i < limit; ++i) + { + string_push_back( s, (char)(i + 1) ); + }; + + for (i = 0; i < limit; ++i) + { + assert( i < s->size ); + assert( s->value[i] == (char)(i + 1)); + } + + string_free(s); + +} +#endif + |