source: mainline/libc/generic/string.c@ b2951e2

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b2951e2 was b2951e2, checked in by Josef Cejka <malyzelenyhnus@…>, 19 years ago

Doxygen comments.

  • Property mode set to 100644
File size: 7.9 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
41
42/* Dummy implementation of mem/ functions */
43
44void * memset(void *s, int c, size_t n)
45{
46 char *os = s;
47 while (n--)
48 *(os++) = c;
49 return s;
50}
51
52struct along {unsigned long n; } __attribute__ ((packed));
53
54static void * unaligned_memcpy(void *dst, const void *src, size_t n)
55{
56 int i, j;
57 struct along *adst = dst;
58 const struct along *asrc = src;
59
60 for (i = 0; i < n/sizeof(unsigned long); i++)
61 adst[i].n = asrc[i].n;
62
63 for (j = 0; j < n%sizeof(unsigned long); j++)
64 ((unsigned char *)(((unsigned long *) dst) + i))[j] = ((unsigned char *)(((unsigned long *) src) + i))[j];
65
66 return (char *)src;
67}
68
69void * memcpy(void *dst, const void *src, size_t n)
70{
71 int i, j;
72
73 if (((long)dst & (sizeof(long)-1)) || ((long)src & (sizeof(long)-1)))
74 return unaligned_memcpy(dst, src, n);
75
76 for (i = 0; i < n/sizeof(unsigned long); i++)
77 ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
78
79 for (j = 0; j < n%sizeof(unsigned long); j++)
80 ((unsigned char *)(((unsigned long *) dst) + i))[j] = ((unsigned char *)(((unsigned long *) src) + i))[j];
81
82 return (char *)src;
83}
84
85void * memmove(void *dst, const void *src, size_t n)
86{
87 int i, j;
88
89 if (src > dst)
90 return memcpy(dst, src, n);
91
92 for (j = (n%sizeof(unsigned long))-1; j >= 0; j--)
93 ((unsigned char *)(((unsigned long *) dst) + i))[j] = ((unsigned char *)(((unsigned long *) src) + i))[j];
94
95 for (i = n/sizeof(unsigned long)-1; i >=0 ; i--)
96 ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
97
98 return (char *)src;
99}
100
101
102/** Count the number of characters in the string, not including terminating 0.
103 * @param str string
104 * @return number of characters in string.
105 */
106size_t strlen(const char *str)
107{
108 size_t counter = 0;
109
110 while (str[counter] != 0) {
111 counter++;
112 }
113
114 return counter;
115}
116
117int strcmp(const char *a,const char *b)
118{
119 int c=0;
120
121 while(a[c]&&b[c]&&(!(a[c]-b[c]))) c++;
122
123 return a[c]-b[c];
124
125}
126
127
128
129/** Return pointer to the first occurence of character c in string
130 * @param str scanned string
131 * @param c searched character (taken as one byte)
132 * @return pointer to the matched character or NULL if it is not found in given string.
133 */
134char *strchr(const char *str, int c)
135{
136 while (*str != '\0') {
137 if (*str == (char)c)
138 return (char *)str;
139 str++;
140 }
141
142 return NULL;
143}
144
145/** Return pointer to the last occurence of character c in string
146 * @param str scanned string
147 * @param c searched character (taken as one byte)
148 * @return pointer to the matched character or NULL if it is not found in given string.
149 */
150char *strrchr(const char *str, int c)
151{
152 char *retval = NULL;
153
154 while (*str != '\0') {
155 if (*str == (char)c)
156 retval = (char *)str;
157 str++;
158 }
159
160 return (char *)retval;
161}
162
163/** Convert string to a number.
164 * Core of strtol and strtoul functions.
165 * @param nptr pointer to string
166 * @param endptr if not NULL, function stores here pointer to the first invalid character
167 * @param base zero or number between 2 and 36 inclusive
168 * @param sgn its set to 1 if minus found
169 * @return result of conversion.
170 */
171static unsigned long _strtoul(const char *nptr, char **endptr, int base, char *sgn)
172{
173 unsigned char c;
174 unsigned long result = 0;
175 unsigned long a, b;
176 const char *str = nptr;
177 const char *tmpptr;
178
179 while (isspace(*str))
180 str++;
181
182 if (*str == '-') {
183 *sgn = 1;
184 ++str;
185 } else if (*str == '+')
186 ++str;
187
188 if (base) {
189 if ((base == 1) || (base > 36)) {
190 /* FIXME: set errno to EINVAL */
191 return 0;
192 }
193 if ((base == 16) && (*str == '0') && ((str[1] == 'x') || (str[1] == 'X'))) {
194 str += 2;
195 }
196 } else {
197 base = 10;
198
199 if (*str == '0') {
200 base = 8;
201 if ((str[1] == 'X') || (str[1] == 'x')) {
202 base = 16;
203 str += 2;
204 }
205 }
206 }
207
208 tmpptr = str;
209
210 while (*str) {
211 c = *str;
212 c = ( c >= 'a'? c-'a'+10:(c >= 'A'?c-'A'+10:(c <= '9'?c-'0':0xff)));
213 if (c > base) {
214 break;
215 }
216
217 a = (result & 0xff) * base + c;
218 b = (result >> 8) * base + (a >> 8);
219
220 if (b > (ULONG_MAX >> 8)) {
221 /* overflow */
222 /* FIXME: errno = ERANGE*/
223 return ULONG_MAX;
224 }
225
226 result = (b << 8) + (a & 0xff);
227 ++str;
228 }
229
230 if (str == tmpptr) {
231 /* no number was found => first invalid character is the first character of the string */
232 /* FIXME: set errno to EINVAL */
233 str = nptr;
234 result = 0;
235 }
236
237 if (endptr)
238 *endptr = (char *)str;
239
240 if (nptr == str) {
241 /*FIXME: errno = EINVAL*/
242 return 0;
243 }
244
245 return result;
246}
247
248/** Convert initial part of string to long int according to given base.
249 * The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-').
250 * If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one.
251 * If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8).
252 * Otherwise the base 0 is taken as decimal.
253 * @param nptr pointer to string
254 * @param endptr if not NULL, function stores here pointer to the first invalid character
255 * @param base zero or number between 2 and 36 inclusive
256 * @return result of conversion.
257 */
258long int strtol(const char *nptr, char **endptr, int base)
259{
260 char sgn = 0;
261 unsigned long number = 0;
262
263 number = _strtoul(nptr, endptr, base, &sgn);
264
265 if (number > LONG_MAX) {
266 if ((sgn) && (number == (unsigned long)(LONG_MAX) + 1)) {
267 /* FIXME: set 0 to errno */
268 return number;
269 }
270 /* FIXME: set ERANGE to errno */
271 return (sgn?LONG_MIN:LONG_MAX);
272 }
273
274 return (sgn?-number:number);
275}
276
277
278/** Convert initial part of string to unsigned long according to given base.
279 * The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-').
280 * If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one.
281 * If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8).
282 * Otherwise the base 0 is taken as decimal.
283 * @param nptr pointer to string
284 * @param endptr if not NULL, function stores here pointer to the first invalid character
285 * @param base zero or number between 2 and 36 inclusive
286 * @return result of conversion.
287 */
288unsigned long strtoul(const char *nptr, char **endptr, int base)
289{
290 char sgn = 0;
291 unsigned long number = 0;
292
293 number = _strtoul(nptr, endptr, base, &sgn);
294
295 return (sgn?-number:number);
296}
297
298char *strcpy(char *dest, const char *src)
299{
300 while (*(dest++) = *(src++))
301 ;
302}
303
304char *strncpy(char *dest, const char *src, size_t n)
305{
306 while ((*(dest++) = *(src++)) && --n)
307 ;
308}
309
310
311 /** @}
312 */
313
314
Note: See TracBrowser for help on using the repository browser.