1 // Basic string routines. Not hardware optimized, but not shabby.
3 #include <inc/string.h>
5 // Using assembly for memset/memmove
6 // makes some difference on real hardware,
7 // but it makes an even bigger difference on bochs.
8 // Primespipe runs 3x faster this way.
16 for (n
= 0; *s
!= '\0'; s
++)
22 strnlen(const char *s
, size_t size
)
26 for (n
= 0; size
> 0 && *s
!= '\0'; s
++, size
--)
32 strcpy(char *dst
, const char *src
)
37 while ((*dst
++ = *src
++) != '\0')
43 strcat(char *dst
, const char *src
)
45 int len
= strlen(dst
);
46 strcpy(dst
+ len
, src
);
51 strncpy(char *dst
, const char *src
, size_t size
) {
56 for (i
= 0; i
< size
; i
++) {
58 // If strlen(src) < size, null-pad 'dst' out to 'size' chars
66 strlcpy(char *dst
, const char *src
, size_t size
)
72 while (--size
> 0 && *src
!= '\0')
80 strcmp(const char *p
, const char *q
)
82 while (*p
&& *p
== *q
)
84 return (int) ((unsigned char) *p
- (unsigned char) *q
);
88 strncmp(const char *p
, const char *q
, size_t n
)
90 while (n
> 0 && *p
&& *p
== *q
)
95 return (int) ((unsigned char) *p
- (unsigned char) *q
);
98 // Return a pointer to the first occurrence of 'c' in 's',
99 // or a null pointer if the string has no 'c'.
101 strchr(const char *s
, char c
)
109 // Return a pointer to the first occurrence of 'c' in 's',
110 // or a pointer to the string-ending null character if the string has no 'c'.
112 strfind(const char *s
, char c
)
122 memset(void *v
, int c
, size_t n
)
128 if ((int)v
%4 == 0 && n
%4 == 0) {
130 c
= (c
<<24)|(c
<<16)|(c
<<8)|c
;
131 asm volatile("cld; rep stosl\n"
132 :: "D" (v
), "a" (c
), "c" (n
/4)
135 asm volatile("cld; rep stosb\n"
136 :: "D" (v
), "a" (c
), "c" (n
)
142 memmove(void *dst
, const void *src
, size_t n
)
149 if (s
< d
&& s
+ n
> d
) {
152 if ((int)s
%4 == 0 && (int)d
%4 == 0 && n
%4 == 0)
153 asm volatile("std; rep movsl\n"
154 :: "D" (d
-4), "S" (s
-4), "c" (n
/4) : "cc", "memory");
156 asm volatile("std; rep movsb\n"
157 :: "D" (d
-1), "S" (s
-1), "c" (n
) : "cc", "memory");
158 // Some versions of GCC rely on DF being clear
159 asm volatile("cld" ::: "cc");
161 if ((int)s
%4 == 0 && (int)d
%4 == 0 && n
%4 == 0)
162 asm volatile("cld; rep movsl\n"
163 :: "D" (d
), "S" (s
), "c" (n
/4) : "cc", "memory");
165 asm volatile("cld; rep movsb\n"
166 :: "D" (d
), "S" (s
), "c" (n
) : "cc", "memory");
174 memset(void *v
, int c
, size_t n
)
187 /* no memcpy - use memmove instead */
190 memmove(void *dst
, const void *src
, size_t n
)
197 if (s
< d
&& s
+ n
> d
) {
210 /* sigh - gcc emits references to this for structure assignments! */
211 /* it is *not* prototyped in inc/string.h - do not use directly. */
213 memcpy(void *dst
, void *src
, size_t n
)
215 return memmove(dst
, src
, n
);
219 memcmp(const void *v1
, const void *v2
, size_t n
)
221 const uint8_t *s1
= (const uint8_t *) v1
;
222 const uint8_t *s2
= (const uint8_t *) v2
;
226 return (int) *s1
- (int) *s2
;
234 memfind(const void *s
, int c
, size_t n
)
236 const void *ends
= (const char *) s
+ n
;
237 for (; s
< ends
; s
++)
238 if (*(const unsigned char *) s
== (unsigned char) c
)
244 strtol(const char *s
, char **endptr
, int base
)
249 // gobble initial whitespace
250 while (*s
== ' ' || *s
== '\t')
259 // hex or octal base prefix
260 if ((base
== 0 || base
== 16) && (s
[0] == '0' && s
[1] == 'x'))
262 else if (base
== 0 && s
[0] == '0')
271 if (*s
>= '0' && *s
<= '9')
273 else if (*s
>= 'a' && *s
<= 'z')
275 else if (*s
>= 'A' && *s
<= 'Z')
281 s
++, val
= (val
* base
) + dig
;
282 // we don't properly detect overflow!
286 *endptr
= (char *) s
;
287 return (neg
? -val
: val
);