diff --git a/include/ft/all-tests.h b/include/ft/all-tests.h index 9730c84..a2c334c 100644 --- a/include/ft/all-tests.h +++ b/include/ft/all-tests.h @@ -27,5 +27,6 @@ extern ft_test ft_string_memset; extern ft_test ft_string_memcpy; extern ft_test ft_string_memmove; extern ft_test ft_string_memcmp; +extern ft_test ft_string_memchr; #endif /* _FT_ALL_TESTS_H_ */ diff --git a/src/main.c b/src/main.c index a563f2a..08ee01c 100644 --- a/src/main.c +++ b/src/main.c @@ -45,6 +45,7 @@ ft_list headers_libc[] = { &ft_string_memcpy, &ft_string_memmove, &ft_string_memcmp, + &ft_string_memchr, NULL, }}, { "", NULL }, diff --git a/src/string/core.c b/src/string/core.c index 84728f4..adf70ce 100644 --- a/src/string/core.c +++ b/src/string/core.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include "memarray.h" //--- @@ -13,9 +13,9 @@ static void fill(uint8_t *buf, int size, int start) for(int i = 0; i < size; i++) buf[i] = start+i; } /* Clear buffer */ -static void clear(uint8_t *buf, int size) +static void clear(uint8_t *buf, int size, int value) { - for(int i = 0; i < size; i++) buf[i] = 0; + for(int i = 0; i < size; i++) buf[i] = value; } /* Check buffer equality (returns zero on equal) */ static int cmp(uint8_t *left, uint8_t *right, int size) @@ -103,8 +103,8 @@ static int _string_memcpy_func(memarray_args_t const *args) { fill(args->full_left1, args->full_size, 0); fill(args->full_left2, args->full_size, 0); - clear(args->full_right1, args->full_size); - clear(args->full_right2, args->full_size); + clear(args->full_right1, args->full_size, 0); + clear(args->full_right2, args->full_size, 0); memcpy(args->right1, args->left1, args->size); naive_memcpy(args->right2, args->left2, args->size); @@ -205,8 +205,84 @@ static jwidget *_string_memcmp_widget(GUNUSED ft_test *t) return memarray_widget(_string_memcmp_rc); } -ft_test ft_string_memcmp= { +ft_test ft_string_memcmp = { .name = "Configurations of memcmp", .function = _string_memcmp, .widget = _string_memcmp_widget, }; + +//--- +// memchr +//--- + +static int _string_memchr_func(memarray_args_t const *args) +{ + /* Start at 2, and search for byte 1 (inserted manually). Fill the region + around with 1s to make sure they are ignored */ + clear(args->full_buf1, args->full_size, 0); + fill(args->buf1, args->size, 2); + + /* Check that no byte is found initially */ + if(memchr(args->buf1, 0x01, args->size)) return 1; + + /* We'll try bytes at all of these locations */ + char *p1 = (char *)args->buf1; + char *p2 = (char *)args->buf1 + (args->size / 4); + char *p3 = (char *)args->buf1 + (3 * args->size / 4); + char *p4 = (char *)args->buf1 + (args->size - 1); + + *p1 = 0x01; + *p2 = 0x01; + *p3 = 0x01; + *p4 = 0x01; + + /* First byte in the area */ + if(memchr(args->buf1, 0x01, args->size) != p1) return 1; + *p1 = 0x02; + + /* First quarter */ + if(memchr(args->buf1, 0x01, args->size) != p2) return 1; + *p2 = 0x02; + + /* Third quarter */ + if(memchr(args->buf1, 0x01, args->size) != p3) return 1; + *p3 = 0x02; + + /* Last byte */ + if(memchr(args->buf1, 0x01, args->size) != p4) return 1; + *p4 = 0x02; + + return 0; +} + +uint8_t _string_memchr_rc[MEMARRAY_RC_SINGLE]; + +static void _string_memchr(ft_test *t) +{ + #define memchr_dist(str, byte, size) ({ \ + void const *_str = (str); \ + memchr(_str, byte, size) - _str; \ + }) + + ft_assert(t, memchr("xyztu", 'x', 0) == NULL); + ft_assert(t, memchr_dist("xyztu", 'x', 5) == 0); + ft_assert(t, memchr_dist("xyztu", 'y', 5) == 1); + ft_assert(t, memchr_dist("xyztu", 'z', 5) == 2); + ft_assert(t, memchr_dist("xyztu", 't', 5) == 3); + ft_assert(t, memchr_dist("xyztu", 'u', 5) == 4); + ft_assert(t, memchr("xyztu", 'v', 5) == NULL); + + memarray_single(_string_memchr_rc, _string_memchr_func); + memarray_assert(_string_memchr_rc, t); +} + +static jwidget *_string_memchr_widget(GUNUSED ft_test *t) +{ + return memarray_widget(_string_memchr_rc); +} + +ft_test ft_string_memchr = { + .name = "Configurations of memchr", + .function = _string_memchr, + .widget = _string_memchr_widget, +};