Skip to content

Commit 8c1312a

Browse files
ZERICO2005adriweb
authored andcommitted
added memmem
1 parent a3d855f commit 8c1312a

File tree

3 files changed

+177
-2
lines changed

3 files changed

+177
-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: 97 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,98 @@ int stpncpy_test(void) {
700704
return 0;
701705
}
702706

707+
int memmem_test(void) {
708+
const char str1[] = "abcdef123\0aababc123";
709+
const char str2[] = "wxyz";
710+
711+
/* Test NULL */
712+
713+
C(T_memmem(NULL_ptr, 0, NULL_ptr, 0) == NULL_ptr);
714+
C(T_memmem(NULL_ptr, 0, SINK, 0) == NULL_ptr);
715+
C(T_memmem(NULL_ptr, 0, SINK, 1) == NULL_ptr);
716+
C(T_memmem(NULL_ptr, 0, SINK, 2) == NULL_ptr);
717+
C(T_memmem(SINK, 0, NULL_ptr, 0) == SINK);
718+
C(T_memmem(SINK, 1, NULL_ptr, 0) == SINK);
719+
C(T_memmem(SINK, 2, NULL_ptr, 0) == SINK);
720+
721+
/* Test same */
722+
723+
C(T_memmem(SINK, 0, SINK, 0) == SINK);
724+
C(T_memmem(SINK, 1, SINK, 0) == SINK);
725+
C(T_memmem(SINK, 2, SINK, 0) == SINK);
726+
C(T_memmem(SINK, 0, SINK, 1) == NULL);
727+
C(T_memmem(SINK, 1, SINK, 1) == SINK);
728+
C(T_memmem(SINK, 2, SINK, 1) == SINK);
729+
C(T_memmem(SINK, 0, SINK, 2) == NULL);
730+
C(T_memmem(SINK, 1, SINK, 2) == NULL);
731+
C(T_memmem(SINK, 2, SINK, 2) == SINK);
732+
733+
C(T_memmem(SINK, 300, SINK, 300) == SINK);
734+
C(T_memmem(SINK, 300, SINK, 301) == NULL);
735+
C(T_memmem(SINK, 300, SINK, 299) == SINK);
736+
C(T_memmem(SINK, 300, SINK, 30 ) == SINK);
737+
C(T_memmem(SINK, 30, SINK, 300) == NULL);
738+
739+
C(T_memmem(SINK + 30, 60, SINK + 0, 60) == SINK + 30);
740+
C(T_memmem(SINK + 0, 60, SINK + 30, 60) == SINK + 0);
741+
C(T_memmem(SINK + 30, 60, SINK + 0, 59) == SINK + 30);
742+
C(T_memmem(SINK + 0, 60, SINK + 30, 59) == SINK + 0);
743+
744+
C(T_memmem(str1, 20, str1, 0) == str1);
745+
C(T_memmem(str1, 20, str1, 1) == str1);
746+
C(T_memmem(str1, 20, str1, 2) == str1);
747+
C(T_memmem(str1, 20, str1, 3) == str1);
748+
C(T_memmem(str1, 20, str1, 9) == str1);
749+
C(T_memmem(str1, 20, str1, 10) == str1);
750+
C(T_memmem(str1, 20, str1, 20) == str1);
751+
752+
/* Test different */
753+
754+
C(T_memmem(str1, 0, SINK, 0) == str1);
755+
C(T_memmem(str1, 1, SINK, 0) == str1);
756+
C(T_memmem(str1, 2, SINK, 0) == str1);
757+
C(T_memmem(str1, 0, SINK, 1) == NULL);
758+
C(T_memmem(str1, 1, SINK, 1) == NULL);
759+
C(T_memmem(str1, 2, SINK, 1) == NULL);
760+
C(T_memmem(str1, 0, SINK, 2) == NULL);
761+
C(T_memmem(str1, 1, SINK, 2) == NULL);
762+
C(T_memmem(str1, 2, SINK, 2) == NULL);
763+
764+
/* Other tests */
765+
766+
C(T_memmem(str1 + 1, 19, "abc", 3) == str1 + 13);
767+
C(T_memmem(str1 + 0, 20, "123", 4) == str1 + 6);
768+
C(T_memmem(str1 + 7, 13, "123", 4) == str1 + 16);
769+
770+
C(T_memmem(str1 + 0, 20, "aabaab", 6) == NULL);
771+
C(T_memmem(str1 + 0, 20, "\xff\x00\xff", 4) == NULL);
772+
C(T_memmem(str1 + 0, 20, "\xff", 1) == NULL);
773+
774+
C(T_memmem(SINK, 300, "\xff", 1) == NULL);
775+
C(T_memmem(SINK, 300, "\xff\xff", 2) == NULL);
776+
C(T_memmem(SINK, 300, "\xff\0", 2) == NULL);
777+
C(T_memmem(SINK, 300, "\0\xff", 2) == NULL);
778+
779+
C(T_memmem(str2 + 0, 5, "", 1) == str2 + 4);
780+
C(T_memmem(str2 + 4, 1, "", 1) == str2 + 4);
781+
C(T_memmem(str2 + 0, 5, "z", 1) == str2 + 3);
782+
C(T_memmem(str2 + 0, 5, "z", 2) == str2 + 3);
783+
C(T_memmem(str2 + 2, 5, "z", 1) == str2 + 3);
784+
C(T_memmem(str2 + 2, 5, "z", 2) == str2 + 3);
785+
C(T_memmem(str2 + 0, 3, "z", 1) == NULL);
786+
C(T_memmem(str2 + 0, 4, "z", 2) == NULL);
787+
C(T_memmem(str2 + 0, 5, "w", 1) == str2 + 0);
788+
C(T_memmem(str2 + 0, 5, "x", 1) == str2 + 1);
789+
C(T_memmem(str2 + 0, 5, "wx", 2) == str2 + 0);
790+
C(T_memmem(str2 + 0, 5, "xy", 2) == str2 + 1);
791+
C(T_memmem(str2 + 0, 5, "w", 2) == NULL);
792+
C(T_memmem(str2 + 0, 5, "x", 2) == NULL);
793+
C(T_memmem(str2 + 0, 5, "wx", 3) == NULL);
794+
C(T_memmem(str2 + 0, 5, "xy", 3) == NULL);
795+
796+
return 0;
797+
}
798+
703799
int run_tests(void) {
704800
int ret = 0;
705801
/* boot_asprintf */
@@ -728,6 +824,7 @@ int run_tests(void) {
728824
TEST(memmove_test());
729825
TEST(strlcat_test());
730826
TEST(stpncpy_test());
827+
TEST(memmem_test());
731828

732829
return 0;
733830
}

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)