diff --git a/HISTORY b/HISTORY index 585348b..b6e9913 100644 --- a/HISTORY +++ b/HISTORY @@ -1,5 +1,5 @@ -Version 1.44 2020-10-28 +Version 1.44 2020-10-31 * add test file src/tests/test_pthread_lock.c * add uniq_skiplist.[hc] * add function split_string_ex diff --git a/src/ini_file_reader.c b/src/ini_file_reader.c index 59adae4..5e71eeb 100644 --- a/src/ini_file_reader.c +++ b/src/ini_file_reader.c @@ -3268,3 +3268,41 @@ char *iniGetRequiredStrValueEx(const char *szSectionName, const char *szItemName return value; } +int iniGetPercentValueEx(IniFullContext *ini_ctx, + const char *item_name, double *item_value, + const double default_value, const bool retry_global) +{ + char *value; + char *last; + + value = iniGetStrValueEx(ini_ctx->section_name, item_name, + ini_ctx->context, retry_global); + if (value == NULL || *value == '\0') { + *item_value = default_value; + } else { + double d; + char *endptr; + + last = value + strlen(value) - 1; + if (*last != '%') { + logError("file: "__FILE__", line: %d, " + "config file: %s, item: %s, value: %s " + "is NOT a valid ratio, expect end char: %%", + __LINE__, ini_ctx->filename, item_name, value); + return EINVAL; + } + + d = strtod(value, &endptr); + if ((endptr != last) || (d <= 0.00001 || d >= 100.00001)) { + logError("file: "__FILE__", line: %d, " + "config file: %s, item: %s, " + "value: %s is NOT a valid ratio", + __LINE__, ini_ctx->filename, item_name, value); + return EINVAL; + } + + *item_value = d / 100.00; + } + + return 0; +} diff --git a/src/ini_file_reader.h b/src/ini_file_reader.h index 52bbfe0..ab75081 100644 --- a/src/ini_file_reader.h +++ b/src/ini_file_reader.h @@ -133,6 +133,8 @@ extern "C" { iniGetBoolValueEx(szSectionName, szItemName, pContext, \ bDefaultValue, false) +#define iniGetPercentValue(ini_ctx, item_name, item_value, default_value) \ + iniGetPercentValueEx(ini_ctx, item_name, item_value, default_value, false) int iniSetAnnotationCallBack(AnnotationEntry *annotations, int count); void iniDestroyAnnotationCallBack(); @@ -284,6 +286,20 @@ double iniGetDoubleValueEx(const char *szSectionName, const char *szItemName, IniContext *pContext, const double dbDefaultValue, const bool bRetryGlobal); + +/** get item percent double value + * parameters: + * ini_ctx: the full context + * item_name: the item name + * item_value: store the item value + * default_value: the default value + * retry_global: if fetch from global section when the item not exist + * return: error no, 0 for success, != 0 for fail +*/ +int iniGetPercentValueEx(IniFullContext *ini_ctx, + const char *item_name, double *item_value, + const double default_value, const bool retry_global); + /** print all items * parameters: * pContext: the ini context diff --git a/src/uniq_skiplist.c b/src/uniq_skiplist.c index 2928d78..2739f90 100644 --- a/src/uniq_skiplist.c +++ b/src/uniq_skiplist.c @@ -454,25 +454,16 @@ static UniqSkiplistNode *uniq_skiplist_get_first_larger( return (UniqSkiplistNode *)previous->links[0]; } -int uniq_skiplist_delete_ex(UniqSkiplist *sl, void *data, +void uniq_skiplist_delete_node_ex(UniqSkiplist *sl, + UniqSkiplistNode *previous, UniqSkiplistNode *deleted, const bool need_free) { int i; - int level_index; - volatile UniqSkiplistNode *previous; - volatile UniqSkiplistNode *deleted; - - previous = uniq_skiplist_get_equal_previous(sl, data, &level_index); - if (previous == NULL) { - return ENOENT; - } - - deleted = previous->links[level_index]; - for (i=level_index; i>=0; i--) { + for (i=deleted->level_index; i>=0; i--) { while (previous->links[i] != sl->factory->tail && previous->links[i] != deleted) { - previous = previous->links[i]; + previous = (UniqSkiplistNode *)previous->links[i]; } previous->links[i] = previous->links[i]->links[i]; @@ -493,8 +484,24 @@ int uniq_skiplist_delete_ex(UniqSkiplist *sl, void *data, sl->factory->delay_free_seconds); } - UNIQ_SKIPLIST_FREE_MBLOCK_OBJECT(sl, level_index, deleted); + UNIQ_SKIPLIST_FREE_MBLOCK_OBJECT(sl, deleted->level_index, deleted); sl->element_count--; +} + +int uniq_skiplist_delete_ex(UniqSkiplist *sl, void *data, + const bool need_free) +{ + int level_index; + UniqSkiplistNode *previous; + UniqSkiplistNode *deleted; + + previous = uniq_skiplist_get_equal_previous(sl, data, &level_index); + if (previous == NULL) { + return ENOENT; + } + + deleted = (UniqSkiplistNode *)previous->links[level_index]; + uniq_skiplist_delete_node_ex(sl, previous, deleted, need_free); return 0; } @@ -524,6 +531,16 @@ int uniq_skiplist_replace_ex(UniqSkiplist *sl, void *data, return 0; } +UniqSkiplistNode *uniq_skiplist_find_node(UniqSkiplist *sl, void *data) +{ + int level_index; + UniqSkiplistNode *previous; + + previous = uniq_skiplist_get_equal_previous(sl, data, &level_index); + return (previous != NULL) ? (UniqSkiplistNode *) + previous->links[level_index] : NULL; +} + void *uniq_skiplist_find(UniqSkiplist *sl, void *data) { int level_index; diff --git a/src/uniq_skiplist.h b/src/uniq_skiplist.h index 960e7fb..a27305d 100644 --- a/src/uniq_skiplist.h +++ b/src/uniq_skiplist.h @@ -80,6 +80,9 @@ extern "C" { #define uniq_skiplist_delete(sl, data) \ uniq_skiplist_delete_ex(sl, data, true) +#define uniq_skiplist_delete_node(sl, previous, node) \ + uniq_skiplist_delete_node_ex(sl, previous, node, true) + #define uniq_skiplist_replace(sl, data) \ uniq_skiplist_replace_ex(sl, data, true) @@ -108,6 +111,11 @@ int uniq_skiplist_find_all(UniqSkiplist *sl, void *data, int uniq_skiplist_find_range(UniqSkiplist *sl, void *start_data, void *end_data, UniqSkiplistIterator *iterator); +UniqSkiplistNode *uniq_skiplist_find_node(UniqSkiplist *sl, void *data); +void uniq_skiplist_delete_node_ex(UniqSkiplist *sl, + UniqSkiplistNode *previous, UniqSkiplistNode *deleted, + const bool need_free); + UniqSkiplistNode *uniq_skiplist_find_ge_node(UniqSkiplist *sl, void *data); static inline void *uniq_skiplist_find_ge(UniqSkiplist *sl, void *data)