1 /* Copyright David Abrahams 2004. Distributed under the Boost */
2 /* Software License, Version 1.0. (See accompanying */
3 /* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
14 # define JAM_STRING_MAGIC ((char)0xcf)
15 # define JAM_STRING_MAGIC_SIZE 4
16 static void assert_invariants( string* self )
20 if ( self->value == 0 )
22 assert( self->size == 0 );
23 assert( self->capacity == 0 );
24 assert( self->opt[0] == 0 );
28 assert( self->size < self->capacity );
29 assert( ( self->capacity <= sizeof(self->opt) ) == ( self->value == self->opt ) );
30 assert( strlen( self->value ) == self->size );
32 for (i = 0; i < 4; ++i)
34 assert( self->magic[i] == JAM_STRING_MAGIC );
35 assert( self->value[self->capacity + i] == JAM_STRING_MAGIC );
39 # define JAM_STRING_MAGIC_SIZE 0
40 # define assert_invariants(x) do {} while (0)
43 void string_new( string* s )
47 s->capacity = sizeof(s->opt);
50 memset(s->magic, JAM_STRING_MAGIC, sizeof(s->magic));
52 assert_invariants( s );
55 void string_free( string* s )
57 assert_invariants( s );
58 if ( s->value != s->opt )
59 BJAM_FREE( s->value );
63 static void string_reserve_internal( string* self, size_t capacity )
65 if ( self->value == self->opt )
67 self->value = (char*)BJAM_MALLOC_ATOMIC( capacity + JAM_STRING_MAGIC_SIZE );
69 strncat( self->value, self->opt, sizeof(self->opt) );
70 assert( strlen( self->value ) <= self->capacity ); /* This is a regression test */
74 self->value = (char*)BJAM_REALLOC( self->value, capacity + JAM_STRING_MAGIC_SIZE );
77 memcpy( self->value + capacity, self->magic, JAM_STRING_MAGIC_SIZE );
79 self->capacity = capacity;
82 void string_reserve( string* self, size_t capacity )
84 assert_invariants( self );
85 if ( capacity <= self->capacity )
87 string_reserve_internal( self, capacity );
88 assert_invariants( self );
91 static void extend_full( string* self, char const* start, char const* finish )
93 size_t new_size = self->capacity + ( finish - start );
94 size_t new_capacity = self->capacity;
95 size_t old_size = self->capacity;
96 while ( new_capacity < new_size + 1)
98 string_reserve_internal( self, new_capacity );
99 memcpy( self->value + old_size, start, new_size - old_size );
100 self->value[new_size] = 0;
101 self->size = new_size;
104 void string_append( string* self, char const* rhs )
106 char* p = self->value + self->size;
107 char* end = self->value + self->capacity;
108 assert_invariants( self );
110 while ( *rhs && p != end)
116 self->size = p - self->value;
120 extend_full( self, rhs, rhs + strlen(rhs) );
122 assert_invariants( self );
125 void string_append_range( string* self, char const* start, char const* finish )
127 char* p = self->value + self->size;
128 char* end = self->value + self->capacity;
129 assert_invariants( self );
131 while ( p != end && start != finish )
137 self->size = p - self->value;
141 extend_full( self, start, finish );
143 assert_invariants( self );
146 void string_copy( string* s, char const* rhs )
149 string_append( s, rhs );
152 void string_truncate( string* self, size_t n )
154 assert_invariants( self );
155 assert( n <= self->capacity );
156 self->value[self->size = n] = 0;
157 assert_invariants( self );
160 void string_pop_back( string* self )
162 string_truncate( self, self->size - 1 );
165 void string_push_back( string* self, char x )
167 string_append_range( self, &x, &x + 1 );
170 char string_back( string* self )
172 assert_invariants( self );
173 return self->value[self->size - 1];
177 void string_unit_test()
181 char buffer[sizeof(s->opt) * 2 + 2];
182 int limit = sizeof(buffer) > 254 ? 254 : sizeof(buffer);
186 for (i = 0; i < limit; ++i)
188 string_push_back( s, (char)(i + 1) );
191 for (i = 0; i < limit; ++i)
193 assert( i < s->size );
194 assert( s->value[i] == (char)(i + 1));