Usermode/libc - Minor fix to memmove
[tpg/acess2.git] / Usermode / Libraries / libc.so_src / string.c
1 /*
2  * AcessOS Basic C Library
3  * string.c
4  */
5 #include <acess/sys.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <ctype.h>
9 #include "lib.h"
10
11 /**
12  * \fn EXPORT int strcmp(const char *s1, const char *s2)
13  * \brief Compare two strings
14  */
15 EXPORT int strcmp(const char *s1, const char *s2)
16 {
17         while(*s1 && *s1 == *s2) {
18                 s1++; s2++;
19         }
20         return (int)*s1 - (int)*s2;
21 }
22
23 /**
24  * \fn EXPORT int strncmp(const char *s1, const char *s2)
25  * \brief Compare two strings
26  */
27 EXPORT int strncmp(const char *s1, const char *s2, size_t n)
28 {
29         while(n && *s1 && *s1 == *s2)
30         {
31                 s1++; s2++;
32                 n --;
33         }
34         if( n == 0 )
35                 return 0;
36         else
37                 return (int)*s1 - (int)*s2;
38 }
39
40 EXPORT int strcasecmp(const char *s1, const char *s2)
41 {
42          int    rv;
43         while( (rv = toupper(*s1) - toupper(*s2)) == 0 && *s1 != '\0' && *s2 != '\0' ) {
44                 s1++; s2++;
45         }
46         return rv;
47 }
48
49 EXPORT int strncasecmp(const char *s1, const char *s2, size_t n)
50 {
51          int    rv = 0;
52         if( n == 0 )    return 0;
53         while(n -- && (rv = toupper(*s1) - toupper(*s2)) == 0 && *s1 != '\0' && *s2 != '\0') {
54                 s1++; s2++;
55         }
56         return rv;
57 }
58
59 /**
60  * \fn EXPORT char *strcpy(char *dst, const char *src)
61  * \brief Copy a string to another
62  */
63 EXPORT char *strcpy(char *dst, const char *src)
64 {
65         char *_dst = dst;
66         while(*src) {
67                 *dst = *src;
68                 src++; dst++;
69         }
70         *dst = '\0';
71         return _dst;
72 }
73
74 /**
75  * \fn EXPORT char *strncpy(char *dst, const char *src)
76  * \brief Copy at most \a num characters from \a src to \a dst
77  * \return \a dst
78  */
79 EXPORT char *strncpy(char *dst, const char *src, size_t num)
80 {
81         char *to = dst;
82         while(*src && num--)    *to++ = *src++;
83         *to = '\0';
84         return dst;
85 }
86
87 /**
88  * \fn EXPORT char *strcat(char *dst, const char *src)
89  * \brief Append a string onto another
90  */
91 EXPORT char *strcat(char *dst, const char *src)
92 {
93         char    *to = dst;
94         // Find the end
95         while(*to)      to++;
96         // Copy
97         while(*src)     *to++ = *src++;
98         // End string
99         *to = '\0';
100         return dst;
101 }
102
103 EXPORT char *strncat(char *dst, const char *src, size_t n)
104 {
105         char    *to = dst;
106         // Find the end
107         while(*to)      to++;
108         // Copy
109         while(*src && n--)      *to++ = *src++;
110         // End string
111         *to = '\0';
112         return dst;
113 }
114
115 /**
116  * \brief Get the length of a string
117  */
118 EXPORT size_t strlen(const char *str)
119 {
120         size_t  retval;
121         for(retval = 0; *str != '\0'; str++, retval++);
122         return retval;
123 }
124
125 /**
126  * \brief Get the length of a string, with a maximum of \a maxlen
127  * 
128  * Gets the length of a string (excluding the terminating \0 byte)
129  */
130 EXPORT size_t strnlen(const char *str, size_t maxlen)
131 {
132         size_t  len;
133         for( len = 0; maxlen -- && *str; str ++, len ++ );
134         return len;
135 }
136
137 /**
138  * \fn EXPORT char *strdup(const char *str)
139  * \brief Duplicate a string using heap memory
140  * \note Defined in POSIX Spec, not C spec
141  */
142 EXPORT char *strdup(const char *str)
143 {
144         size_t  len = strlen(str);
145         char    *ret = malloc(len+1);
146         if(ret == NULL) return NULL;
147         strcpy(ret, str);
148         return ret;
149 }
150
151 /**
152  * \fn EXPORT char *strndup(const char *str, size_t maxlen)
153  * \brief Duplicate a string into the heap with a maximum length
154  * \param str   Input string buffer
155  * \param maxlen        Maximum valid size of the \a str buffer
156  * \return Heap string with the same value of \a str
157  */
158 EXPORT char *strndup(const char *str, size_t maxlen)
159 {
160         size_t  len;
161         char    *ret;
162         for( len = 0; len < maxlen && str[len]; len ++) ;
163         ret = malloc( len + 1);
164         memcpy( ret, str, len );
165         ret[len] = '\0';
166         return ret;
167 }
168
169 /**
170  * \fn EXPORT char *strchr(char *str, int character)
171  * \brief Locate a character in a string
172  */
173 EXPORT char *strchr(const char *str, int character)
174 {
175         for(;*str;str++)
176         {
177                 if(*str == character)
178                         return (char*)str;
179         }
180         return NULL;
181 }
182
183 /**
184  * \fn EXPORT char *strrchr(char *str, int character)
185  * \brief Locate the last occurance of a character in a string
186  */
187 EXPORT char *strrchr(const char *str, int character)
188 {
189          int    i;
190         i = strlen(str)-1;
191         while(i--)
192         {
193                 if(str[i] == character)
194                         return (void*)&str[i];
195         }
196         return NULL;
197 }
198
199 /**
200  * \fn EXPORT char *strstr(char *str1, const char *str2)
201  * \brief Search a \a str1 for the first occurance of \a str2
202  */
203 EXPORT char *strstr(const char *str1, const char *str2)
204 {
205         const char      *test = str2;
206         
207         for(;*str1;str1++)
208         {
209                 if(*test == '\0')       return (char*)str1;
210                 if(*str1 == *test)      test++;
211                 else    test = str2;
212         }
213         return NULL;
214 }
215
216 // --- Memory ---
217 /**
218  * \fn EXPORT void *memset(void *dest, int val, size_t num)
219  * \brief Clear memory with the specified value
220  */
221 EXPORT void *memset(void *dest, int val, size_t num)
222 {
223         unsigned char *p = dest;
224         while(num--)    *p++ = val;
225         return dest;
226 }
227
228 /**
229  * \fn EXPORT void *memcpy(void *dest, const void *src, size_t count)
230  * \brief Copy one memory area to another
231  */
232 EXPORT void *memcpy(void *__dest, const void *__src, size_t count)
233 {
234         const int       wordmask = sizeof(void*)-1;
235         uintptr_t       src = (uintptr_t)__src;
236         uintptr_t       dst = (uintptr_t)__dest;
237
238         if( count < sizeof(void*)*2 || (dst & wordmask) != (src & wordmask) )
239         {
240                 char    *dp = __dest;
241                 const char      *sp = __src;
242                 while(count--) *dp++ = *sp ++;
243         }
244         // TODO: Bulk aligned copies
245         #if 0
246         else if(count > 128 && (dst & 15) == (src & 15) )
247         {
248                 // SSE/bulk copy
249                 for( ; dst & 15; count -- )
250                         *(char*)dst++ = *(char*)src++;
251                 memcpy_16byte(dst, src, count / 16);
252                 dst += count & ~15;
253                 src += count & ~15;
254                 count &= 15;
255                 while(count --)
256                         *(char*)dst++ = *(char*)src++;
257         }
258         #endif
259         else
260         {
261                 void    **dp, **sp;
262                 for( ; count && (dst & wordmask) != 0; count -- )
263                         *(char*)dst++ = *(char*)src++;
264
265                 dp = (void*)dst; sp = (void*)src;
266                 while( count >= sizeof(void*) )
267                 {
268                         *dp++ = *sp++;
269                         count -= sizeof(void*);
270                 }
271                 dst = (uintptr_t)dp; src = (uintptr_t)sp;
272                 for( ; count; count -- )
273                         *(char*)dst++ = *(char*)src++;
274         }
275
276         return __dest;
277 }
278
279 /**
280  * \fn EXPORT void *memmove(void *dest, const void *src, size_t count)
281  * \brief Copy data in memory, avoiding overlap problems
282  */
283 EXPORT void *memmove(void *dest, const void *src, size_t count)
284 {
285         const char *sp = (const char *)src;
286         char *dp = (char *)dest;
287         // Check if the areas overlap
288         if( sp >= dp+count )
289                 memcpy(dest, src, count);
290         else if( dp >= sp+count )
291                 memcpy(dest, src, count);
292         else {
293                 if( sp < dp ) {
294                         while(count--)
295                                 dp[count] = sp[count];
296                 }
297                 else {
298                         while(count--)
299                                 *dp++ = *sp++;
300                 }
301         }
302         return dest;
303 }
304
305 /**
306  * \fn EXPORT int memcmp(const void *mem1, const void *mem2, size_t count)
307  * \brief Compare two regions of memory
308  * \param mem1  Region 1
309  * \param mem2  Region 2
310  * \param count Number of bytes to check
311  */
312 EXPORT int memcmp(const void *mem1, const void *mem2, size_t count)
313 {
314         const unsigned char     *p1 = mem1, *p2 = mem2;
315         while(count--)
316         {
317                 if( *p1 != *p2 )
318                         return *p1 - *p2;
319                 p1 ++;
320                 p2 ++;
321         }
322         return 0;
323 }
324
325 /**
326  * \fn EXPORT void *memchr(void *ptr, int value, size_t num)
327  * \brief Locates the first occurence of \a value starting at \a ptr
328  * \param ptr   Starting memory location
329  * \param value Value to find
330  * \param num   Size of memory area to check
331  */
332 EXPORT void *memchr(const void *ptr, int value, size_t num)
333 {
334         while(num--)
335         {
336                 if( *(const unsigned char*)ptr == (unsigned char)value )
337                         return (void*)ptr;
338                 ptr ++;
339         }
340         return NULL;
341 }
342
343 EXPORT size_t strcspn(const char *haystack, const char *reject)
344 {
345         size_t  ret = 0;
346          int    i;
347         while( *haystack )
348         {
349                 for( i = 0; reject[i] && reject[i] == *haystack; i ++ );
350
351                 if( reject[i] ) return ret;
352                 ret ++;
353         }
354         return ret;
355 }
356
357 EXPORT size_t strspn(const char *haystack, const char *accept)
358 {
359         size_t  ret = 0;
360          int    i;
361         while( *haystack )
362         {
363                 for( i = 0; accept[i] && accept[i] == *haystack; i ++ );
364
365                 if( !accept[i] )        return ret;
366                 ret ++;
367         }
368         return ret;
369 }

UCC git Repository :: git.ucc.asn.au