blob: 78cb389ac3bdf49c32111688ac05f7cbaf4f02ec [file] [log] [blame]
Yingdi Yu5e974202014-01-29 16:59:06 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2013 Regents of the University of California.
4 * @author: Yingdi Yu <yingdi@cs.ucla.edu>
5 * See COPYING for copyright and distribution information.
6 */
7
Yingdi Yu5e974202014-01-29 16:59:06 -08008#include "regex-top-matcher.hpp"
9
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080010#include "regex-backref-manager.hpp"
11#include "regex-pattern-list-matcher.hpp"
Yingdi Yu5e974202014-01-29 16:59:06 -080012
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080013namespace ndn {
Yingdi Yu5e974202014-01-29 16:59:06 -080014
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080015RegexTopMatcher::RegexTopMatcher(const std::string& expr, const std::string& expand)
Yingdi Yu5e974202014-01-29 16:59:06 -080016 : RegexMatcher(expr, EXPR_TOP),
17 m_expand(expand),
18 m_secondaryUsed(false)
19{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080020 m_primaryBackRefManager = make_shared<RegexBackrefManager>();
21 m_secondaryBackRefManager = make_shared<RegexBackrefManager>();
Yingdi Yu5e974202014-01-29 16:59:06 -080022 compile();
Yingdi Yu5e974202014-01-29 16:59:06 -080023}
24
25RegexTopMatcher::~RegexTopMatcher()
26{
27 // delete m_backRefManager;
28}
29
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070030void
Yingdi Yu5e974202014-01-29 16:59:06 -080031RegexTopMatcher::compile()
32{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080033 std::string errMsg = "Error: RegexTopMatcher.Compile(): ";
Yingdi Yu5e974202014-01-29 16:59:06 -080034
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080035 std::string expr = m_expr;
Yingdi Yu5e974202014-01-29 16:59:06 -080036
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070037 if ('$' != expr[expr.size() - 1])
Yingdi Yu5e974202014-01-29 16:59:06 -080038 expr = expr + "<.*>*";
39 else
40 expr = expr.substr(0, expr.size()-1);
41
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070042 if ('^' != expr[0])
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080043 m_secondaryMatcher = make_shared<RegexPatternListMatcher>(boost::cref("<.*>*" + expr),
44 boost::cref(m_secondaryBackRefManager));
Yingdi Yu5e974202014-01-29 16:59:06 -080045 else
46 expr = expr.substr(1, expr.size()-1);
47
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080048 m_primaryMatcher = make_shared<RegexPatternListMatcher>(boost::cref(expr),
49 boost::cref(m_primaryBackRefManager));
Yingdi Yu5e974202014-01-29 16:59:06 -080050}
51
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070052bool
53RegexTopMatcher::match(const Name& name)
Yingdi Yu5e974202014-01-29 16:59:06 -080054{
Yingdi Yu5e974202014-01-29 16:59:06 -080055 m_secondaryUsed = false;
56
57 m_matchResult.clear();
58
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070059 if (m_primaryMatcher->match(name, 0, name.size()))
Yingdi Yu5e974202014-01-29 16:59:06 -080060 {
61 m_matchResult = m_primaryMatcher->getMatchResult();
62 return true;
63 }
64 else
65 {
66 if (NULL != m_secondaryMatcher && m_secondaryMatcher->match(name, 0, name.size()))
67 {
68 m_matchResult = m_secondaryMatcher->getMatchResult();
69 m_secondaryUsed = true;
70 return true;
71 }
72 return false;
73 }
74}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070075
76bool
77RegexTopMatcher::match (const Name& name, const int& offset, const int& len)
Yingdi Yu5e974202014-01-29 16:59:06 -080078{
79 return match(name);
80}
81
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070082Name
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080083RegexTopMatcher::expand (const std::string& expandStr)
Yingdi Yu5e974202014-01-29 16:59:06 -080084{
Yingdi Yu5e974202014-01-29 16:59:06 -080085 Name result;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070086
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080087 shared_ptr<RegexBackrefManager> backRefManager = (m_secondaryUsed ? m_secondaryBackRefManager : m_primaryBackRefManager);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070088
Yingdi Yu5e974202014-01-29 16:59:06 -080089 int backRefNum = backRefManager->size();
90
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080091 std::string expand;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070092
93 if (expandStr != "")
Yingdi Yu5e974202014-01-29 16:59:06 -080094 expand = expandStr;
95 else
96 expand = m_expand;
97
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070098 size_t offset = 0;
99 while (offset < expand.size())
Yingdi Yu5e974202014-01-29 16:59:06 -0800100 {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800101 std::string item = getItemFromExpand(expand, offset);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700102 if (item[0] == '<')
Yingdi Yu5e974202014-01-29 16:59:06 -0800103 {
104 result.append(item.substr(1, item.size() - 2));
105 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700106 if (item[0] == '\\')
Yingdi Yu5e974202014-01-29 16:59:06 -0800107 {
108
109 int index = atoi(item.substr(1, item.size() - 1).c_str());
110
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700111 if (0 == index){
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800112 std::vector<name::Component>::iterator it = m_matchResult.begin();
113 std::vector<name::Component>::iterator end = m_matchResult.end();
Yingdi Yu5e974202014-01-29 16:59:06 -0800114 for(; it != end; it++)
115 result.append (*it);
116 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700117 else if (index <= backRefNum)
Yingdi Yu5e974202014-01-29 16:59:06 -0800118 {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800119 std::vector<name::Component>::const_iterator it = backRefManager->getBackRef (index - 1)->getMatchResult ().begin();
120 std::vector<name::Component>::const_iterator end = backRefManager->getBackRef (index - 1)->getMatchResult ().end();
Yingdi Yu5e974202014-01-29 16:59:06 -0800121 for(; it != end; it++)
122 result.append (*it);
123 }
124 else
125 throw RegexMatcher::Error("Exceed the range of back reference!");
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700126 }
Yingdi Yu5e974202014-01-29 16:59:06 -0800127 }
128 return result;
129}
130
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800131std::string
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700132RegexTopMatcher::getItemFromExpand(const std::string& expand, size_t& offset)
Yingdi Yu5e974202014-01-29 16:59:06 -0800133{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700134 size_t begin = offset;
Yingdi Yu5e974202014-01-29 16:59:06 -0800135
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700136 if (expand[offset] == '\\')
Yingdi Yu5e974202014-01-29 16:59:06 -0800137 {
138 offset++;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700139 if (offset >= expand.size())
Yingdi Yu5e974202014-01-29 16:59:06 -0800140 throw RegexMatcher::Error("wrong format of expand string!");
141
142 while(expand[offset] <= '9' and expand[offset] >= '0'){
143 offset++;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700144 if (offset > expand.size())
Yingdi Yu5e974202014-01-29 16:59:06 -0800145 throw RegexMatcher::Error("wrong format of expand string!");
146 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700147 if (offset > begin + 1)
Yingdi Yu5e974202014-01-29 16:59:06 -0800148 return expand.substr(begin, offset - begin);
149 else
150 throw RegexMatcher::Error("wrong format of expand string!");
151 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700152 else if (expand[offset] == '<')
Yingdi Yu5e974202014-01-29 16:59:06 -0800153 {
154 offset++;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700155 if (offset >= expand.size())
Yingdi Yu5e974202014-01-29 16:59:06 -0800156 throw RegexMatcher::Error("wrong format of expand string!");
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700157
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700158 size_t left = 1;
159 size_t right = 0;
Yingdi Yu5e974202014-01-29 16:59:06 -0800160 while(right < left)
161 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700162 if (expand[offset] == '<')
Yingdi Yu5e974202014-01-29 16:59:06 -0800163 left++;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700164 if (expand[offset] == '>')
165 right++;
Yingdi Yu5e974202014-01-29 16:59:06 -0800166 offset++;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700167 if (offset >= expand.size())
Yingdi Yu5e974202014-01-29 16:59:06 -0800168 throw RegexMatcher::Error("wrong format of expand string!");
169 }
170 return expand.substr(begin, offset - begin);
171 }
172 else
173 throw RegexMatcher::Error("wrong format of expand string!");
174}
175
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800176shared_ptr<RegexTopMatcher>
Yingdi Yu5e974202014-01-29 16:59:06 -0800177RegexTopMatcher::fromName(const Name& name, bool hasAnchor)
178{
179 Name::const_iterator it = name.begin();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800180 std::string regexStr("^");
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700181
Yingdi Yu5e974202014-01-29 16:59:06 -0800182 for(; it != name.end(); it++)
183 {
184 regexStr.append("<");
185 regexStr.append(convertSpecialChar(it->toEscapedString()));
186 regexStr.append(">");
187 }
188
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700189 if (hasAnchor)
Yingdi Yu5e974202014-01-29 16:59:06 -0800190 regexStr.append("$");
191
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800192 return make_shared<RegexTopMatcher>(boost::cref(regexStr));
Yingdi Yu5e974202014-01-29 16:59:06 -0800193}
194
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800195std::string
196RegexTopMatcher::convertSpecialChar(const std::string& str)
Yingdi Yu5e974202014-01-29 16:59:06 -0800197{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800198 std::string newStr;
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700199 for(size_t i = 0; i < str.size(); i++)
Yingdi Yu5e974202014-01-29 16:59:06 -0800200 {
201 char c = str[i];
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700202 switch (c)
Yingdi Yu5e974202014-01-29 16:59:06 -0800203 {
204 case '.':
205 case '[':
206 case '{':
207 case '}':
208 case '(':
209 case ')':
210 case '\\':
211 case '*':
212 case '+':
213 case '?':
214 case '|':
215 case '^':
216 case '$':
217 newStr.push_back('\\');
218 default:
219 newStr.push_back(c);
220 }
221 }
222
223 return newStr;
224}
225
226}//ndn