diff --git a/.gitignore b/.gitignore index 642d5a1..03a9130 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,9 @@ src/tests/test_sched_thread src/tests/test_skiplist src/tests/test_skiplist_set src/tests/test_thourands_seperator +src/tests/test_pthread_lock +src/tests/test_split_string +src/tests/test_uniq_skiplist # other php-fastcommon/.deps diff --git a/HISTORY b/HISTORY index 5483375..1db0fa0 100644 --- a/HISTORY +++ b/HISTORY @@ -1,7 +1,8 @@ -Version 1.44 2020-01-19 +Version 1.44 2020-02-02 * add test file src/tests/test_pthread_lock.c * add uniq_skiplist.[hc] + * add function split_string_ex Version 1.43 2019-12-25 * replace function call system to getExecResult, diff --git a/src/fast_allocator.c b/src/fast_allocator.c index c56c6d4..d08809f 100644 --- a/src/fast_allocator.c +++ b/src/fast_allocator.c @@ -287,31 +287,23 @@ int fast_allocator_init_ex(struct fast_allocator_context *acontext, return result; } -#define INIT_REGION(region, _start, _end, _step, _alloc_once) \ - do { \ - region.start = _start; \ - region.end = _end; \ - region.step = _step; \ - region.alloc_elements_once = _alloc_once; \ - } while(0) - int fast_allocator_init(struct fast_allocator_context *acontext, const int64_t alloc_bytes_limit, const double expect_usage_ratio, const int reclaim_interval, const bool need_lock) { #define DEFAULT_REGION_COUNT 5 - struct fast_region_info regions[DEFAULT_REGION_COUNT]; + struct fast_region_info regions[DEFAULT_REGION_COUNT]; - INIT_REGION(regions[0], 0, 256, 8, 4096); - INIT_REGION(regions[1], 256, 1024, 16, 1024); - INIT_REGION(regions[2], 1024, 4096, 64, 256); - INIT_REGION(regions[3], 4096, 16384, 256, 64); - INIT_REGION(regions[4], 16384, 65536, 1024, 16); + FAST_ALLOCATOR_INIT_REGION(regions[0], 0, 256, 8, 4096); + FAST_ALLOCATOR_INIT_REGION(regions[1], 256, 1024, 16, 1024); + FAST_ALLOCATOR_INIT_REGION(regions[2], 1024, 4096, 64, 256); + FAST_ALLOCATOR_INIT_REGION(regions[3], 4096, 16384, 256, 64); + FAST_ALLOCATOR_INIT_REGION(regions[4], 16384, 65536, 1024, 16); - return fast_allocator_init_ex(acontext, regions, - DEFAULT_REGION_COUNT, alloc_bytes_limit, - expect_usage_ratio, reclaim_interval, need_lock); + return fast_allocator_init_ex(acontext, regions, + DEFAULT_REGION_COUNT, alloc_bytes_limit, + expect_usage_ratio, reclaim_interval, need_lock); } void fast_allocator_destroy(struct fast_allocator_context *acontext) diff --git a/src/fast_allocator.h b/src/fast_allocator.h index 7bcae41..37a939f 100644 --- a/src/fast_allocator.h +++ b/src/fast_allocator.h @@ -28,8 +28,8 @@ struct fast_allocator_info struct fast_region_info { - int start; - int end; + int start; //exclude + int end; //include int step; int alloc_elements_once; int pad_mask; //for internal use @@ -60,6 +60,14 @@ struct fast_allocator_context bool need_lock; //if need mutex lock for acontext }; +#define FAST_ALLOCATOR_INIT_REGION(region, _start, _end, _step, _alloc_once) \ + do { \ + region.start = _start; \ + region.end = _end; \ + region.step = _step; \ + region.alloc_elements_once = _alloc_once; \ + } while(0) + #ifdef __cplusplus extern "C" { #endif diff --git a/src/shared_func.c b/src/shared_func.c index 995edc3..b8999e6 100644 --- a/src/shared_func.c +++ b/src/shared_func.c @@ -793,6 +793,47 @@ int splitEx(char *src, const char seperator, char **pCols, const int nMaxCols) return count; } +int split_string_ex(const string_t *src, const char seperator, + string_t *dest, const int max_count, const bool ignore_empty) +{ + const char *p; + string_t *current; + int len; + + p = src->str; + len = src->len; + current = dest; + while (true) + { + if ((int)(current - dest) >= max_count) + { + break; + } + + current->str = (char *)p; + p = memchr(p, seperator, len); + if (p == NULL) + { + if (len > 0 || !ignore_empty) + { + current->len = len; + current++; + } + break; + } + + current->len = (char *)p - current->str; + len -= current->len + 1; + if (current->len > 0 || !ignore_empty) + { + current++; + } + p++; + } + + return (int)(current - dest); +} + bool fc_match_delim(const char *str, const char *delim) { const char *sp; diff --git a/src/shared_func.h b/src/shared_func.h index 2ffc2fa..16c6abd 100644 --- a/src/shared_func.h +++ b/src/shared_func.h @@ -392,6 +392,18 @@ void freeSplit(char **p); int splitEx(char *src, const char seperator, char **pCols, const int nMaxCols); +/** split string + * parameters: + * src: the source string + * seperator: seperator char + * dest: store split strings + * max_count: max split count + * ignore_empty: if ignore empty string + * return: string array count +*/ +int split_string_ex(const string_t *src, const char seperator, + string_t *dest, const int max_count, const bool ignore_empty); + /** split string by delimiter characters * parameters: * src: the source string, will be modified by this function diff --git a/src/tests/Makefile b/src/tests/Makefile index a689cb2..b61efb5 100644 --- a/src/tests/Makefile +++ b/src/tests/Makefile @@ -7,7 +7,7 @@ LIB_PATH = -lfastcommon -lpthread ALL_PRGS = test_allocator test_skiplist test_multi_skiplist test_mblock test_blocked_queue \ test_id_generator test_ini_parser test_char_convert test_char_convert_loader \ test_logger test_skiplist_set test_crc32 test_thourands_seperator test_sched_thread \ - test_json_parser test_pthread_lock test_uniq_skiplist + test_json_parser test_pthread_lock test_uniq_skiplist test_split_string all: $(ALL_PRGS) .c: diff --git a/src/tests/test_split_string.c b/src/tests/test_split_string.c new file mode 100644 index 0000000..5ec5bac --- /dev/null +++ b/src/tests/test_split_string.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fastcommon/logger.h" +#include "fastcommon/shared_func.h" +#include "fastcommon/sched_thread.h" +#include "fastcommon/ini_file_reader.h" +#include "fastcommon/fast_allocator.h" + +#define MAX_PATH_COUNT 100 + +int main(int argc, char *argv[]) +{ + string_t path; + string_t paths[MAX_PATH_COUNT]; + char new_path[PATH_MAX]; + int count; + int i; + int len; + bool ignore_empty = false; + + log_init(); + srand(time(NULL)); + g_log_context.log_level = LOG_DEBUG; + + if (argc < 2) { + fprintf(stderr, "Usage: %s [ignore_empty=false]\n", argv[0]); + return EINVAL; + } + + FC_SET_STRING(path, argv[1]); + if (path.len >= PATH_MAX) { + fprintf(stderr, "path length: %d exceeds %d\n", path.len, PATH_MAX); + return ENAMETOOLONG; + } + + if (argc > 2) { + ignore_empty = FAST_INI_STRING_IS_TRUE(argv[2]); + } + + count = split_string_ex(&path, '/', paths, MAX_PATH_COUNT, ignore_empty); + if (ignore_empty && (path.len > 0 && path.str[0] == '/')) { + strcpy(new_path, "/"); + len = 1; + } else { + *new_path = '\0'; + len = 0; + } + if (count > 0) { + len += sprintf(new_path + len, "%.*s", paths[0].len, paths[0].str); + for (i=1; i