summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertise.dev>2020-12-15 15:45:08 -0300
committerFelipe Magno de Almeida <felipe@expertise.dev>2020-12-15 16:10:26 -0300
commit886723d47b27d61bae31b767b308b75c0d909ee9 (patch)
treedfb0f3aed4fc67923845d36d9af476e2ffd348ff
parent1bd1c85a672fcd6f693bf22d837ac60597b27b58 (diff)
downloadefl-886723d47b27d61bae31b767b308b75c0d909ee9.tar.gz
eina: Add eina_fnmatch win32 implementation
-rw-r--r--src/bin/edje/edje_external_inspector.c6
-rw-r--r--src/bin/edje/edje_inspector.c4
-rw-r--r--src/lib/ecore_x/ecore_x_vsync.c4
-rw-r--r--src/lib/eet/eet_lib.c3
-rw-r--r--src/lib/efreet/efreet_mime.c4
-rw-r--r--src/lib/efreet/efreet_utils.c4
-rw-r--r--src/lib/eina/Eina.h1
-rw-r--r--src/lib/eina/eina_fnmatch.c250
-rw-r--r--src/lib/eina/eina_fnmatch.h37
-rw-r--r--src/lib/eina/eina_log.c5
-rw-r--r--src/lib/eina/eina_main.c1
-rw-r--r--src/lib/eina/meson.build2
-rw-r--r--src/lib/elementary/Efl_Ui.h2
-rw-r--r--src/lib/elementary/Elementary.h1
-rw-r--r--src/lib/elementary/elm_gengrid.c8
-rw-r--r--src/lib/elementary/elm_genlist.c10
-rw-r--r--src/lib/embryo/embryo_str.c4
-rw-r--r--src/lib/eo/eo_base_class.c3
-rw-r--r--src/lib/evas/canvas/evas_font_dir.c4
-rw-r--r--src/lib/evas/file/evas_path.c4
-rw-r--r--src/tests/eina/eina_fnmatch_test.c174
-rwxr-xr-xsrc/tests/eina/eina_fnmatch_test.sh63
-rw-r--r--src/tests/evil/unposix/eina_fnmatch_test.c172
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(&regex, reg_pattern, regex_flags))
+ {
+ regfree(&regex);
+ 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(&regex, unix_path, 0, NULL, 0);
+
+ // Cleans-up and returns
+ free(unix_path);
+ free(reg_pattern);
+ regfree(&regex);
+ 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;
+}