blob: ec89125ebe735cf0df7ff578b51bab94a621dc5b [file] [log] [blame]
Qiuhan Ding699725d2015-05-24 01:41:09 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2015 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "regex-component-set-matcher.hpp"
23
24namespace ndn {
25
26RegexComponentSetMatcher::RegexComponentSetMatcher(const std::string& expr,
27 shared_ptr<RegexBackrefManager> backrefManager)
28 : RegexMatcher(expr, EXPR_COMPONENT_SET, backrefManager)
29 , m_isInclusion(true)
30{
31 compile();
32}
33
34RegexComponentSetMatcher::~RegexComponentSetMatcher()
35{
36}
37
38bool
39RegexComponentSetMatcher::match(const Name& name, size_t offset, size_t len)
40{
41 bool isMatched = false;
42
43 /* componentset only matches one component */
44 if (len != 1)
45 {
46 return false;
47 }
48
49 for (auto& component : m_components) {
50 if (component->match(name, offset, len)) {
51 isMatched = true;
52 break;
53 }
54 }
55
56 m_matchResult.clear();
57
58 if (m_isInclusion ? isMatched : !isMatched) {
59 m_matchResult.push_back(name.get(offset));
60 return true;
61 }
62 else
63 return false;
64}
65
66void
67RegexComponentSetMatcher::compile()
68{
69 if (m_expr.size() < 2)
70 throw Error("Regexp compile error (cannot parse " + m_expr + ")");
71
72 switch (m_expr[0]) {
73 case '<':
74 return compileSingleComponent();
75 case '[':
76 {
77 size_t lastIndex = m_expr.size() - 1;
78 if (']' != m_expr[lastIndex])
79 throw Error("Regexp compile error (no matching ']' in " + m_expr + ")");
80
81 if ('^' == m_expr[1]) {
82 m_isInclusion = false;
83 compileMultipleComponents(2, lastIndex);
84 }
85 else
86 compileMultipleComponents(1, lastIndex);
87 break;
88 }
89 default:
90 throw Error("Regexp compile error (cannot parse " + m_expr + ")");
91 }
92}
93
94void
95RegexComponentSetMatcher::compileSingleComponent()
96{
97 size_t end = extractComponent(1);
98
99 if (m_expr.size() != end) {
100 throw Error("Component expr error " + m_expr);
101 }
102 else {
103 auto component = make_shared<RegexComponentMatcher>(m_expr.substr(1, end - 2),
104 m_backrefManager);
105
106 m_components.insert(component);
107 }
108}
109
110void
111RegexComponentSetMatcher::compileMultipleComponents(size_t start, size_t lastIndex)
112{
113 size_t index = start;
114 size_t tempIndex = start;
115
116 while (index < lastIndex) {
117 if ('<' != m_expr[index])
118 throw Error("Component expr error " + m_expr);
119
120 tempIndex = index + 1;
121 index = extractComponent(tempIndex);
122
123 auto component = make_shared<RegexComponentMatcher>(m_expr.substr(tempIndex,
124 index - tempIndex - 1),
125 m_backrefManager);
126
127 m_components.insert(component);
128 }
129
130 if (index != lastIndex)
131 throw Error("Not sufficient expr to parse " + m_expr);
132}
133
134size_t
135RegexComponentSetMatcher::extractComponent(size_t index)
136{
137 size_t lcount = 1;
138 size_t rcount = 0;
139
140 while (lcount > rcount) {
141 switch (m_expr[index]) {
142 case '<':
143 lcount++;
144 break;
145
146 case '>':
147 rcount++;
148 break;
149
150 case 0:
151 throw Error("Error: square brackets mismatch");
152 break;
153 }
154 index++;
155
156 }
157
158 return index;
159}
160
161} // namespace ndn