blob: 2c93f17ef71129223ae111de36ea46980dd9040d [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 -080013// #include "../logging.hpp"
Yingdi Yu5e974202014-01-29 16:59:06 -080014
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080015// INIT_LOGGER ("RegexTopMatcher");
Yingdi Yu5e974202014-01-29 16:59:06 -080016
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080017namespace ndn {
Yingdi Yu5e974202014-01-29 16:59:06 -080018
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080019RegexTopMatcher::RegexTopMatcher(const std::string& expr, const std::string& expand)
Yingdi Yu5e974202014-01-29 16:59:06 -080020 : RegexMatcher(expr, EXPR_TOP),
21 m_expand(expand),
22 m_secondaryUsed(false)
23{
24 // _LOG_TRACE ("Enter RegexTopMatcher Constructor");
25
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080026 m_primaryBackRefManager = make_shared<RegexBackrefManager>();
27 m_secondaryBackRefManager = make_shared<RegexBackrefManager>();
Yingdi Yu5e974202014-01-29 16:59:06 -080028 compile();
29
30 // _LOG_TRACE ("Exit RegexTopMatcher Constructor");
31}
32
33RegexTopMatcher::~RegexTopMatcher()
34{
35 // delete m_backRefManager;
36}
37
38void
39RegexTopMatcher::compile()
40{
41 // _LOG_TRACE ("Enter RegexTopMatcher::compile");
42
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080043 std::string errMsg = "Error: RegexTopMatcher.Compile(): ";
Yingdi Yu5e974202014-01-29 16:59:06 -080044
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080045 std::string expr = m_expr;
Yingdi Yu5e974202014-01-29 16:59:06 -080046
47 if('$' != expr[expr.size() - 1])
48 expr = expr + "<.*>*";
49 else
50 expr = expr.substr(0, expr.size()-1);
51
52 if('^' != expr[0])
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080053 m_secondaryMatcher = make_shared<RegexPatternListMatcher>(boost::cref("<.*>*" + expr),
54 boost::cref(m_secondaryBackRefManager));
Yingdi Yu5e974202014-01-29 16:59:06 -080055 else
56 expr = expr.substr(1, expr.size()-1);
57
58 // _LOG_DEBUG ("reconstructed expr: " << expr);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080059
60 m_primaryMatcher = make_shared<RegexPatternListMatcher>(boost::cref(expr),
61 boost::cref(m_primaryBackRefManager));
Yingdi Yu5e974202014-01-29 16:59:06 -080062
63 // _LOG_TRACE ("Exit RegexTopMatcher::compile");
64}
65
66bool
67RegexTopMatcher::match(const Name & name)
68{
69 // _LOG_DEBUG("Enter RegexTopMatcher::match");
70
71 m_secondaryUsed = false;
72
73 m_matchResult.clear();
74
75 if(m_primaryMatcher->match(name, 0, name.size()))
76 {
77 m_matchResult = m_primaryMatcher->getMatchResult();
78 return true;
79 }
80 else
81 {
82 if (NULL != m_secondaryMatcher && m_secondaryMatcher->match(name, 0, name.size()))
83 {
84 m_matchResult = m_secondaryMatcher->getMatchResult();
85 m_secondaryUsed = true;
86 return true;
87 }
88 return false;
89 }
90}
91
92bool
93RegexTopMatcher::match (const Name & name, const int & offset, const int & len)
94{
95 return match(name);
96}
97
98Name
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080099RegexTopMatcher::expand (const std::string& expandStr)
Yingdi Yu5e974202014-01-29 16:59:06 -0800100{
101 // _LOG_TRACE("Enter RegexTopMatcher::expand");
102
103 Name result;
104
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800105 shared_ptr<RegexBackrefManager> backRefManager = (m_secondaryUsed ? m_secondaryBackRefManager : m_primaryBackRefManager);
Yingdi Yu5e974202014-01-29 16:59:06 -0800106
107 int backRefNum = backRefManager->size();
108
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800109 std::string expand;
Yingdi Yu5e974202014-01-29 16:59:06 -0800110
111 if(expandStr != "")
112 expand = expandStr;
113 else
114 expand = m_expand;
115
116 int offset = 0;
117 while(offset < expand.size())
118 {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800119 std::string item = getItemFromExpand(expand, offset);
Yingdi Yu5e974202014-01-29 16:59:06 -0800120 if(item[0] == '<')
121 {
122 result.append(item.substr(1, item.size() - 2));
123 }
124 if(item[0] == '\\')
125 {
126
127 int index = atoi(item.substr(1, item.size() - 1).c_str());
128
129 if(0 == index){
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800130 std::vector<name::Component>::iterator it = m_matchResult.begin();
131 std::vector<name::Component>::iterator end = m_matchResult.end();
Yingdi Yu5e974202014-01-29 16:59:06 -0800132 for(; it != end; it++)
133 result.append (*it);
134 }
135 else if(index <= backRefNum)
136 {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800137 std::vector<name::Component>::const_iterator it = backRefManager->getBackRef (index - 1)->getMatchResult ().begin();
138 std::vector<name::Component>::const_iterator end = backRefManager->getBackRef (index - 1)->getMatchResult ().end();
Yingdi Yu5e974202014-01-29 16:59:06 -0800139 for(; it != end; it++)
140 result.append (*it);
141 }
142 else
143 throw RegexMatcher::Error("Exceed the range of back reference!");
144 }
145 }
146 return result;
147}
148
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800149std::string
150RegexTopMatcher::getItemFromExpand(const std::string& expand, int & offset)
Yingdi Yu5e974202014-01-29 16:59:06 -0800151{
152 // _LOG_TRACE("Enter RegexTopMatcher::getItemFromExpand ");
153 int begin = offset;
154
155 if(expand[offset] == '\\')
156 {
157 offset++;
158 if(offset >= expand.size())
159 throw RegexMatcher::Error("wrong format of expand string!");
160
161 while(expand[offset] <= '9' and expand[offset] >= '0'){
162 offset++;
163 if(offset > expand.size())
164 throw RegexMatcher::Error("wrong format of expand string!");
165 }
166 if(offset > begin + 1)
167 return expand.substr(begin, offset - begin);
168 else
169 throw RegexMatcher::Error("wrong format of expand string!");
170 }
171 else if(expand[offset] == '<')
172 {
173 offset++;
174 if(offset >= expand.size())
175 throw RegexMatcher::Error("wrong format of expand string!");
176
177 int left = 1;
178 int right = 0;
179 while(right < left)
180 {
181 if(expand[offset] == '<')
182 left++;
183 if(expand[offset] == '>')
184 right++;
185 offset++;
186 if(offset >= expand.size())
187 throw RegexMatcher::Error("wrong format of expand string!");
188 }
189 return expand.substr(begin, offset - begin);
190 }
191 else
192 throw RegexMatcher::Error("wrong format of expand string!");
193}
194
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800195shared_ptr<RegexTopMatcher>
Yingdi Yu5e974202014-01-29 16:59:06 -0800196RegexTopMatcher::fromName(const Name& name, bool hasAnchor)
197{
198 Name::const_iterator it = name.begin();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800199 std::string regexStr("^");
Yingdi Yu5e974202014-01-29 16:59:06 -0800200
201 for(; it != name.end(); it++)
202 {
203 regexStr.append("<");
204 regexStr.append(convertSpecialChar(it->toEscapedString()));
205 regexStr.append(">");
206 }
207
208 if(hasAnchor)
209 regexStr.append("$");
210
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800211 return make_shared<RegexTopMatcher>(boost::cref(regexStr));
Yingdi Yu5e974202014-01-29 16:59:06 -0800212}
213
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800214std::string
215RegexTopMatcher::convertSpecialChar(const std::string& str)
Yingdi Yu5e974202014-01-29 16:59:06 -0800216{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800217 std::string newStr;
Yingdi Yu5e974202014-01-29 16:59:06 -0800218 for(int i = 0; i < str.size(); i++)
219 {
220 char c = str[i];
221 switch(c)
222 {
223 case '.':
224 case '[':
225 case '{':
226 case '}':
227 case '(':
228 case ')':
229 case '\\':
230 case '*':
231 case '+':
232 case '?':
233 case '|':
234 case '^':
235 case '$':
236 newStr.push_back('\\');
237 default:
238 newStr.push_back(c);
239 }
240 }
241
242 return newStr;
243}
244
245}//ndn