blob: 38f1a5a0807b2d0eadd4690d495a0c8616612e2b [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
30void
31RegexTopMatcher::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
37 if('$' != expr[expr.size() - 1])
38 expr = expr + "<.*>*";
39 else
40 expr = expr.substr(0, expr.size()-1);
41
42 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
52bool
53RegexTopMatcher::match(const Name & name)
54{
Yingdi Yu5e974202014-01-29 16:59:06 -080055 m_secondaryUsed = false;
56
57 m_matchResult.clear();
58
59 if(m_primaryMatcher->match(name, 0, name.size()))
60 {
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}
75
76bool
77RegexTopMatcher::match (const Name & name, const int & offset, const int & len)
78{
79 return match(name);
80}
81
82Name
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;
86
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080087 shared_ptr<RegexBackrefManager> backRefManager = (m_secondaryUsed ? m_secondaryBackRefManager : m_primaryBackRefManager);
Yingdi Yu5e974202014-01-29 16:59:06 -080088
89 int backRefNum = backRefManager->size();
90
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080091 std::string expand;
Yingdi Yu5e974202014-01-29 16:59:06 -080092
93 if(expandStr != "")
94 expand = expandStr;
95 else
96 expand = m_expand;
97
98 int offset = 0;
99 while(offset < expand.size())
100 {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800101 std::string item = getItemFromExpand(expand, offset);
Yingdi Yu5e974202014-01-29 16:59:06 -0800102 if(item[0] == '<')
103 {
104 result.append(item.substr(1, item.size() - 2));
105 }
106 if(item[0] == '\\')
107 {
108
109 int index = atoi(item.substr(1, item.size() - 1).c_str());
110
111 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 }
117 else if(index <= backRefNum)
118 {
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!");
126 }
127 }
128 return result;
129}
130
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800131std::string
132RegexTopMatcher::getItemFromExpand(const std::string& expand, int & offset)
Yingdi Yu5e974202014-01-29 16:59:06 -0800133{
Yingdi Yu5e974202014-01-29 16:59:06 -0800134 int begin = offset;
135
136 if(expand[offset] == '\\')
137 {
138 offset++;
139 if(offset >= expand.size())
140 throw RegexMatcher::Error("wrong format of expand string!");
141
142 while(expand[offset] <= '9' and expand[offset] >= '0'){
143 offset++;
144 if(offset > expand.size())
145 throw RegexMatcher::Error("wrong format of expand string!");
146 }
147 if(offset > begin + 1)
148 return expand.substr(begin, offset - begin);
149 else
150 throw RegexMatcher::Error("wrong format of expand string!");
151 }
152 else if(expand[offset] == '<')
153 {
154 offset++;
155 if(offset >= expand.size())
156 throw RegexMatcher::Error("wrong format of expand string!");
157
158 int left = 1;
159 int right = 0;
160 while(right < left)
161 {
162 if(expand[offset] == '<')
163 left++;
164 if(expand[offset] == '>')
165 right++;
166 offset++;
167 if(offset >= expand.size())
168 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("^");
Yingdi Yu5e974202014-01-29 16:59:06 -0800181
182 for(; it != name.end(); it++)
183 {
184 regexStr.append("<");
185 regexStr.append(convertSpecialChar(it->toEscapedString()));
186 regexStr.append(">");
187 }
188
189 if(hasAnchor)
190 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;
Yingdi Yu5e974202014-01-29 16:59:06 -0800199 for(int i = 0; i < str.size(); i++)
200 {
201 char c = str[i];
202 switch(c)
203 {
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