Skip to content

Commit 08ea8b3

Browse files
ZERICO2005mateoconlechuga
authored andcommitted
added strsep
1 parent b8bd9e5 commit 08ea8b3

5 files changed

Lines changed: 175 additions & 7 deletions

File tree

src/libc/include/string.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ char *strtok(char *__restrict s, const char *__restrict delim)
8989
char *strtok_r(char *__restrict s, const char *__restrict delim, char **__restrict save_ptr)
9090
__attribute__((nonnull(2, 3)));
9191

92+
char *strsep(char **__restrict s, const char *__restrict delim)
93+
__NOEXCEPT __attribute__((nonnull(1, 2)));
94+
9295
char *strdup(const char *s)
9396
__attribute__((__malloc__)) __attribute__((nonnull(1)));
9497

src/libc/strsep.src

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
.assume adl=1
2+
3+
.section .text
4+
5+
.global _strsep
6+
.type _strsep, @function
7+
8+
; char *strsep(char **__restrict stringp, const char *__restrict delim)
9+
_strsep:
10+
pop bc
11+
pop hl
12+
pop de
13+
push de
14+
push hl
15+
push bc
16+
push hl ; stringp
17+
ld hl, (hl)
18+
add hl, de
19+
or a, a
20+
sbc hl, de
21+
jr z, .L.ret_null
22+
push de ; delim
23+
push hl ; *stringp
24+
call _strcspn
25+
pop de
26+
pop de
27+
pop iy ; stringp
28+
ld de, (iy)
29+
add hl, de ; *stringp + length
30+
xor a, a
31+
cp a, (hl) ; test for the nul terminator
32+
jr nz, .L.not_last_token
33+
sbc hl, hl ; last token
34+
jr .L.finish
35+
.L.not_last_token:
36+
ld (hl), a ; nul terminate
37+
inc hl ; next token
38+
.L.finish:
39+
ld (iy), hl ; store the next token
40+
ex de, hl
41+
; return *stringp
42+
ret
43+
.L.ret_null:
44+
pop de
45+
ret
46+
47+
.extern _strcspn

src/libcxx/include/cstring

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ using ::strrstr;
3737
using ::strcasestr;
3838
using ::strtok;
3939
using ::strtok_r;
40+
using ::strsep;
4041
using ::strdup;
4142
using ::strndup;
4243
using ::strcspn;

test/standalone/asprintf_fprintf/src/main.c

Lines changed: 119 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
#endif
4444

4545
/* pass NULL into functions without triggering -Wnonnull */
46-
extern void* NULL_ptr;
46+
extern void * NULL_ptr;
4747

4848
//------------------------------------------------------------------------------
4949
// Debug routines
@@ -177,6 +177,9 @@ char *T_strrchr(const char *s, int c)
177177
char *T_strrstr(const char *haystack, const char *needle)
178178
__attribute__((nonnull(1, 2)));
179179

180+
char *T_strsep(char **__restrict s, const char *__restrict delim)
181+
__attribute__((nonnull(1, 2)));
182+
180183
char *T_strstr(const char *haystack, const char *needle)
181184
__attribute__((nonnull(1, 2)));
182185

