util: Adding regex support.
Change-Id: I33d84f4ae9076ff5a9db5232f2955f4be0ed820c
diff --git a/src/util/regex/regex-top-matcher.cpp b/src/util/regex/regex-top-matcher.cpp
new file mode 100644
index 0000000..3e7d4ce
--- /dev/null
+++ b/src/util/regex/regex-top-matcher.cpp
@@ -0,0 +1,246 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Yingdi Yu <yingdi@cs.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#include <stdlib.h>
+
+#include "regex-top-matcher.hpp"
+
+#include "../logging.hpp"
+
+INIT_LOGGER ("RegexTopMatcher");
+
+using namespace std;
+
+namespace ndn
+{
+
+RegexTopMatcher::RegexTopMatcher(const string & expr, const string & expand)
+ : RegexMatcher(expr, EXPR_TOP),
+ m_expand(expand),
+ m_secondaryUsed(false)
+{
+ // _LOG_TRACE ("Enter RegexTopMatcher Constructor");
+
+ m_primaryBackRefManager = ptr_lib::make_shared<RegexBackrefManager>();
+ m_secondaryBackRefManager = ptr_lib::make_shared<RegexBackrefManager>();
+ compile();
+
+ // _LOG_TRACE ("Exit RegexTopMatcher Constructor");
+}
+
+RegexTopMatcher::~RegexTopMatcher()
+{
+ // delete m_backRefManager;
+}
+
+void
+RegexTopMatcher::compile()
+{
+ // _LOG_TRACE ("Enter RegexTopMatcher::compile");
+
+ string errMsg = "Error: RegexTopMatcher.Compile(): ";
+
+ string expr = m_expr;
+
+ if('$' != expr[expr.size() - 1])
+ expr = expr + "<.*>*";
+ else
+ expr = expr.substr(0, expr.size()-1);
+
+ if('^' != expr[0])
+ m_secondaryMatcher = ptr_lib::make_shared<RegexPatternListMatcher>("<.*>*" + expr, m_secondaryBackRefManager);
+ else
+ expr = expr.substr(1, expr.size()-1);
+
+ // _LOG_DEBUG ("reconstructed expr: " << expr);
+
+
+ m_primaryMatcher = ptr_lib::make_shared<RegexPatternListMatcher>(expr, m_primaryBackRefManager);
+
+ // _LOG_TRACE ("Exit RegexTopMatcher::compile");
+}
+
+bool
+RegexTopMatcher::match(const Name & name)
+{
+ // _LOG_DEBUG("Enter RegexTopMatcher::match");
+
+ m_secondaryUsed = false;
+
+ m_matchResult.clear();
+
+ if(m_primaryMatcher->match(name, 0, name.size()))
+ {
+ m_matchResult = m_primaryMatcher->getMatchResult();
+ return true;
+ }
+ else
+ {
+ if (NULL != m_secondaryMatcher && m_secondaryMatcher->match(name, 0, name.size()))
+ {
+ m_matchResult = m_secondaryMatcher->getMatchResult();
+ m_secondaryUsed = true;
+ return true;
+ }
+ return false;
+ }
+}
+
+bool
+RegexTopMatcher::match (const Name & name, const int & offset, const int & len)
+{
+ return match(name);
+}
+
+Name
+RegexTopMatcher::expand (const string & expandStr)
+{
+ // _LOG_TRACE("Enter RegexTopMatcher::expand");
+
+ Name result;
+
+ ptr_lib::shared_ptr<RegexBackrefManager> backRefManager = (m_secondaryUsed ? m_secondaryBackRefManager : m_primaryBackRefManager);
+
+ int backRefNum = backRefManager->size();
+
+ string expand;
+
+ if(expandStr != "")
+ expand = expandStr;
+ else
+ expand = m_expand;
+
+ int offset = 0;
+ while(offset < expand.size())
+ {
+ string item = getItemFromExpand(expand, offset);
+ if(item[0] == '<')
+ {
+ result.append(item.substr(1, item.size() - 2));
+ }
+ if(item[0] == '\\')
+ {
+
+ int index = atoi(item.substr(1, item.size() - 1).c_str());
+
+ if(0 == index){
+ vector<Name::Component>::iterator it = m_matchResult.begin();
+ vector<Name::Component>::iterator end = m_matchResult.end();
+ for(; it != end; it++)
+ result.append (*it);
+ }
+ else if(index <= backRefNum)
+ {
+ vector<Name::Component>::const_iterator it = backRefManager->getBackRef (index - 1)->getMatchResult ().begin();
+ vector<Name::Component>::const_iterator end = backRefManager->getBackRef (index - 1)->getMatchResult ().end();
+ for(; it != end; it++)
+ result.append (*it);
+ }
+ else
+ throw RegexMatcher::Error("Exceed the range of back reference!");
+ }
+ }
+ return result;
+}
+
+string
+RegexTopMatcher::getItemFromExpand(const string & expand, int & offset)
+{
+ // _LOG_TRACE("Enter RegexTopMatcher::getItemFromExpand ");
+ int begin = offset;
+
+ if(expand[offset] == '\\')
+ {
+ offset++;
+ if(offset >= expand.size())
+ throw RegexMatcher::Error("wrong format of expand string!");
+
+ while(expand[offset] <= '9' and expand[offset] >= '0'){
+ offset++;
+ if(offset > expand.size())
+ throw RegexMatcher::Error("wrong format of expand string!");
+ }
+ if(offset > begin + 1)
+ return expand.substr(begin, offset - begin);
+ else
+ throw RegexMatcher::Error("wrong format of expand string!");
+ }
+ else if(expand[offset] == '<')
+ {
+ offset++;
+ if(offset >= expand.size())
+ throw RegexMatcher::Error("wrong format of expand string!");
+
+ int left = 1;
+ int right = 0;
+ while(right < left)
+ {
+ if(expand[offset] == '<')
+ left++;
+ if(expand[offset] == '>')
+ right++;
+ offset++;
+ if(offset >= expand.size())
+ throw RegexMatcher::Error("wrong format of expand string!");
+ }
+ return expand.substr(begin, offset - begin);
+ }
+ else
+ throw RegexMatcher::Error("wrong format of expand string!");
+}
+
+ptr_lib::shared_ptr<RegexTopMatcher>
+RegexTopMatcher::fromName(const Name& name, bool hasAnchor)
+{
+ Name::const_iterator it = name.begin();
+ string regexStr("^");
+
+ for(; it != name.end(); it++)
+ {
+ regexStr.append("<");
+ regexStr.append(convertSpecialChar(it->toEscapedString()));
+ regexStr.append(">");
+ }
+
+ if(hasAnchor)
+ regexStr.append("$");
+
+ return ptr_lib::make_shared<RegexTopMatcher>(regexStr);
+}
+
+string
+RegexTopMatcher::convertSpecialChar(const string& str)
+{
+ string newStr;
+ for(int i = 0; i < str.size(); i++)
+ {
+ char c = str[i];
+ switch(c)
+ {
+ case '.':
+ case '[':
+ case '{':
+ case '}':
+ case '(':
+ case ')':
+ case '\\':
+ case '*':
+ case '+':
+ case '?':
+ case '|':
+ case '^':
+ case '$':
+ newStr.push_back('\\');
+ default:
+ newStr.push_back(c);
+ }
+ }
+
+ return newStr;
+}
+
+}//ndn