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