Skip to content

Commit 97cddd9

Browse files
committed
added memmem
1 parent e4ff641 commit 97cddd9

File tree

3 files changed

+159
-2
lines changed

3 files changed

+159
-2
lines changed

src/libc/memmem.src

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
assume adl=1
2+
3+
section .text
4+
5+
public _memmem
6+
7+
; void *memmem(const void *haystack, size_t haystack_len, const void *needle, size_t needle_len)
8+
haystack := iy + 3
9+
haystack_len := iy + 6
10+
needle := iy + 9
11+
needle_len := iy + 12
12+
_memmem:
13+
ld iy, 0
14+
add iy, sp
15+
ld hl, (haystack_len)
16+
ld bc, (needle_len)
17+
sbc hl, bc
18+
jr c, .ret_null ; (haystack_len < needle_len)
19+
; (haystack_len >= needle_len)
20+
21+
push hl
22+
scf
23+
sbc hl, hl
24+
add hl, bc
25+
pop bc
26+
ld hl, (haystack)
27+
ret nc ; return haystack if needle_len is zero
28+
inc bc
29+
; BC = (haystack_len - needle_len + 1) = search_len
30+
; haystack_len >= needle_len && needle_len != 0, therefore haystack_len >= 1
31+
call .begin_loop
32+
jr nz, .ret_null
33+
; test for a match at the last possible position
34+
dec hl
35+
push hl
36+
call _memcmp_fast
37+
pop hl
38+
ret z
39+
.ret_null:
40+
or a, a
41+
sbc hl, hl
42+
ret
43+
44+
.loop:
45+
pop bc
46+
.begin_loop:
47+
ld de, (needle)
48+
ld a, (de)
49+
cpir ; search for the start of the string
50+
ret po ; end of search_len
51+
push bc
52+
push hl
53+
dec hl
54+
call _memcmp_fast
55+
pop hl
56+
jr nz, .loop
57+
; pop bc
58+
ld sp, iy
59+
dec hl
60+
ret
61+
62+
_memcmp_fast:
63+
; Input:
64+
; HL = haystack
65+
; DE = needle
66+
; A = (DE)
67+
; Output:
68+
; Z = match
69+
; NZ = no match
70+
ld bc, (needle_len)
71+
.loop:
72+
cpi
73+
ret po
74+
inc de
75+
ld a, (de)
76+
jr z, .loop
77+
ret

test/standalone/asprintf_fprintf/src/main.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ void *T_mempcpy(void *__restrict dest, const void *__restrict src, size_t n)
5353
void *T_memrchr(const void *s, int c, size_t n)
5454
__attribute__((nonnull(1)));
5555

56+
void *T_memmem(const void *haystack, size_t haystack_len, const void *needle, size_t needle_len)
57+
__attribute__((nonnull(1, 3)));
58+
5659
char *T_stpcpy(char *__restrict dest, const char *__restrict src)
5760
__attribute__((nonnull(1, 2)));
5861

@@ -82,6 +85,7 @@ void T_bzero(void* s, size_t n);
8285
#define T_memccpy memccpy
8386
#define T_mempcpy mempcpy
8487
#define T_memrchr memrchr
88+
#define T_memmem memmem
8589
#define T_stpcpy stpcpy
8690
#define T_stpncpy stpncpy
8791
#define T_strlcat strlcat
@@ -700,6 +704,80 @@ int stpncpy_test(void) {
700704
return 0;
701705
}
702706

