1 /*
2 * Copyright (C) 2000-2005 Chris Ross and various contributors
3 * Copyright (C) 1999-2000 Chris Ross
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * o Redistributions of source code must retain the above copyright notice, this
10 * list of conditions and the following disclaimer.
11 * o Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * o Neither the name of the ferite software nor the names of its contributors may
15 * be used to endorse or promote products derived from this software without
16 * specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifdef HAVE_CONFIG_HEADER
32 #include "../config.h"
33 #endif
34
35 #include "ferite.h"
36
37 /**
38 * @group Strings
39 * @description Ferite strings provide a nice clean method for encoding and storing strings, and
40 * managing binary data. The functions below provide several means of string mangement
41 * which makes twiddling 'string' variables easier.
42 */
43
44 /**
45 * @function ferite_str_new
46 * @declaration FeriteString *ferite_str_new( char *str, int length, int encoding )
47 * @brief Create a new string with exisitng data and encoding
48 * @param char *str The data to use
49 * @param int length The length of the data, if it is 0, strlen() is called on the data.
50 * @param int encoding The encoding to use, if you are not sure use FE_CHARSET_DEFAULT
51 * @return A FeriteString containing the data
52 */
ferite_str_new(char * str,size_t length,int encoding)53 FeriteString *ferite_str_new( char *str, size_t length, int encoding )
54 {
55 FeriteString *ptr;
56
57 FE_ENTER_FUNCTION;
58 ptr = fmalloc( sizeof( FeriteString ) );
59 ptr->pos = -1;
60 ptr->encoding = encoding;
61
62 if( str == NULL || *str == '\0' )
63 {
64 ptr->data = fcalloc( length + 1, sizeof(char) );
65 }
66 else
67 {
68 if(length == 0)
69 length = strlen( str );
70 ptr->data = fmalloc( length + 1 );
71 memcpy( ptr->data, str, length );
72 ptr->data[length] = '\0';
73 }
74 ptr->length = length;
75 FE_LEAVE_FUNCTION( ptr );
76 }
77
78 /**
79 * @function ferite_str_dup
80 * @declaration FeriteString *ferite_str_dup( FeriteString *str )
81 * @brief Duplicate a ferite string
82 * @param FeriteString *str The string to duplicate
83 * @return A new string
84 */
ferite_str_dup(FeriteString * str)85 FeriteString *ferite_str_dup( FeriteString *str )
86 {
87 FeriteString *ptr;
88 FE_ENTER_FUNCTION;
89 if( str == NULL )
90 {
91 ptr = ferite_str_new( NULL, 0, FE_CHARSET_DEFAULT );
92 }
93 else
94 {
95 ptr = fmalloc( sizeof( FeriteString ) );
96 ptr->pos = -1;
97 ptr->data = fmalloc( str->length + 1 );
98 memcpy( ptr->data, str->data, str->length );
99 ptr->data[str->length] = '\0';
100 ptr->length = str->length;
101 ptr->encoding = str->encoding;
102 }
103 FE_LEAVE_FUNCTION( ptr );
104 }
105
106 /**
107 * @function ferite_str_set
108 * @declaration void ferite_str_set( FeriteString *str, char *data, int length, int encoding )
109 * @brief Set the data contained within an existing string
110 * @param FeriteString *str The string to set
111 * @param char *data The data to use
112 * @param int length The length of the data
113 * @param int encoding The encoding of the data, for a default use FE_CHARSET_DEFAULT
114 */
ferite_str_set(FeriteString * str,char * data,size_t length,int encoding)115 void ferite_str_set( FeriteString *str, char *data, size_t length, int encoding )
116 {
117 FE_ENTER_FUNCTION;
118 if( str->data )
119 ffree( str->data );
120 if( data == NULL )
121 data = "";
122 if( length == 0 )
123 length = strlen( data );
124 str->data = fmalloc( length + 1 );
125 memcpy( str->data, data, length );
126 str->data[length] = '\0';
127 str->length = length;
128 str->encoding = encoding;
129 FE_LEAVE_FUNCTION( NOWT );
130 }
131
132 /**
133 * @function ferite_str_destroy
134 * @declaration void ferite_str_destroy( FeriteString *str )
135 * @brief Destroy the string and free all memory
136 * @param FeriteString *str The string to destroy
137 */
ferite_str_destroy(FeriteString * str)138 void ferite_str_destroy( FeriteString *str )
139 {
140 FE_ENTER_FUNCTION;
141 if( str )
142 {
143 if( str->data )
144 {
145 ffree( str->data );
146 }
147 ffree( str );
148 }
149 FE_LEAVE_FUNCTION( NOWT );
150 }
151
152 /**
153 * @function ferite_str_cmp
154 * @declaration int ferite_str_cmp( FeriteString *str1, FeriteString *str2 )
155 * @brief Compare two strings
156 * @param FeriteString *str1 The first string
157 * @param FeriteString *str2 The second string
158 * @return 1 if they match, 0 if they dont
159 */
ferite_str_cmp(FeriteString * str1,FeriteString * str2)160 int ferite_str_cmp( FeriteString *str1, FeriteString *str2 )
161 {
162 size_t i = 0;
163
164 FE_ENTER_FUNCTION;
165 if( str1->length != str2->length )
166 {
167 FE_LEAVE_FUNCTION( 0 );
168 }
169 for( i = 0; i < str1->length; i++ )
170 {
171 if( str1->data[i] != str2->data[i] )
172 {
173 FE_LEAVE_FUNCTION( 0 );
174 }
175 }
176 FE_LEAVE_FUNCTION( 1 );
177 }
178
179 /**
180 * @function ferite_str_case_cmp
181 * @declaration int ferite_str_case_cmp( FeriteString *str1, FeriteString *str2 )
182 * @brief Compare two strings but dont take into consideration what case the strings are
183 * @param FeriteString *str1 The first string
184 * @param FeriteString *str2 The second string
185 * @return 1 if they match, 0 if they dont
186 */
ferite_str_case_cmp(FeriteString * str1,FeriteString * str2)187 int ferite_str_case_cmp( FeriteString *str1, FeriteString *str2 )
188 {
189 size_t i;
190
191 FE_ENTER_FUNCTION;
192
193 if( str1->length != str2->length )
194 {
195 FE_LEAVE_FUNCTION( 0 );
196 }
197 for( i = 0; i < str1->length; i++ )
198 {
199 if( toupper(str1->data[i]) != toupper(str2->data[i]) )
200 {
201 FE_LEAVE_FUNCTION( 0 );
202 }
203 }
204 FE_LEAVE_FUNCTION( 1 );
205 }
206
207 /**
208 * @function ferite_str_ncmp
209 * @declaration int ferite_str_ncmp( FeriteString *str1, FeriteString *str2, int size )
210 * @brief Compare two strings upto a certain size
211 * @param FeriteString *str1 The first string
212 * @param FeriteString *str2 The second string
213 * @param int size The size upto which the strings should be compared
214 * @return 1 if they match, 0 if they dont
215 */
ferite_str_ncmp(FeriteString * str1,FeriteString * str2,size_t size)216 int ferite_str_ncmp( FeriteString *str1, FeriteString *str2, size_t size )
217 {
218 size_t i,len;
219
220 FE_ENTER_FUNCTION;
221 len = (size < str1->length) ? size : str1->length;
222 for( i = 0; i < len; i++ )
223 {
224 if( str1->data[i] != str2->data[i] )
225 {
226 FE_LEAVE_FUNCTION( 0 );
227 }
228 }
229 FE_LEAVE_FUNCTION( 1 );
230 }
231
232 /**
233 * @function ferite_str_case_ncmp
234 * @declaration int ferite_str_case_ncmp( FeriteString *str1, FeriteString *str2, int size )
235 * @brief Compare two strings upto a certain size without considering the case of the strings
236 * @param FeriteString *str1 The first string
237 * @param FeriteString *str2 The second string
238 * @param int size The size upto which the strings should be compared
239 * @return 1 if they match, 0 if they dont
240 */
ferite_str_case_ncmp(FeriteString * str1,FeriteString * str2,size_t size)241 int ferite_str_case_ncmp( FeriteString *str1, FeriteString *str2, size_t size )
242 {
243 size_t i,len;
244
245 FE_ENTER_FUNCTION;
246 len = (size < str1->length) ? size : str1->length;
247 for( i = 0; i < len; i++ )
248 {
249 if( toupper(str1->data[i]) != toupper(str2->data[i]) )
250 {
251 FE_LEAVE_FUNCTION( 0 );
252 }
253 }
254 FE_LEAVE_FUNCTION( 1 );
255 }
256
257 /**
258 * @function ferite_str_cpy
259 * @declaration int ferite_str_cpy( FeriteString *str1, FeriteString *str2 )
260 * @brief Copy the contents of the second string to the first string
261 * @param FeriteString *str1 The first string
262 * @param FeriteString *str2 The second string
263 * @return The amount of data copied
264 */
ferite_str_cpy(FeriteString * str1,FeriteString * str2)265 int ferite_str_cpy( FeriteString *str1, FeriteString *str2 )
266 {
267 FE_ENTER_FUNCTION;
268 ffree( str1->data);
269 str1->data = fmalloc( str2->length + 1 );
270 memcpy( str1->data, str2->data, str2->length );
271 str1->data[str2->length] = '\0';
272 str1->length = str2->length;
273 FE_LEAVE_FUNCTION((int)str1->length);
274 }
275
276 /**
277 * @function ferite_str_ncpy
278 * @declaration int ferite_str_ncpy( FeriteString *str1, FeriteString *str2, int size )
279 * @brief Copy the contents of the second string to the first string upto size character
280 * @param FeriteString *str1 The first string
281 * @param FeriteString *str2 The second string
282 * @param int size The amount of data to copy
283 * @return The amount of data copied
284 */
ferite_str_ncpy(FeriteString * str1,FeriteString * str2,size_t size)285 int ferite_str_ncpy( FeriteString *str1, FeriteString *str2, size_t size )
286 {
287 size_t len;
288
289 FE_ENTER_FUNCTION;
290 ffree( str1->data);
291 len = (size >= str2->length) ? str2->length : size;
292 str1->data = fmalloc( len + 1 );
293 str1->length = len;
294 memcpy( str1->data, str2->data, len );
295 str1->data[len] = '\0';
296 FE_LEAVE_FUNCTION((int)len);
297 }
298
299 /**
300 * @function ferite_str_cat
301 * @declaration int ferite_str_cat( FeriteString *str1, FeriteString *str2 )
302 * @brief Concatenate the second string onto the first
303 * @param FeriteString *str1 The first string
304 * @param FeriteString *str2 The second string
305 */
ferite_str_cat(FeriteString * str1,FeriteString * str2)306 int ferite_str_cat( FeriteString *str1, FeriteString *str2 )
307 {
308 char *newbuf;
309
310 FE_ENTER_FUNCTION;
311 newbuf = fmalloc( str1->length + str2->length + 1);
312 memcpy( newbuf, str1->data, str1->length );
313 memcpy( newbuf + str1->length, str2->data, str2->length );
314 newbuf[ str1->length + str2->length ] = '\0';
315 ffree( str1->data );
316 str1->data = newbuf;
317 str1->length = str1->length + str2->length;
318 FE_LEAVE_FUNCTION(0);
319 }
320
321 /**
322 * @function ferite_str_data_cat
323 * @declaration int ferite_str_data_cat( FeriteString *str1, void *data, int size )
324 * @brief Concatenate the data onto the first string
325 * @param FeriteString *str1 The first string
326 * @param void *data The data to concatenate
327 * @param int size The length of the data to concatenate
328 */
ferite_str_data_cat(FeriteString * str,void * data,size_t size)329 int ferite_str_data_cat( FeriteString *str, void *data, size_t size )
330 {
331 char *newbuf;
332 FE_ENTER_FUNCTION;
333 newbuf = fmalloc( str->length + size + 1);
334 memcpy( newbuf, str->data, str->length );
335 memcpy( newbuf + str->length, data, size );
336 newbuf[ str->length + size ] = '\0';
337 ffree( str->data );
338 str->data = newbuf;
339 str->length = str->length + size;
340 FE_LEAVE_FUNCTION(1);
341 }
342
343 /**
344 * @function ferite_str_replace
345 * @declaration FeriteString *ferite_str_replace( FeriteString *str, FeriteString *what, FeriteString *with )
346 * @brief Replace all occurances of a string with another
347 * @param FeriteString *str The string to scane
348 * @param FeriteString *what The string to scan for
349 * @param FeriteString *with The string to replace 'what' with
350 * @return A new string with the replacements
351 */
ferite_str_replace(FeriteString * str,FeriteString * what,FeriteString * with)352 FeriteString *ferite_str_replace( FeriteString *str, FeriteString *what, FeriteString *with )
353 {
354 FeriteString *ptr = NULL;
355 char *data = NULL;
356
357 FE_ENTER_FUNCTION;
358 if( str != NULL && what != NULL && with != NULL )
359 {
360 data = ferite_replace_string( str->data, what->data, with->data );
361 ptr = ferite_str_new( data, strlen(data), FE_CHARSET_DEFAULT );
362 ffree( data );
363 FE_LEAVE_FUNCTION( ptr );
364 }
365 ptr = ferite_str_new( "", 0, FE_CHARSET_DEFAULT );
366 FE_LEAVE_FUNCTION( ptr );
367 }
368
369 /* FIXME
370 FeriteString *ferite_str_copy( FeriteString *str, size_t from, size_t to )
371 {
372 FeriteString *ptr = NULL;
373
374 FE_ENTER_FUNCTION;
375 FE_LEAVE_FUNCTION( ptr );
376 }
377
378 FeriteUnifiedArray *ferite_str_split( FeriteScript *script, FeriteString *str, FeriteString *spliter )
379 {
380 FeriteUnifiedArray *ptr = NULL;
381 FE_ENTER_FUNCTION;
382 FE_LEAVE_FUNCTION( ptr );
383 }
384 */
385 /*
386 * int ferite_str_ncat( FeriteString *str1, FeriteString *str2, int size );
387 * int ferite_str_find( FeriteString *str, char *token );
388 * int ferite_str_delete( FeriteString *str, int from, int to );
389 * int ferite_str_insert( FeriteString *str, FeriteString *data, int pos );
390 */
391
392 /**
393 * @end
394 */
395