blob: 6a4cf36fc47602149f7eb24a11a33aa0fb6e3080 [file] [log] [blame]
Yingdi Yu5e974202014-01-29 16:59:06 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 *
12 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Yingdi Yu5e974202014-01-29 16:59:06 -080013 */
14
Yingdi Yu5e974202014-01-29 16:59:06 -080015#include "regex-top-matcher.hpp"
16
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080017#include "regex-backref-manager.hpp"
18#include "regex-pattern-list-matcher.hpp"
Yingdi Yu5e974202014-01-29 16:59:06 -080019
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080020namespace ndn {
Yingdi Yu5e974202014-01-29 16:59:06 -080021
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080022RegexTopMatcher::RegexTopMatcher(const std::string& expr, const std::string& expand)
Yingdi Yu5e974202014-01-29 16:59:06 -080023 : RegexMatcher(expr, EXPR_TOP),
24 m_expand(expand),
25 m_secondaryUsed(false)
26{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080027 m_primaryBackRefManager = make_shared<RegexBackrefManager>();
28 m_secondaryBackRefManager = make_shared<RegexBackrefManager>();
Yingdi Yu5e974202014-01-29 16:59:06 -080029 compile();
Yingdi Yu5e974202014-01-29 16:59:06 -080030}
31
32RegexTopMatcher::~RegexTopMatcher()
33{
34 // delete m_backRefManager;
35}
36
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070037void
Yingdi Yu5e974202014-01-29 16:59:06 -080038RegexTopMatcher::compile()
39{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080040 std::string errMsg = "Error: RegexTopMatcher.Compile(): ";
Yingdi Yu5e974202014-01-29 16:59:06 -080041
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080042 std::string expr = m_expr;
Yingdi Yu5e974202014-01-29 16:59:06 -080043
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070044 if ('$' != expr[expr.size() - 1])
Yingdi Yu5e974202014-01-29 16:59:06 -080045 expr = expr + "<.*>*";
46 else
47 expr = expr.substr(0, expr.size()-1);
48
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070049 if ('^' != expr[0])
Alexander Afanasyevb67090a2014-04-29 22:31:01 -070050 m_secondaryMatcher = make_shared<RegexPatternListMatcher>("<.*>*" + expr,
51 cref(m_secondaryBackRefManager));
Yingdi Yu5e974202014-01-29 16:59:06 -080052 else
53 expr = expr.substr(1, expr.size()-1);
54
Alexander Afanasyevb67090a2014-04-29 22:31:01 -070055 m_primaryMatcher = make_shared<RegexPatternListMatcher>(func_lib::cref(expr),
56 func_lib::cref(m_primaryBackRefManager));
Yingdi Yu5e974202014-01-29 16:59:06 -080057}
58
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070059bool
60RegexTopMatcher::match(const Name& name)
Yingdi Yu5e974202014-01-29 16:59:06 -080061{
Yingdi Yu5e974202014-01-29 16:59:06 -080062 m_secondaryUsed = false;
63
64 m_matchResult.clear();
65
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070066 if (m_primaryMatcher->match(name, 0, name.size()))
Yingdi Yu5e974202014-01-29 16:59:06 -080067 {
68 m_matchResult = m_primaryMatcher->getMatchResult();
69 return true;
70 }
71 else
72 {
73 if (NULL != m_secondaryMatcher && m_secondaryMatcher->match(name, 0, name.size()))
74 {
75 m_matchResult = m_secondaryMatcher->getMatchResult();
76 m_secondaryUsed = true;
77 return true;
78 }
79 return false;
80 }
81}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070082
83bool
84RegexTopMatcher::match (const Name& name, const int& offset, const int& len)
Yingdi Yu5e974202014-01-29 16:59:06 -080085{
86 return match(name);
87}
88
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070089Name
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080090RegexTopMatcher::expand (const std::string& expandStr)
Yingdi Yu5e974202014-01-29 16:59:06 -080091{
Yingdi Yu5e974202014-01-29 16:59:06 -080092 Name result;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070093
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070094 shared_ptr<RegexBackrefManager> backRefManager =
95 (m_secondaryUsed ? m_secondaryBackRefManager : m_primaryBackRefManager);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070096
Yingdi Yu5e974202014-01-29 16:59:06 -080097 int backRefNum = backRefManager->size();
98
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080099 std::string expand;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700100
101 if (expandStr != "")
Yingdi Yu5e974202014-01-29 16:59:06 -0800102 expand = expandStr;
103 else
104 expand = m_expand;
105
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700106 size_t offset = 0;
107 while (offset < expand.size())
Yingdi Yu5e974202014-01-29 16:59:06 -0800108 {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800109 std::string item = getItemFromExpand(expand, offset);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700110 if (item[0] == '<')
Yingdi Yu5e974202014-01-29 16:59:06 -0800111 {
112 result.append(item.substr(1, item.size() - 2));
113 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700114 if (item[0] == '\\')
Yingdi Yu5e974202014-01-29 16:59:06 -0800115 {
116
117 int index = atoi(item.substr(1, item.size() - 1).c_str());
118
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700119 if (0 == index){
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800120 std::vector<name::Component>::iterator it = m_matchResult.begin();
121 std::vector<name::Component>::iterator end = m_matchResult.end();
Yingdi Yu5e974202014-01-29 16:59:06 -0800122 for(; it != end; it++)
123 result.append (*it);
124 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700125 else if (index <= backRefNum)
Yingdi Yu5e974202014-01-29 16:59:06 -0800126 {
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -0700127 std::vector<name::Component>::const_iterator it =
128 backRefManager->getBackRef (index - 1)->getMatchResult ().begin();
129 std::vector<name::Component>::const_iterator end =
130 backRefManager->getBackRef (index - 1)->getMatchResult ().end();
Yingdi Yu5e974202014-01-29 16:59:06 -0800131 for(; it != end; it++)
132 result.append (*it);
133 }
134 else
135 throw RegexMatcher::Error("Exceed the range of back reference!");
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700136 }
Yingdi Yu5e974202014-01-29 16:59:06 -0800137 }
138 return result;
139}
140
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800141std::string
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700142RegexTopMatcher::getItemFromExpand(const std::string& expand, size_t& offset)
Yingdi Yu5e974202014-01-29 16:59:06 -0800143{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700144 size_t begin = offset;
Yingdi Yu5e974202014-01-29 16:59:06 -0800145
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700146 if (expand[offset] == '\\')
Yingdi Yu5e974202014-01-29 16:59:06 -0800147 {
148 offset++;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700149 if (offset >= expand.size())
Yingdi Yu5e974202014-01-29 16:59:06 -0800150 throw RegexMatcher::Error("wrong format of expand string!");
151
152 while(expand[offset] <= '9' and expand[offset] >= '0'){
153 offset++;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700154 if (offset > expand.size())
Yingdi Yu5e974202014-01-29 16:59:06 -0800155 throw RegexMatcher::Error("wrong format of expand string!");
156 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700157 if (offset > begin + 1)
Yingdi Yu5e974202014-01-29 16:59:06 -0800158 return expand.substr(begin, offset - begin);
159 else
160 throw RegexMatcher::Error("wrong format of expand string!");
161 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700162 else if (expand[offset] == '<')
Yingdi Yu5e974202014-01-29 16:59:06 -0800163 {
164 offset++;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700165 if (offset >= expand.size())
Yingdi Yu5e974202014-01-29 16:59:06 -0800166 throw RegexMatcher::Error("wrong format of expand string!");
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700167
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700168 size_t left = 1;
169 size_t right = 0;
Yingdi Yu5e974202014-01-29 16:59:06 -0800170 while(right < left)
171 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700172 if (expand[offset] == '<')
Yingdi Yu5e974202014-01-29 16:59:06 -0800173 left++;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700174 if (expand[offset] == '>')
175 right++;
Yingdi Yu5e974202014-01-29 16:59:06 -0800176 offset++;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700177 if (offset >= expand.size())
Yingdi Yu5e974202014-01-29 16:59:06 -0800178 throw RegexMatcher::Error("wrong format of expand string!");
179 }
180 return expand.substr(begin, offset - begin);
181 }
182 else
183 throw RegexMatcher::Error("wrong format of expand string!");
184}
185
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800186shared_ptr<RegexTopMatcher>
Yingdi Yu5e974202014-01-29 16:59:06 -0800187RegexTopMatcher::fromName(const Name& name, bool hasAnchor)
188{
189 Name::const_iterator it = name.begin();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800190 std::string regexStr("^");
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700191
Yingdi Yu5e974202014-01-29 16:59:06 -0800192 for(; it != name.end(); it++)
193 {
194 regexStr.append("<");
195 regexStr.append(convertSpecialChar(it->toEscapedString()));
196 regexStr.append(">");
197 }
198
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700199 if (hasAnchor)
Yingdi Yu5e974202014-01-29 16:59:06 -0800200 regexStr.append("$");
201
Alexander Afanasyevb67090a2014-04-29 22:31:01 -0700202 // OSX 10.9 has problems with just cref
203 return make_shared<RegexTopMatcher>(func_lib::cref(regexStr));
Yingdi Yu5e974202014-01-29 16:59:06 -0800204}
205
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800206std::string
207RegexTopMatcher::convertSpecialChar(const std::string& str)
Yingdi Yu5e974202014-01-29 16:59:06 -0800208{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800209 std::string newStr;
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700210 for(size_t i = 0; i < str.size(); i++)
Yingdi Yu5e974202014-01-29 16:59:06 -0800211 {
212 char c = str[i];
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700213 switch (c)
Yingdi Yu5e974202014-01-29 16:59:06 -0800214 {
215 case '.':
216 case '[':
217 case '{':
218 case '}':
219 case '(':
220 case ')':
221 case '\\':
222 case '*':
223 case '+':
224 case '?':
225 case '|':
226 case '^':
227 case '$':
228 newStr.push_back('\\');
229 default:
230 newStr.push_back(c);
231 }
232 }
233
234 return newStr;
235}
236
237}//ndn