diff options
author | Felipe Magno de Almeida <felipe@expertise.dev> | 2020-12-15 15:45:08 -0300 |
---|---|---|
committer | Felipe Magno de Almeida <felipe@expertise.dev> | 2020-12-15 16:10:26 -0300 |
commit | 886723d47b27d61bae31b767b308b75c0d909ee9 (patch) | |
tree | dfb0f3aed4fc67923845d36d9af476e2ffd348ff | |
parent | 1bd1c85a672fcd6f693bf22d837ac60597b27b58 (diff) | |
download | efl-886723d47b27d61bae31b767b308b75c0d909ee9.tar.gz |
eina: Add eina_fnmatch win32 implementation
-rw-r--r-- | src/bin/edje/edje_external_inspector.c | 6 | ||||
-rw-r--r-- | src/bin/edje/edje_inspector.c | 4 | ||||
-rw-r--r-- | src/lib/ecore_x/ecore_x_vsync.c | 4 | ||||
-rw-r--r-- | src/lib/eet/eet_lib.c | 3 | ||||
-rw-r--r-- | src/lib/efreet/efreet_mime.c | 4 | ||||
-rw-r--r-- | src/lib/efreet/efreet_utils.c | 4 | ||||
-rw-r--r-- | src/lib/eina/Eina.h | 1 | ||||
-rw-r--r-- | src/lib/eina/eina_fnmatch.c | 250 | ||||
-rw-r--r-- | src/lib/eina/eina_fnmatch.h | 37 | ||||
-rw-r--r-- | src/lib/eina/eina_log.c | 5 | ||||
-rw-r--r-- | src/lib/eina/eina_main.c | 1 | ||||
-rw-r--r-- | src/lib/eina/meson.build | 2 | ||||
-rw-r--r-- | src/lib/elementary/Efl_Ui.h | 2 | ||||
-rw-r--r-- | src/lib/elementary/Elementary.h | 1 | ||||
-rw-r--r-- | src/lib/elementary/elm_gengrid.c | 8 | ||||
-rw-r--r-- | src/lib/elementary/elm_genlist.c | 10 | ||||
-rw-r--r-- | src/lib/embryo/embryo_str.c | 4 | ||||
-rw-r--r-- | src/lib/eo/eo_base_class.c | 3 | ||||
-rw-r--r-- | src/lib/evas/canvas/evas_font_dir.c | 4 | ||||
-rw-r--r-- | src/lib/evas/file/evas_path.c | 4 | ||||
-rw-r--r-- | src/tests/eina/eina_fnmatch_test.c | 174 | ||||
-rwxr-xr-x | src/tests/eina/eina_fnmatch_test.sh | 63 | ||||
-rw-r--r-- | src/tests/evil/unposix/eina_fnmatch_test.c | 172 |
23 files changed, 732 insertions, 34 deletions
diff --git a/src/bin/edje/edje_external_inspector.c b/src/bin/edje/edje_external_inspector.c index 3a4f937b06..1ab0383778 100644 --- a/src/bin/edje/edje_external_inspector.c +++ b/src/bin/edje/edje_external_inspector.c @@ -3,7 +3,7 @@ #endif #include <locale.h> -#include <fnmatch.h> +#include <Eina.h> #include <Ecore.h> #include <Ecore_Getopt.h> @@ -56,7 +56,7 @@ module_matches(const char *name) if (!module_patterns) return EINA_TRUE; for (itr = module_patterns; *itr != NULL; itr++) - if (fnmatch(*itr, name, 0) == 0) return EINA_TRUE; + if (eina_fnmatch(*itr, name, 0) == 0) return EINA_TRUE; return EINA_FALSE; } @@ -65,7 +65,7 @@ static inline Eina_Bool type_matches(const char *name) { if (!type_glob) return EINA_TRUE; - return fnmatch(type_glob, name, 0) == 0; + return eina_fnmatch(type_glob, name, 0) == 0; } static int diff --git a/src/bin/edje/edje_inspector.c b/src/bin/edje/edje_inspector.c index 25024cee73..8e39a56081 100644 --- a/src/bin/edje/edje_inspector.c +++ b/src/bin/edje/edje_inspector.c @@ -3,7 +3,7 @@ #endif #include <locale.h> -#include <fnmatch.h> +#include <Eina.h> #include <unistd.h> #include <errno.h> @@ -101,7 +101,7 @@ static inline Eina_Bool matches(const char *name, const char *pattern) { if (!pattern) return EINA_TRUE; - return fnmatch(pattern, name, 0) == 0; + return eina_fnmatch(pattern, name, 0) == 0; } static void diff --git a/src/lib/ecore_x/ecore_x_vsync.c b/src/lib/ecore_x/ecore_x_vsync.c index db43d49814..546859ab70 100644 --- a/src/lib/ecore_x/ecore_x_vsync.c +++ b/src/lib/ecore_x/ecore_x_vsync.c @@ -15,7 +15,7 @@ #include <sys/stat.h> #include <sys/select.h> #include <fcntl.h> -#include <fnmatch.h> +#include <Eina.h> #ifdef HAVE_PRCTL # include <sys/prctl.h> @@ -595,7 +595,7 @@ glob_match(const char *glob, const char *str) { if (!glob) return EINA_TRUE; if (!str) return EINA_FALSE; - if (!fnmatch(glob, str, 0)) return EINA_TRUE; + if (!eina_fnmatch(glob, str, 0)) return EINA_TRUE; return EINA_FALSE; } diff --git a/src/lib/eet/eet_lib.c b/src/lib/eet/eet_lib.c index 0ba2cdaed2..ba78771006 100644 --- a/src/lib/eet/eet_lib.c +++ b/src/lib/eet/eet_lib.c @@ -9,7 +9,6 @@ #include <time.h> #include <string.h> #include <unistd.h> -#include <fnmatch.h> #include <fcntl.h> #include <Eina.h> @@ -2607,7 +2606,7 @@ eet_list(Eet_File *ef, * check for * explicitly, because on some systems, * isn't well * supported */ - if ((!glob) || !fnmatch(glob, efn->name, 0)) + if ((!glob) || !eina_fnmatch(glob, efn->name, 0)) { /* add it to our list */ list_count++; diff --git a/src/lib/efreet/efreet_mime.c b/src/lib/efreet/efreet_mime.c index 076bb4ba26..a186dd754e 100644 --- a/src/lib/efreet/efreet_mime.c +++ b/src/lib/efreet/efreet_mime.c @@ -1246,7 +1246,7 @@ efreet_mime_glob_match(const char *str, const char *glob) if (str[0] == 0) return 1; return 0; } - if (!fnmatch(glob, str, 0)) return 1; + if (!eina_fnmatch(glob, str, 0)) return 1; return 0; } @@ -1272,7 +1272,7 @@ efreet_mime_glob_case_match(char *str, const char *glob) tglob = alloca(strlen(glob) + 1); for (tp = tglob, p = glob; *p; p++, tp++) *tp = tolower(*p); *tp = 0; - if (!fnmatch(str, tglob, 0)) return 1; + if (!eina_fnmatch(str, tglob, 0)) return 1; return 0; } diff --git a/src/lib/efreet/efreet_utils.c b/src/lib/efreet/efreet_utils.c index 807840e267..fc4ae9a8c0 100644 --- a/src/lib/efreet/efreet_utils.c +++ b/src/lib/efreet/efreet_utils.c @@ -4,7 +4,7 @@ /* TODO: add no_display check, as we might want only displayable items */ -#include <fnmatch.h> +#include <Eina.h> #include <ctype.h> #include <Ecore_File.h> @@ -450,7 +450,7 @@ efreet_util_glob_match(const char *str, const char *glob) return 0; } if (!strcmp(glob, "*")) return 1; - if (!fnmatch(glob, str, 0)) return 1; + if (!eina_fnmatch(glob, str, 0)) return 1; return 0; } diff --git a/src/lib/eina/Eina.h b/src/lib/eina/Eina.h index cd9dc513f4..7bf09b739c 100644 --- a/src/lib/eina/Eina.h +++ b/src/lib/eina/Eina.h @@ -278,6 +278,7 @@ extern "C" { #include <eina_promise.h> #include <eina_vpath.h> #include <eina_abstract_content.h> +#include <eina_fnmatch.h> #ifdef __cplusplus diff --git a/src/lib/eina/eina_fnmatch.c b/src/lib/eina/eina_fnmatch.c new file mode 100644 index 0000000000..79df90fe55 --- /dev/null +++ b/src/lib/eina/eina_fnmatch.c @@ -0,0 +1,250 @@ + +#include <Eina.h> + +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <pcreposix.h> + +inline static int +_is_escapable(char c) +{ + switch (c) + { + case '[': case '|': case '(': case ')': case '*': case '?': + case '!': case '^': case '$': case '.': case '+': case '\\': + return 1; + default: + return 0; + } +} + +inline static char * +_wildcards_to_regex(const char *pattern, int flags) +{ + + // Counts how many additional chars needs to be allocated + int pattern_length = strlen(pattern); + int count = 2; // starts with '^' and ends with '$' + for (int j = 0; j < pattern_length; ++j) + { + if (pattern[j] == '\\') + { + if (flags & FNM_NOESCAPE) count++; + else count += 2; + } + else if ((pattern[j] == '*') || (pattern[j] == '?')) + { + if (flags & FNM_PATHNAME) + { + if (flags & FNM_PERIOD) // PATHNAME + PERIOD + { + if (pattern[j] == '*') + { + if (j == 0) count += 10; + else if (pattern[j - 1] == '/') count += 10; + else count += 5; + } + else if ((j == 0) || (pattern[j - 1] == '/')) count += 10; + else count += 4; + } + else if (pattern[j] == '*') count += 5; // PATHNAME + else count += 4; + } + else if (flags & FNM_PERIOD) + { + if (j == 0) // period at init + { + if (pattern[j] == '*') count += 5; + else count += 4; + } + // period at other places + else if (pattern[j] == '*') count += 2; + else count++; + } + else if (pattern[j] == '*') count += 2; // NORMAL + else count++; + } + else if (pattern[j] == '.') count += 4; + else count++; // OTHERS + } + + int reg_length = pattern_length + count + 1; + + // Translates wildcards to regex + char *reg_pattern = calloc(sizeof(char), reg_length); + if (reg_pattern == NULL) exit(ENOMEM); + reg_pattern[0] = '^'; + int i = 1; + for (int j = 0; j < pattern_length; ++j) + { + if (pattern[j] == '\\') + { + if (flags & FNM_NOESCAPE) + reg_pattern[i++] = '/'; + else if (_is_escapable(pattern[j + 1])) + { + reg_pattern[i++] = '\\'; + reg_pattern[i++] = pattern[++j]; + } + else + { + reg_pattern[i++] = '\\'; + reg_pattern[i++] = '/'; + } + } + else if ((pattern[j] == '*') || (pattern[j] == '?')) + { + if (flags & FNM_PATHNAME) + { + if (flags & FNM_PERIOD) // PATHNAME + PERIOD + { + if (pattern[j] == '*') + { + if ( (j == 0) || (pattern[j - 1] == '/') ) + { + strcpy_s(reg_pattern + i, + reg_length - i, + "[^\\.][^/]*"); + i += 10; + } + else + { + strcpy_s(reg_pattern + i, + reg_length - i, + "[^/]*"); + i += 5; + } + } + else if (j == 0) + { + strcpy_s(reg_pattern + i, + reg_length - i, + "[^\\.][^/]?"); + i += 10; + } + else if (pattern[j - 1] == '/') + { + strcpy_s(reg_pattern + i, + reg_length - i, + "[^\\.][^/]?"); + i += 10; + } + else + { + strcpy_s(reg_pattern + i, + reg_length - i, + "[^/]"); + i += 4; + } + } + else if (pattern[j] == '*') // PATHNAME + { + strcpy_s(reg_pattern + i, + reg_length - i, + "[^/]*"); + i += 5; + } + else + { + strcpy_s(reg_pattern + i, + reg_length - i, + "[^/]"); + i += 4; + } + } + else if (flags & FNM_PERIOD) + { + if (j == 0) // period at init + { + if (pattern[j] == '*') + { + strcpy_s(reg_pattern + i, + reg_length - i, + "[\\.]*"); + i += 5; + } + else + { + strcpy_s(reg_pattern + i, + reg_length - i, + "[\\.]"); + i += 4; + } + } + else if (pattern[j] == '*') // period at other places + { + strcpy_s(reg_pattern + i, + reg_length - i, + ".*"); + i += 2; + } + else + reg_pattern[i++] = '.'; + } + else if (pattern[j] == '*') // NORMAL + { + strcpy_s(reg_pattern + i, + reg_length - i, + ".*"); + i += 2; + } + else + { + strcpy_s(reg_pattern + i, + reg_length - i, + "."); + i++; + } + } + else if (pattern[j] == '.') + { + strcpy_s(reg_pattern + i, + reg_length - i, + "[\\.]"); + i += 4; + } + else reg_pattern[i++] = pattern[j]; // OTHERS + } + strcpy_s(reg_pattern + i, + reg_length - i, + "$"); + + return reg_pattern; +} + +EINA_API int +eina_fnmatch(const char *pattern, const char *string, int flags) +{ + // Converts wildcard pattern to regex pattern + char *reg_pattern = _wildcards_to_regex(pattern, flags); + + // Configures regex + int regex_flags = (REG_NOSUB) // Report only success/fail in regexec() + || ((flags & FNM_CASEFOLD) ? REG_ICASE : 0); + + // Compiles regex + regex_t regex; + if (regcomp(®ex, reg_pattern, regex_flags)) + { + regfree(®ex); + return FNM_NOMATCH; + } + + // Replaces '\\' with '/' + int string_length = strlen(string); + char *unix_path = calloc(sizeof(char), string_length + 1); + if (unix_path == NULL) exit(ENOMEM); + unix_path[string_length] = '\0'; + for (int i = 0; i < string_length; ++i) + unix_path[i] = (string[i] == '\\') ? '/' : string[i]; + + // Executes regex + int result = regexec(®ex, unix_path, 0, NULL, 0); + + // Cleans-up and returns + free(unix_path); + free(reg_pattern); + regfree(®ex); + return result ? FNM_NOMATCH : 0; +} diff --git a/src/lib/eina/eina_fnmatch.h b/src/lib/eina/eina_fnmatch.h new file mode 100644 index 0000000000..23f079efed --- /dev/null +++ b/src/lib/eina/eina_fnmatch.h @@ -0,0 +1,37 @@ +#ifndef EINA_FNMATCH_H +#define EINA_FNMATCH_H + +#include "eina_types.h" + +#ifdef _WIN32 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Bits set in the FLAGS argument to `fnmatch'. */ +#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ +#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ +#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ + +#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ +#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ + +/* Value returned by `fnmatch' if STRING does not match PATTERN. */ +#define FNM_NOMATCH 1 + +EINA_API int eina_fnmatch(const char *pattern, const char *string, int flags); + +#ifdef __cplusplus +} +#endif + +#else /* _WIN32 */ + +#include <fnmatch.h> +#define eina_fnmatch fnmatch + +#endif /* _WIN32 */ + +#endif /* EINA_FNMATCH_H */ diff --git a/src/lib/eina/eina_log.c b/src/lib/eina/eina_log.c index 1652332cfb..03145afdbf 100644 --- a/src/lib/eina/eina_log.c +++ b/src/lib/eina/eina_log.c @@ -49,6 +49,7 @@ #include "eina_convert.h" #include "eina_strbuf.h" #include "eina_module.h" +#include "eina_fnmatch.h" /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ #include "eina_safety_checks.h" @@ -1278,7 +1279,7 @@ finish_register: { EINA_INLIST_FOREACH(_glob_list, pending) { - if (!fnmatch(pending->name, name, 0)) + if (!eina_fnmatch(pending->name, name, 0)) { _log_domains[i].level = pending->level; break; @@ -1994,7 +1995,7 @@ eina_log_domain_level_get(const char *domain_name) EINA_INLIST_FOREACH(_glob_list, pending) { - if (!fnmatch(pending->name, domain_name, 0)) + if (!eina_fnmatch(pending->name, domain_name, 0)) return pending->level; } diff --git a/src/lib/eina/eina_main.c b/src/lib/eina/eina_main.c index 961d3fe42e..2b221106f1 100644 --- a/src/lib/eina/eina_main.c +++ b/src/lib/eina/eina_main.c @@ -67,6 +67,7 @@ #include "eina_freeq.h" #include "eina_slstr.h" #include "eina_vpath.h" +#include "eina_fnmatch.h" /*============================================================================* * Local * diff --git a/src/lib/eina/meson.build b/src/lib/eina/meson.build index c1bff12561..45d0781680 100644 --- a/src/lib/eina/meson.build +++ b/src/lib/eina/meson.build @@ -115,6 +115,7 @@ public_sub_headers = [ 'eina_vpath.h', 'eina_abstract_content.h', 'eina_pipe.h', +'eina_fnmatch.h' ] public_headers = [ @@ -203,6 +204,7 @@ eina_src = files([ if sys_windows == true eina_src += files('eina_file_win32.c') + eina_src += 'eina_fnmatch.c' else eina_src += files('eina_file.c') endif diff --git a/src/lib/elementary/Efl_Ui.h b/src/lib/elementary/Efl_Ui.h index d9c5fc8881..5662cf02d5 100644 --- a/src/lib/elementary/Efl_Ui.h +++ b/src/lib/elementary/Efl_Ui.h @@ -14,7 +14,7 @@ #include <sys/time.h> #include <sys/param.h> #include <math.h> -#include <fnmatch.h> +#include <Eina.h> #include <limits.h> #include <ctype.h> #include <time.h> diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h index a65c1a2759..1721be4f73 100644 --- a/src/lib/elementary/Elementary.h +++ b/src/lib/elementary/Elementary.h @@ -22,7 +22,6 @@ #include <sys/time.h> #include <sys/param.h> #include <math.h> -#include <fnmatch.h> #include <limits.h> #include <ctype.h> #include <time.h> diff --git a/src/lib/elementary/elm_gengrid.c b/src/lib/elementary/elm_gengrid.c index ceb707c8d8..78c3f7feff 100644 --- a/src/lib/elementary/elm_gengrid.c +++ b/src/lib/elementary/elm_gengrid.c @@ -435,7 +435,7 @@ _elm_gengrid_search_by_text_item_get(Eo *obj EINA_UNUSED, str = it->itc->func.text_get((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), part_name ? part_name : "elm.text"); if (!str) continue; - if (!fnmatch(pattern, str, fnflags)) + if (!eina_fnmatch(pattern, str, fnflags)) { free(str); return EO_OBJ(it); @@ -1021,7 +1021,7 @@ _item_text_realize(Elm_Gen_Item *it, (edje_object_data_get(target, "texts")); EINA_LIST_FOREACH(*source, l, key) { - if (parts && fnmatch(parts, key, FNM_PERIOD)) continue; + if (parts && eina_fnmatch(parts, key, FNM_PERIOD)) continue; s = it->itc->func.text_get ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key); @@ -1070,7 +1070,7 @@ _item_content_realize(Elm_Gen_Item *it, EINA_LIST_FREE(source, key) { - if (parts && fnmatch(parts, key, FNM_PERIOD)) + if (parts && eina_fnmatch(parts, key, FNM_PERIOD)) continue; Evas_Object *old = edje_object_part_swallow_get(target, key); @@ -1137,7 +1137,7 @@ _item_state_realize(Elm_Gen_Item *it, Evas_Object *target, const char *parts) src = elm_widget_stringlist_get(edje_object_data_get(target, "states")); EINA_LIST_FREE(src, key) { - if (parts && fnmatch(parts, key, FNM_PERIOD)) continue; + if (parts && eina_fnmatch(parts, key, FNM_PERIOD)) continue; Eina_Bool on = it->itc->func.state_get ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key); diff --git a/src/lib/elementary/elm_genlist.c b/src/lib/elementary/elm_genlist.c index 961a75aaea..d9b6873e34 100644 --- a/src/lib/elementary/elm_genlist.c +++ b/src/lib/elementary/elm_genlist.c @@ -2,7 +2,7 @@ # include "elementary_config.h" #endif -#include <fnmatch.h> +#include <Eina.h> #define EFL_ACCESS_OBJECT_PROTECTED #define EFL_ACCESS_SELECTION_PROTECTED @@ -347,7 +347,7 @@ _item_text_realize(Elm_Gen_Item *it, (edje_object_data_get(target, "texts")); EINA_LIST_FOREACH(*source, l, key) { - if (parts && fnmatch(parts, key, FNM_PERIOD)) continue; + if (parts && eina_fnmatch(parts, key, FNM_PERIOD)) continue; s = it->itc->func.text_get ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key); @@ -423,7 +423,7 @@ _item_content_realize(Elm_Gen_Item *it, EINA_LIST_FREE(source, key) { - if (parts && fnmatch(parts, key, FNM_PERIOD)) + if (parts && eina_fnmatch(parts, key, FNM_PERIOD)) continue; Evas_Object *old = NULL; @@ -505,7 +505,7 @@ _item_state_realize(Elm_Gen_Item *it, Evas_Object *target, const char *parts) src = elm_widget_stringlist_get(edje_object_data_get(target, "states")); EINA_LIST_FREE(src, key) { - if (parts && fnmatch(parts, key, FNM_PERIOD)) continue; + if (parts && eina_fnmatch(parts, key, FNM_PERIOD)) continue; Eina_Bool on = it->itc->func.state_get ((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), key); @@ -8757,7 +8757,7 @@ _elm_genlist_search_by_text_item_get(Eo *obj EINA_UNUSED, if (!it->itc->func.text_get) continue; str = it->itc->func.text_get((void *)WIDGET_ITEM_DATA_GET(EO_OBJ(it)), WIDGET(it), part_name); if (!str) continue; - if (!fnmatch(pattern, str, fnflags)) + if (!eina_fnmatch(pattern, str, fnflags)) { free(str); return EO_OBJ(it); diff --git a/src/lib/embryo/embryo_str.c b/src/lib/embryo/embryo_str.c index 6fafa83db0..555dc24f7c 100644 --- a/src/lib/embryo/embryo_str.c +++ b/src/lib/embryo/embryo_str.c @@ -14,7 +14,7 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <fnmatch.h> +#include <Eina.h> #include <Eina.h> @@ -61,7 +61,7 @@ _embryo_str_fnmatch(Embryo_Program *ep, Embryo_Cell *params) STRGET(ep, s1, params[1]); STRGET(ep, s2, params[2]); if ((!s1) || (!s2)) return -1; - return (Embryo_Cell)fnmatch(s1, s2, 0); + return (Embryo_Cell)eina_fnmatch(s1, s2, 0); } static Embryo_Cell diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c index c062833188..2ca39c75e5 100644 --- a/src/lib/eo/eo_base_class.c +++ b/src/lib/eo/eo_base_class.c @@ -3,7 +3,6 @@ #endif #include <Eina.h> -#include <fnmatch.h> #include <Eo.h> @@ -543,7 +542,7 @@ _name_match(const char *match, Eina_Bool is_glob, const char *str) // if match string is "*" special case it and match if ((match[0] == '*') && (match[1] == 0)) return EINA_TRUE; // actual compare - if (!fnmatch(match, str, 0)) return EINA_TRUE; + if (!eina_fnmatch(match, str, 0)) return EINA_TRUE; } else { diff --git a/src/lib/evas/canvas/evas_font_dir.c b/src/lib/evas/canvas/evas_font_dir.c index 2d98916ee6..da136dad3a 100644 --- a/src/lib/evas/canvas/evas_font_dir.c +++ b/src/lib/evas/canvas/evas_font_dir.c @@ -65,7 +65,7 @@ static FcConfig *fc_config = NULL; /* FIXME move these helper function to eina_file or eina_path */ /* get the casefold feature! */ -#include <fnmatch.h> +#include <Eina.h> #include <unistd.h> #include <sys/param.h> int @@ -115,7 +115,7 @@ _file_path_list(char *path, const char *match, int match_case) { if (match) { - if (fnmatch(match, info->path + info->name_start, flags) == 0) + if (eina_fnmatch(match, info->path + info->name_start, flags) == 0) files = eina_list_append(files, strdup(info->path + info->name_start)); } else diff --git a/src/lib/evas/file/evas_path.c b/src/lib/evas/file/evas_path.c index ef3d439018..d064b04401 100644 --- a/src/lib/evas/file/evas_path.c +++ b/src/lib/evas/file/evas_path.c @@ -12,7 +12,7 @@ #include <sys/types.h> #include <sys/stat.h> /* get the casefold feature! */ -#include <fnmatch.h> +#include <Eina.h> #include <unistd.h> #include <sys/param.h> @@ -114,7 +114,7 @@ evas_file_path_list(char *path, const char *match, int match_case) { if (match) { - if (fnmatch(match, info->path + info->name_start, flags) == 0) + if (eina_fnmatch(match, info->path + info->name_start, flags) == 0) files = eina_list_append(files, strdup(info->path + info->name_start)); } else diff --git a/src/tests/eina/eina_fnmatch_test.c b/src/tests/eina/eina_fnmatch_test.c new file mode 100644 index 0000000000..445549aa03 --- /dev/null +++ b/src/tests/eina/eina_fnmatch_test.c @@ -0,0 +1,174 @@ +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> + +#include "eina_fnmatch.h" + +// ref: http://kirste.userpage.fu-berlin.de/chemnet/use/info/libc/libc_16.html + +int +test_normal_string(void) +{ + const char * string = "Yep. This is just a n0rmal string!"; + const char * pattern = "*"; + const int flags = 0; + + int ret = 0; + + ret |= eina_fnmatch(pattern, string, flags); + printf("test normal string (T): %cok!\n", !ret?:'n'); + + return ret; +} + +int +test_unix_path(void) +{ + const char * string_valid = "~/linux/usr/include/bits/types/__fpos64_t.h"; + const char * string_invalid = "~/linux/usr/include/bits/types/__fpos64_t_h"; + const char * pattern = "~/linux/usr/include/bits/types/__fpos64_t.h"; + const int flags = FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD; + + int ret = 0; + + ret |= eina_fnmatch(pattern, string_valid, flags); + printf("test unix path (T): %cok!\n", !ret?:'n'); + + ret |= !eina_fnmatch(pattern, string_invalid, flags); + printf("test unix path (F): %cok!\n", !ret?:'n'); + + return ret; +} + +int +test_win_path(void) +{ + const char * string_valid = "C:\\Program Files (x86)[1]<3>$4?!\\Git"; + const char * string_invalid = "\\Program Files (x86)\\Git"; + const char * pattern = "?:\\Program Files*\\Git"; + const int flags = FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD; + + int ret = 0; + + ret |= eina_fnmatch(pattern, string_valid, flags); + printf("test win path (T): %cok!\n", !ret?:'n'); + + ret |= !eina_fnmatch(pattern, string_invalid, flags); + printf("test win path (F): %cok!\n", !ret?:'n'); + + return ret; +} + +int +test_flag_pathname(void) +{ + const char * string = "/usr/share/clang/"; + const char * pattern_valid = "/*/*/*/"; + const char * pattern_invalid = "*"; + const int flags = FNM_PATHNAME; + + int ret = 0; + + ret |= eina_fnmatch(pattern_valid, string, 0); + printf("test FNM_PATHNAME flag (T): %cok!\n", !ret?:'n'); + + ret |= eina_fnmatch(pattern_invalid, string, 0); + printf("test FNM_PATHNAME flag (T): %cok!\n", !ret?:'n'); + + ret |= eina_fnmatch(pattern_valid, string, flags); + printf("test FNM_PATHNAME flag (T): %cok!\n", !ret?:'n'); + + ret |= !eina_fnmatch(pattern_invalid, string, flags); + printf("test FNM_PATHNAME flag (F): %cok!\n", !ret?:'n'); + + return ret; +} + +int +test_flag_period(void) +{ + const char * string = ".config/.isolated-storage/d.none.FBD7"; + const char * pattern_valid = ".*/*/*"; + const char * pattern_invalid = "*/*/*"; + const int flags = FNM_PERIOD; + + int ret = 0; + + ret |= eina_fnmatch(pattern_valid, string, 0); + printf("test FNM_PERIOD flag (T): %cok!\n", !ret?:'n'); + + ret |= eina_fnmatch(pattern_invalid, string, 0); + printf("test FNM_PERIOD flag (T): %cok!\n", !ret?:'n'); + + ret |= eina_fnmatch(pattern_valid, string, flags); + printf("test FNM_PERIOD flag (T): %cok!\n", !ret?:'n'); + + ret |= !eina_fnmatch(pattern_invalid, string, flags); + printf("test FNM_PERIOD flag (F): %cok!\n", !ret?:'n'); + + return ret; +} + +int +test_flag_pathname_period(void) +{ + const char * string = ".config/.isolated-storage/d.none.FBD7"; + const char * pattern_valid = ".*/.*/*"; + const char * pattern_invalid = ".*/*/*"; + const int flags = FNM_PATHNAME | FNM_PERIOD; + + int ret = 0; + + ret |= eina_fnmatch(pattern_valid, string, 0); + printf("test FNM_PATHNAME+FNM_PERIOD flag (T): %cok!\n", !ret?:'n'); + + ret |= eina_fnmatch(pattern_invalid, string, 0); + printf("test FNM_PATHNAME+FNM_PERIOD flag (T): %cok!\n", !ret?:'n'); + + ret |= eina_fnmatch(pattern_valid, string, flags); + printf("test FNM_PATHNAME+FNM_PERIOD flag (T): %cok!\n", !ret?:'n'); + + ret |= !eina_fnmatch(pattern_invalid, string, flags); + printf("test FNM_PATHNAME+FNM_PERIOD flag (F): %cok!\n", !ret?:'n'); + + return ret; +} + +int +test_flag_noescape(void) +{ + const char * string_valid = "C:\\Program Files"; + const char * pattern = "?:\\*"; + const int flags = FNM_NOESCAPE; + + int ret = 0; + + ret |= eina_fnmatch(pattern, string_valid, flags); + printf("test FNM_NOESCAPE flag (T): %cok!\n", !ret?:'n'); + + ret |= !eina_fnmatch(pattern, string_valid, 0); + printf("test FNM_NOESCAPE flag (F): %cok!\n", !ret?:'n'); + + return ret; +} + +int +main(void) +{ + printf("---\n"); + test_normal_string(); + printf("---\n"); + test_flag_pathname(); + printf("---\n"); + test_flag_period(); + printf("---\n"); + test_flag_pathname_period(); + printf("---\n"); + test_flag_noescape(); + printf("---\n"); + test_unix_path(); + printf("---\n"); + test_win_path(); + + return 0; +} diff --git a/src/tests/eina/eina_fnmatch_test.sh b/src/tests/eina/eina_fnmatch_test.sh new file mode 100755 index 0000000000..c2f3b5f406 --- /dev/null +++ b/src/tests/eina/eina_fnmatch_test.sh @@ -0,0 +1,63 @@ +#!/bin/sh + +if [[ "$OSTYPE" == "linux-gnu" ]]; then + + # clean and update + \rm -f fnmatch_test eina_fnmatch_test eina_fnmatch.[hc] + \cp ../../lib/eina/eina_fnmatch.[hc] . && + + # using strcpy instead of strcpy_s on linux + sed -i '6i#define strcpy_s(a,b,c) strcpy(a,c)\n' eina_fnmatch.c + + # build + gcc eina_fnmatch_test.c -o fnmatch_test + gcc eina_fnmatch_test.c eina_fnmatch.c \ + -lpcreposix -lpcre \ + -o eina_fnmatch_test + + # test + chmod +x fnmatch_test eina_fnmatch_test + ./fnmatch_test + ./eina_fnmatch_test + + # clean again + \rm -f fnmatch_test eina_fnmatch_test eina_fnmatch.[hc] + +elif [[ "$OSTYPE" == "msys" ]]; then + + # clean and update + \rm -f eina_fnmatch_test.exe eina_fnmatch.[hc] + \cp ../../lib/eina/eina_fnmatch.[hc] . && + + ### USING WRAP DEPENDENCY BUILD: + # currently not working here :( + # remember to change libpcre*.lib to libpcre*.a + # build dependency: pcre + #PCRE_SRC_DIR=$(pwd)/"../../../subprojects/pcre-8.37" + #PCRE_BIN_DIR=$PCRE_SRC_DIR/build + #cd $PCRE_SRC_DIR && meson configure && meson --wipe build && cd build && ninja && + #cd ../../../src/tests/eina/ + + ### OR USING CUSTOM BUILD: + PCRE_SRC_DIR="/c/Users/joaoantoniocardo/Desktop/pcre-win-build" + PCRE_BIN_DIR=$PCRE_SRC_DIR/build-VS2019/x64/Release + + # build + PATH=$PATH:$PCRE_BIN_DIR + clang-cl -o eina_fnmatch_test.exe \ + $PCRE_BIN_DIR/libpcre*.lib \ + eina_fnmatch_test.c eina_fnmatch.c \ + -I $PCRE_SRC_DIR && + + # test + chmod +x eina_fnmatch_test.exe && + ./eina_fnmatch_test.exe + + # clean again + \rm -rf eina_fnmatch_test.exe eina_fnmatch.[hc] + +fi + + + + diff --git a/src/tests/evil/unposix/eina_fnmatch_test.c b/src/tests/evil/unposix/eina_fnmatch_test.c new file mode 100644 index 0000000000..2f4e10cd0a --- /dev/null +++ b/src/tests/evil/unposix/eina_fnmatch_test.c @@ -0,0 +1,172 @@ +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> + +// ref: http://kirste.userpage.fu-berlin.de/chemnet/use/info/libc/libc_16.html + +int +test_normal_string(void) +{ + const char * string = "Yep. This is just a n0rmal string!"; + const char * pattern = "*"; + const int flags = 0; + + int ret = 0; + + ret |= eina_fnmatch(pattern, string, flags); + printf("test normal string (T): %cok!\n", !ret?:'n'); + + return ret; +} + +int +test_unix_path(void) +{ + const char * string_valid = "~/linux/usr/include/bits/types/__fpos64_t.h"; + const char * string_invalid = "~/linux/usr/include/bits/types/__fpos64_t_h"; + const char * pattern = "~/linux/usr/include/bits/types/__fpos64_t.h"; + const int flags = FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD; + + int ret = 0; + + ret |= eina_fnmatch(pattern, string_valid, flags); + printf("test unix path (T): %cok!\n", !ret?:'n'); + + ret |= !eina_fnmatch(pattern, string_invalid, flags); + printf("test unix path (F): %cok!\n", !ret?:'n'); + + return ret; +} + +int +test_win_path(void) +{ + const char * string_valid = "C:\\Program Files (x86)[1]<3>$4?!\\Git"; + const char * string_invalid = "\\Program Files (x86)\\Git"; + const char * pattern = "?:\\Program Files*\\Git"; + const int flags = FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD; + + int ret = 0; + + ret |= eina_fnmatch(pattern, string_valid, flags); + printf("test win path (T): %cok!\n", !ret?:'n'); + + ret |= !eina_fnmatch(pattern, string_invalid, flags); + printf("test win path (F): %cok!\n", !ret?:'n'); + + return ret; +} + +int +test_flag_pathname(void) +{ + const char * string = "/usr/share/clang/"; + const char * pattern_valid = "/*/*/*/"; + const char * pattern_invalid = "*"; + const int flags = FNM_PATHNAME; + + int ret = 0; + + ret |= eina_fnmatch(pattern_valid, string, 0); + printf("test FNM_PATHNAME flag (T): %cok!\n", !ret?:'n'); + + ret |= eina_fnmatch(pattern_invalid, string, 0); + printf("test FNM_PATHNAME flag (T): %cok!\n", !ret?:'n'); + + ret |= eina_fnmatch(pattern_valid, string, flags); + printf("test FNM_PATHNAME flag (T): %cok!\n", !ret?:'n'); + + ret |= !eina_fnmatch(pattern_invalid, string, flags); + printf("test FNM_PATHNAME flag (F): %cok!\n", !ret?:'n'); + + return ret; +} + +int +test_flag_period(void) +{ + const char * string = ".config/.isolated-storage/d.none.FBD7"; + const char * pattern_valid = ".*/*/*"; + const char * pattern_invalid = "*/*/*"; + const int flags = FNM_PERIOD; + + int ret = 0; + + ret |= eina_fnmatch(pattern_valid, string, 0); + printf("test FNM_PERIOD flag (T): %cok!\n", !ret?:'n'); + + ret |= eina_fnmatch(pattern_invalid, string, 0); + printf("test FNM_PERIOD flag (T): %cok!\n", !ret?:'n'); + + ret |= eina_fnmatch(pattern_valid, string, flags); + printf("test FNM_PERIOD flag (T): %cok!\n", !ret?:'n'); + + ret |= !eina_fnmatch(pattern_invalid, string, flags); + printf("test FNM_PERIOD flag (F): %cok!\n", !ret?:'n'); + + return ret; +} + +int +test_flag_pathname_period(void) +{ + const char * string = ".config/.isolated-storage/d.none.FBD7"; + const char * pattern_valid = ".*/.*/*"; + const char * pattern_invalid = ".*/*/*"; + const int flags = FNM_PATHNAME | FNM_PERIOD; + + int ret = 0; + + ret |= eina_fnmatch(pattern_valid, string, 0); + printf("test FNM_PATHNAME+FNM_PERIOD flag (T): %cok!\n", !ret?:'n'); + + ret |= eina_fnmatch(pattern_invalid, string, 0); + printf("test FNM_PATHNAME+FNM_PERIOD flag (T): %cok!\n", !ret?:'n'); + + ret |= eina_fnmatch(pattern_valid, string, flags); + printf("test FNM_PATHNAME+FNM_PERIOD flag (T): %cok!\n", !ret?:'n'); + + ret |= !eina_fnmatch(pattern_invalid, string, flags); + printf("test FNM_PATHNAME+FNM_PERIOD flag (F): %cok!\n", !ret?:'n'); + + return ret; +} + +int +test_flag_noescape(void) +{ + const char * string_valid = "C:\\Program Files"; + const char * pattern = "?:\\*"; + const int flags = FNM_NOESCAPE; + + int ret = 0; + + ret |= eina_fnmatch(pattern, string_valid, flags); + printf("test FNM_NOESCAPE flag (T): %cok!\n", !ret?:'n'); + + ret |= !eina_fnmatch(pattern, string_valid, 0); + printf("test FNM_NOESCAPE flag (F): %cok!\n", !ret?:'n'); + + return ret; +} + +int +main(void) +{ + printf("---\n"); + test_normal_string(); + printf("---\n"); + test_flag_pathname(); + printf("---\n"); + test_flag_period(); + printf("---\n"); + test_flag_pathname_period(); + printf("---\n"); + test_flag_noescape(); + printf("---\n"); + test_unix_path(); + printf("---\n"); + test_win_path(); + + return 0; +} |