296 lines
7.3 KiB
C
296 lines
7.3 KiB
C
#include <string.h>
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <ctype.h>
|
|
|
|
void *memset(void *d, int c, size_t n)
|
|
{
|
|
unsigned char *p = (unsigned char *)d;
|
|
while (n--) *p++ = (unsigned char)c;
|
|
return d;
|
|
}
|
|
|
|
void *memcpy(void *d, const void *s, size_t n)
|
|
{
|
|
unsigned char *dd = (unsigned char *)d;
|
|
const unsigned char *ss = (const unsigned char *)s;
|
|
while (n--) *dd++ = *ss++;
|
|
return d;
|
|
}
|
|
|
|
void *memmove(void *d, const void *s, size_t n)
|
|
{
|
|
unsigned char *dd = (unsigned char *)d;
|
|
const unsigned char *ss = (const unsigned char *)s;
|
|
if (dd < ss) { while (n--) *dd++ = *ss++; }
|
|
else { dd += n; ss += n; while (n--) *--dd = *--ss; }
|
|
return d;
|
|
}
|
|
|
|
int memcmp(const void *a, const void *b, size_t n)
|
|
{
|
|
const unsigned char *x = (const unsigned char *)a;
|
|
const unsigned char *y = (const unsigned char *)b;
|
|
for (size_t i = 0; i < n; i++)
|
|
if (x[i] != y[i]) return x[i] - y[i];
|
|
return 0;
|
|
}
|
|
|
|
void *memchr(const void *s, int c, size_t n)
|
|
{
|
|
const unsigned char *p = (const unsigned char *)s;
|
|
while (n--) { if (*p == (unsigned char)c) return (void *)p; p++; }
|
|
return NULL;
|
|
}
|
|
|
|
void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen)
|
|
{
|
|
if (nlen == 0) return (void *)haystack;
|
|
if (hlen < nlen) return NULL;
|
|
const unsigned char *h = (const unsigned char *)haystack;
|
|
const unsigned char *n = (const unsigned char *)needle;
|
|
size_t last = hlen - nlen;
|
|
for (size_t i = 0; i <= last; i++) {
|
|
if (h[i] == n[0] && memcmp(h + i, n, nlen) == 0)
|
|
return (void *)(h + i);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
size_t strlen(const char *s) { size_t n = 0; while (s[n]) n++; return n; }
|
|
|
|
size_t strnlen(const char *s, size_t max)
|
|
{
|
|
size_t n = 0;
|
|
while (n < max && s[n]) n++;
|
|
return n;
|
|
}
|
|
|
|
int strcmp(const char *a, const char *b)
|
|
{
|
|
while (*a && *a == *b) { a++; b++; }
|
|
return (unsigned char)*a - (unsigned char)*b;
|
|
}
|
|
|
|
int strncmp(const char *a, const char *b, size_t n)
|
|
{
|
|
for (size_t i = 0; i < n; i++) {
|
|
if (a[i] != b[i]) return (unsigned char)a[i] - (unsigned char)b[i];
|
|
if (!a[i]) return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int strcasecmp(const char *a, const char *b)
|
|
{
|
|
while (*a && tolower((unsigned char)*a) == tolower((unsigned char)*b)) {
|
|
a++; b++;
|
|
}
|
|
return tolower((unsigned char)*a) - tolower((unsigned char)*b);
|
|
}
|
|
|
|
int strncasecmp(const char *a, const char *b, size_t n)
|
|
{
|
|
for (size_t i = 0; i < n; i++) {
|
|
int ca = tolower((unsigned char)a[i]);
|
|
int cb = tolower((unsigned char)b[i]);
|
|
if (ca != cb) return ca - cb;
|
|
if (!a[i]) return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
char *strcpy(char *d, const char *s)
|
|
{
|
|
char *r = d;
|
|
while ((*d++ = *s++)) { }
|
|
return r;
|
|
}
|
|
|
|
char *strncpy(char *d, const char *s, size_t n)
|
|
{
|
|
size_t i;
|
|
for (i = 0; i < n && s[i]; i++) d[i] = s[i];
|
|
for (; i < n; i++) d[i] = 0;
|
|
return d;
|
|
}
|
|
|
|
char *strcat(char *d, const char *s)
|
|
{
|
|
char *r = d;
|
|
while (*d) d++;
|
|
while ((*d++ = *s++)) { }
|
|
return r;
|
|
}
|
|
|
|
char *strncat(char *d, const char *s, size_t n)
|
|
{
|
|
char *r = d;
|
|
while (*d) d++;
|
|
for (size_t i = 0; i < n && s[i]; i++) *d++ = s[i];
|
|
*d = '\0';
|
|
return r;
|
|
}
|
|
|
|
char *strchr(const char *s, int c)
|
|
{
|
|
for (; *s; s++) if (*s == (char)c) return (char *)s;
|
|
return c == 0 ? (char *)s : NULL;
|
|
}
|
|
|
|
char *strrchr(const char *s, int c)
|
|
{
|
|
const char *r = NULL;
|
|
for (; *s; s++) if (*s == (char)c) r = s;
|
|
return (char *)(c == 0 ? s : r);
|
|
}
|
|
|
|
char *strstr(const char *h, const char *n)
|
|
{
|
|
if (!*n) return (char *)h;
|
|
for (; *h; h++) {
|
|
const char *a = h, *b = n;
|
|
while (*a && *b && *a == *b) { a++; b++; }
|
|
if (!*b) return (char *)h;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
size_t strspn(const char *s, const char *accept)
|
|
{
|
|
size_t n = 0;
|
|
while (s[n]) {
|
|
int found = 0;
|
|
for (size_t i = 0; accept[i]; i++)
|
|
if (s[n] == accept[i]) { found = 1; break; }
|
|
if (!found) break;
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
size_t strcspn(const char *s, const char *reject)
|
|
{
|
|
size_t n = 0;
|
|
while (s[n]) {
|
|
for (size_t i = 0; reject[i]; i++)
|
|
if (s[n] == reject[i]) return n;
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
char *strpbrk(const char *s, const char *accept)
|
|
{
|
|
while (*s) {
|
|
for (const char *a = accept; *a; a++)
|
|
if (*s == *a) return (char *)s;
|
|
s++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
char *strdup(const char *s)
|
|
{
|
|
size_t n = strlen(s) + 1;
|
|
char *p = (char *)malloc(n);
|
|
if (!p) return NULL;
|
|
memcpy(p, s, n);
|
|
return p;
|
|
}
|
|
|
|
char *strndup(const char *s, size_t n)
|
|
{
|
|
size_t len = strnlen(s, n);
|
|
char *p = (char *)malloc(len + 1);
|
|
if (!p) return NULL;
|
|
memcpy(p, s, len);
|
|
p[len] = '\0';
|
|
return p;
|
|
}
|
|
|
|
char *strtok_r(char *str, const char *delim, char **saveptr)
|
|
{
|
|
char *s = str ? str : (saveptr ? *saveptr : NULL);
|
|
if (!s || !delim) return NULL;
|
|
|
|
while (*s) {
|
|
const char *d;
|
|
for (d = delim; *d; d++) if (*s == *d) break;
|
|
if (!*d) break;
|
|
s++;
|
|
}
|
|
if (!*s) {
|
|
if (saveptr) *saveptr = NULL;
|
|
return NULL;
|
|
}
|
|
char *tok = s;
|
|
|
|
while (*s) {
|
|
const char *d;
|
|
for (d = delim; *d; d++) if (*s == *d) break;
|
|
if (*d) {
|
|
*s = '\0';
|
|
if (saveptr) *saveptr = s + 1;
|
|
return tok;
|
|
}
|
|
s++;
|
|
}
|
|
if (saveptr) *saveptr = NULL;
|
|
return tok;
|
|
}
|
|
|
|
static char *__strtok_save = NULL;
|
|
char *strtok(char *str, const char *delim)
|
|
{
|
|
return strtok_r(str, delim, &__strtok_save);
|
|
}
|
|
|
|
char *strerror(int err)
|
|
{
|
|
switch (err) {
|
|
case 0: return "Success";
|
|
case EPERM: return "Operation not permitted";
|
|
case ENOENT: return "No such file or directory";
|
|
case ESRCH: return "No such process";
|
|
case EINTR: return "Interrupted system call";
|
|
case EIO: return "Input/output error";
|
|
case EBADF: return "Bad file descriptor";
|
|
case ECHILD: return "No child processes";
|
|
case EAGAIN: return "Resource temporarily unavailable";
|
|
case ENOMEM: return "Cannot allocate memory";
|
|
case EACCES: return "Permission denied";
|
|
case EFAULT: return "Bad address";
|
|
case EBUSY: return "Device or resource busy";
|
|
case EEXIST: return "File exists";
|
|
case ENODEV: return "No such device";
|
|
case ENOTDIR: return "Not a directory";
|
|
case EISDIR: return "Is a directory";
|
|
case EINVAL: return "Invalid argument";
|
|
case EMFILE: return "Too many open files";
|
|
case ENOTTY: return "Inappropriate ioctl for device";
|
|
case ENOSPC: return "No space left on device";
|
|
case EPIPE: return "Broken pipe";
|
|
case ENOSYS: return "Function not implemented";
|
|
default: return "Unknown error";
|
|
}
|
|
}
|
|
|
|
char *strsignal(int sig)
|
|
{
|
|
switch (sig) {
|
|
case 1: return "Hangup";
|
|
case 2: return "Interrupt";
|
|
case 3: return "Quit";
|
|
case 4: return "Illegal instruction";
|
|
case 6: return "Aborted";
|
|
case 8: return "Floating point exception";
|
|
case 9: return "Killed";
|
|
case 11: return "Segmentation fault";
|
|
case 13: return "Broken pipe";
|
|
case 14: return "Alarm clock";
|
|
case 15: return "Terminated";
|
|
default: return "Unknown signal";
|
|
}
|
|
} |