]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/engine/jam_strings.cpp
c9ed8a17f0a0903fbdb8b90c63ac89b836ecd751
[ceph.git] / ceph / src / boost / tools / build / src / engine / jam_strings.cpp
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) */
4
5 #include "jam.h"
6 #include "jam_strings.h"
7
8 #include <assert.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12
13 #ifndef NDEBUG
14 # define JAM_STRING_MAGIC ((char)0xcf)
15 # define JAM_STRING_MAGIC_SIZE 4
16 static void assert_invariants( string * self )
17 {
18 int i;
19
20 if ( self->value == 0 )
21 {
22 assert( self->size == 0 );
23 assert( self->capacity == 0 );
24 assert( self->opt[ 0 ] == 0 );
25 return;
26 }
27
28 assert( self->size < self->capacity );
29 assert( ( self->capacity <= sizeof( self->opt ) ) == ( self->value == self->opt ) );
30 assert( self->value[ self->size ] == 0 );
31 /* String objects modified manually after construction to contain embedded
32 * '\0' characters are considered structurally valid.
33 */
34 assert( strlen( self->value ) <= self->size );
35
36 for ( i = 0; i < 4; ++i )
37 {
38 assert( self->magic[ i ] == JAM_STRING_MAGIC );
39 assert( self->value[ self->capacity + i ] == JAM_STRING_MAGIC );
40 }
41 }
42 #else
43 # define JAM_STRING_MAGIC_SIZE 0
44 # define assert_invariants(x) do {} while (0)
45 #endif
46
47
48 void string_new( string * s )
49 {
50 s->value = s->opt;
51 s->size = 0;
52 s->capacity = sizeof( s->opt );
53 s->opt[ 0 ] = 0;
54 #ifndef NDEBUG
55 memset( s->magic, JAM_STRING_MAGIC, sizeof( s->magic ) );
56 #endif
57 assert_invariants( s );
58 }
59
60
61 void string_free( string * s )
62 {
63 assert_invariants( s );
64 if ( s->value != s->opt )
65 BJAM_FREE( s->value );
66 string_new( s );
67 }
68
69
70 static void string_reserve_internal( string * self, size_t capacity )
71 {
72 if ( self->value == self->opt )
73 {
74 self->value = (char *)BJAM_MALLOC_ATOMIC( capacity +
75 JAM_STRING_MAGIC_SIZE );
76 self->value[ 0 ] = 0;
77 size_t opt_size = sizeof(self->opt); // Workaround sizeof in strncat warning.
78 strncat( self->value, self->opt, opt_size );
79 assert( strlen( self->value ) <= self->capacity && "Regression test" );
80 }
81 else
82 {
83 self->value = (char *)BJAM_REALLOC( self->value, capacity +
84 JAM_STRING_MAGIC_SIZE );
85 }
86 #ifndef NDEBUG
87 memcpy( self->value + capacity, self->magic, JAM_STRING_MAGIC_SIZE );
88 #endif
89 self->capacity = capacity;
90 }
91
92
93 void string_reserve( string * self, size_t capacity )
94 {
95 assert_invariants( self );
96 if ( capacity <= self->capacity )
97 return;
98 string_reserve_internal( self, capacity );
99 assert_invariants( self );
100 }
101
102
103 static void maybe_reserve( string * self, size_t new_size )
104 {
105 size_t capacity = self->capacity;
106 if ( capacity <= new_size )
107 {
108 size_t new_capacity = capacity;
109 while ( new_capacity <= new_size )
110 new_capacity <<= 1;
111 string_reserve_internal( self, new_capacity );
112 }
113 }
114
115
116 void string_append( string * self, char const * rhs )
117 {
118 size_t rhs_size = strlen( rhs );
119 size_t new_size = self->size + rhs_size;
120 assert_invariants( self );
121
122 maybe_reserve( self, new_size );
123
124 memcpy( self->value + self->size, rhs, rhs_size + 1 );
125 self->size = new_size;
126
127 assert_invariants( self );
128 }
129
130
131 void string_append_range( string * self, char const * start, char const * finish )
132 {
133 size_t rhs_size = finish - start;
134 size_t new_size = self->size + rhs_size;
135 assert_invariants( self );
136
137 maybe_reserve( self, new_size );
138
139 if ( start != finish )
140 memcpy( self->value + self->size, start, rhs_size );
141 self->size = new_size;
142 self->value[ new_size ] = 0;
143
144 assert_invariants( self );
145 }
146
147
148 void string_copy( string * s, char const * rhs )
149 {
150 string_new( s );
151 string_append( s, rhs );
152 }
153
154 void string_truncate( string * self, size_t n )
155 {
156 assert_invariants( self );
157 assert( n <= self->capacity );
158 self->value[ self->size = n ] = 0;
159 assert_invariants( self );
160 }
161
162
163 void string_pop_back( string * self )
164 {
165 string_truncate( self, self->size - 1 );
166 }
167
168
169 void string_push_back( string * self, char x )
170 {
171 string_append_range( self, &x, &x + 1 );
172 }
173
174
175 char string_back( string * self )
176 {
177 assert_invariants( self );
178 return self->value[ self->size - 1 ];
179 }
180
181 void string_rtrim( string * self )
182 {
183 char *p;
184 assert_invariants( self );
185 p = self->value + self->size - 1;
186 for ( ; p >= self->value && ( *p == '\0' || isspace( *p ) ); *p-- = 0 );
187 }
188
189 #ifndef NDEBUG
190 void string_unit_test()
191 {
192 {
193 string s[ 1 ];
194 unsigned long i;
195 unsigned long const limit = sizeof( s->opt ) * 2 + 2;
196 string_new( s );
197 assert( s->value == s->opt );
198 for ( i = 0; i < limit; ++i )
199 {
200 string_push_back( s, (char)( i + 1 ) );
201 assert( s->size == i + 1 );
202 }
203 assert( s->size == limit );
204 assert( s->value != s->opt );
205 for ( i = 0; i < limit; ++i )
206 assert( s->value[ i ] == (char)( i + 1 ) );
207 string_free( s );
208 }
209
210 {
211 const char * const original = " \n\t\v Foo \r\n\v \tBar\n\n\r\r\t\n\v\t \t";
212 string copy[ 1 ];
213 string_copy( copy, original );
214 assert( !strcmp( copy->value, original ) );
215 assert( copy->size == strlen( original ) );
216 string_free( copy );
217 }
218
219 {
220 const char * const foo = "Foo ";
221 string foo_copy[ 1 ];
222 string_copy( foo_copy, foo );
223 string_rtrim( foo_copy );
224 assert( !strcmp( foo_copy->value, "Foo" ) );
225
226 string_rtrim( foo_copy );
227 assert( !strcmp( foo_copy->value, "Foo" ) );
228 }
229 {
230 const char * const bar = "Bar\0\0\0";
231 string bar_copy[ 1 ];
232 string_copy( bar_copy, bar );
233 string_rtrim( bar_copy );
234 assert( !strcmp( bar_copy->value, "Bar" ) );
235
236 string_rtrim( bar_copy );
237 assert( !strcmp( bar_copy->value, "Bar" ) );
238 }
239 }
240 #endif