707+
int memmem_test(void) {
708+
const char str1[] = "abcdef123\0aababc123";
709+
710+
/* Test NULL */
711+
712+
C(T_memmem(NULL_ptr, 0, NULL_ptr, 0) == NULL_ptr);
713+
C(T_memmem(NULL_ptr, 0, SINK, 0) == NULL_ptr);
714+
C(T_memmem(NULL_ptr, 0, SINK, 1) == NULL_ptr);
715+
C(T_memmem(NULL_ptr, 0, SINK, 2) == NULL_ptr);
716+
C(T_memmem(SINK, 0, NULL_ptr, 0) == SINK);
717+
C(T_memmem(SINK, 1, NULL_ptr, 0) == SINK);
718+
C(T_memmem(SINK, 2, NULL_ptr, 0) == SINK);
719+
720+
/* Test same */
721+
722+
C(T_memmem(SINK, 0, SINK, 0) == SINK);
723+
C(T_memmem(SINK, 1, SINK, 0) == SINK);
724+
C(T_memmem(SINK, 2, SINK, 0) == SINK);
725+
C(T_memmem(SINK, 0, SINK, 1) == NULL);
726+
C(T_memmem(SINK, 1, SINK, 1) == SINK);
727+
C(T_memmem(SINK, 2, SINK, 1) == SINK);
728+
C(T_memmem(SINK, 0, SINK, 2) == NULL);
729+
C(T_memmem(SINK, 1, SINK, 2) == NULL);
730+
C(T_memmem(SINK, 2, SINK, 2) == SINK);
731+
732+
C(T_memmem(SINK, 300, SINK, 300) == SINK);
733+
C(T_memmem(SINK, 300, SINK, 301) == NULL);
734+
C(T_memmem(SINK, 300, SINK, 299) == SINK);
735+
C(T_memmem(SINK, 300, SINK, 30 ) == SINK);
736+
C(T_memmem(SINK, 30, SINK, 300) == NULL);
737+
738+
C(T_memmem(SINK + 30, 60, SINK + 0, 60) == SINK + 30);
739+
C(T_memmem(SINK + 0, 60, SINK + 30, 60) == SINK + 0);
740+
C(T_memmem(SINK + 30, 60, SINK + 0, 59) == SINK + 30);
741+
C(T_memmem(SINK + 0, 60, SINK + 30, 59) == SINK + 0);
742+
743+
C(T_memmem(str1, 20, str1, 0) == str1);
744+
C(T_memmem(str1, 20, str1, 1) == str1);
745+
C(T_memmem(str1, 20, str1, 2) == str1);
746+
C(T_memmem(str1, 20, str1, 3) == str1);
747+
C(T_memmem(str1, 20, str1, 9) == str1);
748+
C(T_memmem(str1, 20, str1, 10) == str1);
749+
C(T_memmem(str1, 20, str1, 20) == str1);
750+
751+
/* Test different */
752+
753+
C(T_memmem(str1, 0, SINK, 0) == str1);
754+
C(T_memmem(str1, 1, SINK, 0) == str1);
755+
C(T_memmem(str1, 2, SINK, 0) == str1);
756+
C(T_memmem(str1, 0, SINK, 1) == NULL);
757+
C(T_memmem(str1, 1, SINK, 1) == NULL);
758+
C(T_memmem(str1, 2, SINK, 1) == NULL);
759+
C(T_memmem(str1, 0, SINK, 2) == NULL);
760+
C(T_memmem(str1, 1, SINK, 2) == NULL);
761+
C(T_memmem(str1, 2, SINK, 2) == NULL);
762+
763+
/* Other tests */
764+
765+
C(T_memmem(str1 + 1, 19, "abc", 3) == str1 + 13);
766+
C(T_memmem(str1 + 0, 20, "123", 4) == str1 + 6);
767+
C(T_memmem(str1 + 7, 13, "123", 4) == str1 + 16);
768+
769+
C(T_memmem(str1 + 0, 20, "aabaab", 6) == NULL);
770+
C(T_memmem(str1 + 0, 20, "\xff\x00\xff", 4) == NULL);
771+
C(T_memmem(str1 + 0, 20, "\xff", 1) == NULL);
772+
773+
C(T_memmem(SINK, 300, "\xff", 1) == NULL);
774+
C(T_memmem(SINK, 300, "\xff\xff", 2) == NULL);
775+
C(T_memmem(SINK, 300, "\xff\0", 2) == NULL);
776+
C(T_memmem(SINK, 300, "\0\xff", 2) == NULL);
777+
778+
return 0;
779+
}
780+
703781
int run_tests(void) {
704782
int ret = 0;
705783
/* boot_asprintf */
@@ -728,6 +806,7 @@ int run_tests(void) {
728806
TEST(memmove_test());
729807
TEST(strlcat_test());
730808
TEST(stpncpy_test());
809+
TEST(memmem_test());
731810

732811
return 0;
733812
}

test/standalone/asprintf_fprintf/src/rename.asm

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
section .text
44

5-
public _T_memset, _T_memcpy, _T_memmove, _T_memcmp, _T_memccpy, _T_mempcpy, _T_memrchr
5+
public _T_memset, _T_memcpy, _T_memmove, _T_memcmp, _T_memccpy, _T_mempcpy, _T_memrchr, _T_memmem
66
public _T_strlen, _T_strcmp, _T_strncmp, _T_stpcpy, _T_stpncpy, _T_strlcat
77
public _T_bzero
88

@@ -13,6 +13,7 @@ _T_memcmp := _memcmp
1313
_T_memccpy := _memccpy
1414
_T_mempcpy := _mempcpy
1515
_T_memrchr := _memrchr
16+
_T_memmem := _memmem
1617

1718
_T_strlen := _strlen
1819
_T_strcmp := _strcmp
@@ -29,6 +30,6 @@ _T_bzero := _bzero
2930
_NULL_ptr:
3031
db $00, $00, $00
3132

32-
extern _memset, _memcpy, _memmove, _memcmp, _memccpy, _mempcpy, _memrchr
33+
extern _memset, _memcpy, _memmove, _memcmp, _memccpy, _mempcpy, _memrchr, _memmem
3334
extern _strlen, _strcmp, _strncmp, _stpcpy, _stpncpy, _strlcat
3435
extern _bzero

0 commit comments

Comments
 (0)