bad char
[vg.git] / vg_string.c
1 #include "vg_string.h"
2 #include "vg_platform.h"
3 #include <string.h>
4 #include <stdarg.h>
5 #include <stdio.h>
6
7 i32 vg_str_storage( vg_str *str )
8 {
9 if( str->len == -1 ){
10 if( str->buffer ){
11 vg_str_dynamic *arr = (vg_str_dynamic *)str->buffer;
12 return (arr-1)->len;
13 }
14 else return 0;
15 }
16 else return str->len;
17 }
18
19 /*
20 * Reset string. If len is -1 (dynamically allocated), buffer must be either
21 * NULL or be acquired from malloc or realloc
22 */
23 void vg_strnull( vg_str *str, char *buffer, i32 len )
24 {
25 str->buffer = buffer;
26 if( buffer )
27 str->buffer[0] = '\0';
28
29 str->i = 0;
30 str->len = len;
31
32 if( len == 0 )
33 vg_fatal_error( "0 length string allocation\n" );
34 }
35
36 void vg_strfree( vg_str *str )
37 {
38 if( str->len == -1 ){
39 if( str->buffer ){
40 vg_str_dynamic *arr = (vg_str_dynamic *)str->buffer;
41 free( arr-1 );
42
43 str->buffer = NULL;
44 str->i = 0;
45 }
46 }
47 }
48
49 /*
50 * Double the size of the dynamically allocated string. If unallocated, alloc of
51 * 16 bytes minimum.
52 */
53 static i32 vg_str_dynamic_grow( vg_str *str )
54 {
55 if( str->buffer ){
56 vg_str_dynamic *hdr = ((vg_str_dynamic *)str->buffer) - 1;
57 i32 total = (hdr->len + sizeof(vg_str_dynamic)) * 2;
58 hdr = realloc( hdr, total );
59 hdr->len = total - sizeof(vg_str_dynamic);
60 str->buffer = (char *)(hdr+1);
61 return hdr->len;
62 }
63 else {
64 vg_str_dynamic *hdr = malloc(16);
65 hdr->len = 16-sizeof(vg_str_dynamic);
66 str->buffer = (char *)(hdr+1);
67 str->buffer[0] = '\0';
68 return hdr->len;
69 }
70 }
71
72 static void _vg_strcatch( vg_str *str, char c )
73 {
74 if( str->i == -1 ) return;
75
76 i32 max = vg_str_storage( str );
77 if( str->i == max )
78 {
79 if( str->len == -1 )
80 max = vg_str_dynamic_grow( str );
81 else
82 {
83 str->i = -1;
84 str->buffer[ max-1 ] = '\0';
85 return;
86 }
87 }
88
89 str->buffer[ str->i ++ ] = c;
90 }
91
92 void vg_strcat( vg_str *str, const char *append )
93 {
94 if( !append || (str->i == -1) ) return;
95
96 i32 i = 0;
97
98 append:;
99 char c = append[ i ++ ];
100 _vg_strcatch( str, c );
101
102 if( c == '\0' )
103 {
104 str->i --;
105 return;
106 }
107 else goto append;
108 }
109
110 void vg_strcatch( vg_str *str, char c )
111 {
112 _vg_strcatch( str, c );
113 _vg_strcatch( str, '\x00' );
114 str->i --;
115 }
116
117 /*
118 * FIXME: Negative numbers
119 */
120 void vg_strcati32( vg_str *str, i32 value )
121 {
122 if( value ){
123 char temp[32];
124 int i=0;
125 while( value && (i<31) ){
126 temp[ i ++ ] = '0' + (value % 10);
127 value /= 10;
128 }
129
130 char reverse[32];
131 for( int j=0; j<i; j ++ )
132 reverse[j] = temp[ i-1-j ];
133 reverse[i] = '\0';
134
135 vg_strcat( str, reverse );
136 }
137 else
138 vg_strcat( str, "0" );
139 }
140
141 void vg_strcati32r( vg_str *str, i32 value, i32 n, char alt )
142 {
143 char temp[32];
144 i32 i=0;
145 while( value ){
146 if( i>=n )
147 break;
148
149 temp[ n-1 - (i ++) ] = '0' + (value % 10);
150 value /= 10;
151 }
152
153 for( ;i<n; i ++ )
154 temp[ n-1 - i ] = alt;
155
156 temp[n]='\0';
157 vg_strcat( str, temp );
158 }
159
160 int vg_strgood( vg_str *str )
161 {
162 if( str->i == -1 ) return 0;
163 else return 1;
164 }
165
166 /*
167 * Returns pointer to last instance of character
168 */
169 char *vg_strch( vg_str *str, char c )
170 {
171 char *ptr = NULL;
172 for( i32 i=0; i<str->i; i++ ){
173 if( str->buffer[i] == c )
174 ptr = str->buffer+i;
175 }
176
177 return ptr;
178 }
179
180 u32 vg_strncpy( const char *src, char *dst, u32 len,
181 enum strncpy_behaviour behaviour )
182 {
183 for( u32 i=0; i<len; i++ ){
184 dst[i] = src[i];
185
186 if( !src[i] ) return i;
187
188 if( i == len-1 ){
189 if( behaviour == k_strncpy_always_add_null ){
190 dst[i] = '\0';
191 return i;
192 }
193 else if( behaviour == k_strncpy_overflow_fatal ){
194 vg_fatal_error( "Strncpy dest exceeded buffer length\n" );
195 }
196 }
197 }
198
199 return 0;
200 }
201
202 static void _vg_strcatf_va( vg_str *str, const char *fmt, va_list args )
203 {
204 char buffer[4096];
205 vsnprintf( buffer, vg_list_size(buffer), fmt, args );
206 vg_strcat( str, buffer );
207 }
208
209 void vg_strcatf( vg_str *str, const char *fmt, ... )
210 {
211 va_list args;
212 va_start( args, fmt );
213 _vg_strcatf_va( str, fmt, args );
214 va_end( args );
215 }
216
217 u32 vg_strdjb2( const char *str )
218 {
219 u32 hash = 5381, c;
220
221 while( (c = *str++) )
222 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
223
224 return hash;
225 }
226
227 int vg_strdjb2_eq( const char *s1, u32 h1, const char *s2, u32 h2 )
228 {
229 if( h1 == h2 ){
230 if(!strcmp(s1, s2)) return 1;
231 else return 0;
232 } else return 0;
233 }