Skip to content

Commit 4353f5d

Browse files
Missing string.h functionality.
1 parent 5d078cb commit 4353f5d

14 files changed

+370
-0
lines changed

emcc

+12
Original file line numberDiff line numberDiff line change
@@ -1507,7 +1507,9 @@ try:
15071507
'iswspace_l.c',
15081508
'iswupper_l.c',
15091509
'iswxdigit_l.c',
1510+
'strcasecmp_l.c',
15101511
'strfmon.c',
1512+
'strncasecmp_l.c',
15111513
'strxfrm.c',
15121514
'towctrans_l.c',
15131515
'towlower_l.c',
@@ -1556,6 +1558,16 @@ try:
15561558
'gcvt.c',
15571559
]],
15581560
['string', [
1561+
'memccpy.c',
1562+
'memmem.c',
1563+
'mempcpy.c',
1564+
'memrchr.c',
1565+
'strcasestr.c',
1566+
'strchrnul.c',
1567+
'strlcat.c',
1568+
'strlcpy.c',
1569+
'strsep.c',
1570+
'strverscmp.c',
15591571
'wcpcpy.c',
15601572
'wcpncpy.c',
15611573
'wcscasecmp.c',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <strings.h>
2+
#include <ctype.h>
3+
4+
int strcasecmp_l(const char *l, const char *r, locale_t loc)
5+
{
6+
return strcasecmp(l, r);
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <strings.h>
2+
#include <locale.h>
3+
4+
int strncasecmp_l(const char *l, const char *r, size_t n, locale_t loc)
5+
{
6+
return strncasecmp(l, r, n);
7+
}
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include <string.h>
2+
#include <stdlib.h>
3+
#include <stdint.h>
4+
#include <limits.h>
5+
6+
#define ALIGN (sizeof(size_t)-1)
7+
#define ONES ((size_t)-1/UCHAR_MAX)
8+
#define HIGHS (ONES * (UCHAR_MAX/2+1))
9+
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
10+
11+
void *memccpy(void *restrict dest, const void *restrict src, int c, size_t n)
12+
{
13+
unsigned char *d = dest;
14+
const unsigned char *s = src;
15+
size_t *wd, k;
16+
const size_t *ws;
17+
18+
c = (unsigned char)c;
19+
if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
20+
for (; ((uintptr_t)s & ALIGN) && n && (*d=*s)!=c; n--, s++, d++);
21+
if ((uintptr_t)s & ALIGN) goto tail;
22+
k = ONES * c;
23+
wd=(void *)d; ws=(const void *)s;
24+
for (; n>=sizeof(size_t) && !HASZERO(*ws^k);
25+
n-=sizeof(size_t), ws++, wd++) *wd = *ws;
26+
d=(void *)wd; s=(const void *)ws;
27+
}
28+
for (; n && (*d=*s)!=c; n--, s++, d++);
29+
tail:
30+
if (*s==c) return d+1;
31+
return 0;
32+
}
+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#define _GNU_SOURCE
2+
#include <string.h>
3+
#include <stdlib.h>
4+
#include <stdint.h>
5+
6+
static char *twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
7+
{
8+
uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
9+
for (h++, k--; k; k--, hw = hw<<8 | *++h)
10+
if (hw == nw) return (char *)h-1;
11+
return 0;
12+
}
13+
14+
static char *threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
15+
{
16+
uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8;
17+
uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8;
18+
for (h+=2, k-=2; k; k--, hw = (hw|*++h)<<8)
19+
if (hw == nw) return (char *)h-2;
20+
return 0;
21+
}
22+
23+
static char *fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
24+
{
25+
uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
26+
uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
27+
for (h+=3, k-=3; k; k--, hw = hw<<8 | *++h)
28+
if (hw == nw) return (char *)h-3;
29+
return 0;
30+
}
31+
32+
#define MAX(a,b) ((a)>(b)?(a):(b))
33+
#define MIN(a,b) ((a)<(b)?(a):(b))
34+
35+
#define BITOP(a,b,op) \
36+
((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
37+
38+
static char *twoway_memmem(const unsigned char *h, const unsigned char *z, const unsigned char *n, size_t l)
39+
{
40+
size_t i, ip, jp, k, p, ms, p0, mem, mem0;
41+
size_t byteset[32 / sizeof(size_t)] = { 0 };
42+
size_t shift[256];
43+
44+
/* Computing length of needle and fill shift table */
45+
for (i=0; i<l; i++)
46+
BITOP(byteset, n[i], |=), shift[n[i]] = i+1;
47+
48+
/* Compute maximal suffix */
49+
ip = -1; jp = 0; k = p = 1;
50+
while (jp+k<l) {
51+
if (n[ip+k] == n[jp+k]) {
52+
if (k == p) {
53+
jp += p;
54+
k = 1;
55+
} else k++;
56+
} else if (n[ip+k] > n[jp+k]) {
57+
jp += k;
58+
k = 1;
59+
p = jp - ip;
60+
} else {
61+
ip = jp++;
62+
k = p = 1;
63+
}
64+
}
65+
ms = ip;
66+
p0 = p;
67+
68+
/* And with the opposite comparison */
69+
ip = -1; jp = 0; k = p = 1;
70+
while (jp+k<l) {
71+
if (n[ip+k] == n[jp+k]) {
72+
if (k == p) {
73+
jp += p;
74+
k = 1;
75+
} else k++;
76+
} else if (n[ip+k] < n[jp+k]) {
77+
jp += k;
78+
k = 1;
79+
p = jp - ip;
80+
} else {
81+
ip = jp++;
82+
k = p = 1;
83+
}
84+
}
85+
if (ip+1 > ms+1) ms = ip;
86+
else p = p0;
87+
88+
/* Periodic needle? */
89+
if (memcmp(n, n+p, ms+1)) {
90+
mem0 = 0;
91+
p = MAX(ms, l-ms-1) + 1;
92+
} else mem0 = l-p;
93+
mem = 0;
94+
95+
/* Search loop */
96+
for (;;) {
97+
/* If remainder of haystack is shorter than needle, done */
98+
if (z-h < l) return 0;
99+
100+
/* Check last byte first; advance by shift on mismatch */
101+
if (BITOP(byteset, h[l-1], &)) {
102+
k = l-shift[h[l-1]];
103+
if (k) {
104+
if (mem0 && mem && k < p) k = l-p;
105+
h += k;
106+
mem = 0;
107+
continue;
108+
}
109+
} else {
110+
h += l;
111+
mem = 0;
112+
continue;
113+
}
114+
115+
/* Compare right half */
116+
for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
117+
if (n[k]) {
118+
h += k-ms;
119+
mem = 0;
120+
continue;
121+
}
122+
/* Compare left half */
123+
for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
124+
if (k == mem) return (char *)h;
125+
h += p;
126+
mem = mem0;
127+
}
128+
}
129+
130+
void *memmem(const void *h0, size_t k, const void *n0, size_t l)
131+
{
132+
const unsigned char *h = h0, *n = n0;
133+
134+
/* Return immediately on empty needle */
135+
if (!l) return (void *)h;
136+
137+
/* Return immediately when needle is longer than haystack */
138+
if (k<l) return 0;
139+
140+
/* Use faster algorithms for short needles */
141+
h = memchr(h0, *n, k);
142+
if (!h || l==1) return (void *)h;
143+
if (l==2) return twobyte_memmem(h, k, n);
144+
if (l==3) return threebyte_memmem(h, k, n);
145+
if (l==4) return fourbyte_memmem(h, k, n);
146+
147+
return twoway_memmem(h, h+k, n, l);
148+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <string.h>
2+
3+
void *mempcpy(void *dest, const void *src, size_t n)
4+
{
5+
return (char *)memcpy(dest, src, n) + n;
6+
}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <string.h>
2+
#include "libc.h"
3+
4+
void *__memrchr(const void *m, int c, size_t n)
5+
{
6+
const unsigned char *s = m;
7+
c = (unsigned char)c;
8+
while (n--) if (s[n]==c) return (void *)(s+n);
9+
return 0;
10+
}
11+
12+
weak_alias(__memrchr, memrchr);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#define _GNU_SOURCE
2+
#include <string.h>
3+
4+
char *strcasestr(const char *h, const char *n)
5+
{
6+
size_t l = strlen(n);
7+
for (; *h; h++) if (!strncasecmp(h, n, l)) return (char *)h;
8+
return 0;
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <string.h>
2+
#include <stdlib.h>
3+
#include <stdint.h>
4+
#include <limits.h>
5+
#include "libc.h"
6+
7+
#define ALIGN (sizeof(size_t))
8+
#define ONES ((size_t)-1/UCHAR_MAX)
9+
#define HIGHS (ONES * (UCHAR_MAX/2+1))
10+
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
11+
12+
char *__strchrnul(const char *s, int c)
13+
{
14+
size_t *w, k;
15+
16+
c = (unsigned char)c;
17+
if (!c) return (char *)s + strlen(s);
18+
19+
for (; (uintptr_t)s % ALIGN; s++)
20+
if (!*s || *(unsigned char *)s == c) return (char *)s;
21+
k = ONES * c;
22+
for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++);
23+
for (s = (void *)w; *s && *(unsigned char *)s != c; s++);
24+
return (char *)s;
25+
}
26+
27+
weak_alias(__strchrnul, strchrnul);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#define _BSD_SOURCE
2+
#include <string.h>
3+
4+
size_t strlcat(char *d, const char *s, size_t n)
5+
{
6+
size_t l = strnlen(d, n);
7+
if (l == n) return l + strlen(s);
8+
return l + strlcpy(d+l, s, n-l);
9+
}
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include <string.h>
2+
#include <stdlib.h>
3+
#include <stdint.h>
4+
#include <limits.h>
5+
#include "libc.h"
6+
7+
#define ALIGN (sizeof(size_t)-1)
8+
#define ONES ((size_t)-1/UCHAR_MAX)
9+
#define HIGHS (ONES * (UCHAR_MAX/2+1))
10+
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
11+
12+
size_t strlcpy(char *d, const char *s, size_t n)
13+
{
14+
char *d0 = d;
15+
size_t *wd;
16+
const size_t *ws;
17+
18+
if (!n--) goto finish;
19+
if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
20+
for (; ((uintptr_t)s & ALIGN) && n && (*d=*s); n--, s++, d++);
21+
if (n && *s) {
22+
wd=(void *)d; ws=(const void *)s;
23+
for (; n>=sizeof(size_t) && !HASZERO(*ws);
24+
n-=sizeof(size_t), ws++, wd++) *wd = *ws;
25+
d=(void *)wd; s=(const void *)ws;
26+
}
27+
}
28+
for (; n && (*d=*s); n--, s++, d++);
29+
*d = 0;
30+
finish:
31+
return d-d0 + strlen(s);
32+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#define _GNU_SOURCE
2+
#include <string.h>
3+
4+
char *strsep(char **str, const char *sep)
5+
{
6+
char *s = *str, *end;
7+
if (!s) return NULL;
8+
end = s + strcspn(s, sep);
9+
if (*end) *end++ = 0;
10+
else end = 0;
11+
*str = end;
12+
return s;
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#define _GNU_SOURCE
2+
#include <ctype.h>
3+
#include <string.h>
4+
#include <sys/types.h>
5+
6+
int strverscmp(const char *l, const char *r)
7+
{
8+
int haszero=1;
9+
while (*l==*r) {
10+
if (!*l) return 0;
11+
12+
if (*l=='0') {
13+
if (haszero==1) {
14+
haszero=0;
15+
}
16+
} else if (isdigit(*l)) {
17+
if (haszero==1) {
18+
haszero=2;
19+
}
20+
} else {
21+
haszero=1;
22+
}
23+
l++; r++;
24+
}
25+
if (haszero==1 && (*l=='0' || *r=='0')) {
26+
haszero=0;
27+
}
28+
if ((isdigit(*l) && isdigit(*r) ) && haszero) {
29+
size_t lenl=0, lenr=0;
30+
while (isdigit(l[lenl]) ) lenl++;
31+
while (isdigit(r[lenr]) ) lenr++;
32+
if (lenl==lenr) {
33+
return (*l - *r);
34+
} else if (lenl>lenr) {
35+
return 1;
36+
} else {
37+
return -1;
38+
}
39+
} else {
40+
return (*l - *r);
41+
}
42+
}

0 commit comments

Comments
 (0)