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
RevLine 
[936351c1]1/*
[df4ed85]2 * Copyright (c) 2005 Martin Decky
[936351c1]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
[a46da63]29/** @addtogroup libc
[b2951e2]30 * @{
31 */
32/** @file
33 */
34
[936351c1]35#include <string.h>
[672a24d]36#include <unistd.h>
37#include <ctype.h>
38#include <limits.h>
[7f079d9]39#include <align.h>
[5d4e90f0]40#include <sys/types.h>
[566987b0]41#include <malloc.h>
[936351c1]42
43/* Dummy implementation of mem/ functions */
44
[a46da63]45void *memset(void *s, int c, size_t n)
[936351c1]46{
47 char *os = s;
[a46da63]48
[936351c1]49 while (n--)
50 *(os++) = c;
[a46da63]51
[936351c1]52 return s;
53}
54
[a46da63]55struct along {
56 unsigned long n;
57} __attribute__ ((packed));
[7f079d9]58
[a46da63]59static void *unaligned_memcpy(void *dst, const void *src, size_t n)
[7f079d9]60{
61 int i, j;
62 struct along *adst = dst;
63 const struct along *asrc = src;
64
[a46da63]65 for (i = 0; i < n / sizeof(unsigned long); i++)
[7f079d9]66 adst[i].n = asrc[i].n;
67
[a46da63]68 for (j = 0; j < n % sizeof(unsigned long); j++)
[838e14e2]69 ((unsigned char *) (((unsigned long *) dst) + i))[j] =
70 ((unsigned char *) (((unsigned long *) src) + i))[j];
[7f079d9]71
[da349da0]72 return (char *) dst;
[7f079d9]73}
74
[a46da63]75void *memcpy(void *dst, const void *src, size_t n)
[936351c1]76{
[a2ae4f4]77 int i, j;
78
[838e14e2]79 if (((long) dst & (sizeof(long) - 1)) ||
80 ((long) src & (sizeof(long) - 1)))
[7f079d9]81 return unaligned_memcpy(dst, src, n);
82
[a46da63]83 for (i = 0; i < n / sizeof(unsigned long); i++)
[a2ae4f4]84 ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
85
[a46da63]86 for (j = 0; j < n % sizeof(unsigned long); j++)
[838e14e2]87 ((unsigned char *) (((unsigned long *) dst) + i))[j] =
88 ((unsigned char *) (((unsigned long *) src) + i))[j];
[a2ae4f4]89
[da349da0]90 return (char *) dst;
[936351c1]91}
[c9857c6]92
[a46da63]93void *memmove(void *dst, const void *src, size_t n)
[a2ae4f4]94{
95 int i, j;
96
97 if (src > dst)
98 return memcpy(dst, src, n);
99
[a46da63]100 for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--)
[838e14e2]101 ((unsigned char *) ((unsigned long *) dst))[j] =
102 ((unsigned char *) ((unsigned long *) src))[j];
[a2ae4f4]103
[a46da63]104 for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--)
[a2ae4f4]105 ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
106
[da349da0]107 return (char *) dst;
[a2ae4f4]108}
109
[df24ec3]110/** Compare two memory areas.
111 *
[838e14e2]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.
[df24ec3]118 */
119int bcmp(const char *s1, const char *s2, size_t len)
120{
121 for (; len && *s1++ == *s2++; len--)
122 ;
123 return len;
124}
[a2ae4f4]125
[672a24d]126/** Count the number of characters in the string, not including terminating 0.
[838e14e2]127 *
128 * @param str String.
129 * @return Number of characters in string.
[672a24d]130 */
[c9857c6]131size_t strlen(const char *str)
132{
[523fad8]133 size_t counter = 0;
[c9857c6]134
[a46da63]135 while (str[counter] != 0)
[c9857c6]136 counter++;
137
138 return counter;
139}
[672a24d]140
[a46da63]141int strcmp(const char *a, const char *b)
[c0535f80]142{
[a46da63]143 int c = 0;
[c0535f80]144
[a46da63]145 while (a[c] && b[c] && (!(a[c] - b[c])))
146 c++;
[c0535f80]147
[a46da63]148 return (a[c] - b[c]);
[c0535f80]149}
150
[5832e9b]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}
[c0535f80]161
[2dd7288]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
[838e14e2]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.
[672a24d]178 */
179char *strchr(const char *str, int c)
180{
181 while (*str != '\0') {
[a46da63]182 if (*str == (char) c)
183 return (char *) str;
[672a24d]184 str++;
185 }
186
187 return NULL;
188}
189
[838e14e2]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.
[672a24d]196 */
197char *strrchr(const char *str, int c)
198{
199 char *retval = NULL;
200
201 while (*str != '\0') {
[a46da63]202 if (*str == (char) c)
203 retval = (char *) str;
[672a24d]204 str++;
205 }
206
[a46da63]207 return (char *) retval;
[672a24d]208}
209
210/** Convert string to a number.
211 * Core of strtol and strtoul functions.
[838e14e2]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.
[672a24d]219 */
[838e14e2]220static unsigned long
221_strtoul(const char *nptr, char **endptr, int base, char *sgn)
[672a24d]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 }
[838e14e2]243 if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
244 (str[1] == 'X'))) {
[672a24d]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;
[838e14e2]263 c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
264 (c <= '9' ? c - '0' : 0xff)));
[672a24d]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) {
[838e14e2]283 /*
284 * No number was found => first invalid character is the first
285 * character of the string.
286 */
[672a24d]287 /* FIXME: set errno to EINVAL */
288 str = nptr;
289 result = 0;
290 }
291
292 if (endptr)
[a46da63]293 *endptr = (char *) str;
[672a24d]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.
[838e14e2]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.
[672a24d]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) {
[a46da63]324 if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
[672a24d]325 /* FIXME: set 0 to errno */
326 return number;
327 }
328 /* FIXME: set ERANGE to errno */
[a46da63]329 return (sgn ? LONG_MIN : LONG_MAX);
[672a24d]330 }
331
[a46da63]332 return (sgn ? -number : number);
[672a24d]333}
334
335
336/** Convert initial part of string to unsigned long according to given base.
[838e14e2]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.
[672a24d]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
[a46da63]356 return (sgn ? -number : number);
[672a24d]357}
[c594489]358
359char *strcpy(char *dest, const char *src)
360{
[a46da63]361 char *orig = dest;
362
[1526594c]363 while ((*(dest++) = *(src++)))
364 ;
[a46da63]365 return orig;
[c594489]366}
367
368char *strncpy(char *dest, const char *src, size_t n)
369{
[a46da63]370 char *orig = dest;
371
[1526594c]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 ;
[a46da63]385 return orig;
[c594489]386}
[b2951e2]387
[566987b0]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
[a46da63]399/** @}
[b2951e2]400 */
Note: See TracBrowser for help on using the repository browser.