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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0516fd7 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
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 *) src;
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 *) src;
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 *) src;
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}
151
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}
162
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.
169 */
170char *strchr(const char *str, int c)
171{
172 while (*str != '\0') {
173 if (*str == (char) c)
174 return (char *) str;
175 str++;
176 }
177
178 return NULL;
179}
180
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.
187 */
188char *strrchr(const char *str, int c)
189{
190 char *retval = NULL;
191
192 while (*str != '\0') {
193 if (*str == (char) c)
194 retval = (char *) str;
195 str++;
196 }
197
198 return (char *) retval;
199}
200
201/** Convert string to a number.
202 * Core of strtol and strtoul functions.
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.
210 */
211static unsigned long
212_strtoul(const char *nptr, char **endptr, int base, char *sgn)
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 }
234 if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
235 (str[1] == 'X'))) {
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;
254 c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
255 (c <= '9' ? c - '0' : 0xff)));
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) {
274 /*
275 * No number was found => first invalid character is the first
276 * character of the string.
277 */
278 /* FIXME: set errno to EINVAL */
279 str = nptr;
280 result = 0;
281 }
282
283 if (endptr)
284 *endptr = (char *) str;
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.
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.
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) {
315 if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
316 /* FIXME: set 0 to errno */
317 return number;
318 }
319 /* FIXME: set ERANGE to errno */
320 return (sgn ? LONG_MIN : LONG_MAX);
321 }
322
323 return (sgn ? -number : number);
324}
325
326
327/** Convert initial part of string to unsigned long according to given base.
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.
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
347 return (sgn ? -number : number);
348}
349
350char *strcpy(char *dest, const char *src)
351{
352 char *orig = dest;
353
354 while ((*(dest++) = *(src++)))
355 ;
356 return orig;
357}
358
359char *strncpy(char *dest, const char *src, size_t n)
360{
361 char *orig = dest;
362
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 ;
376 return orig;
377}
378
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
390/** @}
391 */
Note: See TracBrowser for help on using the repository browser.