1 /* sdb - MIT - Copyright 2015-2016 - pancake */
2 
3 #include "sdb.h"
4 #include <ctype.h>
5 
haveSuffix(const char * glob,int glob_len,const char * sfx)6 static inline int haveSuffix(const char *glob, int glob_len, const char *sfx) {
7 	const int sfx_len = strlen (sfx);
8 	return (glob_len>sfx_len && !strcmp (glob+glob_len-sfx_len, sfx));
9 }
10 
havePrefix(const char * glob,int glob_len,const char * pfx)11 static inline int havePrefix(const char *glob, int glob_len, const char *pfx) {
12 	const int pfx_len = strlen (pfx);
13 	return (pfx_len<glob_len && !strncmp (glob, pfx, pfx_len));
14 }
15 
16 enum MatchFlag {
17 	SDB_LIKE_NONE = 0,
18 	SDB_LIKE_ICASE = 1, // ?i
19 	SDB_LIKE_START = 2, // ^
20 	SDB_LIKE_END = 4,   // $
21 	SDB_LIKE_BASE64 = 8 // %
22 };
23 
mycmp(const char * a,const char * b,int n,int any)24 static inline int mycmp(const char *a, const char *b, int n, int any) {
25 	int i, j;
26 	for (i = j = 0; a[i] && b[j] && j < n; i++) {
27 		if (tolower ((const ut8)a[i]) == tolower ((const ut8)b[j])) {
28 			j++;
29 		} else {
30 			if (!any) {
31 				return 0;
32 			}
33 			j = 0;
34 		}
35 	}
36 	return any? j != n: 1;
37 }
38 
strstr2(const char * a,const char * b,int n)39 static inline int strstr2(const char *a, const char *b, int n) {
40 	int i, j;
41 	for (i = j = 0; a[i] && b[j] && j < n; i++) {
42 		if (a[i] == b[j]) {
43 			j++;
44 		} else {
45 			j = 0;
46 		}
47 	}
48 	return j == n;
49 }
50 
compareString(const char * a,const char * b,int blen,int flags)51 static inline bool compareString(const char *a, const char *b, int blen, int flags) {
52 	const int start = flags & SDB_LIKE_START;
53 	const int end = flags & SDB_LIKE_END;
54 	char *aa = NULL;
55 	int alen;
56 	bool ret = false;
57 	if (!a || !b || blen < 0) {
58 		return 0;
59 	}
60 	if (flags & SDB_LIKE_BASE64) {
61 		aa = (char*)sdb_decode (a, &alen);
62 		if (!aa) {
63 			return 0;
64 		}
65 		a = (const char *)aa;
66 	} else {
67 		alen = strlen (a);
68 	}
69 	if (blen <= alen) {
70 		if (flags & SDB_LIKE_ICASE) {
71 			if (start && end) ret = (alen==blen && !mycmp (a, b, blen, 0));
72 			else if (start) ret = !mycmp (a, b, blen, 0);
73 			else if (end) ret = !mycmp (a+(alen-blen), b, blen, 0);
74 			else ret = !mycmp (a, b, blen, 1);
75 		} else {
76 			if (start && end) ret = (alen==blen && !strncmp (a, b, blen));
77 			else if (start) ret = !strncmp (a, b, blen);
78 			else if (end) ret = !strncmp (a+(alen-blen), b, blen);
79 			else ret = strstr2 (a, b, blen);
80 		}
81 	}
82 	free (aa);
83 	return ret;
84 }
85 
sdb_match(const char * str,const char * glob)86 SDB_API bool sdb_match (const char *str, const char *glob) {
87 	int glob_len, flags = SDB_LIKE_NONE;
88 	if (!str || !glob) {
89 		return false;
90 	}
91 	glob_len = strlen (glob);
92 	if (haveSuffix (glob, glob_len, "?i")) {
93 		glob_len -= 2;
94 		flags |= SDB_LIKE_ICASE;
95 	}
96 	if (havePrefix (glob, glob_len, "%")) {
97 		glob++;
98 		glob_len--;
99 		flags |= SDB_LIKE_BASE64;
100 	}
101 	if (havePrefix (glob, glob_len, "^")) {
102 		glob++;
103 		glob_len--;
104 		flags |= SDB_LIKE_START;
105 	}
106 	if (haveSuffix (glob, glob_len, "$")) {
107 		glob_len--;
108 		flags |= SDB_LIKE_END;
109 	}
110 	return compareString (str, glob, glob_len, flags);
111 }
112