/*
* Copyright (c) 2012-2017 Richard Braun.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*
* Trivial, portable implementations.
*/
#include
#include
#include
#include
#include
#ifndef STRING_ARCH_MEMCPY
void *
memcpy(void *dest, const void *src, size_t n)
{
const char *src_ptr;
char *dest_ptr;
size_t i;
dest_ptr = dest;
src_ptr = src;
for (i = 0; i < n; i++) {
*dest_ptr = *src_ptr;
dest_ptr++;
src_ptr++;
}
return dest;
}
#endif /* STRING_ARCH_MEMCPY */
#ifndef STRING_ARCH_MEMMOVE
void *
memmove(void *dest, const void *src, size_t n)
{
const char *src_ptr;
char *dest_ptr;
size_t i;
if (dest <= src) {
dest_ptr = dest;
src_ptr = src;
for (i = 0; i < n; i++) {
*dest_ptr = *src_ptr;
dest_ptr++;
src_ptr++;
}
} else {
dest_ptr = dest + n - 1;
src_ptr = src + n - 1;
for (i = 0; i < n; i++) {
*dest_ptr = *src_ptr;
dest_ptr--;
src_ptr--;
}
}
return dest;
}
#endif /* STRING_ARCH_MEMMOVE */
#ifndef STRING_ARCH_MEMSET
void *
memset(void *s, int c, size_t n)
{
char *buffer;
size_t i;
buffer = s;
for (i = 0; i < n; i++) {
buffer[i] = c;
}
return s;
}
#endif /* STRING_ARCH_MEMSET */
#ifndef STRING_ARCH_MEMCMP
int
memcmp(const void *s1, const void *s2, size_t n)
{
const unsigned char *a1, *a2;
size_t i;
a1 = s1;
a2 = s2;
for (i = 0; i < n; i++) {
if (a1[i] != a2[i]) {
return (int)a1[i] - (int)a2[i];
}
}
return 0;
}
#endif /* STRING_ARCH_MEMCMP */
#ifndef STRING_ARCH_STRLEN
size_t
strlen(const char *s)
{
const char *start;
start = s;
while (*s != '\0') {
s++;
}
return (s - start);
}
#endif /* STRING_ARCH_STRLEN */
#ifndef STRING_ARCH_STRCPY
char *
strcpy(char *dest, const char *src)
{
char *tmp;
tmp = dest;
while ((*dest = *src) != '\0') {
dest++;
src++;
}
return tmp;
}
#endif /* STRING_ARCH_STRCPY */
size_t
strlcpy(char *dest, const char *src, size_t n)
{
size_t len;
len = strlen(src);
if (n == 0) {
goto out;
}
n = (len < n) ? len : n - 1;
memcpy(dest, src, n);
dest[n] = '\0';
out:
return len;
}
#ifndef STRING_ARCH_STRCMP
int
strcmp(const char *s1, const char *s2)
{
char c1, c2;
while ((c1 = *s1) == (c2 = *s2)) {
if (c1 == '\0') {
return 0;
}
s1++;
s2++;
}
/* See C11 7.24.4 Comparison functions */
return (int)(unsigned char)c1 - (int)(unsigned char)c2;
}
#endif /* STRING_ARCH_STRCMP */
#ifndef STRING_ARCH_STRNCMP
int
strncmp(const char *s1, const char *s2, size_t n)
{
char c1, c2;
if (unlikely(n == 0)) {
return 0;
}
while ((n != 0) && (c1 = *s1) == (c2 = *s2)) {
if (c1 == '\0') {
return 0;
}
n--;
s1++;
s2++;
}
/* See C11 7.24.4 Comparison functions */
return (int)(unsigned char)c1 - (int)(unsigned char)c2;
}
#endif /* STRING_ARCH_STRNCMP */
#ifndef STRING_ARCH_STRCHR
char *
strchr(const char *s, int c)
{
for (;;) {
if (*s == c) {
return (char *)s;
} else if (*s == '\0') {
return NULL;
}
s++;
}
}
#endif /* STRING_ARCH_STRCHR */
const char *
strerror(int error)
{
switch (error) {
case 0:
return "success";
case ENOMEM:
return "out of memory";
case EAGAIN:
return "resource temporarily unavailable";
case EINVAL:
return "invalid argument";
case EBUSY:
return "device or resource busy";
case EFAULT:
return "bad address";
case ENODEV:
return "no such device";
case EEXIST:
return "entry exists";
case EIO:
return "input/output error";
case ESRCH:
return "no such process";
case ETIMEDOUT:
return "timeout error";
case ENOENT:
return "no such file or directory";
default:
return "unknown error";
}
}