You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Tools/SceneAPI/SceneCore/Utilities/PatternMatcher.cpp

174 lines
6.7 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/std/string/regex.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
#include <SceneAPI/SceneCore/Utilities/PatternMatcher.h>
namespace AZ
{
namespace SceneAPI
{
namespace SceneCore
{
PatternMatcher::PatternMatcher(const char* pattern, MatchApproach matcher)
: m_pattern(pattern)
, m_matcher(matcher)
{
}
PatternMatcher::PatternMatcher(const AZStd::string& pattern, MatchApproach matcher)
: m_pattern(pattern)
, m_matcher(matcher)
{
}
PatternMatcher::PatternMatcher(AZStd::string&& pattern, MatchApproach matcher)
: m_pattern(AZStd::move(pattern))
, m_matcher(matcher)
{
}
PatternMatcher::PatternMatcher(PatternMatcher&& rhs)
: m_pattern(AZStd::move(rhs.m_pattern))
, m_matcher(rhs.m_matcher)
{
}
PatternMatcher& PatternMatcher::operator=(PatternMatcher&& rhs)
{
m_pattern = AZStd::move(rhs.m_pattern);
m_matcher = rhs.m_matcher;
return *this;
}
bool PatternMatcher::LoadFromJson(rapidjson::Document::ConstMemberIterator member)
{
if (!member->value.HasMember("PatternMatcher"))
{
AZ_TracePrintf(Utilities::WarningWindow, "Missing element 'PatternMatcher'.");
return false;
}
if (!member->value.HasMember("Pattern"))
{
AZ_TracePrintf(Utilities::WarningWindow, "Missing element 'Pattern'.");
return false;
}
const auto& patternMatcherValue = member->value["PatternMatcher"];
if (!patternMatcherValue.IsString())
{
AZ_TracePrintf(Utilities::WarningWindow, "Element 'PatternMatcher' is not a string.");
return false;
}
const auto& patternValue = member->value["Pattern"];
if (!patternValue.IsString())
{
AZ_TracePrintf(Utilities::WarningWindow, "Element 'Pattern' is not a string.");
return false;
}
if (AzFramework::StringFunc::Equal(patternMatcherValue.GetString(), "postfix"))
{
m_matcher = MatchApproach::PostFix;
}
else if (AzFramework::StringFunc::Equal(patternMatcherValue.GetString(), "prefix"))
{
m_matcher = MatchApproach::PreFix;
}
else if (AzFramework::StringFunc::Equal(patternMatcherValue.GetString(), "regex"))
{
m_matcher = MatchApproach::Regex;
}
else
{
AZ_TracePrintf(Utilities::WarningWindow,
"Element 'PatternMatcher' is no one of the available options postfix, prefix or regex.");
return false;
}
m_pattern = patternValue.GetString();
return true;
}
bool PatternMatcher::MatchesPattern(const char* name, size_t nameLength) const
{
switch (m_matcher)
{
case MatchApproach::PreFix:
return AzFramework::StringFunc::Equal(name, m_pattern.c_str(), false, m_pattern.size());
case MatchApproach::PostFix:
{
if (m_pattern.size() > nameLength)
{
return false;
}
size_t offset = nameLength - m_pattern.size();
return AzFramework::StringFunc::Equal(name + offset, m_pattern.c_str());
}
case MatchApproach::Regex:
{
AZStd::regex comparer(m_pattern, AZStd::regex::extended);
AZStd::smatch match;
return AZStd::regex_match(name, match, comparer);
}
default:
AZ_Assert(false, "Unknown option '%i' for pattern matcher.", m_matcher);
return false;
}
}
bool PatternMatcher::MatchesPattern(const AZStd::string& name) const
{
return MatchesPattern(name.c_str(), name.length());
}
const AZStd::string& PatternMatcher::GetPattern() const
{
return m_pattern;
}
PatternMatcher::MatchApproach PatternMatcher::GetMatchApproach() const
{
return m_matcher;
}
void PatternMatcher::Reflect(ReflectContext* context)
{
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<PatternMatcher>()
->Version(1)
->Field("pattern", &PatternMatcher::m_pattern)
->Field("matcher", &PatternMatcher::m_matcher);
EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<PatternMatcher>("Pattern matcher", "")
->ClassElement(Edit::ClassElements::EditorData, "")
->Attribute(Edit::Attributes::AutoExpand, true)
->DataElement(Edit::UIHandlers::Default, &PatternMatcher::m_pattern, "Pattern", "The pattern the matcher will check against.")
->DataElement(Edit::UIHandlers::ComboBox, &PatternMatcher::m_matcher, "Matcher", "The used approach for matching.")
->EnumAttribute(MatchApproach::PreFix, "PreFix")
->EnumAttribute(MatchApproach::PostFix, "PostFix")
->EnumAttribute(MatchApproach::Regex, "Regex");
}
}
}
} // SceneCore
} // SceneAPI
} // AZ