Add basic character classes to WildcardMatch()

master
Lukas Werling 2019-02-02 23:52:02 +01:00
parent 75d4ac2512
commit ee35d256aa
4 changed files with 71 additions and 6 deletions

View File

@ -89,7 +89,7 @@ void C4SoundSystem::Execute()
C4SoundEffect* C4SoundSystem::GetEffect(const char *szSndName)
{
// Remember wildcards before adding .* extension - if there are 2 versions with different file extensions, play the last added
bool bRandomSound = SCharCount('?',szSndName) || SCharCount('*',szSndName);
bool bRandomSound = IsWildcardString(szSndName);
// Evaluate sound name
char szName[C4MaxSoundName+2+1];
SCopy(szSndName,szName,C4MaxSoundName);

View File

@ -364,8 +364,33 @@ bool IsWildcardString(const char *szString)
{
// safety
if (!szString) return false;
// known wildcard characters: *?
return (SCharCount('?', szString)>0) || (SCharCount('*', szString)>0);
// known wildcard characters: *?[
return (SCharCount('?', szString)>0) || (SCharCount('*', szString)>0) || (SCharCount('[', szString)>0);
}
// Parses a character class, skips over it and returns whether it matches the given character.
static bool WildcardMatchCharacterClass(const char **charclass, char matchchar)
{
const char *cc = *charclass;
if (*cc++ != '[') return false;
bool match = false;
// ] is allowed as first character, e.g. []]
do
{
// range, e.g. [a-z]
if (cc[1] == '-' && cc[2] != ']')
{
if (matchchar >= cc[0] && matchchar <= cc[2])
match = true;
cc += 2;
}
// single character
else if (*cc == matchchar)
match = true;
}
while (*++cc && *cc != ']');
*charclass = cc;
return match;
}
bool WildcardMatch(const char *szWildcard, const char *szString)
@ -382,8 +407,10 @@ bool WildcardMatch(const char *szWildcard, const char *szString)
// nothing left to match?
else if (!*pPos)
break;
// equal or one-character-wildcard? proceed
else if (*pWild == '?' || tolower(*pWild) == tolower(*pPos))
// character class, equal or one-character-wildcard? proceed
else if ((*pWild == '[' && WildcardMatchCharacterClass(&pWild, *pPos))
|| *pWild == '?'
|| tolower(*pWild) == tolower(*pPos))
{ pWild++; pPos++; }
// backtrack possible?
else if (pLPos)

View File

@ -113,7 +113,7 @@ if (GTEST_FOUND AND GMOCK_FOUND)
AUX_SOURCE_DIRECTORY("${CMAKE_CURRENT_LIST_DIR}" TESTS_SOURCES)
add_executable(tests EXCLUDE_FROM_ALL ${TESTS_SOURCES} ${C4SCRIPT_SOURCES})
set_property(TARGET "tests" PROPERTY FOLDER "Testing")
target_link_libraries(tests gtest libc4script libmisc)
target_link_libraries(tests gtest gmock libc4script libmisc)
if(UNIX AND NOT APPLE)
target_link_libraries(tests rt)
endif()

View File

@ -0,0 +1,38 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2019, The OpenClonk Team and contributors
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
*/
#include <C4Include.h>
#include "platform/StdFile.h"
#include <gtest/gtest.h>
TEST(StdFileTest, IsWildcardStringTest)
{
EXPECT_TRUE(IsWildcardString("ab*cde"));
EXPECT_TRUE(IsWildcardString("abcd?e"));
EXPECT_TRUE(IsWildcardString("[abc]de"));
EXPECT_FALSE(IsWildcardString("foobar"));
}
TEST(StdFileTest, WildcardMatchTest)
{
EXPECT_TRUE(WildcardMatch("abc*", "abcdefg"));
EXPECT_FALSE(WildcardMatch("abc*", "Xabcdefg"));
EXPECT_TRUE(WildcardMatch("a?c*g", "abcdefg"));
EXPECT_TRUE(WildcardMatch("a[1-9]?", "a5b"));
EXPECT_TRUE(WildcardMatch("a[abc][A-Z]", "acX"));
EXPECT_TRUE(WildcardMatch("[[]", "["));
EXPECT_TRUE(WildcardMatch("[[-]", "-"));
}