windows: Add fnmatch win32 implementation

This commit is contained in:
João Antônio Cardoso 2020-04-15 15:39:50 -03:00 committed by Felipe Magno de Almeida
parent cb1b57ec6a
commit 64964ed930
25 changed files with 736 additions and 64 deletions

View File

@ -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

View File

@ -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

View File

@ -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>
@ -457,7 +457,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;
}

View File

@ -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++;

View File

@ -6,7 +6,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <fnmatch.h>
#include <Eina.h>
#include <Ecore.h>
#include <Ecore_File.h>
@ -1243,7 +1243,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;
}
@ -1269,7 +1269,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;
}

View File

@ -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;
}

View File

@ -277,6 +277,7 @@ extern "C" {
#include <eina_promise.h>
#include <eina_vpath.h>
#include <eina_abstract_content.h>
#include <eina_fnmatch.h>
#ifdef __cplusplus

249
src/lib/eina/eina_fnmatch.c Normal file
View File

@ -0,0 +1,249 @@
#include "eina_fnmatch.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;
// Translates wildcards to regex
char *reg_pattern = (char *)malloc(reg_length * sizeof(char));
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,
sizeof(reg_pattern + i),
"[^\\.][^/]*");
i += 10;
}
else
{
strcpy_s(reg_pattern + i,
sizeof(reg_pattern + i),
"[^/]*");
i += 5;
}
}
else if (j == 0)
{
strcpy_s(reg_pattern + i,
sizeof(reg_pattern + i),
"[^\\.][^/]?");
i += 10;
}
else if (pattern[j - 1] == '/')
{
strcpy_s(reg_pattern + i,
sizeof(reg_pattern + i),
"[^\\.][^/]?");
i += 10;
}
else
{
strcpy_s(reg_pattern + i,
sizeof(reg_pattern + i),
"[^/]");
i += 4;
}
}
else if (pattern[j] == '*') // PATHNAME
{
strcpy_s(reg_pattern + i,
sizeof(reg_pattern + i),
"[^/]*");
i += 5;
}
else
{
strcpy_s(reg_pattern + i,
sizeof(reg_pattern + i),
"[^/]");
i += 4;
}
}
else if (flags & FNM_PERIOD)
{
if (j == 0) // period at init
{
if (pattern[j] == '*')
{
strcpy_s(reg_pattern + i,
sizeof(reg_pattern + i),
"[\\.]*");
i += 5;
}
else
{
strcpy_s(reg_pattern + i,
sizeof(reg_pattern + i),
"[\\.]");
i += 4;
}
}
else if (pattern[j] == '*') // period at other places
{
strcpy_s(reg_pattern + i,
sizeof(reg_pattern + i),
".*");
i += 2;
}
else
reg_pattern[i++] = '.';
}
else if (pattern[j] == '*') // NORMAL
{
strcpy_s(reg_pattern + i,
sizeof(reg_pattern + i),
".*");
i += 2;
}
else
{
strcpy_s(reg_pattern + i,
sizeof(reg_pattern + i),
".");
i++;
}
}
else if (pattern[j] == '.')
{
strcpy_s(reg_pattern + i,
sizeof(reg_pattern + i),
"[\\.]");
i += 4;
}
else reg_pattern[i++] = pattern[j]; // OTHERS
}
strcpy_s(reg_pattern + i,
sizeof(reg_pattern + i),
"$\0");
return reg_pattern;
}
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 = (char *)malloc(string_length * sizeof(char));
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;
}

View File

@ -0,0 +1,37 @@
#ifndef EINA_FNMATCH_H
#define EINA_FNMATCH_H
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef _WIN32
/* 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
int eina_fnmatch(const char *pattern, const char *string, int flags);
#else /* _WIN32 */
//#define eina_fnmatch(a,b,c) fnmatch(a,b,c)
#include <fnmatch.h>
#define eina_fnmatch fnmatch
#endif /* _WIN32 */
#ifdef __cplusplus
}
#endif
#endif /* EINA_FNMATCH_H */

View File

@ -25,7 +25,6 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fnmatch.h>
#include <assert.h>
#include <errno.h>
@ -51,6 +50,7 @@
#include "eina_thread.h"
#include "eina_convert.h"
#include "eina_strbuf.h"
#include "eina_fnmatch.h"
/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
#include "eina_safety_checks.h"
@ -1280,7 +1280,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;
@ -1996,7 +1996,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;
}

View File

@ -67,6 +67,7 @@
#include "eina_slstr.h"
#include "eina_vpath.h"
#include "eina_thread.h"
#include "eina_fnmatch.h"
/*============================================================================*
* Local *

View File

@ -1,7 +1,7 @@
if not sys_windows
eina_deps = [dl]
else
eina_deps = []
eina_deps = [pcre_dep]
endif
eina_pub_deps = [thread_dep]
@ -109,7 +109,8 @@ public_sub_headers = [
'eina_freeq.h',
'eina_slstr.h',
'eina_vpath.h',
'eina_abstract_content.h'
'eina_abstract_content.h',
'eina_fnmatch.h'
]
public_headers = [
@ -199,6 +200,7 @@ if sys_windows == true
public_sub_headers += 'eina_inline_thread_win32.x'
sources += 'eina_file_win32.c'
sources += 'eina_sched_win32.c'
sources += 'eina_fnmatch.c'
public_sub_headers += 'eina_inline_lock_win32.x'
else
public_sub_headers += 'eina_thread_posix.h'

View File

@ -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>

View File

@ -20,7 +20,6 @@
#include <sys/time.h>
#include <sys/param.h>
#include <math.h>
#include <fnmatch.h>
#include <limits.h>
#include <ctype.h>
#include <time.h>

View File

@ -433,7 +433,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);
@ -1019,7 +1019,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);
@ -1068,7 +1068,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);
@ -1135,7 +1135,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);

View File

@ -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);
@ -8746,7 +8746,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);

View File

@ -14,7 +14,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fnmatch.h>
#include <Eina.h>
#include "Embryo.h"
#include "embryo_private.h"
@ -59,7 +59,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

View File

@ -3,7 +3,6 @@
#endif
#include <Eina.h>
#include <fnmatch.h>
#include <Eo.h>
@ -544,7 +543,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
{

View File

@ -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

View File

@ -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

View File

@ -1,23 +0,0 @@
#ifndef UNPOSIX_FNMATCH_H
#define UNPOSIX_FNMATCH_H
#ifdef __cplusplus
extern "C" {
#endif
// The string does not match the specified pattern.
#define FNM_NOMATCH 1
// <slash> in string only matches <slash> in pattern.
#define FNM_PATHNAME (1 << 0)
// Disable backslash escaping.
#define FNM_NOESCAPE (1 << 1)
// Leading <period> in string must be exactly matched by <period> in pattern.
#define FNM_PERIOD (1 << 2)
int fnmatch(const char *, const char *, int);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -4,7 +4,6 @@ if sys_windows
evil_unposix_src = []
evil_unposix_header_src = [
'fnmatch.h',
'libgen.h',
'limits.h',
'locale.h',
@ -22,14 +21,14 @@ if sys_windows
evil_unposix_lib = static_library('evil_unposix',
evil_unposix_src,
include_directories: [include_directories('.'), config_dir],
dependencies : [pcre_dep, getopt_dep],
dependencies : [getopt_dep],
install: true,
version: meson.project_version(),
)
evil_unposix = declare_dependency(
include_directories: [include_directories('.')],
dependencies: [pcre_dep, getopt_dep],
dependencies: [getopt_dep],
link_with: evil_unposix_lib,
)

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}