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

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

Cstyle for string.c

  • Property mode set to 100644
File size: 9.1 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
[a46da63]72 return (char *) src;
[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
[a46da63]90 return (char *) src;
[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
[a46da63]107 return (char *) src;
[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}
151
[5832e9b]152int strncmp(const char *a, const char *b, size_t n)
153{
154 size_t c = 0;
155
156 while (c < n && a[c] && b[c] && (!(a[c] - b[c])))
157 c++;
158
159 return ( c < n ? a[c] - b[c] : 0);
160
161}
[c0535f80]162
[838e14e2]163/** Return pointer to the first occurence of character c in string.
164 *
165 * @param str Scanned string.
166 * @param c Searched character (taken as one byte).
167 * @return Pointer to the matched character or NULL if it is not
168 * found in given string.
[672a24d]169 */
170char *strchr(const char *str, int c)
171{
172 while (*str != '\0') {
[a46da63]173 if (*str == (char) c)
174 return (char *) str;
[672a24d]175 str++;
176 }
177
178 return NULL;
179}
180
[838e14e2]181/** Return pointer to the last occurence of character c in string.
182 *
183 * @param str Scanned string.
184 * @param c Searched character (taken as one byte).
185 * @return Pointer to the matched character or NULL if it is not
186 * found in given string.
[672a24d]187 */
188char *strrchr(const char *str, int c)
189{
190 char *retval = NULL;
191
192 while (*str != '\0') {
[a46da63]193 if (*str == (char) c)
194 retval = (char *) str;
[672a24d]195 str++;
196 }
197
[a46da63]198 return (char *) retval;
[672a24d]199}
200
201/** Convert string to a number.
202 * Core of strtol and strtoul functions.
[838e14e2]203 *
204 * @param nptr Pointer to string.
205 * @param endptr If not NULL, function stores here pointer to the first
206 * invalid character.
207 * @param base Zero or number between 2 and 36 inclusive.
208 * @param sgn It's set to 1 if minus found.
209 * @return Result of conversion.
[672a24d]210 */
[838e14e2]211static unsigned long
212_strtoul(const char *nptr, char **endptr, int base, char *sgn)
[672a24d]213{
214 unsigned char c;
215 unsigned long result = 0;
216 unsigned long a, b;
217 const char *str = nptr;
218 const char *tmpptr;
219
220 while (isspace(*str))
221 str++;
222
223 if (*str == '-') {
224 *sgn = 1;
225 ++str;
226 } else if (*str == '+')
227 ++str;
228
229 if (base) {
230 if ((base == 1) || (base > 36)) {
231 /* FIXME: set errno to EINVAL */
232 return 0;
233 }
[838e14e2]234 if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
235 (str[1] == 'X'))) {
[672a24d]236 str += 2;
237 }
238 } else {
239 base = 10;
240
241 if (*str == '0') {
242 base = 8;
243 if ((str[1] == 'X') || (str[1] == 'x')) {
244 base = 16;
245 str += 2;
246 }
247 }
248 }
249
250 tmpptr = str;
251
252 while (*str) {
253 c = *str;
[838e14e2]254 c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
255 (c <= '9' ? c - '0' : 0xff)));
[672a24d]256 if (c > base) {
257 break;
258 }
259
260 a = (result & 0xff) * base + c;
261 b = (result >> 8) * base + (a >> 8);
262
263 if (b > (ULONG_MAX >> 8)) {
264 /* overflow */
265 /* FIXME: errno = ERANGE*/
266 return ULONG_MAX;
267 }
268
269 result = (b << 8) + (a & 0xff);
270 ++str;
271 }
272
273 if (str == tmpptr) {
[838e14e2]274 /*
275 * No number was found => first invalid character is the first
276 * character of the string.
277 */
[672a24d]278 /* FIXME: set errno to EINVAL */
279 str = nptr;
280 result = 0;
281 }
282
283 if (endptr)
[a46da63]284 *endptr = (char *) str;
[672a24d]285
286 if (nptr == str) {
287 /*FIXME: errno = EINVAL*/
288 return 0;
289 }
290
291 return result;
292}
293
294/** Convert initial part of string to long int according to given base.
[838e14e2]295 * The number may begin with an arbitrary number of whitespaces followed by
296 * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
297 * inserted and the number will be taken as hexadecimal one. If the base is 0
298 * and the number begin with a zero, number will be taken as octal one (as with
299 * base 8). Otherwise the base 0 is taken as decimal.
300 *
301 * @param nptr Pointer to string.
302 * @param endptr If not NULL, function stores here pointer to the first
303 * invalid character.
304 * @param base Zero or number between 2 and 36 inclusive.
305 * @return Result of conversion.
[672a24d]306 */
307long int strtol(const char *nptr, char **endptr, int base)
308{
309 char sgn = 0;
310 unsigned long number = 0;
311
312 number = _strtoul(nptr, endptr, base, &sgn);
313
314 if (number > LONG_MAX) {
[a46da63]315 if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
[672a24d]316 /* FIXME: set 0 to errno */
317 return number;
318 }
319 /* FIXME: set ERANGE to errno */
[a46da63]320 return (sgn ? LONG_MIN : LONG_MAX);
[672a24d]321 }
322
[a46da63]323 return (sgn ? -number : number);
[672a24d]324}
325
326
327/** Convert initial part of string to unsigned long according to given base.
[838e14e2]328 * The number may begin with an arbitrary number of whitespaces followed by
329 * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
330 * inserted and the number will be taken as hexadecimal one. If the base is 0
331 * and the number begin with a zero, number will be taken as octal one (as with
332 * base 8). Otherwise the base 0 is taken as decimal.
333 *
334 * @param nptr Pointer to string.
335 * @param endptr If not NULL, function stores here pointer to the first
336 * invalid character
337 * @param base Zero or number between 2 and 36 inclusive.
338 * @return Result of conversion.
[672a24d]339 */
340unsigned long strtoul(const char *nptr, char **endptr, int base)
341{
342 char sgn = 0;
343 unsigned long number = 0;
344
345 number = _strtoul(nptr, endptr, base, &sgn);
346
[a46da63]347 return (sgn ? -number : number);
[672a24d]348}
[c594489]349
350char *strcpy(char *dest, const char *src)
351{
[a46da63]352 char *orig = dest;
353
[1526594c]354 while ((*(dest++) = *(src++)))
355 ;
[a46da63]356 return orig;
[c594489]357}
358
359char *strncpy(char *dest, const char *src, size_t n)
360{
[a46da63]361 char *orig = dest;
362
[1526594c]363 while ((*(dest++) = *(src++)) && --n)
364 ;
365 return orig;
366}
367
368char *strcat(char *dest, const char *src)
369{
370 char *orig = dest;
371 while (*dest++)
372 ;
373 --dest;
374 while ((*dest++ = *src++))
375 ;
[a46da63]376 return orig;
[c594489]377}
[b2951e2]378
[566987b0]379char * strdup(const char *s1)
380{
381 size_t len = strlen(s1) + 1;
382 void *ret = malloc(len);
383
384 if (ret == NULL)
385 return (char *) NULL;
386
387 return (char *) memcpy(ret, s1, len);
388}
389
[a46da63]390/** @}
[b2951e2]391 */
Note: See TracBrowser for help on using the repository browser.