mirror of
https://gitee.com/Lamdonn/varch.git
synced 2025-12-06 08:46:42 +08:00
620 lines
10 KiB
C
620 lines
10 KiB
C
#include "vstring.h"
|
|
#include "vctype.h"
|
|
#include "vstdlib.h"
|
|
|
|
void *v_memcpy(void *dest, const void *src, size_t n)
|
|
{
|
|
char *dst = dest;
|
|
const char *s = src;
|
|
while (n--)
|
|
{
|
|
*dst++ = *s++;
|
|
}
|
|
return dest;
|
|
}
|
|
|
|
void *v_mempcpy(void *dest, const void *src, size_t n)
|
|
{
|
|
char *p1 = (char *)dest;
|
|
const char *p2 = (const char *)src;
|
|
size_t i;
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
p1[i] = p2[i];
|
|
}
|
|
return (void *)(p1 + i);
|
|
}
|
|
|
|
void *v_memmove(void *dest, const void *src, size_t n)
|
|
{
|
|
char *dst = dest;
|
|
const char *s = src;
|
|
if (dst <= s)
|
|
{
|
|
while (n--)
|
|
{
|
|
*dst++ = *s++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dst += n;
|
|
s += n;
|
|
while (n--)
|
|
{
|
|
*--dst = *--s;
|
|
}
|
|
}
|
|
return dest;
|
|
}
|
|
|
|
void *v_memccpy(void *dest, const void *src, int c, size_t n)
|
|
{
|
|
char *dst = dest;
|
|
const char *s = src;
|
|
while (n--)
|
|
{
|
|
*dst++ = *s;
|
|
if (*s++ == c)
|
|
{
|
|
return dst;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void *v_memset(void *s, int c, size_t n)
|
|
{
|
|
char *p = s;
|
|
while (n--)
|
|
{
|
|
*p++ = (char) c;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
int v_memcmp(const void *s1, const void *s2, size_t n)
|
|
{
|
|
const unsigned char *p1 = s1, *p2 = s2;
|
|
for (size_t i = 0; i < n; ++i, ++p1, ++p2)
|
|
{
|
|
if (*p1 != *p2)
|
|
{
|
|
return (*p1 < *p2) ? -1 : 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void *v_memchr(const void *s, int c, size_t n)
|
|
{
|
|
const unsigned char *p = s;
|
|
for (size_t i = 0; i < n; ++i, ++p)
|
|
{
|
|
if (*p == (unsigned char) c)
|
|
{
|
|
return (void *) p;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void *v_memrchr(const void *s, int c, size_t n)
|
|
{
|
|
const unsigned char *p = (const unsigned char *) s + n - 1;
|
|
for (; p >= (const unsigned char *) s; --p)
|
|
{
|
|
if (*p == (unsigned char) c)
|
|
{
|
|
return (void *) p;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void *v_memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen)
|
|
{
|
|
const char *p1 = (const char *)haystack;
|
|
const char *p2 = (const char *)needle;
|
|
size_t i;
|
|
if (needlelen == 0)
|
|
{
|
|
return (void *)p1;
|
|
}
|
|
if (haystacklen < needlelen)
|
|
{
|
|
return NULL;
|
|
}
|
|
for (i = 0; i <= haystacklen - needlelen; i++)
|
|
{
|
|
if (p1[i] == *p2 && v_memcmp(p1 + i, p2, needlelen) == 0)
|
|
{
|
|
return (void *)(p1 + i);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void *v_memfrob(void *s, size_t n)
|
|
{
|
|
unsigned char *p = (unsigned char *)s;
|
|
for (size_t i = 0; i < n; i++)
|
|
{
|
|
p[i] ^= 42;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
char *v_strcpy(char *dest, const char *src)
|
|
{
|
|
char *p = dest;
|
|
while (*src)
|
|
{
|
|
*p++ = *src++;
|
|
}
|
|
*p = '\0';
|
|
return dest;
|
|
}
|
|
|
|
char *v_strncpy(char *dest, const char *src, size_t n)
|
|
{
|
|
char *p = dest;
|
|
size_t i = 0;
|
|
while (i < n && *src)
|
|
{
|
|
*p++ = *src++;
|
|
++i;
|
|
}
|
|
while (i < n)
|
|
{
|
|
*p++ = '\0';
|
|
++i;
|
|
}
|
|
return dest;
|
|
}
|
|
|
|
size_t v_strlen(const char *s)
|
|
{
|
|
const char *p = s;
|
|
while (*p)
|
|
{
|
|
++p;
|
|
}
|
|
return p - s;
|
|
}
|
|
|
|
size_t v_strnlen(const char *s, size_t n)
|
|
{
|
|
const char *p = s;
|
|
size_t i;
|
|
for (i = 0; i < n && *p != '\0'; i++, p++);
|
|
return i;
|
|
}
|
|
|
|
char *v_strcat(char *dest, const char *src)
|
|
{
|
|
char *p = dest + v_strlen(dest);
|
|
while (*src)
|
|
{
|
|
*p++ = *src++;
|
|
}
|
|
*p = '\0';
|
|
return dest;
|
|
}
|
|
|
|
int v_strcmp(const char *s1, const char *s2)
|
|
{
|
|
while (*s1 && *s1 == *s2)
|
|
{
|
|
++s1;
|
|
++s2;
|
|
}
|
|
return *s1 - *s2;
|
|
}
|
|
|
|
int v_strncmp(const char *s1, const char *s2, size_t n)
|
|
{
|
|
size_t i = 0;
|
|
while (i < n && *s1 && *s1 == *s2)
|
|
{
|
|
++s1;
|
|
++s2;
|
|
++i;
|
|
}
|
|
if (i == n)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return *s1 - *s2;
|
|
}
|
|
}
|
|
|
|
static int v_strcoll_helper(char c1, char c2)
|
|
{
|
|
if (c1 < c2)
|
|
{
|
|
return -1;
|
|
}
|
|
else if (c1 > c2)
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int v_strcoll(const char *s1, const char *s2)
|
|
{
|
|
while (*s1 && *s1 == *s2)
|
|
{
|
|
++s1;
|
|
++s2;
|
|
}
|
|
return v_strcoll_helper(*s1, *s2);
|
|
}
|
|
|
|
size_t v_strxfrm(char *dest, const char *src, size_t n)
|
|
{
|
|
size_t i = 0;
|
|
while (*src && i < n)
|
|
{
|
|
*dest = *src;
|
|
++dest;
|
|
++src;
|
|
++i;
|
|
}
|
|
if (i == n)
|
|
{
|
|
*dest = '\0';
|
|
return n;
|
|
}
|
|
else
|
|
{
|
|
*dest = '\0';
|
|
return i;
|
|
}
|
|
}
|
|
|
|
char *v_strdup(const char *s)
|
|
{
|
|
size_t len = v_strlen(s) + 1;
|
|
char *p = v_malloc(len);
|
|
if (p == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
return (char *) v_memcpy(p, s, len);
|
|
}
|
|
|
|
char *v_strndup(const char *str, size_t n)
|
|
{
|
|
size_t len = v_strlen(str);
|
|
if (n < len)
|
|
{
|
|
len = n;
|
|
}
|
|
char *new_str = (char *) v_malloc(len + 1);
|
|
if (new_str == NULL) {
|
|
return NULL;
|
|
}
|
|
v_memcpy(new_str, str, len);
|
|
new_str[len] = '\0';
|
|
return new_str;
|
|
}
|
|
|
|
char *v_strchr(const char *str, int ch)
|
|
{
|
|
while (*str != '\0' && *str != ch)
|
|
{
|
|
str++;
|
|
}
|
|
if (*str == ch)
|
|
{
|
|
return (char *) str;
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
char *v_strrchr(const char *str, int ch)
|
|
{
|
|
const char *last = NULL;
|
|
while (*str != '\0')
|
|
{
|
|
if (*str == ch)
|
|
{
|
|
last = str;
|
|
}
|
|
str++;
|
|
}
|
|
if (*str == ch)
|
|
{
|
|
return (char *) str;
|
|
}
|
|
else
|
|
{
|
|
return (char *) last;
|
|
}
|
|
}
|
|
|
|
char *v_strchrnul(const char *str, int ch)
|
|
{
|
|
while (*str != '\0' && *str != ch)
|
|
{
|
|
str++;
|
|
}
|
|
return (char *) str;
|
|
}
|
|
|
|
size_t v_strcspn(const char *str, const char *charset)
|
|
{
|
|
size_t len = 0;
|
|
while (*str != '\0')
|
|
{
|
|
const char *p = charset;
|
|
while (*p != '\0')
|
|
{
|
|
if (*str == *p)
|
|
{
|
|
return len;
|
|
}
|
|
p++;
|
|
}
|
|
str++;
|
|
len++;
|
|
}
|
|
return len;
|
|
}
|
|
|
|
char *v_strpbrk(const char *str, const char *charset)
|
|
{
|
|
while (*str != '\0')
|
|
{
|
|
const char *p = charset;
|
|
while (*p != '\0')
|
|
{
|
|
if (*str == *p)
|
|
{
|
|
return (char *) str;
|
|
}
|
|
p++;
|
|
}
|
|
str++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
char *v_strstr(const char *str, const char *substr)
|
|
{
|
|
if (*substr == '\0')
|
|
{
|
|
return (char *) str;
|
|
}
|
|
while (*str != '\0')
|
|
{
|
|
const char *p = str;
|
|
const char *q = substr;
|
|
while (*p != '\0' && *q != '\0' && *p == *q)
|
|
{
|
|
p++;
|
|
q++;
|
|
}
|
|
if (*q == '\0')
|
|
{
|
|
return (char *) str;
|
|
}
|
|
str++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
char *v_strrstr(const char *str, const char *substr)
|
|
{
|
|
size_t len = v_strlen(substr);
|
|
if (len == 0) {
|
|
return (char *) (str + v_strlen(str));
|
|
}
|
|
const char *end = str + v_strlen(str) - len;
|
|
for (const char *p = end; p >= str; p--)
|
|
{
|
|
if (v_strncmp(p, substr, len) == 0)
|
|
{
|
|
return (char *) p;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
char *v_strtok(char *str, const char *delim)
|
|
{
|
|
static char *last_str = NULL;
|
|
static const char *last_delim = NULL;
|
|
char *ret = NULL;
|
|
if (str != NULL)
|
|
{
|
|
last_str = str;
|
|
}
|
|
else if (last_str == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
if (delim != NULL)
|
|
{
|
|
last_delim = delim;
|
|
}
|
|
else if (last_delim == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
ret = last_str;
|
|
while (*last_str != '\0')
|
|
{
|
|
const char *p = last_delim;
|
|
while (*p != '\0' && *p != *last_str)
|
|
{
|
|
p++;
|
|
}
|
|
if (*p != '\0')
|
|
{
|
|
*last_str = '\0';
|
|
last_str++;
|
|
break;
|
|
}
|
|
last_str++;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
char *v_strtok_r(char *str, const char *delim, char **saveptr)
|
|
{
|
|
char *last_str = NULL;
|
|
const char *last_delim = NULL;
|
|
char *ret = NULL;
|
|
if (str != NULL)
|
|
{
|
|
last_str = str;
|
|
}
|
|
else if (*saveptr == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
last_str = *saveptr;
|
|
}
|
|
if (delim != NULL)
|
|
{
|
|
last_delim = delim;
|
|
}
|
|
else if (*saveptr == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
last_delim = *saveptr;
|
|
}
|
|
ret = last_str;
|
|
while (*last_str != '\0')
|
|
{
|
|
const char *p = last_delim;
|
|
while (*p != '\0' && *p != *last_str)
|
|
{
|
|
p++;
|
|
}
|
|
if (*p != '\0')
|
|
{
|
|
*last_str = '\0';
|
|
last_str++;
|
|
break;
|
|
}
|
|
last_str++;
|
|
}
|
|
*saveptr = last_str;
|
|
return ret;
|
|
}
|
|
|
|
char *v_strcasestr(const char *haystack, const char *needle)
|
|
{
|
|
const char *p1 = haystack;
|
|
while (*p1 != '\0')
|
|
{
|
|
const char *p2 = needle;
|
|
const char *p3 = p1;
|
|
while (*p2 != '\0' && v_tolower(*p2) == v_tolower(*p3))
|
|
{
|
|
p2++;
|
|
p3++;
|
|
}
|
|
if (*p2 == '\0')
|
|
{
|
|
return (char *)p1;
|
|
}
|
|
p1++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
char *v_strsep(char **stringp, const char *delim)
|
|
{
|
|
char *p, *start;
|
|
start = *stringp;
|
|
p = (start != NULL) ? v_strpbrk(start, delim) : NULL;
|
|
if (p == NULL)
|
|
{
|
|
*stringp = NULL;
|
|
}
|
|
else
|
|
{
|
|
*p = '\0';
|
|
*stringp = p + 1;
|
|
}
|
|
return start;
|
|
}
|
|
|
|
char *v_stpcpy(char *dest, const char *src)
|
|
{
|
|
while ((*dest++ = *src++));
|
|
return dest - 1;
|
|
}
|
|
|
|
char *v_stpncpy(char *dest, const char *src, size_t n)
|
|
{
|
|
char *p = dest;
|
|
while (n-- && *src)
|
|
{
|
|
*p++ = *src++;
|
|
}
|
|
while (n--)
|
|
{
|
|
*p++ = '\0';
|
|
}
|
|
return p;
|
|
}
|
|
|
|
int v_strverscmp(const char *s1, const char *s2)
|
|
{
|
|
const unsigned char *p1 = (const unsigned char *)s1;
|
|
const unsigned char *p2 = (const unsigned char *)s2;
|
|
int num1 = 0, num2 = 0;
|
|
while (*p1 || *p2)
|
|
{
|
|
while (v_isdigit(*p1))
|
|
{
|
|
num1 = num1 * 10 + (*p1 - '0');
|
|
p1++;
|
|
}
|
|
while (v_isdigit(*p2))
|
|
{
|
|
num2 = num2 * 10 + (*p2 - '0');
|
|
p2++;
|
|
}
|
|
if (num1 != num2)
|
|
{
|
|
return num1 > num2 ? 1 : -1;
|
|
}
|
|
if (*p1 != *p2)
|
|
{
|
|
return *p1 > *p2 ? 1 : -1;
|
|
}
|
|
if (*p1)
|
|
{
|
|
p1++;
|
|
}
|
|
if (*p2)
|
|
{
|
|
p2++;
|
|
}
|
|
num1 = num2 = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|