diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2015-01-03 12:13:02 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2015-01-03 12:13:44 +0300 |
commit | 16ed20ff3cc68589a5fe48075d2b80692d3c90ea (patch) | |
tree | 83aa3159bc18939a89e223b5eb8f73c4e0cf9179 | |
parent | 6b8b3badf58942356d4cc8aa64214f94272a7958 (diff) |
Add some BLI helpers needed by asset branch.
`BLI_strncpy_ensure_pad()` is also useful with current master code.
The two others (`BLI_strcmp_ignore_pad()` and `BLI_filelist_duplicate()`)
are only used in asset branch currently, but think they could be useful
in other places too, and simplifies handling of asset branch & future patch review.
Reviewers: campbellbarton
Reviewed By: campbellbarton
Differential Revision: https://developer.blender.org/D965
-rw-r--r-- | source/blender/blenlib/BLI_fileops.h | 3 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_string.h | 4 | ||||
-rw-r--r-- | source/blender/blenlib/intern/storage.c | 35 | ||||
-rw-r--r-- | source/blender/blenlib/intern/string.c | 92 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_templates.c | 10 | ||||
-rw-r--r-- | source/blender/editors/space_outliner/outliner_tree.c | 49 | ||||
-rw-r--r-- | tests/gtests/blenlib/BLI_path_util_test.cc | 1 |
7 files changed, 151 insertions, 43 deletions
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index 4f451a6c741..8e056651f7f 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -89,6 +89,9 @@ double BLI_dir_free_space(const char *dir); char *BLI_current_working_dir(char *dir, const size_t maxlen); unsigned int BLI_dir_contents(const char *dir, struct direntry **filelist); +void BLI_filelist_duplicate( + struct direntry **dest_filelist, struct direntry *src_filelist, unsigned int nrentries, + void *(*dup_poin)(void *)); void BLI_free_filelist(struct direntry *filelist, unsigned int nrentries); /* Files */ diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index b249bc720c6..a390b419c18 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -48,6 +48,8 @@ char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) AT char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL(); +char *BLI_strncpy_ensure_pad(char *dst, const char *src, const char pad, size_t maxncpy) ATTR_NONNULL(); + size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -71,6 +73,8 @@ char *BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT AT int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int BLI_strncasecmp(const char *s1, const char *s2, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int BLI_natstrcmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int BLI_strcmp_ignore_pad(const char *str1, const char *str2, const char pad) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); + size_t BLI_strnlen(const char *str, const size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void BLI_timestr(double _time, char *str, size_t maxlen) ATTR_NONNULL(); diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index c062d62bca5..78057b1655f 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -409,7 +409,40 @@ unsigned int BLI_dir_contents(const char *dirname, struct direntry **filelist) return dir_ctx.nrfiles; } -/* frees storage for an array of direntries, including the array itself. */ +/** + * Deep-duplicate of an array of direntries, including the array itself. + * + * \param dup_poin If given, called for each non-NULL direntry->poin. Otherwise, pointer is always simply copied over. + */ +void BLI_filelist_duplicate( + struct direntry **dest_filelist, struct direntry *src_filelist, unsigned int nrentries, + void *(*dup_poin)(void *)) +{ + unsigned int i; + + *dest_filelist = malloc(sizeof(**dest_filelist) * (size_t)(nrentries)); + for (i = 0; i < nrentries; ++i) { + struct direntry * const src = &src_filelist[i]; + struct direntry *dest = &(*dest_filelist)[i]; + *dest = *src; + if (dest->image) { + dest->image = IMB_dupImBuf(src->image); + } + if (dest->relname) { + dest->relname = MEM_dupallocN(src->relname); + } + if (dest->path) { + dest->path = MEM_dupallocN(src->path); + } + if (dest->poin && dup_poin) { + dest->poin = dup_poin(src->poin); + } + } +} + +/** + * frees storage for an array of direntries, including the array itself. + */ void BLI_free_filelist(struct direntry *filelist, unsigned int nrentries) { unsigned int i; diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index eeafc1a9e8f..765e2ea127b 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -126,6 +126,54 @@ char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t } /** + * Like BLI_strncpy but ensures dst is always padded by given char, on both sides (unless src is empty). + * + * \param dst Destination for copy + * \param src Source string to copy + * \param pad the char to use for padding + * \param maxncpy Maximum number of characters to copy (generally the size of dst) + * \retval Returns dst + */ +char *BLI_strncpy_ensure_pad(char *__restrict dst, const char *__restrict src, const char pad, size_t maxncpy) +{ + BLI_assert(maxncpy != 0); + +#ifdef DEBUG_STRSIZE + memset(dst, 0xff, sizeof(*dst) * maxncpy); +#endif + + if (src[0] == '\0') { + dst[0] = '\0'; + } + else { + /* Add heading/trailing wildcards if needed. */ + size_t idx = 0; + size_t srclen; + + if (src[idx] != pad) { + dst[idx++] = pad; + maxncpy--; + } + maxncpy--; /* trailing '\0' */ + + srclen = BLI_strnlen(src, maxncpy); + if ((src[srclen - 1] != pad) && (srclen == maxncpy)) { + srclen--; + } + + memcpy(&dst[idx], src, srclen); + idx += srclen; + + if (dst[idx - 1] != pad) { + dst[idx++] = pad; + } + dst[idx] = '\0'; + } + + return dst; +} + +/** * Like strncpy but ensures dst is always * '\0' terminated. * @@ -566,6 +614,50 @@ int BLI_natstrcmp(const char *s1, const char *s2) return strcmp(s1, s2); } +/** + * Like strcmp, but will ignore any heading/trailing pad char for comparison. + * So e.g. if pad is '*', '*world' and 'world*' will compare equal. + */ +int BLI_strcmp_ignore_pad(const char *str1, const char *str2, const char pad) +{ + size_t str1_len, str2_len; + + while (*str1 == pad) { + str1++; + } + while (*str2 == pad) { + str2++; + } + + str1_len = strlen(str1); + str2_len = strlen(str2); + + while (str1_len && (str1[str1_len - 1] == pad)) { + str1_len--; + } + while (str2_len && (str2[str2_len - 1] == pad)) { + str2_len--; + } + + if (str1_len == str2_len) { + return strncmp(str1, str2, str2_len); + } + else if (str1_len > str2_len) { + int ret = strncmp(str1, str2, str2_len); + if (ret == 0) { + ret = 1; + } + return ret; + } + else { + int ret = strncmp(str1, str2, str1_len); + if (ret == 0) { + ret = -1; + } + return ret; + } +} + void BLI_timestr(double _time, char *str, size_t maxlen) { /* format 00:00:00.00 (hr:min:sec) string has to be 12 long */ diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 214fcfa2389..e3fa591a60f 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2684,15 +2684,7 @@ static void uilist_filter_items_default(struct uiList *ui_list, struct bContext else { filter = filter_dyn = MEM_mallocN((slen + 3) * sizeof(char), "filter_dyn"); } - if (filter_raw[idx] != '*') { - filter[idx++] = '*'; - } - memcpy(filter + idx, filter_raw, slen); - idx += slen; - if (filter[idx - 1] != '*') { - filter[idx++] = '*'; - } - filter[idx] = '\0'; + BLI_strncpy_ensure_pad(filter, filter_raw, '*', slen + 3); } RNA_PROP_BEGIN (dataptr, itemptr, prop) diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index f8a90c942bc..10cde8b3316 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -1371,59 +1371,42 @@ static void outliner_sort(SpaceOops *soops, ListBase *lb) /* Filtering ----------------------------------------------- */ -static int outliner_filter_has_name(TreeElement *te, const char *name, int flags) +static bool outliner_filter_has_name(TreeElement *te, const char *name, int flags) { -#if 0 - int found = 0; - - /* determine if match */ - if (flags & SO_FIND_CASE_SENSITIVE) { - if (flags & SO_FIND_COMPLETE) - found = strcmp(te->name, name) == 0; - else - found = strstr(te->name, name) != NULL; - } - else { - if (flags & SO_FIND_COMPLETE) - found = BLI_strcasecmp(te->name, name) == 0; - else - found = BLI_strcasestr(te->name, name) != NULL; - } -#else - int fn_flag = 0; - int found = 0; - + if ((flags & SO_FIND_CASE_SENSITIVE) == 0) fn_flag |= FNM_CASEFOLD; - if (flags & SO_FIND_COMPLETE) { - found = fnmatch(name, te->name, fn_flag) == 0; - } - else { - char fn_name[sizeof(((struct SpaceOops *)NULL)->search_string) + 2]; - BLI_snprintf(fn_name, sizeof(fn_name), "*%s*", name); - found = fnmatch(fn_name, te->name, fn_flag) == 0; - } - return found; -#endif + return fnmatch(name, te->name, fn_flag) == 0; } static int outliner_filter_tree(SpaceOops *soops, ListBase *lb) { TreeElement *te, *ten; TreeStoreElem *tselem; - + char search_buff[sizeof(((struct SpaceOops *)NULL)->search_string) + 2]; + char *search_string; + /* although we don't have any search string, we return true * since the entire tree is ok then... */ if (soops->search_string[0] == 0) return 1; + if (soops->search_flags & SO_FIND_COMPLETE) { + search_string = soops->search_string; + } + else { + search_string = search_buff; + /* Implicitly add heading/trailing wildcards if needed. */ + BLI_strncpy_ensure_pad(search_string, soops->search_string, '*', sizeof(search_string)); + } + for (te = lb->first; te; te = ten) { ten = te->next; - if (0 == outliner_filter_has_name(te, soops->search_string, soops->search_flags)) { + if (!outliner_filter_has_name(te, search_string, soops->search_flags)) { /* item isn't something we're looking for, but... * - if the subtree is expanded, check if there are any matches that can be easily found * so that searching for "cu" in the default scene will still match the Cube diff --git a/tests/gtests/blenlib/BLI_path_util_test.cc b/tests/gtests/blenlib/BLI_path_util_test.cc index ea761bcf32e..c4ef7c2c970 100644 --- a/tests/gtests/blenlib/BLI_path_util_test.cc +++ b/tests/gtests/blenlib/BLI_path_util_test.cc @@ -31,6 +31,7 @@ const char *GHOST_getSystemDir(int version, const char *versionstr) struct ImBuf; void IMB_freeImBuf(struct ImBuf *ibuf) {} +struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf) {return NULL;} #ifdef __linux__ char *zLhm65070058860608_br_find_exe(const char *default_exe) |