Permalink
Browse files

Add basic character classes to WildcardMatch()

  • Loading branch information...
lluchs committed Feb 2, 2019
1 parent 75d4ac2 commit ee35d256aa485d35be1bab307ec9833780934577
Showing with 71 additions and 6 deletions.
  1. +1 −1 src/platform/C4SoundSystem.cpp
  2. +31 −4 src/platform/StdFile.cpp
  3. +1 −1 tests/CMakeLists.txt
  4. +38 −0 tests/StdFileTest.cpp
@@ -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);
@@ -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)
@@ -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()
@@ -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("[[-]", "-"));
}

0 comments on commit ee35d25

Please sign in to comment.