fixed and reworked cutils_memmem() and added more tests for string_find_str()

AuthorKonata <konata@posteo.jp>
Date
Commitd893ce4a2c75403ef13588b5328737e9726b47b5
Parente2601f0
2 files changed, 74 insertions(+), 8 deletions(-)
Msrc/extensions.c
@@ -68,27 +68,59 @@ char* cutil_strndup(const char* s, size_t n)
6868
6969 bool cutil_memmem(const void* haystack, size_t haystacklen, const void* needle, size_t needlelen, size_t* pos)
7070 {
71- size_t i, j;
71+ size_t newoffset, offset = 0, i, j;
7272 const byte* haystackb = haystack;
7373 const byte* needleb = needle;
74+ byte* start;
75+ bool newoffset_set = false;
7476
7577 if(needlelen == 0)
78+ {
79+ *pos = 0;
7680 return true;
81+ }
7782
78- if(HEDLEY_UNLIKELY((haystacklen == 0 && needlelen != 0 )|| haystacklen < needlelen))
83+ if(HEDLEY_UNLIKELY((haystacklen == 0 && needlelen > 0 )|| haystacklen < needlelen))
7984 return false;
80- //TODO: use memchr as base search
81- for(i = 0; i < haystacklen; i++)
85+
86+ CUTIL_LOOP
8287 {
83- for(j = 0, *pos = i; j < needlelen && i < haystacklen; j++, i++)
88+ start = memchr(haystackb+offset, needleb[0], haystacklen-offset);
89+ if(!start)
90+ {
91+ return false;
92+ } else if(needlelen == 1) {
93+ *pos = (size_t)(start-haystackb);
94+ return true;
95+ }
96+
97+ for(i = (size_t)(start-haystackb+1), j = 1; i < haystacklen && j < needlelen; i++, j++)
8498 {
99+ if(!newoffset_set && haystackb[i] == needleb[0])
100+ {
101+ newoffset = i;
102+ newoffset_set = true;
103+ }
104+
85105 if(haystackb[i] != needleb[j])
106+ {
86107 break;
87- else if(j == needlelen-1)
108+ } else if(j == needlelen-1) {
109+ *pos = (size_t)(start-haystackb);
88110 return true;
111+ }
112+ }
113+
114+ if(newoffset_set)
115+ {
116+ offset = newoffset;
117+ newoffset_set = false;
118+ } else {
119+ offset = i;
89120 }
90121 }
91122
123+
92124 return false;
93125 }
94126
Msrc/test.c
@@ -108,11 +108,44 @@ static void test_string(void)
108108 delete_string(string2);
109109 delete_string(string);
110110
111- string = from_cstring("abcd", truth);
112- string2 = from_cstring("cd", truth);
111+ string = from_cstring("abababcd", truth);
112+ string2 = from_cstring("ababcd", truth);
113113 assert(string_find_str(string, string2, &tmp));
114114 assert(tmp == 2);
115+ delete_string(string2);
116+ delete_string(string);
117+
118+ string = from_cstring("abab", truth);
119+ string2 = from_cstring("abc", truth);
120+ assert(!string_find_str(string, string2, &tmp));
121+ delete_string(string2);
122+ delete_string(string);
123+
124+ string = from_cstring("abababcd", truth);
125+ string2 = from_cstring("ab", truth);
126+ assert(string_find_str(string, string2, &tmp));
127+ assert(tmp == 0);
128+ delete_string(string2);
129+ delete_string(string);
115130
131+ string = from_cstring("ABC ABCDAB ABCDABCDABDE", truth);
132+ string2 = from_cstring("ABCDABD", truth);
133+ assert(string_find_str(string, string2, &tmp));
134+ assert(tmp == 15);
135+ delete_string(string2);
136+ delete_string(string);
137+
138+ string = from_cstring("asdasdasdasdp", truth);
139+ string2 = from_cstring("p", truth);
140+ assert(string_find_str(string, string2, &tmp));
141+ assert(tmp == 12);
142+ delete_string(string2);
143+ delete_string(string);
144+
145+ string = from_cstring("asdpsdasdasdpa", truth);
146+ string2 = from_cstring("pa", truth);
147+ assert(string_find_str(string, string2, &tmp));
148+ assert(tmp == 12);
116149 delete_string(string2);
117150 delete_string(string);
118151
@@ -385,3 +418,4 @@ int main(int argc, char** argv)
385418
386419 return 0;
387420 }
421+/* TODO: split up test files */