initial version
This commit is contained in:
367
code/lab6/libs/string.c
Normal file
367
code/lab6/libs/string.c
Normal file
@@ -0,0 +1,367 @@
|
||||
#include <string.h>
|
||||
#include <x86.h>
|
||||
|
||||
/* *
|
||||
* strlen - calculate the length of the string @s, not including
|
||||
* the terminating '\0' character.
|
||||
* @s: the input string
|
||||
*
|
||||
* The strlen() function returns the length of string @s.
|
||||
* */
|
||||
size_t
|
||||
strlen(const char *s) {
|
||||
size_t cnt = 0;
|
||||
while (*s ++ != '\0') {
|
||||
cnt ++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/* *
|
||||
* strnlen - calculate the length of the string @s, not including
|
||||
* the terminating '\0' char acter, but at most @len.
|
||||
* @s: the input string
|
||||
* @len: the max-length that function will scan
|
||||
*
|
||||
* Note that, this function looks only at the first @len characters
|
||||
* at @s, and never beyond @s + @len.
|
||||
*
|
||||
* The return value is strlen(s), if that is less than @len, or
|
||||
* @len if there is no '\0' character among the first @len characters
|
||||
* pointed by @s.
|
||||
* */
|
||||
size_t
|
||||
strnlen(const char *s, size_t len) {
|
||||
size_t cnt = 0;
|
||||
while (cnt < len && *s ++ != '\0') {
|
||||
cnt ++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/* *
|
||||
* strcpy - copies the string pointed by @src into the array pointed by @dst,
|
||||
* including the terminating null character.
|
||||
* @dst: pointer to the destination array where the content is to be copied
|
||||
* @src: string to be copied
|
||||
*
|
||||
* The return value is @dst.
|
||||
*
|
||||
* To avoid overflows, the size of array pointed by @dst should be long enough to
|
||||
* contain the same string as @src (including the terminating null character), and
|
||||
* should not overlap in memory with @src.
|
||||
* */
|
||||
char *
|
||||
strcpy(char *dst, const char *src) {
|
||||
#ifdef __HAVE_ARCH_STRCPY
|
||||
return __strcpy(dst, src);
|
||||
#else
|
||||
char *p = dst;
|
||||
while ((*p ++ = *src ++) != '\0')
|
||||
/* nothing */;
|
||||
return dst;
|
||||
#endif /* __HAVE_ARCH_STRCPY */
|
||||
}
|
||||
|
||||
/* *
|
||||
* strncpy - copies the first @len characters of @src to @dst. If the end of string @src
|
||||
* if found before @len characters have been copied, @dst is padded with '\0' until a
|
||||
* total of @len characters have been written to it.
|
||||
* @dst: pointer to the destination array where the content is to be copied
|
||||
* @src: string to be copied
|
||||
* @len: maximum number of characters to be copied from @src
|
||||
*
|
||||
* The return value is @dst
|
||||
* */
|
||||
char *
|
||||
strncpy(char *dst, const char *src, size_t len) {
|
||||
char *p = dst;
|
||||
while (len > 0) {
|
||||
if ((*p = *src) != '\0') {
|
||||
src ++;
|
||||
}
|
||||
p ++, len --;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
/* *
|
||||
* strcmp - compares the string @s1 and @s2
|
||||
* @s1: string to be compared
|
||||
* @s2: string to be compared
|
||||
*
|
||||
* This function starts comparing the first character of each string. If
|
||||
* they are equal to each other, it continues with the following pairs until
|
||||
* the characters differ or until a terminanting null-character is reached.
|
||||
*
|
||||
* Returns an integral value indicating the relationship between the strings:
|
||||
* - A zero value indicates that both strings are equal;
|
||||
* - A value greater than zero indicates that the first character that does
|
||||
* not match has a greater value in @s1 than in @s2;
|
||||
* - And a value less than zero indicates the opposite.
|
||||
* */
|
||||
int
|
||||
strcmp(const char *s1, const char *s2) {
|
||||
#ifdef __HAVE_ARCH_STRCMP
|
||||
return __strcmp(s1, s2);
|
||||
#else
|
||||
while (*s1 != '\0' && *s1 == *s2) {
|
||||
s1 ++, s2 ++;
|
||||
}
|
||||
return (int)((unsigned char)*s1 - (unsigned char)*s2);
|
||||
#endif /* __HAVE_ARCH_STRCMP */
|
||||
}
|
||||
|
||||
/* *
|
||||
* strncmp - compares up to @n characters of the string @s1 to those of the string @s2
|
||||
* @s1: string to be compared
|
||||
* @s2: string to be compared
|
||||
* @n: maximum number of characters to compare
|
||||
*
|
||||
* This function starts comparing the first character of each string. If
|
||||
* they are equal to each other, it continues with the following pairs until
|
||||
* the characters differ, until a terminating null-character is reached, or
|
||||
* until @n characters match in both strings, whichever happens first.
|
||||
* */
|
||||
int
|
||||
strncmp(const char *s1, const char *s2, size_t n) {
|
||||
while (n > 0 && *s1 != '\0' && *s1 == *s2) {
|
||||
n --, s1 ++, s2 ++;
|
||||
}
|
||||
return (n == 0) ? 0 : (int)((unsigned char)*s1 - (unsigned char)*s2);
|
||||
}
|
||||
|
||||
/* *
|
||||
* strchr - locates first occurrence of character in string
|
||||
* @s: the input string
|
||||
* @c: character to be located
|
||||
*
|
||||
* The strchr() function returns a pointer to the first occurrence of
|
||||
* character in @s. If the value is not found, the function returns 'NULL'.
|
||||
* */
|
||||
char *
|
||||
strchr(const char *s, char c) {
|
||||
while (*s != '\0') {
|
||||
if (*s == c) {
|
||||
return (char *)s;
|
||||
}
|
||||
s ++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* *
|
||||
* strfind - locates first occurrence of character in string
|
||||
* @s: the input string
|
||||
* @c: character to be located
|
||||
*
|
||||
* The strfind() function is like strchr() except that if @c is
|
||||
* not found in @s, then it returns a pointer to the null byte at the
|
||||
* end of @s, rather than 'NULL'.
|
||||
* */
|
||||
char *
|
||||
strfind(const char *s, char c) {
|
||||
while (*s != '\0') {
|
||||
if (*s == c) {
|
||||
break;
|
||||
}
|
||||
s ++;
|
||||
}
|
||||
return (char *)s;
|
||||
}
|
||||
|
||||
/* *
|
||||
* strtol - converts string to long integer
|
||||
* @s: the input string that contains the representation of an integer number
|
||||
* @endptr: reference to an object of type char *, whose value is set by the
|
||||
* function to the next character in @s after the numerical value. This
|
||||
* parameter can also be a null pointer, in which case it is not used.
|
||||
* @base: x
|
||||
*
|
||||
* The function first discards as many whitespace characters as necessary until
|
||||
* the first non-whitespace character is found. Then, starting from this character,
|
||||
* takes as many characters as possible that are valid following a syntax that
|
||||
* depends on the base parameter, and interprets them as a numerical value. Finally,
|
||||
* a pointer to the first character following the integer representation in @s
|
||||
* is stored in the object pointed by @endptr.
|
||||
*
|
||||
* If the value of base is zero, the syntax expected is similar to that of
|
||||
* integer constants, which is formed by a succession of:
|
||||
* - An optional plus or minus sign;
|
||||
* - An optional prefix indicating octal or hexadecimal base ("0" or "0x" respectively)
|
||||
* - A sequence of decimal digits (if no base prefix was specified) or either octal
|
||||
* or hexadecimal digits if a specific prefix is present
|
||||
*
|
||||
* If the base value is between 2 and 36, the format expected for the integral number
|
||||
* is a succession of the valid digits and/or letters needed to represent integers of
|
||||
* the specified radix (starting from '0' and up to 'z'/'Z' for radix 36). The
|
||||
* sequence may optionally be preceded by a plus or minus sign and, if base is 16,
|
||||
* an optional "0x" or "0X" prefix.
|
||||
*
|
||||
* The strtol() function returns the converted integral number as a long int value.
|
||||
* */
|
||||
long
|
||||
strtol(const char *s, char **endptr, int base) {
|
||||
int neg = 0;
|
||||
long val = 0;
|
||||
|
||||
// gobble initial whitespace
|
||||
while (*s == ' ' || *s == '\t') {
|
||||
s ++;
|
||||
}
|
||||
|
||||
// plus/minus sign
|
||||
if (*s == '+') {
|
||||
s ++;
|
||||
}
|
||||
else if (*s == '-') {
|
||||
s ++, neg = 1;
|
||||
}
|
||||
|
||||
// hex or octal base prefix
|
||||
if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x')) {
|
||||
s += 2, base = 16;
|
||||
}
|
||||
else if (base == 0 && s[0] == '0') {
|
||||
s ++, base = 8;
|
||||
}
|
||||
else if (base == 0) {
|
||||
base = 10;
|
||||
}
|
||||
|
||||
// digits
|
||||
while (1) {
|
||||
int dig;
|
||||
|
||||
if (*s >= '0' && *s <= '9') {
|
||||
dig = *s - '0';
|
||||
}
|
||||
else if (*s >= 'a' && *s <= 'z') {
|
||||
dig = *s - 'a' + 10;
|
||||
}
|
||||
else if (*s >= 'A' && *s <= 'Z') {
|
||||
dig = *s - 'A' + 10;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
if (dig >= base) {
|
||||
break;
|
||||
}
|
||||
s ++, val = (val * base) + dig;
|
||||
// we don't properly detect overflow!
|
||||
}
|
||||
|
||||
if (endptr) {
|
||||
*endptr = (char *) s;
|
||||
}
|
||||
return (neg ? -val : val);
|
||||
}
|
||||
|
||||
/* *
|
||||
* memset - sets the first @n bytes of the memory area pointed by @s
|
||||
* to the specified value @c.
|
||||
* @s: pointer the the memory area to fill
|
||||
* @c: value to set
|
||||
* @n: number of bytes to be set to the value
|
||||
*
|
||||
* The memset() function returns @s.
|
||||
* */
|
||||
void *
|
||||
memset(void *s, char c, size_t n) {
|
||||
#ifdef __HAVE_ARCH_MEMSET
|
||||
return __memset(s, c, n);
|
||||
#else
|
||||
char *p = s;
|
||||
while (n -- > 0) {
|
||||
*p ++ = c;
|
||||
}
|
||||
return s;
|
||||
#endif /* __HAVE_ARCH_MEMSET */
|
||||
}
|
||||
|
||||
/* *
|
||||
* memmove - copies the values of @n bytes from the location pointed by @src to
|
||||
* the memory area pointed by @dst. @src and @dst are allowed to overlap.
|
||||
* @dst pointer to the destination array where the content is to be copied
|
||||
* @src pointer to the source of data to by copied
|
||||
* @n: number of bytes to copy
|
||||
*
|
||||
* The memmove() function returns @dst.
|
||||
* */
|
||||
void *
|
||||
memmove(void *dst, const void *src, size_t n) {
|
||||
#ifdef __HAVE_ARCH_MEMMOVE
|
||||
return __memmove(dst, src, n);
|
||||
#else
|
||||
const char *s = src;
|
||||
char *d = dst;
|
||||
if (s < d && s + n > d) {
|
||||
s += n, d += n;
|
||||
while (n -- > 0) {
|
||||
*-- d = *-- s;
|
||||
}
|
||||
} else {
|
||||
while (n -- > 0) {
|
||||
*d ++ = *s ++;
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
#endif /* __HAVE_ARCH_MEMMOVE */
|
||||
}
|
||||
|
||||
/* *
|
||||
* memcpy - copies the value of @n bytes from the location pointed by @src to
|
||||
* the memory area pointed by @dst.
|
||||
* @dst pointer to the destination array where the content is to be copied
|
||||
* @src pointer to the source of data to by copied
|
||||
* @n: number of bytes to copy
|
||||
*
|
||||
* The memcpy() returns @dst.
|
||||
*
|
||||
* Note that, the function does not check any terminating null character in @src,
|
||||
* it always copies exactly @n bytes. To avoid overflows, the size of arrays pointed
|
||||
* by both @src and @dst, should be at least @n bytes, and should not overlap
|
||||
* (for overlapping memory area, memmove is a safer approach).
|
||||
* */
|
||||
void *
|
||||
memcpy(void *dst, const void *src, size_t n) {
|
||||
#ifdef __HAVE_ARCH_MEMCPY
|
||||
return __memcpy(dst, src, n);
|
||||
#else
|
||||
const char *s = src;
|
||||
char *d = dst;
|
||||
while (n -- > 0) {
|
||||
*d ++ = *s ++;
|
||||
}
|
||||
return dst;
|
||||
#endif /* __HAVE_ARCH_MEMCPY */
|
||||
}
|
||||
|
||||
/* *
|
||||
* memcmp - compares two blocks of memory
|
||||
* @v1: pointer to block of memory
|
||||
* @v2: pointer to block of memory
|
||||
* @n: number of bytes to compare
|
||||
*
|
||||
* The memcmp() functions returns an integral value indicating the
|
||||
* relationship between the content of the memory blocks:
|
||||
* - A zero value indicates that the contents of both memory blocks are equal;
|
||||
* - A value greater than zero indicates that the first byte that does not
|
||||
* match in both memory blocks has a greater value in @v1 than in @v2
|
||||
* as if evaluated as unsigned char values;
|
||||
* - And a value less than zero indicates the opposite.
|
||||
* */
|
||||
int
|
||||
memcmp(const void *v1, const void *v2, size_t n) {
|
||||
const char *s1 = (const char *)v1;
|
||||
const char *s2 = (const char *)v2;
|
||||
while (n -- > 0) {
|
||||
if (*s1 != *s2) {
|
||||
return (int)((unsigned char)*s1 - (unsigned char)*s2);
|
||||
}
|
||||
s1 ++, s2 ++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user