The Machine Perception Toolbox

[Introduction]- [News]- [Download]- [Screenshots]- [Manual (pdf)]- [Forums]- [API Reference]- [Repository ]

 

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

strings.c

Go to the documentation of this file.
00001 #include "strings.h"
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <assert.h>
00005 #include <stdio.h>
00006 
00007 
00008 #ifndef NDEBUG
00009 # define JAM_STRING_MAGIC ((char)0xcf)
00010 # define JAM_STRING_MAGIC_SIZE 4
00011 static void assert_invariants( string* self )
00012 {
00013     int i;
00014     
00015     assert( self->size < self->capacity );
00016     assert( ( self->capacity <= sizeof(self->opt) ) == ( self->value == self->opt ) );
00017     assert( strlen( self->value ) == self->size );
00018 
00019     for (i = 0; i < 4; ++i)
00020     {
00021         assert( self->magic[i] == JAM_STRING_MAGIC );
00022         assert( self->value[self->capacity + i] == JAM_STRING_MAGIC );
00023     }
00024 }
00025 #else
00026 # define JAM_STRING_MAGIC_SIZE 0
00027 # define assert_invariants(x) do {} while (0)
00028 #endif
00029 
00030 void string_new( string* s )
00031 {
00032     s->value = s->opt;
00033     s->size = 0;
00034     s->capacity = sizeof(s->opt);
00035     s->opt[0] = 0;
00036 #ifndef NDEBUG
00037     memset(s->magic, JAM_STRING_MAGIC, sizeof(s->magic));
00038 #endif
00039     assert_invariants( s );
00040 }
00041 
00042 void string_free( string* s )
00043 {
00044     assert_invariants( s );
00045     if ( s->value != s->opt )
00046         free( s->value );
00047 }
00048 
00049 static void string_reserve_internal( string* self, size_t capacity )
00050 {
00051     if ( self->value == self->opt )
00052     {
00053         self->value = (char*)malloc( capacity + JAM_STRING_MAGIC_SIZE );
00054         self->value[0] = 0;
00055         strncat( self->value, self->opt, sizeof(self->opt) );
00056         assert( strlen( self->value ) <= self->capacity ); /* This is a regression test */
00057     }
00058     else
00059     {
00060         self->value = (char*)realloc( self->value, capacity + JAM_STRING_MAGIC_SIZE );
00061     }
00062 #ifndef NDEBUG
00063     memcpy( self->value + capacity, self->magic, JAM_STRING_MAGIC_SIZE );
00064 #endif
00065     self->capacity = capacity;
00066 }
00067 
00068 void string_reserve( string* self, size_t capacity )
00069 {
00070     assert_invariants( self );
00071     if ( capacity <= self->capacity )
00072         return;
00073     string_reserve_internal( self, capacity );
00074     assert_invariants( self );
00075 }
00076 
00077 static void extend_full( string* self, char* start, char *finish )
00078 {
00079     size_t new_size = self->capacity + ( finish - start );
00080     size_t new_capacity = self->capacity;
00081     size_t old_size = self->capacity;
00082     while ( new_capacity < new_size + 1)
00083         new_capacity <<= 1;
00084     string_reserve_internal( self, new_capacity );
00085     memcpy( self->value + old_size, start, new_size - old_size );
00086     self->value[new_size] = 0;
00087     self->size = new_size;
00088 }
00089 
00090 void string_append( string* self, char* rhs )
00091 {
00092     char* p = self->value + self->size;
00093     char* end = self->value + self->capacity;
00094     assert_invariants( self );
00095     
00096     while ( *rhs && p != end)
00097         *p++ = *rhs++;
00098     
00099     if ( p != end )
00100     {
00101         *p = 0;
00102         self->size = p - self->value;
00103     }
00104     else
00105     {
00106         extend_full( self, rhs, rhs + strlen(rhs) );
00107     }
00108     assert_invariants( self );
00109 }
00110 
00111 void string_append_range( string* self, char* start, char* finish )
00112 {
00113     char* p = self->value + self->size;
00114     char* end = self->value + self->capacity;
00115     assert_invariants( self );
00116     
00117     while ( p != end && start != finish )
00118         *p++ = *start++;
00119     
00120     if ( p != end )
00121     {
00122         *p = 0;
00123         self->size = p - self->value;
00124     }
00125     else
00126     {
00127         extend_full( self, start, finish );
00128     }
00129     assert_invariants( self );
00130 }
00131 
00132 void string_copy( string* s, char* rhs )
00133 {
00134     string_new( s );
00135     string_append( s, rhs );
00136 }
00137 
00138 void string_truncate( string* self, size_t n )
00139 {
00140     assert_invariants( self );
00141     assert( n <= self->capacity );
00142     self->value[self->size = n] = 0;
00143     assert_invariants( self );
00144 }
00145 
00146 void string_pop_back( string* self )
00147 {
00148     string_truncate( self, self->size - 1 );
00149 }
00150 
00151 void string_push_back( string* self, char x )
00152 {
00153     string_append_range( self, &x, &x + 1 );
00154 }
00155 
00156 char string_back( string* self )
00157 {
00158     assert_invariants( self );
00159     return self->value[self->size - 1];
00160 }
00161 
00162 #ifndef NDEBUG
00163 void string_unit_test()
00164 {
00165     string s[1];
00166     int i;
00167     char buffer[sizeof(s->opt) * 2 + 2];
00168     int limit = sizeof(buffer) > 254 ? 254 : sizeof(buffer);
00169 
00170     string_new(s);
00171     
00172     for (i = 0; i < limit; ++i)
00173     {
00174         string_push_back( s, (char)(i + 1) );
00175     };
00176 
00177     for (i = 0; i < limit; ++i)
00178     {
00179         assert( i < s->size );
00180         assert( s->value[i] == (char)(i + 1));
00181     }
00182 
00183     string_free(s);
00184     
00185 }
00186 #endif
00187 

Generated on Mon Nov 8 17:07:52 2004 for MPT by  doxygen 1.3.9.1