diff --git a/.gitignore b/.gitignore index 154defda..df66545a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,10 @@ CMakeFiles/ Testing/ generated/ +export/ CMakeCache.txt CTestTestfile.cmake cmake_install.cmake Makefile +bfdev-* libbfdev.* diff --git a/examples/array/.gitignore b/examples/array/.gitignore index e18d4665..a3bf5be7 100644 --- a/examples/array/.gitignore +++ b/examples/array/.gitignore @@ -1,2 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-or-later -/array-simple +/array-simple-append +/array-simple-splice +/array-simple-stack +/array-simple-write diff --git a/examples/array/CMakeLists.txt b/examples/array/CMakeLists.txt index 3f90958f..6b30e52c 100644 --- a/examples/array/CMakeLists.txt +++ b/examples/array/CMakeLists.txt @@ -3,19 +3,37 @@ # Copyright(c) 2023 ffashion # -add_executable(array-simple simple.c) -target_link_libraries(array-simple bfdev) -add_test(array-simple array-simple) +add_executable(array-simple-append simple-append.c) +target_link_libraries(array-simple-append bfdev) +add_test(array-simple-append array-simple-append) + +add_executable(array-simple-splice simple-splice.c) +target_link_libraries(array-simple-splice bfdev) +add_test(array-simple-splice array-simple-splice) + +add_executable(array-simple-stack simple-stack.c) +target_link_libraries(array-simple-stack bfdev) +add_test(array-simple-stack array-simple-stack) + +add_executable(array-simple-write simple-write.c) +target_link_libraries(array-simple-write bfdev) +add_test(array-simple-write array-simple-write) if(${CMAKE_PROJECT_NAME} STREQUAL "bfdev") install(FILES - simple.c + simple-append.c + simple-splice.c + simple-stack.c + simple-write.c DESTINATION ${CMAKE_INSTALL_DOCDIR}/examples/array ) install(TARGETS - array-simple + array-simple-append + array-simple-splice + array-simple-stack + array-simple-write DESTINATION ${CMAKE_INSTALL_DOCDIR}/bin ) diff --git a/examples/array/simple-append.c b/examples/array/simple-append.c new file mode 100644 index 00000000..af49737e --- /dev/null +++ b/examples/array/simple-append.c @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright(c) 2023 John Sanpe + */ + +#define MODULE_NAME "array-simple-append" +#define bfdev_log_fmt(fmt) MODULE_NAME ": " fmt + +#include +#include +#include +#include +#include + +int +main(int argc, const char *argv[]) +{ + BFDEV_CLASS(bfdev_array, array)(NULL, 1); + const char *result; + + if (bfdev_array_append_cstr(array, "Hello")) + return 1; + + if (bfdev_array_append_cstr(array, "World")) + return 1; + + result = bfdev_array_data(array, 0); + if (!result) + return 1; + bfdev_log_info("%.5s\n", result); + + result = bfdev_array_data(array, 5); + if (!result) + return 1; + bfdev_log_info("%.5s\n", result); + + return 0; +} diff --git a/examples/array/simple-splice.c b/examples/array/simple-splice.c new file mode 100644 index 00000000..1ee641cd --- /dev/null +++ b/examples/array/simple-splice.c @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright(c) 2023 John Sanpe + */ + +#define MODULE_NAME "array-simple-splice" +#define bfdev_log_fmt(fmt) MODULE_NAME ": " fmt + +#include +#include +#include +#include +#include + +int +main(int argc, const char *argv[]) +{ + BFDEV_CLASS(bfdev_array, array)(NULL, 1); + const char *result; + void *pmem; + + if (bfdev_array_append_cstr(array, "Hello123X")) + return 1; + + bfdev_array_seek(array, 4); + pmem = bfdev_array_splice(array, 1, 3, 5); + if (!pmem) + return 1; + memcpy(pmem, "World", 5); + + bfdev_array_seek(array, 0); + result = bfdev_array_data(array, 0); + if (!result) + return 1; + bfdev_log_info("%.11s\n", result); + + return 0; +} diff --git a/examples/array/simple-stack.c b/examples/array/simple-stack.c new file mode 100644 index 00000000..687b7159 --- /dev/null +++ b/examples/array/simple-stack.c @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright(c) 2023 John Sanpe + */ + +#define MODULE_NAME "array-simple-stack" +#define bfdev_log_fmt(fmt) MODULE_NAME ": " fmt + +#include +#include +#include +#include + +int +main(int argc, const char *argv[]) +{ + BFDEV_CLASS(bfdev_array, array)(NULL, 1); + const char *result; + void *pmem; + + pmem = bfdev_array_push(array, 5); + if (!pmem) + return 1; + memcpy(pmem, "World", 5); + + pmem = bfdev_array_push(array, 5); + if (!pmem) + return 1; + memcpy(pmem, "Hello", 5); + + result = bfdev_array_pop(array, 5); + if (!result) + return 1; + bfdev_log_info("%.5s\n", result); + + result = bfdev_array_pop(array, 5); + if (!result) + return 1; + bfdev_log_info("%.5s\n", result); + + return 0; +} diff --git a/examples/array/simple-write.c b/examples/array/simple-write.c new file mode 100644 index 00000000..de1d4c15 --- /dev/null +++ b/examples/array/simple-write.c @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright(c) 2025 John Sanpe + */ + +#define MODULE_NAME "array-simple-write" +#define bfdev_log_fmt(fmt) MODULE_NAME ": " fmt + +#include +#include +#include +#include + +int +main(int argc, const char *argv[]) +{ + BFDEV_CLASS(bfdev_array, array)(NULL, sizeof(char)); + const char *result; + void *pmem; + + pmem = bfdev_array_write(array, 5); + if (!pmem) + return 1; + memcpy(pmem, "Hello", 5); + + pmem = bfdev_array_write(array, 5); + if (!pmem) + return 1; + memcpy(pmem, "World", 5); + + bfdev_array_seek(array, 0); + result = bfdev_array_read(array, 5); + if (!result) + return 1; + bfdev_log_info("%.5s\n", result); + + result = bfdev_array_read(array, 5); + if (!result) + return 1; + bfdev_log_info("%.5s\n", result); + + return 0; +} diff --git a/examples/array/simple.c b/examples/array/simple.c deleted file mode 100644 index 2eb59596..00000000 --- a/examples/array/simple.c +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright(c) 2023 John Sanpe - */ - -#include -#include -#include -#include - -#define TEST_LOOP 100 -#define TEST_SIZE 64 - -int -main(int argc, const char *argv[]) -{ - BFDEV_CLASS(bfdev_array, array)(NULL, TEST_SIZE); - unsigned int count; - - for (count = 0; count < TEST_LOOP; ++count) { - unsigned int num; - void *buff; - - num = rand() % TEST_SIZE; - buff = bfdev_array_push(array, num); - if (!buff) - return 1; - - memset(buff, 0, TEST_SIZE * num); - printf("array bfdev_array_push test: %02u: %u\n", count, num); - } - - return 0; -} diff --git a/examples/guards/.gitignore b/examples/guards/.gitignore index b5a0ea0f..016bc78b 100644 --- a/examples/guards/.gitignore +++ b/examples/guards/.gitignore @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-or-later +/guards-class /guards-cleanup diff --git a/examples/log/.gitignore b/examples/log/.gitignore index 20227489..7a8307f5 100644 --- a/examples/log/.gitignore +++ b/examples/log/.gitignore @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-or-later +/log-date /log-simple diff --git a/include/bfdev/array.h b/include/bfdev/array.h index d2395ec0..97223b6f 100644 --- a/include/bfdev/array.h +++ b/include/bfdev/array.h @@ -66,13 +66,14 @@ bfdev_array_init(bfdev_array_t *array, const bfdev_alloc_t *alloc, * bfdev_array_reset() - reset array. * @array: the array object. * - * Reset the length of the stored data to zero and also - * free the internal memory buffer + * Reset the length of the stored data to zero and + * also reset the current seek position. */ static inline void bfdev_array_reset(bfdev_array_t *array) { array->index = 0; + array->seek = 0; } /** @@ -88,6 +89,12 @@ bfdev_array_index(const bfdev_array_t *array) return array->index; } +/** + * bfdev_array_tell() - get current position in array. + * @array: the array object. + * + * Returns the current seek position of the array. + */ static inline unsigned long bfdev_array_tell(const bfdev_array_t *array) { @@ -131,29 +138,10 @@ bfdev_array_size(const bfdev_array_t *array) static inline bfdev_size_t bfdev_array_remain(const bfdev_array_t *array) { - return bfdev_array_offset(array, array->index - array->seek); -} - -/** - * bfdev_array_data() - get elements pointer in array. - * @array: the array object. - * @index: elements index. - * - * Return the offset value of the object indexed - * by @index in the array. - */ -static inline void * -bfdev_array_data(const bfdev_array_t *array, unsigned long index) -{ - void *data; - - if (bfdev_unlikely(array->seek + index >= array->index)) - return BFDEV_NULL; + if (array->index <= array->seek) + return 0; - data = array->data + bfdev_array_offset(array, array->seek); - data += bfdev_array_offset(array, index); - - return data; + return bfdev_array_offset(array, array->index - array->seek); } /** @@ -164,17 +152,11 @@ bfdev_array_data(const bfdev_array_t *array, unsigned long index) * Set the current position of the array to @seek. * The next call to bfdev_array_data() will start * from this position. - * - * Return 0 on success or a negative error code on failure. */ -static inline int +static inline void bfdev_array_seek(bfdev_array_t *array, unsigned long seek) { - if (bfdev_unlikely(seek > array->index)) - return -BFDEV_EOVERFLOW; array->seek = seek; - - return -BFDEV_ENOERR; } /** @@ -182,7 +164,7 @@ bfdev_array_seek(bfdev_array_t *array, unsigned long seek) * @array: the array object. * @num: the number of element to push. * - * Creates a number of new elements on the array and + * Creates a number of new elements at the end of array and * returns a pointer to the first of these elements. * * this may cause a re-allocation of the array depending on @@ -199,25 +181,64 @@ extern void * bfdev_array_peek(const bfdev_array_t *array, unsigned long num); /** - * bfdev_array_remove() - remove elements from the array. + * bfdev_array_data() - get elements pointer in array. * @array: the array object. - * @index: the index of the first elements to remove. - * @num: the number of element to remove. + * @index: elements index. * - * Return 0 on success or a negative error code on failure. + * Return the offset value of the object indexed + * by @index in the array. */ -extern int -bfdev_array_remove(bfdev_array_t *array, unsigned long index, unsigned long num); +extern void * +bfdev_array_data(const bfdev_array_t *array, unsigned long index); /** - * bfdev_array_resize() - directly set the number of elements in array. + * bfdev_array_read() - read elements from the array. * @array: the array object. - * @num: the number required resize. + * @num: the number of element to read. + * + * Retrieves a block of @num elements starting from the current seek position + * in the array and returns a pointer to the first element. + */ +extern const void * +bfdev_array_read(bfdev_array_t *array, unsigned long num); + +/** + * bfdev_array_write() - write elements to the array. + * @array: the array object. + * @num: the number of element to write. + * + * Reserves space for @num elements starting from the current seek position, + * allocating memory if necessary, and returns a pointer to the first element. + * The caller is responsible for writing the data to the return memory. + */ +extern void * +bfdev_array_write(bfdev_array_t *array, unsigned long num); + +/** + * bfdev_array_append() - append elements into the array. + * @array: the array object. + * @data: the elements to append. + * @num: the number of element to append. * * Return 0 on success or a negative error code on failure. */ extern int -bfdev_array_resize(bfdev_array_t *array, unsigned long num); +bfdev_array_append(bfdev_array_t *array, const void *data, unsigned long num); + +/** + * bfdev_array_splice() - splice elements in the array. + * @array: the array object. + * @index: the index to splice. + * @delnum: the number of element to delete. + * @newnum: the number of element to insert. + * + * Used to change the contents of an array by removing or replacing existing + * elements and/or adding new elements, and returns a pointer to the + * first element of the newly inserted elements. + */ +extern void * +bfdev_array_splice(bfdev_array_t *array, unsigned long index, + unsigned long delnum, unsigned long newnum); /** * bfdev_array_reserve() - reserve array buffer. @@ -233,6 +254,16 @@ bfdev_array_resize(bfdev_array_t *array, unsigned long num); extern int bfdev_array_reserve(bfdev_array_t *array, unsigned long num); +/** + * bfdev_array_resize() - directly set the number of elements in array. + * @array: the array object. + * @num: the number required resize. + * + * Return 0 on success or a negative error code on failure. + */ +extern int +bfdev_array_resize(bfdev_array_t *array, unsigned long num); + /** * bfdev_array_release() - release array. * @array: the array object @@ -246,21 +277,21 @@ bfdev_array_release(bfdev_array_t *array); static inline bfdev_array_t * bfdev_array_create(const bfdev_alloc_t *alloc, bfdev_size_t cells) { - bfdev_array_t *obj; + bfdev_array_t *array; - obj = bfdev_malloc(alloc, sizeof(*obj)); - if (bfdev_unlikely(!obj)) + array = bfdev_malloc(alloc, sizeof(*array)); + if (bfdev_unlikely(!array)) return BFDEV_NULL; - bfdev_array_init(obj, alloc, cells); + bfdev_array_init(array, alloc, cells); - return obj; + return array; } static inline void -bfdev_array_destroy(bfdev_array_t *obj) +bfdev_array_destroy(bfdev_array_t *array) { - bfdev_array_release(obj); - bfdev_free(obj->alloc, obj); + bfdev_array_release(array); + bfdev_free(array->alloc, array); } BFDEV_DEFINE_CLASS(bfdev_array, bfdev_array_t *, diff --git a/include/bfdev/template/array.h b/include/bfdev/template/array.h index 7571e3a1..b90024a8 100644 --- a/include/bfdev/template/array.h +++ b/include/bfdev/template/array.h @@ -12,17 +12,6 @@ BFDEV_BEGIN_DECLS -/** - * bfdev_array_append() - append elements into the array. - * @array: the array object. - * @data: the elements to append. - * @num: the number of element to append. - * - * Return 0 on success or a negative error code on failure. - */ -extern int -bfdev_array_append(bfdev_array_t *array, const void *data, unsigned long num); - /** * bfdev_array_append_array() - append array into the array. * @array: the array object. @@ -53,6 +42,17 @@ bfdev_array_append_buff(bfdev_array_t *array, bfdev_buff_t *append); extern int bfdev_array_append_cstr(bfdev_array_t *array, const char *append); + +/** + * bfdev_array_append_char() - append char into the array. + * @array: the array object. + * @append: the char to append. + * + * Return 0 on success or a negative error code on failure. + */ +extern int +bfdev_array_append_char(bfdev_array_t *array, char append); + BFDEV_END_DECLS #endif /* _BFDEV_TEMPLATE_ARRAY_H_ */ diff --git a/src/array.c b/src/array.c index d46a6c99..58516f87 100644 --- a/src/array.c +++ b/src/array.c @@ -70,6 +70,34 @@ array_peek(const bfdev_array_t *array, unsigned long num, unsigned long *idxp) return array->data + offset; } +static inline void * +array_consume(bfdev_array_t *array, unsigned long num, bfdev_bool extend) +{ + unsigned long end; + bfdev_bool overflow; + void *data; + int retval; + + overflow = bfdev_overflow_check_add(array->seek, num, &end); + if (bfdev_unlikely(overflow)) + return BFDEV_NULL; + + if (end > array->index) { + if (bfdev_unlikely(!extend)) + return BFDEV_NULL; + + retval = array_apply(array, end); + if (bfdev_unlikely(retval)) + return BFDEV_NULL; + array->index = end; + } + + data = array->data + bfdev_array_offset(array, array->seek); + array->seek = end; + + return data; +} + export void * bfdev_array_push(bfdev_array_t *array, unsigned long num) { @@ -104,46 +132,96 @@ bfdev_array_peek(const bfdev_array_t *array, unsigned long num) { return array_peek(array, num, BFDEV_NULL); } -export int -bfdev_array_remove(bfdev_array_t *array, unsigned long index, unsigned long num) + +export void * +bfdev_array_data(const bfdev_array_t *array, unsigned long index) { - unsigned long cut; - void *start, *end; - bfdev_size_t behind; + unsigned long actual; bfdev_bool overflow; - if (bfdev_unlikely(index >= array->index)) - return -BFDEV_EFBIG; - - overflow = bfdev_overflow_check_add(index, num, &cut); + overflow = bfdev_overflow_check_add(array->seek, index, &actual); if (bfdev_unlikely(overflow)) - return -BFDEV_EOVERFLOW; + return BFDEV_NULL; - if (bfdev_unlikely(cut > array->index)) - return -BFDEV_EFBIG; + if (bfdev_unlikely(actual >= array->index)) + return BFDEV_NULL; - start = array->data + bfdev_array_offset(array, index); - end = array->data + bfdev_array_offset(array, cut); - behind = bfdev_array_offset(array, array->index - cut); + return array->data + bfdev_array_offset(array, actual); +} - bfdev_memmove(start, end, behind); - array->index -= num; +export const void * +bfdev_array_read(bfdev_array_t *array, unsigned long num) +{ + return array_consume(array, num, bfdev_false); +} - return -BFDEV_ENOERR; +export void * +bfdev_array_write(bfdev_array_t *array, unsigned long num) +{ + return array_consume(array, num, bfdev_true); } export int -bfdev_array_resize(bfdev_array_t *array, unsigned long num) +bfdev_array_append(bfdev_array_t *array, const void *data, unsigned long num) +{ + bfdev_size_t size; + void *buff; + + buff = bfdev_array_push(array, num); + if (bfdev_unlikely(!buff)) + return -BFDEV_ENOMEM; + + size = bfdev_array_offset(array, num); + bfdev_memcpy(buff, data, size); + + return -BFDEV_ENOERR; +} + +export void * +bfdev_array_splice(bfdev_array_t *array, unsigned long index, + unsigned long delnum, unsigned long newnum) { + unsigned long actual, delcut, newcut, count; + void *start, *end; + bfdev_size_t behind; + bfdev_bool overflow; int retval; - retval = array_apply(array, num); + overflow = bfdev_overflow_check_add(array->seek, index, &actual); + if (bfdev_unlikely(overflow)) + return BFDEV_NULL; + + if (bfdev_unlikely(actual >= array->index)) + return BFDEV_NULL; + + overflow = bfdev_overflow_check_add(actual, delnum, &delcut); + if (bfdev_unlikely(overflow)) + return BFDEV_NULL; + + if (bfdev_unlikely(delcut > array->index)) + return BFDEV_NULL; + + overflow = bfdev_overflow_check_add(actual, newnum, &newcut); + if (bfdev_unlikely(overflow)) + return BFDEV_NULL; + + overflow = bfdev_overflow_check_add(array->index, newnum, &count) || + bfdev_overflow_check_sub(count, delnum, &count); + if (bfdev_unlikely(overflow)) + return BFDEV_NULL; + + behind = bfdev_array_offset(array, array->index - delcut); + array->index = count; + + retval = array_apply(array, count); if (bfdev_unlikely(retval)) - return retval; + return BFDEV_NULL; - array->index = num; + start = array->data + bfdev_array_offset(array, delcut); + end = array->data + bfdev_array_offset(array, newcut); + bfdev_memmove(end, start, behind); - return -BFDEV_ENOERR; + return array->data + bfdev_array_offset(array, actual); } export int @@ -159,13 +237,27 @@ bfdev_array_reserve(bfdev_array_t *array, unsigned long num) return array_apply(array, count); } +export int +bfdev_array_resize(bfdev_array_t *array, unsigned long num) +{ + int retval; + + retval = array_apply(array, num); + if (bfdev_unlikely(retval)) + return retval; + + array->index = num; + + return -BFDEV_ENOERR; +} + export void bfdev_array_release(bfdev_array_t *array) { const bfdev_alloc_t *alloc; + bfdev_array_reset(array); array->capacity = 0; - array->index = 0; alloc = array->alloc; bfdev_free(alloc, array->data); diff --git a/template/array.c b/template/array.c index 8ec13d5a..2f133675 100644 --- a/template/array.c +++ b/template/array.c @@ -8,22 +8,6 @@ #include #include -export int -bfdev_array_append(bfdev_array_t *array, const void *data, unsigned long num) -{ - bfdev_size_t size; - void *buff; - - buff = bfdev_array_push(array, num); - if (bfdev_unlikely(!buff)) - return -BFDEV_ENOMEM; - - size = bfdev_array_offset(array, num); - bfdev_memcpy(buff, data, size); - - return -BFDEV_ENOERR; -} - export int bfdev_array_append_array(bfdev_array_t *array, const bfdev_array_t *append) { @@ -68,3 +52,18 @@ bfdev_array_append_cstr(bfdev_array_t *array, const char *append) return -BFDEV_ENOERR; } + +export int +bfdev_array_append_char(bfdev_array_t *array, char append) +{ + int retval; + + if (array->cells != sizeof(append)) + return -BFDEV_EPROTO; + + retval = bfdev_array_append(array, &append, 1); + if (bfdev_unlikely(retval)) + return retval; + + return -BFDEV_ENOERR; +} diff --git a/testsuite/glob/.gitignore b/testsuite/glob/.gitignore index ffc5fcc1..76f2ca97 100644 --- a/testsuite/glob/.gitignore +++ b/testsuite/glob/.gitignore @@ -1,2 +1,2 @@ # SPDX-License-Identifier: GPL-2.0-or-later -/fifo-selftest +/glob-selftest