diff options
Diffstat (limited to 'src/string')
| -rw-r--r-- | src/string/NULL.ref | 3 | ||||
| -rw-r--r-- | src/string/memchr.c | 31 | ||||
| -rw-r--r-- | src/string/memcmp.c | 34 | ||||
| -rw-r--r-- | src/string/memcpy.c | 31 | ||||
| -rw-r--r-- | src/string/memmove.c | 35 | ||||
| -rw-r--r-- | src/string/memset.c | 28 | ||||
| -rw-r--r-- | src/string/size_t.ref | 3 | ||||
| -rw-r--r-- | src/string/strcat.c | 24 | ||||
| -rw-r--r-- | src/string/strchr.c | 22 | ||||
| -rw-r--r-- | src/string/strcmp.c | 29 | ||||
| -rw-r--r-- | src/string/strcoll.c | 44 | ||||
| -rw-r--r-- | src/string/strcpy.c | 29 | ||||
| -rw-r--r-- | src/string/strcspn.c | 28 | ||||
| -rw-r--r-- | src/string/strerror.c | 31 | ||||
| -rw-r--r-- | src/string/strlen.c | 25 | ||||
| -rw-r--r-- | src/string/strncat.c | 40 | ||||
| -rw-r--r-- | src/string/strncmp.c | 31 | ||||
| -rw-r--r-- | src/string/strncpy.c | 34 | ||||
| -rw-r--r-- | src/string/strpbrk.c | 28 | ||||
| -rw-r--r-- | src/string/strrchr.c | 30 | ||||
| -rw-r--r-- | src/string/strspn.c | 28 | ||||
| -rw-r--r-- | src/string/strstr.c | 43 | ||||
| -rw-r--r-- | src/string/strtok.c | 34 | ||||
| -rw-r--r-- | src/string/strxfrm.c | 32 |
24 files changed, 697 insertions, 0 deletions
diff --git a/src/string/NULL.ref b/src/string/NULL.ref new file mode 100644 index 00000000..5d6e9890 --- /dev/null +++ b/src/string/NULL.ref @@ -0,0 +1,3 @@ +#include <string.h> +REFERENCE(stddef/NULL.c) +STDC(1) diff --git a/src/string/memchr.c b/src/string/memchr.c new file mode 100644 index 00000000..97f6b257 --- /dev/null +++ b/src/string/memchr.c @@ -0,0 +1,31 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** search memory **/ +void * memchr(const void *s, int c, size_t n) +{ + char *p = (char*)s; + size_t i = 0; + + ASSERT_NONNULL(s); + + for (i = 0; i < n; i++) { + if (p[i] == (unsigned char)c) { + return p + i; + } + } + + /* + RETURN_FAILURE(CONSTANT(NULL)); + RETURN_SUCCESS(a pointer to the located byte); + */ + return NULL; +} + +/*** +searches the first ARGUMENT(n) bytes of memory at ARGUMENT(s) for +ARGUMENT(c) (converted to an TYPE(unsigned char)). +***/ +/* +STDC(1) +*/ diff --git a/src/string/memcmp.c b/src/string/memcmp.c new file mode 100644 index 00000000..64dcb464 --- /dev/null +++ b/src/string/memcmp.c @@ -0,0 +1,34 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** compare memory regions **/ +int memcmp(const void *s1, const void *s2, size_t n) +{ + unsigned char *p = (unsigned char*)s1; + unsigned char *q = (unsigned char*)s2; + size_t i = 0; + + ASSERT_NONNULL(s1); + ASSERT_NONNULL(s2); + + for (i = 0; i < n; i++) { + if (p[i] != q[i]) { + break; + } + } + + /* + RETURN(NEGATIVE, ARGUMENT(s1) is less than ARGUMENT(s2)); + RETURN(ZERO, ARGUMENT(s1) and ARGUMENT(s2) are equal); + RETURN(POSITIVE(), ARGUMENT(s1) is greater than ARGUMENT(s2)); + */ + return p[i] - q[i]; +} + +/*** +compares the first ARGUMENT(n) bytes of memory at ARGUMENT(s1) +and ARGUMENT(s2). +***/ +/* +STDC(1) +*/ diff --git a/src/string/memcpy.c b/src/string/memcpy.c new file mode 100644 index 00000000..f53fe5d8 --- /dev/null +++ b/src/string/memcpy.c @@ -0,0 +1,31 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** copy memory **/ +void * memcpy(void * restrict s1, const void * restrict s2, size_t n) +{ + char *dst = (char*)s1; + char *src = (char*)s2; + size_t i = 0; + + ASSERT_NONNULL(s1); + ASSERT_NONNULL(s2); + ASSERT_NOOVERLAP(s1, s2, n); + + for (i = 0; i < n; i++) { + dst[i] = src[i]; + } + + /* + RETURN_ALWAYS(ARGUMENT(s1)); + */ + return dst; +} + +/*** +copies ARGUMENT(n) bytes from the object at ARGUMENT(s2) to the object at +ARGUMENT(s1). +***/ +/* +STDC(1) +*/ diff --git a/src/string/memmove.c b/src/string/memmove.c new file mode 100644 index 00000000..33000e0e --- /dev/null +++ b/src/string/memmove.c @@ -0,0 +1,35 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** move memory **/ +void * memmove(void *s1, const void *s2, size_t n) +{ + ASSERT_NONNULL(s1); + ASSERT_NONNULL(s2); + + if (s1 < s2) { + return memcpy(s1, s2, n); + } + + /* reverse memcpy() */ + while (n > 0) { + ((char*)s1)[n] = ((char*)s2)[n]; + n--; + } + /* last byte */ + ((char*)s1)[n] = ((char*)s2)[n]; + + /* + RETURN_ALWAYS(ARGUMENT(s1)); + */ + return s1; +} + +/*** +copies ARGUMENT(n) bytes of memory from the object at +ARGUMENT(s2) to the object at ARGUMENT(s1). If ARGUMENT(s1) and ARGUMENT(s2) overlap, the memory +is copied so that the ARGUMENT(n) bytes are safely written to ARGUMENT(s1). +***/ +/* +STDC(1) +*/ diff --git a/src/string/memset.c b/src/string/memset.c new file mode 100644 index 00000000..1f3d14ff --- /dev/null +++ b/src/string/memset.c @@ -0,0 +1,28 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** fill memory **/ +void * memset(void *s, int c, size_t n) +{ + unsigned char *p = (unsigned char *)s; + size_t i = 0; + + ASSERT_NONNULL(s); + + for (i = 0; i < n; i++) { + p[i] = (unsigned char)c; + } + + /* + RETURN_ALWAYS(ARGUMENT(s)); + */ + return s; +} + +/*** +fills the first ARGUMENT(n) bytes of memory at ARGUMENT(s) with +the value ARGUMENT(c) (converted to an TYPE(unsigned char)). +***/ +/* +STDC(1) +*/ diff --git a/src/string/size_t.ref b/src/string/size_t.ref new file mode 100644 index 00000000..3c087e0b --- /dev/null +++ b/src/string/size_t.ref @@ -0,0 +1,3 @@ +#include <string.h> +REFERENCE(stddef/size_t.c) +STDC(1) diff --git a/src/string/strcat.c b/src/string/strcat.c new file mode 100644 index 00000000..9526cd59 --- /dev/null +++ b/src/string/strcat.c @@ -0,0 +1,24 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** concatenate strings **/ +char * strcat(char * restrict s1, const char * restrict s2) +{ + ASSERT_NONNULL(s1); + ASSERT_NONNULL(s2); + ASSERT_NOOVERLAP(s1, s2, strlen(s1) + strlen(s2)); + + /* + RETURN_ALWAYS(ARGUMENT(s1)); + */ + return strncat(s1, s2, strlen(s2)); +} + +/*** +appends a copy of the string at ARGUMENT(s2) to the end of +the string at ARGUMENT(s1). The first byte of ARGUMENT(s2) will overwrite the terminating +null character of ARGUMENT(s1). +***/ +/* +STDC(1) +*/ diff --git a/src/string/strchr.c b/src/string/strchr.c new file mode 100644 index 00000000..874db9be --- /dev/null +++ b/src/string/strchr.c @@ -0,0 +1,22 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** string search **/ +char * strchr(const char *s, int c) +{ + ASSERT_NONNULL(s); + + /* + RETURN_FAILURE(CONSTANT(NULL)); + RETURN_SUCCESS(a pointer to the located character); + */ + return (char*)memchr(s, (char)c, strlen(s)); +} + +/*** +searches the string ARGUMENT(s) for the first occurrence of +ARGUMENT(c) (converted to a TYPE(char)). +***/ +/* +STDC(1) +*/ diff --git a/src/string/strcmp.c b/src/string/strcmp.c new file mode 100644 index 00000000..ed089c77 --- /dev/null +++ b/src/string/strcmp.c @@ -0,0 +1,29 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** compare strings **/ +int strcmp(const char *s1, const char *s2) +{ + size_t n1 = 0; + size_t n2 = 0; + + ASSERT_NONNULL(s1); + ASSERT_NONNULL(s2); + + n1 = strlen(s1); + n2 = strlen(s2); + + /* + RETURN(NEGATIVE, ARGUMENT(s1) is less than ARGUMENT(s2)); + RETURN(ZERO, ARGUMENT(s1) is equal to ARGUMENT(s2)); + RETURN(POSITIVE, ARGUMENT(s1) is greater than ARGUMENT(s2)); + */ + return strncmp(s1, s2, n1 < n2 ? n1 : n2); +} + +/*** +compares the strings at ARGUMENT(s1) and ARGUMENT(s2). +***/ +/* +STDC(1) +*/ diff --git a/src/string/strcoll.c b/src/string/strcoll.c new file mode 100644 index 00000000..8707ba73 --- /dev/null +++ b/src/string/strcoll.c @@ -0,0 +1,44 @@ +#include <string.h> +#include "stdlib.h" +#include "nonstd/assert.h" + +/** collate strings **/ +int strcoll(const char *s1, const char *s2) +{ + char *x1 = NULL; + char *x2 = NULL; + int ret = 0; + + ASSERT_NONNULL(s1); + ASSERT_NONNULL(s2); + + x1 = malloc(strxfrm(x1, s1, 0)); + x2 = malloc(strxfrm(x2, s2, 0)); + + if (x1 && x2) { + strxfrm(x1, s1, 0); + strxfrm(x2, s2, 0); + ret = strcmp(x1, x2); + } + + free(x1); + free(x2); + + /* + RETURN(NEGATIVE, ARGUMENT(s1) collates before ARGUMENT(s2)); + RETURN(ZERO, ARGUMENT(s1) collates equal to ARGUMENT(s2)); + RETURN(POSITIVE, ARGUMENT(s1) collates after ARGUMENT(s2)); + */ + return ret; +} + +/*** +compares the collation values of the strings at ARGUMENT(s1) and ARGUMENT(s2). +***/ + +/* +LC_COLLATE +*/ +/* +STDC(1) +*/ diff --git a/src/string/strcpy.c b/src/string/strcpy.c new file mode 100644 index 00000000..cf4eeb21 --- /dev/null +++ b/src/string/strcpy.c @@ -0,0 +1,29 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** copy string **/ +char * strcpy(char * restrict s1, const char * restrict s2) +{ + char *p = s1; + + ASSERT_NONNULL(s1); + ASSERT_NONNULL(s2); + ASSERT_NOOVERLAP(s1, s2, strlen(s2)); + + while ((*s1++ = *s2++) != '\0') { + continue; + } + + /* + RETURN_ALWAYS(ARGUMENT(s1)); + */ + return p; +} + +/*** +copies the string at ARGUMENT(s2) to ARGUMENT(s1), up to and +including the terminating CHAR(\0). +***/ +/* +STDC(1) +*/ diff --git a/src/string/strcspn.c b/src/string/strcspn.c new file mode 100644 index 00000000..4bbdee2e --- /dev/null +++ b/src/string/strcspn.c @@ -0,0 +1,28 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** count non-matching characters **/ +size_t strcspn(const char *s1, const char *s2) +{ + size_t i = 0; + + ASSERT_NONNULL(s1); + ASSERT_NONNULL(s2); + + for (i = 0; s1[i] != '\0'; i++) { + if (strchr (s2, s1[i]) != NULL) { + break; + } + } + + return i; +} + +/*** +the number of characters that the beginning of +the string ARGUMENT(s1) that are not in the string ARGUMENT(s2). +***/ +/* + RETURN_ALWAYS(the number of non-matching characters); +STDC(1) +*/ diff --git a/src/string/strerror.c b/src/string/strerror.c new file mode 100644 index 00000000..055a11f7 --- /dev/null +++ b/src/string/strerror.c @@ -0,0 +1,31 @@ +#include <string.h> +#include "errno.h" +#include "stdio.h" +# define __LONGEST_STRERR 64 /* FIXME */ + +/** convert error number to string **/ +char * strerror(int errnum) +{ + static char errstr[__LONGEST_STRERR+1]; + + switch (errnum) { + #include "_strerror.h" + default: + sprintf(errstr, "unknown error [%d]", errnum); + break; + } + + /* + RETURN_ALWAYS(a pointer to the message string); + */ + return errstr; +} + +/*** +converts the error number ARGUMENT(errnum) to an error message +string. The string returned should not be modified, and may be overwritten by +subsequent calls. +***/ +/* +STDC(1) +*/ diff --git a/src/string/strlen.c b/src/string/strlen.c new file mode 100644 index 00000000..89ccbfcc --- /dev/null +++ b/src/string/strlen.c @@ -0,0 +1,25 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** find string length **/ +size_t strlen(const char *s) +{ + size_t i = 0; + + ASSERT_NONNULL(s); + + for (i = 0; s[i] != '\0'; i++) { + continue; + } + + return i; +} + +/*** +counts the number of bytes in the string ARGUMENT(s), not +including the terminating null character. +***/ +/* + RETURN_ALWAYS(the length of the string); +STDC(1) +*/ diff --git a/src/string/strncat.c b/src/string/strncat.c new file mode 100644 index 00000000..34800069 --- /dev/null +++ b/src/string/strncat.c @@ -0,0 +1,40 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** concatenate bounded string **/ +char * strncat(char * restrict s1, const char * restrict s2, size_t n) +{ + char *append = NULL; + size_t i; + + ASSERT_NONNULL(s1); + ASSERT_NONNULL(s2); + ASSERT_NOOVERLAP(s1, s2, strlen(s1) + strlen(s2)); + + append = s1 + strlen(s1); + + for (i = 0; i < n; i++) { + append[i] = s2[i]; + if (append[i] == '\0') { + break; + } + } + + if (append[i - 1] != '\0') { + append[i] = '\0'; + } + + return s1; +} + +/*** +appends a copy of the frist ARGUMENT(n) bytes of the string +at ARGUMENT(s2) to the end of the string at ARGUMENT(s1). The first byte of ARGUMENT(s2) will +overwrite the terminating null character of ARGUMENT(s1). No characters after the +first CHAR(\0) will be copied. The resulting string will always be null +terminated. +***/ +/* + RETURN_ALWAYS(ARGUMENT(s1)); +STDC(1) +*/ diff --git a/src/string/strncmp.c b/src/string/strncmp.c new file mode 100644 index 00000000..23c8104e --- /dev/null +++ b/src/string/strncmp.c @@ -0,0 +1,31 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** compare bound strings **/ +int strncmp(const char *s1, const char *s2, size_t n) +{ + ASSERT_NONNULL(s1); + ASSERT_NONNULL(s2); + + if (strlen(s1) < n) { + n = strlen(s1); + } + if (strlen(s2) < n) { + n = strlen(s2); + } + + /* + RETURN(NEGATIVE, ARGUMENT(s1) is less than ARGUMENT(s2)); + RETURN(ZERO, ARGUMENT(s1) is equal to ARGUMENT(s2)); + RETURN(POSITIVE, ARGUMENT(s1) is greater than ARGUMENT(s2)); + */ + return memcmp(s1, s2, n); +} + +/*** +compares up to the first ARGUMENT(n) bytes of the strings at ARGUMENT(s1) and +ARGUMENT(s2), or until the first CHAR(\0), whichever comes first. +***/ +/* +STDC(1) +*/ diff --git a/src/string/strncpy.c b/src/string/strncpy.c new file mode 100644 index 00000000..ee632d69 --- /dev/null +++ b/src/string/strncpy.c @@ -0,0 +1,34 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** copy bounded string **/ +char * strncpy(char * restrict s1, const char * restrict s2, size_t n) +{ + size_t i; + + ASSERT_NONNULL(s1); + ASSERT_NONNULL(s2); + ASSERT_NOOVERLAP(s1, s2, n); + + for (i = 0; i < n; i++) { + s1[i] = s2[i]; + if (s1[i] == '\0') { + memset(s1 + i, '\0', n - i); + break; + } + } + + return s1; +} + +/*** +copies up to ARGUMENT(n) bytes from the string at ARGUMENT(s2) +to ARGUMENT(s1). If a CHAR(\0) is encountered, null characters are appended to +ARGUMENT(s1) until ARGUMENT(n) bytes have been written. If no null characters are copied +in the first ARGUMENT(n) bytes of ARGUMENT(s2), the resulting string will not be null +terminated. +***/ +/* + RETURN_ALWAYS(ARGUMENT(s1)); +STDC(1) +*/ diff --git a/src/string/strpbrk.c b/src/string/strpbrk.c new file mode 100644 index 00000000..0b88b999 --- /dev/null +++ b/src/string/strpbrk.c @@ -0,0 +1,28 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** count matching characters **/ +char * strpbrk(const char *s1, const char *s2) +{ + size_t i; + + ASSERT_NONNULL(s1); + ASSERT_NONNULL(s2); + + for (i = 0; i < strlen (s1); i++) { + if (strchr(s2, s1[i]) != NULL) { + return (char*)s1 + i; + } + } + + return NULL; +} + +/*** +locates the first occurence in ARGUMENT(s1) of any character in ARGUMENT(s2). +***/ +/* + RETURN_FAILURE(CONSTANT(NULL)); + RETURN_SUCCESS(a pointer to the located character); +STDC(1) +*/ diff --git a/src/string/strrchr.c b/src/string/strrchr.c new file mode 100644 index 00000000..0427aa66 --- /dev/null +++ b/src/string/strrchr.c @@ -0,0 +1,30 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** search string from end **/ +char * strrchr(const char *s, int c) +{ + int i = 0; + + ASSERT_NONNULL(s); + + for (i = strlen(s) + 1; i >= 0; i--) { + if (s[i] == (char)c) { + return (char*)s + i; + } + } + + /* + RETURN_SUCCESS(a pointer to the found character); + RETURN_FAILURE(CONSTANT(NULL)); + */ + return NULL; +} + +/*** +finds the last occurence of ARGUMENT(c) (converted to TYPE(char)) in the +string ARGUMENT(s). +***/ +/* +STDC(1) +*/ diff --git a/src/string/strspn.c b/src/string/strspn.c new file mode 100644 index 00000000..e67461a5 --- /dev/null +++ b/src/string/strspn.c @@ -0,0 +1,28 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** count matching characters **/ +size_t strspn(const char *s1, const char *s2) +{ + size_t i = 0; + + ASSERT_NONNULL(s1); + ASSERT_NONNULL(s2); + + for (i = 0; i < strlen (s1); i++) { + if (strchr(s2, s1[i]) == NULL) { + break; + } + } + + return i; +} + +/*** +computes the length of the maximum initial segment of the ARGUMENT(s1) made +up of characters from ARGUMENT(s2). +***/ +/* + RETURN_ALWAYS(the number of matching characters); +STDC(1) +*/ diff --git a/src/string/strstr.c b/src/string/strstr.c new file mode 100644 index 00000000..898db1be --- /dev/null +++ b/src/string/strstr.c @@ -0,0 +1,43 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** search for substring **/ +char * strstr(const char *s1, const char *s2) +{ + size_t l1 = 0; + size_t l2 = 0; + char *p = (char*)s1; + + ASSERT_NONNULL(s1); + ASSERT_NONNULL(s2); + + l2 = strlen(s2); + if (l2 == 0) { + return p; + } + + l1 = strlen(s1); + + do { + p = memchr(p, *s2, l1); + if (p == NULL || strcmp(p + 1, s2 + 1) == 0) { + break; + } + p++; + } while (p < s1 + l2); + + /* + RETURN_FAILURE(CONSTANT(NULL)); + RETURN_SUCCESS(a pointer to the located string); + */ + return p; +} + +/*** +finds the first occurrence of the string ARGUMENT(s2) in the string +ARGUMENT(s1). Specifying the empty string for ARGUMENT(s2) matches the first +character of ARGUMENT(s1). +***/ +/* +STDC(1) +*/ diff --git a/src/string/strtok.c b/src/string/strtok.c new file mode 100644 index 00000000..9a7137cf --- /dev/null +++ b/src/string/strtok.c @@ -0,0 +1,34 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** split string into tokens **/ +char * strtok(char * restrict s1, const char * restrict s2) +{ + extern char * strtok_r(char *restr, const char *restrict, char **); + static char *current; + + /* TODO */ + ASSERT_NONNULL(s2); + + /* + RETURN(CONSTANT(NULL), there are no further tokens, only token separators); + RETURN(NONNULL, a pointer to the first character of the next token); + */ + + return strtok_r (s1, s2, ¤t); +} + +/*** +splits the string ARGUMENT(s1) into a series of tokens +delimited by characters from the string ARGUMENT(s2). + +The first call in a sequence specifies a string for ARGUMENT(s1). Further calls +specify CONSTANT(NULL) in order to continue from the end of the previous token. +The list of token separators in ARGUMENT(s2) may vary from call to call. + +When tokens are found, the next token separate character is replaced with a +CHAR(\0), terminating the token. +***/ +/* +STDC(1) +*/ diff --git a/src/string/strxfrm.c b/src/string/strxfrm.c new file mode 100644 index 00000000..b6ec62b6 --- /dev/null +++ b/src/string/strxfrm.c @@ -0,0 +1,32 @@ +#include <string.h> +#include "nonstd/assert.h" + +/** transform string **/ +size_t strxfrm(char * restrict s1, const char * restrict s2, size_t n) +{ + /* TODO */ + (void)s1; (void)s2; (void)n; + ASSERT_NONNULL(s2); + + if (n != 0) { + ASSERT_NONNULL(s1); + ASSERT_NOOVERLAP(s1, s2, n); + } + + return 0; +} + +/*** +transforms up to ARGUMENT(n) bytes of the string at ARGUMENT(s2), +placing the transformed string at ARGUMENT(s1). The transformed string is the +canonical form of the string used for collation purposes. If a CHAR(\0) is +transformed, no further characters are transformed. +***/ + +/* +UNDEFINED(ARGUMENT(n) is not ZERO and ARGUMENT(s1) is CONSTANT(NULL)) +*/ +/* + RETURN_ALWAYS(the length of the transformed string, not including the terminating CHAR(\0)); +STDC(1) +*/ |