@@ -217,6 +220,7 @@ char *T_strtok_r(char *__restrict s, const char *__restrict delim, char **__rest
217220
#define T_strnlen strnlen
218221
#define T_strrchr strrchr
219222
#define T_strrstr strrstr
223+
#define T_strsep strsep
220224
#define T_strstr strstr
221225
#define T_strtok strtok
222226
#define T_strtok_r strtok_r
@@ -529,11 +533,10 @@ int memccpy_tests(void) {
529533
char dest[sizeof src];
530534
const char alt = '@';
531535

532-
for (size_t i = 0; i != sizeof terminal; ++i)
533-
{
536+
for (size_t i = 0; i != sizeof terminal; ++i) {
534537
void* to = T_memccpy(dest, src, terminal[i], sizeof dest);
535538

536-
fprintf(file,"Terminal '%c' (%s):\t\"", terminal[i], to ? "found" : "absent");
539+
fprintf(file, "Terminal '%c' (%s):\t\"", terminal[i], to ? "found" : "absent");
537540

538541
// if `terminal` character was not found - print the whole `dest`
539542
to = to ? to : dest + sizeof dest;
@@ -545,7 +548,6 @@ int memccpy_tests(void) {
545548
fputs("\"\n", file);
546549
}
547550

548-
549551
fprintf(file, "%c%s", '\n', "Separate star names from distances (ly):\n");
550552
const char *star_distance[] = {
551553
"Arcturus : 37", "Vega : 25", "Capella : 43", "Rigel : 860", "Procyon : 11"
@@ -554,8 +556,7 @@ int memccpy_tests(void) {
554556
char *first = names_only;
555557
char *last = names_only + sizeof names_only;
556558

557-
for (size_t t = 0; t != (sizeof star_distance) / (sizeof star_distance[0]); ++t)
558-
{
559+
for (size_t t = 0; t != (sizeof star_distance) / (sizeof star_distance[0]); ++t) {
559560
if (first) {
560561
first = T_memccpy(first, star_distance[t], ' ', last - first);
561562
} else {
@@ -1474,6 +1475,106 @@ int strtok_test(void) {
14741475
return 0;
14751476
}
14761477

1478+
static char *truth_strsep(char **__restrict stringp, const char *__restrict delim) {
1479+
char * const begin_str = *stringp;
1480+
if (begin_str == NULL) {
1481+
return NULL;
1482+
}
1483+
size_t length = strcspn(begin_str, delim);
1484+
char * end_str = begin_str + length;
1485+
if (*end_str != '\0') {
1486+
*end_str++ = '\0';
1487+
*stringp = end_str;
1488+
} else {
1489+
*stringp = NULL;
1490+
}
1491+
return begin_str;
1492+
}
1493+
1494+
static int strsep_loop_test(char * str_1, char * str_2) {
1495+
for (;;) {
1496+
char *__restrict prev_1 = T_strsep(&str_1, ", .");
1497+
char *__restrict prev_2 = truth_strsep(&str_2, ", .");
1498+
if (str_1 == NULL || str_2 == NULL) {
1499+
break;
1500+
}
1501+
ptrdiff_t diff_1 = (str_1 - prev_1);
1502+
ptrdiff_t diff_2 = (str_2 - prev_2);
1503+
if (diff_1 != diff_2) {
1504+
test_printf("%td != %td\n%p %p\n1: %.20s\n2: %.20s\n", diff_1, diff_2, prev_1, prev_2, str_1, str_2);
1505+
return __LINE__;
1506+
}
1507+
C(diff_1 == diff_2);
1508+
}
1509+
C(str_1 == NULL && str_2 == NULL);
1510+
return 0;
1511+
}
1512+
1513+
int strsep_test(char** dup_1, char** dup_2) {
1514+
{
1515+
char *ptr = NULL_ptr;
1516+
C(T_strsep(&ptr, SINK) == NULL);
1517+
C(T_strsep(&ptr, NULL_ptr) == NULL);
1518+
C(T_strsep((char**)SINK, SINK) == NULL);
1519+
C(T_strsep((char**)SINK, NULL_ptr) == NULL);
1520+
}
1521+
{
1522+
// example taken straight from the man page
1523+
char * argv[] = {
1524+
NULL,
1525+
"a/bbb///cc;xxx:yyy:",
1526+
":;",
1527+
"/"
1528+
};
1529+
char *token, *subtoken;
1530+
1531+
token = T_strsep((char**)&argv[1], argv[2]); C(strcmp_exact(token, "a/bbb///cc"));
1532+
subtoken = T_strsep(&token, argv[3]); C(strcmp_exact(subtoken, "a"));
1533+
subtoken = T_strsep(&token, argv[3]); C(strcmp_exact(subtoken, "bbb"));
1534+
subtoken = T_strsep(&token, argv[3]); C(strcmp_exact(subtoken, ""));
1535+
subtoken = T_strsep(&token, argv[3]); C(strcmp_exact(subtoken, ""));
1536+
subtoken = T_strsep(&token, argv[3]); C(strcmp_exact(subtoken, "cc"));
1537+
subtoken = T_strsep(&token, argv[3]); C(subtoken == NULL);
1538+
1539+
token = T_strsep((char**)&argv[1], argv[2]); C(strcmp_exact(token, "xxx"));
1540+
subtoken = T_strsep(&token, argv[3]); C(strcmp_exact(subtoken, "xxx"));
1541+
subtoken = T_strsep(&token, argv[3]); C(subtoken == NULL);
1542+
1543+
token = T_strsep((char**)&argv[1], argv[2]); C(strcmp_exact(token, "yyy"));
1544+
subtoken = T_strsep(&token, argv[3]); C(strcmp_exact(subtoken, "yyy"));
1545+
subtoken = T_strsep(&token, argv[3]); C(subtoken == NULL);
1546+
1547+
token = T_strsep((char**)&argv[1], argv[2]); C(strcmp_exact(token, ""));
1548+
subtoken = T_strsep(&token, argv[3]); C(strcmp_exact(subtoken, ""));
1549+
subtoken = T_strsep(&token, argv[3]); C(subtoken == NULL);
1550+
}
1551+
1552+
const size_t len = strlen(gnu_copypasta);
1553+
const size_t size = len + 1;
1554+
*dup_1 = strdup(gnu_copypasta);
1555+
*dup_2 = strndup(gnu_copypasta, len);
1556+
C(*dup_1 != NULL && *dup_2 != NULL);
1557+
C(strcmp(*dup_1, *dup_2) == 0);
1558+
{
1559+
char *ptr, *prev;
1560+
ptr = *dup_2;
1561+
prev = T_strsep(&ptr, "");
1562+
C(ptr == NULL);
1563+
C(prev == *dup_2);
1564+
ptr = *dup_2;
1565+
prev = T_strsep(&ptr, "zZ");
1566+
C(ptr == NULL);
1567+
C(prev == *dup_2);
1568+
C(memcmp(*dup_1, *dup_2, size) == 0);
1569+
}
1570+
{
1571+
int ret;
1572+
TEST(strsep_loop_test(*dup_1, *dup_2));
1573+
C(memcmp(*dup_1, *dup_2, size) == 0);
1574+
}
1575+
return 0;
1576+
}
1577+
14771578
int mem65536_test(void) {
14781579
void fill_mem32(void *dst, size_t bytes, uint32_t pattern);
14791580

@@ -1592,6 +1693,17 @@ int run_tests(void) {
15921693
}
15931694
if (ret != 0) { return ret; }
15941695

1696+
/* strsep */ {
1697+
char *dup_1 = SINK, *dup_2 = SINK;
1698+
ret = strsep_test(&dup_1, &dup_2);
1699+
if (dup_1 == NULL || dup_2 == NULL) {
1700+
perror("str(n)dup returned NULL");
1701+
}
1702+
free(dup_1); dup_1 = NULL;
1703+
free(dup_2); dup_2 = NULL;
1704+
if (ret != 0) { return ret; }
1705+
}
1706+
15951707
TEST(mempcpy_test());
15961708
TEST(bzero_test());
15971709
TEST(strncmp_test());

test/standalone/asprintf_fprintf/src/rename.s

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ _NULL_ptr:
3838
.global _T_strnlen
3939
.global _T_strrchr
4040
.global _T_strrstr
41+
.global _T_strsep
4142
.global _T_strstr
4243
.global _T_strtok
4344
.global _T_strtok_r
@@ -128,6 +129,9 @@ _T_strrchr:
128129
_T_strrstr:
129130
jp _strrstr
130131

132+
_T_strsep:
133+
jp _strsep
134+
131135
_T_strstr:
132136
jp _strstr
133137

@@ -168,5 +172,6 @@ _T_strtok_r:
168172
.extern _strrchr
169173
.extern _strrstr
170174
.extern _strstr
175+
.extern _strsep
171176
.extern _strtok
172177
.extern _strtok_r

0 commit comments

Comments
 (0)