source: mainline/uspace/lib/libc/generic/string.c@ ab00d5a

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ab00d5a was da349da0, checked in by Jakub Jermar <jakub@…>, 17 years ago

memcpy(), memmove() and similar functions return dst instead of src.
Fix all implementations, including those in assembly. ppc32 assembly
version didn't seem to be affected by this.

  • Property mode set to 100644
File size: 9.3 KB
Line 
1/*
2 * Copyright (c) 2005 Martin Decky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/** @file
33 */
34
35#include <string.h>
36#include <unistd.h>
37#include <ctype.h>
38#include <limits.h>
39#include <align.h>
40#include <sys/types.h>
41#include <malloc.h>
42
43/* Dummy implementation of mem/ functions */
44
45void *memset(void *s, int c, size_t n)
46{
47 char *os = s;
48
49 while (n--)
50 *(os++) = c;
51
52 return s;
53}
54
55struct along {
56 unsigned long n;
57} __attribute__ ((packed));
58
59static void *unaligned_memcpy(void *dst, const void *src, size_t n)
60{
61 int i, j;
62 struct along *adst = dst;
63 const struct along *asrc = src;
64
65 for (i = 0; i < n / sizeof(unsigned long); i++)
66 adst[i].n = asrc[i].n;
67
68 for (j = 0; j < n % sizeof(unsigned long); j++)
69 ((unsigned char *) (((unsigned long *) dst) + i))[j] =
70 ((unsigned char *) (((unsigned long *) src) + i))[j];
71
72 return (char *) dst;
73}
74
75void *memcpy(void *dst, const void *src, size_t n)
76{
77 int i, j;
78
79 if (((long) dst & (sizeof(long) - 1)) ||
80 ((long) src & (sizeof(long) - 1)))
81 return unaligned_memcpy(dst, src, n);
82
83 for (i = 0; i < n / sizeof(unsigned long); i++)
84 ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
85
86 for (j = 0; j < n % sizeof(unsigned long); j++)
87 ((unsigned char *) (((unsigned long *) dst) + i))[j] =
88 ((unsigned char *) (((unsigned long *) src) + i))[j];
89
90 return (char *) dst;
91}
92
93void *memmove(void *dst, const void *src, size_t n)
94{
95 int i, j;
96
97 if (src > dst)
98 return memcpy(dst, src, n);
99
100 for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--)
101 ((unsigned char *) ((unsigned long *) dst))[j] =
102 ((unsigned char *) ((unsigned long *) src))[j];
103
104 for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--)
105 ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
106
107 return (char *) dst;
108}
109
110/** Compare two memory areas.
111 *
112 * @param s1 Pointer to the first area to compare.
113 * @param s2 Pointer to the second area to compare.
114 * @param len Size of the first area in bytes. Both areas must have
115 * the same length.
116 * @return If len is 0, return zero. If the areas match, return
117 * zero. Otherwise return non-zero.
118 */
119int bcmp(const char *s1, const char *s2, size_t len)
120{
121 for (; len && *s1++ == *s2++; len--)
122 ;
123 return len;
124}
125
126/** Count the number of characters in the string, not including terminating 0.
127 *
128 * @param str String.
129 * @return Number of characters in string.
130 */
131size_t strlen(const char *str)
132{
133 size_t counter = 0;
134
135 while (str[counter] != 0)
136 counter++;
137
138 return counter;
139}
140
141int strcmp(const char *a, const char *b)
142{
143 int c = 0;
144
145 while (a[c] && b[c] && (!(a[c] - b[c])))
146 c++;
147
148 return (a[c] - b[c]);
149}
150
151int strncmp(const char *a, const char *b, size_t n)
152{
153 size_t c = 0;
154
155 while (c < n && a[c] && b[c] && (!(a[c] - b[c])))
156 c++;
157
158 return ( c < n ? a[c] - b[c] : 0);
159
160}
161
162int stricmp(const char *a, const char *b)
163{
164 int c = 0;
165
166 while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c]))))
167 c++;
168
169 return (tolower(a[c]) - tolower(b[c]));
170}
171
172/** Return pointer to the first occurence of character c in string.
173 *
174 * @param str Scanned string.
175 * @param c Searched character (taken as one byte).
176 * @return Pointer to the matched character or NULL if it is not
177 * found in given string.
178 */
179char *strchr(const char *str, int c)
180{
181 while (*str != '\0') {
182 if (*str == (char) c)
183 return (char *) str;
184 str++;
185 }
186
187 return NULL;
188}
189
190/** Return pointer to the last occurence of character c in string.
191 *
192 * @param str Scanned string.
193 * @param c Searched character (taken as one byte).
194 * @return Pointer to the matched character or NULL if it is not
195 * found in given string.
196 */
197char *strrchr(const char *str, int c)
198{
199 char *retval = NULL;
200
201 while (*str != '\0') {
202 if (*str == (char) c)
203 retval = (char *) str;
204 str++;
205 }
206
207 return (char *) retval;
208}
209
210/** Convert string to a number.
211 * Core of strtol and strtoul functions.
212 *
213 * @param nptr Pointer to string.
214 * @param endptr If not NULL, function stores here pointer to the first
215 * invalid character.
216 * @param base Zero or number between 2 and 36 inclusive.
217 * @param sgn It's set to 1 if minus found.
218 * @return Result of conversion.
219 */
220static unsigned long
221_strtoul(const char *nptr, char **endptr, int base, char *sgn)
222{
223 unsigned char c;
224 unsigned long result = 0;
225 unsigned long a, b;
226 const char *str = nptr;
227 const char *tmpptr;
228
229 while (isspace(*str))
230 str++;
231
232 if (*str == '-') {
233 *sgn = 1;
234 ++str;
235 } else if (*str == '+')
236 ++str;
237
238 if (base) {
239 if ((base == 1) || (base > 36)) {
240 /* FIXME: set errno to EINVAL */
241 return 0;
242 }
243 if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
244 (str[1] == 'X'))) {
245 str += 2;
246 }
247 } else {
248 base = 10;
249
250 if (*str == '0') {
251 base = 8;
252 if ((str[1] == 'X') || (str[1] == 'x')) {
253 base = 16;
254 str += 2;
255 }
256 }
257 }
258
259 tmpptr = str;
260
261 while (*str) {
262 c = *str;
263 c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
264 (c <= '9' ? c - '0' : 0xff)));
265 if (c > base) {
266 break;
267 }
268
269 a = (result & 0xff) * base + c;
270 b = (result >> 8) * base + (a >> 8);
271
272 if (b > (ULONG_MAX >> 8)) {
273 /* overflow */
274 /* FIXME: errno = ERANGE*/
275 return ULONG_MAX;
276 }
277
278 result = (b << 8) + (a & 0xff);
279 ++str;
280 }
281
282 if (str == tmpptr) {
283 /*
284 * No number was found => first invalid character is the first
285 * character of the string.
286 */
287 /* FIXME: set errno to EINVAL */
288 str = nptr;
289 result = 0;
290 }
291
292 if (endptr)
293 *endptr = (char *) str;
294
295 if (nptr == str) {
296 /*FIXME: errno = EINVAL*/
297 return 0;
298 }
299
300 return result;
301}
302
303/** Convert initial part of string to long int according to given base.
304 * The number may begin with an arbitrary number of whitespaces followed by
305 * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
306 * inserted and the number will be taken as hexadecimal one. If the base is 0
307 * and the number begin with a zero, number will be taken as octal one (as with
308 * base 8). Otherwise the base 0 is taken as decimal.
309 *
310 * @param nptr Pointer to string.
311 * @param endptr If not NULL, function stores here pointer to the first
312 * invalid character.
313 * @param base Zero or number between 2 and 36 inclusive.
314 * @return Result of conversion.
315 */
316long int strtol(const char *nptr, char **endptr, int base)
317{
318 char sgn = 0;
319 unsigned long number = 0;
320
321 number = _strtoul(nptr, endptr, base, &sgn);
322
323 if (number > LONG_MAX) {
324 if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
325 /* FIXME: set 0 to errno */
326 return number;
327 }
328 /* FIXME: set ERANGE to errno */
329 return (sgn ? LONG_MIN : LONG_MAX);
330 }
331
332 return (sgn ? -number : number);
333}
334
335
336/** Convert initial part of string to unsigned long according to given base.
337 * The number may begin with an arbitrary number of whitespaces followed by
338 * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
339 * inserted and the number will be taken as hexadecimal one. If the base is 0
340 * and the number begin with a zero, number will be taken as octal one (as with
341 * base 8). Otherwise the base 0 is taken as decimal.
342 *
343 * @param nptr Pointer to string.
344 * @param endptr If not NULL, function stores here pointer to the first
345 * invalid character
346 * @param base Zero or number between 2 and 36 inclusive.
347 * @return Result of conversion.
348 */
349unsigned long strtoul(const char *nptr, char **endptr, int base)
350{
351 char sgn = 0;
352 unsigned long number = 0;
353
354 number = _strtoul(nptr, endptr, base, &sgn);
355
356 return (sgn ? -number : number);
357}
358
359char *strcpy(char *dest, const char *src)
360{
361 char *orig = dest;
362
363 while ((*(dest++) = *(src++)))
364 ;
365 return orig;
366}
367
368char *strncpy(char *dest, const char *src, size_t n)
369{
370 char *orig = dest;
371
372 while ((*(dest++) = *(src++)) && --n)
373 ;
374 return orig;
375}
376
377char *strcat(char *dest, const char *src)
378{
379 char *orig = dest;
380 while (*dest++)
381 ;
382 --dest;
383 while ((*dest++ = *src++))
384 ;
385 return orig;
386}
387
388char * strdup(const char *s1)
389{
390 size_t len = strlen(s1) + 1;
391 void *ret = malloc(len);
392
393 if (ret == NULL)
394 return (char *) NULL;
395
396 return (char *) memcpy(ret, s1, len);
397}
398
399/** @}
400 */
Note: See TracBrowser for help on using the repository browser.