blob: ec89125ebe735cf0df7ff578b51bab94a621dc5b [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#include "regex-component-set-matcher.hpp"
namespace ndn {
RegexComponentSetMatcher::RegexComponentSetMatcher(const std::string& expr,
shared_ptr<RegexBackrefManager> backrefManager)
: RegexMatcher(expr, EXPR_COMPONENT_SET, backrefManager)
, m_isInclusion(true)
{
compile();
}
RegexComponentSetMatcher::~RegexComponentSetMatcher()
{
}
bool
RegexComponentSetMatcher::match(const Name& name, size_t offset, size_t len)
{
bool isMatched = false;
/* componentset only matches one component */
if (len != 1)
{
return false;
}
for (auto& component : m_components) {
if (component->match(name, offset, len)) {
isMatched = true;
break;
}
}
m_matchResult.clear();
if (m_isInclusion ? isMatched : !isMatched) {
m_matchResult.push_back(name.get(offset));
return true;
}
else
return false;
}
void
RegexComponentSetMatcher::compile()
{
if (m_expr.size() < 2)
throw Error("Regexp compile error (cannot parse " + m_expr + ")");
switch (m_expr[0]) {
case '<':
return compileSingleComponent();
case '[':
{
size_t lastIndex = m_expr.size() - 1;
if (']' != m_expr[lastIndex])
throw Error("Regexp compile error (no matching ']' in " + m_expr + ")");
if ('^' == m_expr[1]) {
m_isInclusion = false;
compileMultipleComponents(2, lastIndex);
}
else
compileMultipleComponents(1, lastIndex);
break;
}
default:
throw Error("Regexp compile error (cannot parse " + m_expr + ")");
}
}
void
RegexComponentSetMatcher::compileSingleComponent()
{
size_t end = extractComponent(1);
if (m_expr.size() != end) {
throw Error("Component expr error " + m_expr);
}
else {
auto component = make_shared<RegexComponentMatcher>(m_expr.substr(1, end - 2),
m_backrefManager);
m_components.insert(component);
}
}
void
RegexComponentSetMatcher::compileMultipleComponents(size_t start, size_t lastIndex)
{
size_t index = start;
size_t tempIndex = start;
while (index < lastIndex) {
if ('<' != m_expr[index])
throw Error("Component expr error " + m_expr);
tempIndex = index + 1;
index = extractComponent(tempIndex);
auto component = make_shared<RegexComponentMatcher>(m_expr.substr(tempIndex,
index - tempIndex - 1),
m_backrefManager);
m_components.insert(component);
}
if (index != lastIndex)
throw Error("Not sufficient expr to parse " + m_expr);
}
size_t
RegexComponentSetMatcher::extractComponent(size_t index)
{
size_t lcount = 1;
size_t rcount = 0;
while (lcount > rcount) {
switch (m_expr[index]) {
case '<':
lcount++;
break;
case '>':
rcount++;
break;
case 0:
throw Error("Error: square brackets mismatch");
break;
}
index++;
}
return index;
}
} // namespace ndn