aboutsummaryrefslogtreecommitdiff
path: root/src/zenutil/wildcard.cpp
blob: df69f6a5e78862dcb437abb434c67ee7fe114fab (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Copyright Epic Games, Inc. All Rights Reserved.

#include <zencore/string.h>
#include <zenutil/wildcard.h>

#if ZEN_WITH_TESTS
#	include <zencore/testing.h>
#endif	// ZEN_WITH_TESTS

namespace zen {

bool
MatchWildcard(std::string_view::const_iterator WildcardIt,
			  std::string_view::const_iterator WildcardEnd,
			  std::string_view::const_iterator StringIt,
			  std::string_view::const_iterator StringEnd)
{
	for (; WildcardIt != WildcardEnd; WildcardIt++)
	{
		switch (*WildcardIt)
		{
			case '?':
				if (StringIt == StringEnd)
				{
					return false;
				}
				StringIt++;
				break;
			case '*':
				{
					if ((WildcardIt + 1) == WildcardEnd)
					{
						return true;
					}
					size_t Max = std::distance(StringIt, StringEnd);
					for (size_t i = 0; i < Max; i++)
					{
						if (MatchWildcard(WildcardIt + 1, WildcardEnd, StringIt + i, StringEnd))
						{
							return true;
						}
					}
					return false;
				}
			default:
				if (*StringIt != *WildcardIt)
				{
					return false;
				}
				++StringIt;
		}
	}
	return StringIt == StringEnd;
}

bool
MatchWildcard(std::string_view Wildcard, std::string_view String, bool CaseSensitive)
{
	if (CaseSensitive)
	{
		return MatchWildcard(begin(Wildcard), end(Wildcard), begin(String), end(String));
	}
	else
	{
		std::string		 LowercaseWildcard = ToLower(Wildcard);
		std::string		 LowercaseString   = ToLower(String);
		std::string_view LowercaseWildcardView(LowercaseWildcard);
		std::string_view LowercaseStringView(LowercaseString);
		return MatchWildcard(begin(LowercaseWildcardView),
							 end(LowercaseWildcardView),
							 begin(LowercaseStringView),
							 end(LowercaseStringView));
	}
}

#if ZEN_WITH_TESTS

void
wildcard_forcelink()
{
}

TEST_CASE("Wildcard")
{
	CHECK(MatchWildcard("*.*", "normal.txt", true));
	CHECK(MatchWildcard("*.*", "normal.txt", false));

	CHECK(!MatchWildcard("*.*", "normal", true));
	CHECK(!MatchWildcard("*.*", "normal", false));

	CHECK(MatchWildcard("*", "hey/normal", true));
	CHECK(MatchWildcard("*", "hey/normal", false));

	CHECK(MatchWildcard("hey/*.txt", "hey/normal.txt", true));
	CHECK(MatchWildcard("*/?ormal.txt", "hey/normal.txt", true));
	CHECK(!MatchWildcard("*/?rmal.txt", "hey/normal.txt", true));
	CHECK(MatchWildcard("*/?ormal.*", "hey/normal.txt", true));
	CHECK(MatchWildcard("*/?ormal", "hey/normal", true));

	CHECK(MatchWildcard("hey/*.txt", "hey/normaL.txt", false));
	CHECK(MatchWildcard("*/?ormal.TXT", "hey/normal.txt", false));
	CHECK(MatchWildcard("*/?ORMAL.*", "hey/normal.txt", false));
	CHECK(MatchWildcard("*/?ormal", "HEY/normal", false));

	CHECK(!MatchWildcard("hey/*.txt", "heY/normal.txt", true));
	CHECK(!MatchWildcard("*/?ormal.TXT", "hey/normal.txt", true));
	CHECK(!MatchWildcard("*/?ORMAL.*", "hey/normal.txt", true));
	CHECK(!MatchWildcard("*/?ormal", "hey/normaL", true));
}

#endif
}  // namespace zen