Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/tools/build/jam_src/strings.c @ 12

Last change on this file since 12 was 12, checked in by landauf, 18 years ago

added boost

File size: 4.4 KB
Line 
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 "strings.h"
6#include <stdlib.h>
7#include <string.h>
8#include <assert.h>
9#include <stdio.h>
10
11
12#ifndef NDEBUG
13# define JAM_STRING_MAGIC ((char)0xcf)
14# define JAM_STRING_MAGIC_SIZE 4
15static void assert_invariants( string* self )
16{
17    int i;
18   
19    assert( self->size < self->capacity );
20    assert( ( self->capacity <= sizeof(self->opt) ) == ( self->value == self->opt ) );
21    assert( strlen( self->value ) == self->size );
22
23    for (i = 0; i < 4; ++i)
24    {
25        assert( self->magic[i] == JAM_STRING_MAGIC );
26        assert( self->value[self->capacity + i] == JAM_STRING_MAGIC );
27    }
28}
29#else
30# define JAM_STRING_MAGIC_SIZE 0
31# define assert_invariants(x) do {} while (0)
32#endif
33
34void string_new( string* s )
35{
36    s->value = s->opt;
37    s->size = 0;
38    s->capacity = sizeof(s->opt);
39    s->opt[0] = 0;
40#ifndef NDEBUG
41    memset(s->magic, JAM_STRING_MAGIC, sizeof(s->magic));
42#endif
43    assert_invariants( s );
44}
45
46void string_free( string* s )
47{
48    assert_invariants( s );
49    if ( s->value != s->opt )
50        free( s->value );
51}
52
53static void string_reserve_internal( string* self, size_t capacity )
54{
55    if ( self->value == self->opt )
56    {
57        self->value = (char*)malloc( capacity + JAM_STRING_MAGIC_SIZE );
58        self->value[0] = 0;
59        strncat( self->value, self->opt, sizeof(self->opt) );
60        assert( strlen( self->value ) <= self->capacity ); /* This is a regression test */
61    }
62    else
63    {
64        self->value = (char*)realloc( self->value, capacity + JAM_STRING_MAGIC_SIZE );
65    }
66#ifndef NDEBUG
67    memcpy( self->value + capacity, self->magic, JAM_STRING_MAGIC_SIZE );
68#endif
69    self->capacity = capacity;
70}
71
72void string_reserve( string* self, size_t capacity )
73{
74    assert_invariants( self );
75    if ( capacity <= self->capacity )
76        return;
77    string_reserve_internal( self, capacity );
78    assert_invariants( self );
79}
80
81static void extend_full( string* self, char const* start, char const* finish )
82{
83    size_t new_size = self->capacity + ( finish - start );
84    size_t new_capacity = self->capacity;
85    size_t old_size = self->capacity;
86    while ( new_capacity < new_size + 1)
87        new_capacity <<= 1;
88    string_reserve_internal( self, new_capacity );
89    memcpy( self->value + old_size, start, new_size - old_size );
90    self->value[new_size] = 0;
91    self->size = new_size;
92}
93
94void string_append( string* self, char const* rhs )
95{
96    char* p = self->value + self->size;
97    char* end = self->value + self->capacity;
98    assert_invariants( self );
99   
100    while ( *rhs && p != end)
101        *p++ = *rhs++;
102   
103    if ( p != end )
104    {
105        *p = 0;
106        self->size = p - self->value;
107    }
108    else
109    {
110        extend_full( self, rhs, rhs + strlen(rhs) );
111    }
112    assert_invariants( self );
113}
114
115void string_append_range( string* self, char const* start, char const* finish )
116{
117    char* p = self->value + self->size;
118    char* end = self->value + self->capacity;
119    assert_invariants( self );
120   
121    while ( p != end && start != finish )
122        *p++ = *start++;
123   
124    if ( p != end )
125    {
126        *p = 0;
127        self->size = p - self->value;
128    }
129    else
130    {
131        extend_full( self, start, finish );
132    }
133    assert_invariants( self );
134}
135
136void string_copy( string* s, char const* rhs )
137{
138    string_new( s );
139    string_append( s, rhs );
140}
141
142void string_truncate( string* self, size_t n )
143{
144    assert_invariants( self );
145    assert( n <= self->capacity );
146    self->value[self->size = n] = 0;
147    assert_invariants( self );
148}
149
150void string_pop_back( string* self )
151{
152    string_truncate( self, self->size - 1 );
153}
154
155void string_push_back( string* self, char x )
156{
157    string_append_range( self, &x, &x + 1 );
158}
159
160char string_back( string* self )
161{
162    assert_invariants( self );
163    return self->value[self->size - 1];
164}
165
166#ifndef NDEBUG
167void string_unit_test()
168{
169    string s[1];
170    int i;
171    char buffer[sizeof(s->opt) * 2 + 2];
172    int limit = sizeof(buffer) > 254 ? 254 : sizeof(buffer);
173
174    string_new(s);
175   
176    for (i = 0; i < limit; ++i)
177    {
178        string_push_back( s, (char)(i + 1) );
179    };
180
181    for (i = 0; i < limit; ++i)
182    {
183        assert( i < s->size );
184        assert( s->value[i] == (char)(i + 1));
185    }
186
187    string_free(s);
188   
189}
190#endif
191
Note: See TracBrowser for help on using the repository browser.