blob: 3e7d4ce9fa1825f8ea2ebd5fc8481767d406ac90 [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
8#include <stdlib.h>
9
10#include "regex-top-matcher.hpp"
11
12#include "../logging.hpp"
13
14INIT_LOGGER ("RegexTopMatcher");
15
16using namespace std;
17
18namespace ndn
19{
20
21RegexTopMatcher::RegexTopMatcher(const string & expr, const string & expand)
22 : RegexMatcher(expr, EXPR_TOP),
23 m_expand(expand),
24 m_secondaryUsed(false)
25{
26 // _LOG_TRACE ("Enter RegexTopMatcher Constructor");
27
28 m_primaryBackRefManager = ptr_lib::make_shared<RegexBackrefManager>();
29 m_secondaryBackRefManager = ptr_lib::make_shared<RegexBackrefManager>();
30 compile();
31
32 // _LOG_TRACE ("Exit RegexTopMatcher Constructor");
33}
34
35RegexTopMatcher::~RegexTopMatcher()
36{
37 // delete m_backRefManager;
38}
39
40void
41RegexTopMatcher::compile()
42{
43 // _LOG_TRACE ("Enter RegexTopMatcher::compile");
44
45 string errMsg = "Error: RegexTopMatcher.Compile(): ";
46
47 string expr = m_expr;
48
49 if('$' != expr[expr.size() - 1])
50 expr = expr + "<.*>*";
51 else
52 expr = expr.substr(0, expr.size()-1);
53
54 if('^' != expr[0])
55 m_secondaryMatcher = ptr_lib::make_shared<RegexPatternListMatcher>("<.*>*" + expr, m_secondaryBackRefManager);
56 else
57 expr = expr.substr(1, expr.size()-1);
58
59 // _LOG_DEBUG ("reconstructed expr: " << expr);
60
61
62 m_primaryMatcher = ptr_lib::make_shared<RegexPatternListMatcher>(expr, m_primaryBackRefManager);
63
64 // _LOG_TRACE ("Exit RegexTopMatcher::compile");
65}
66
67bool
68RegexTopMatcher::match(const Name & name)
69{
70 // _LOG_DEBUG("Enter RegexTopMatcher::match");
71
72 m_secondaryUsed = false;
73
74 m_matchResult.clear();
75
76 if(m_primaryMatcher->match(name, 0, name.size()))
77 {
78 m_matchResult = m_primaryMatcher->getMatchResult();
79 return true;
80 }
81 else
82 {
83 if (NULL != m_secondaryMatcher && m_secondaryMatcher->match(name, 0, name.size()))
84 {
85 m_matchResult = m_secondaryMatcher->getMatchResult();
86 m_secondaryUsed = true;
87 return true;
88 }
89 return false;
90 }
91}
92
93bool
94RegexTopMatcher::match (const Name & name, const int & offset, const int & len)
95{
96 return match(name);
97}
98
99Name
100RegexTopMatcher::expand (const string & expandStr)
101{
102 // _LOG_TRACE("Enter RegexTopMatcher::expand");
103
104 Name result;
105
106 ptr_lib::shared_ptr<RegexBackrefManager> backRefManager = (m_secondaryUsed ? m_secondaryBackRefManager : m_primaryBackRefManager);
107
108 int backRefNum = backRefManager->size();
109
110 string expand;
111
112 if(expandStr != "")
113 expand = expandStr;
114 else
115 expand = m_expand;
116
117 int offset = 0;
118 while(offset < expand.size())
119 {
120 string item = getItemFromExpand(expand, offset);
121 if(item[0] == '<')
122 {
123 result.append(item.substr(1, item.size() - 2));
124 }
125 if(item[0] == '\\')
126 {
127
128 int index = atoi(item.substr(1, item.size() - 1).c_str());
129
130 if(0 == index){
131 vector<Name::Component>::iterator it = m_matchResult.begin();
132 vector<Name::Component>::iterator end = m_matchResult.end();
133 for(; it != end; it++)
134 result.append (*it);
135 }
136 else if(index <= backRefNum)
137 {
138 vector<Name::Component>::const_iterator it = backRefManager->getBackRef (index - 1)->getMatchResult ().begin();
139 vector<Name::Component>::const_iterator end = backRefManager->getBackRef (index - 1)->getMatchResult ().end();
140 for(; it != end; it++)
141 result.append (*it);
142 }
143 else
144 throw RegexMatcher::Error("Exceed the range of back reference!");
145 }
146 }
147 return result;
148}
149
150string
151RegexTopMatcher::getItemFromExpand(const string & expand, int & offset)
152{
153 // _LOG_TRACE("Enter RegexTopMatcher::getItemFromExpand ");
154 int begin = offset;
155
156 if(expand[offset] == '\\')
157 {
158 offset++;
159 if(offset >= expand.size())
160 throw RegexMatcher::Error("wrong format of expand string!");
161
162 while(expand[offset] <= '9' and expand[offset] >= '0'){
163 offset++;
164 if(offset > expand.size())
165 throw RegexMatcher::Error("wrong format of expand string!");
166 }
167 if(offset > begin + 1)
168 return expand.substr(begin, offset - begin);
169 else
170 throw RegexMatcher::Error("wrong format of expand string!");
171 }
172 else if(expand[offset] == '<')
173 {
174 offset++;
175 if(offset >= expand.size())
176 throw RegexMatcher::Error("wrong format of expand string!");
177
178 int left = 1;
179 int right = 0;
180 while(right < left)
181 {
182 if(expand[offset] == '<')
183 left++;
184 if(expand[offset] == '>')
185 right++;
186 offset++;
187 if(offset >= expand.size())
188 throw RegexMatcher::Error("wrong format of expand string!");
189 }
190 return expand.substr(begin, offset - begin);
191 }
192 else
193 throw RegexMatcher::Error("wrong format of expand string!");
194}
195
196ptr_lib::shared_ptr<RegexTopMatcher>
197RegexTopMatcher::fromName(const Name& name, bool hasAnchor)
198{
199 Name::const_iterator it = name.begin();
200 string regexStr("^");
201
202 for(; it != name.end(); it++)
203 {
204 regexStr.append("<");
205 regexStr.append(convertSpecialChar(it->toEscapedString()));
206 regexStr.append(">");
207 }
208
209 if(hasAnchor)
210 regexStr.append("$");
211
212 return ptr_lib::make_shared<RegexTopMatcher>(regexStr);
213}
214
215string
216RegexTopMatcher::convertSpecialChar(const string& str)
217{
218 string newStr;
219 for(int i = 0; i < str.size(); i++)
220 {
221 char c = str[i];
222 switch(c)
223 {
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 case '$':
237 newStr.push_back('\\');
238 default:
239 newStr.push_back(c);
240 }
241 }
242
243 return newStr;
244}
245
246}//ndn