blob: 4dcaeb473be413e92b6b76d1fb3b400a75f855c5 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yingdi Yu5e974202014-01-29 16:59:06 -08002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * 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.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Yingdi Yu5e974202014-01-29 16:59:06 -080022 */
23
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080024#ifndef NDN_UTIL_REGEX_REGEX_MATCHER_H
25#define NDN_UTIL_REGEX_REGEX_MATCHER_H
Yingdi Yu5e974202014-01-29 16:59:06 -080026
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080027#include "../../common.hpp"
Yingdi Yu5e974202014-01-29 16:59:06 -080028#include "../../name.hpp"
Yingdi Yu5e974202014-01-29 16:59:06 -080029
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080030namespace ndn {
31
32class RegexBackrefManager;
Yingdi Yu5e974202014-01-29 16:59:06 -080033
34class RegexMatcher
35{
36public:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070037 class Error : public std::runtime_error
38 {
39 public:
40 explicit
41 Error(const std::string& what)
42 : std::runtime_error(what)
43 {
44 }
45 };
Yingdi Yu5e974202014-01-29 16:59:06 -080046
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070047 enum RegexExprType {
Yingdi Yu5e974202014-01-29 16:59:06 -080048 EXPR_TOP,
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070049 EXPR_PATTERN_LIST,
Yingdi Yu5e974202014-01-29 16:59:06 -080050 EXPR_REPEAT_PATTERN,
Yingdi Yu5e974202014-01-29 16:59:06 -080051 EXPR_BACKREF,
52 EXPR_COMPONENT_SET,
53 EXPR_COMPONENT,
Yingdi Yu5e974202014-01-29 16:59:06 -080054 EXPR_PSEUDO
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070055 };
Yingdi Yu5e974202014-01-29 16:59:06 -080056
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070057 RegexMatcher(const std::string& expr,
58 const RegexExprType& type,
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080059 shared_ptr<RegexBackrefManager> backrefManager = shared_ptr<RegexBackrefManager>());
Yingdi Yu5e974202014-01-29 16:59:06 -080060
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070061 virtual
Yingdi Yu5e974202014-01-29 16:59:06 -080062 ~RegexMatcher();
63
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070064 virtual bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070065 match(const Name& name, size_t offset, size_t len);
Yingdi Yu5e974202014-01-29 16:59:06 -080066
67 /**
68 * @brief get the matched name components
69 * @returns the matched name components
70 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070071 const std::vector<name::Component>&
Yingdi Yu5e974202014-01-29 16:59:06 -080072 getMatchResult() const
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070073 {
74 return m_matchResult;
75 }
Yingdi Yu5e974202014-01-29 16:59:06 -080076
77 const std::string&
78 getExpr() const
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070079 {
80 return m_expr;
81 }
Yingdi Yu5e974202014-01-29 16:59:06 -080082
83protected:
84 /**
85 * @brief Compile the regular expression to generate the more matchers when necessary
86 * @returns true if compiling succeeds
87 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070088 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080089 compile() = 0;
90
91private:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070092 bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070093 recursiveMatch(size_t matcherNo, const Name& name, size_t offset, size_t len);
Yingdi Yu5e974202014-01-29 16:59:06 -080094
95
96protected:
97 const std::string m_expr;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070098 const RegexExprType m_type;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080099 shared_ptr<RegexBackrefManager> m_backrefManager;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700100 std::vector<shared_ptr<RegexMatcher> > m_matchers;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800101 std::vector<name::Component> m_matchResult;
Yingdi Yu5e974202014-01-29 16:59:06 -0800102};
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800103
Alexander Afanasyev90164962014-03-06 08:29:59 +0000104inline std::ostream&
105operator<<(std::ostream& os, const RegexMatcher& regex)
106{
107 os << regex.getExpr();
108 return os;
109}
110
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800111} // namespace ndn
112
113#include "regex-backref-manager.hpp"
114
115namespace ndn {
116
117inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700118RegexMatcher::RegexMatcher(const std::string& expr,
119 const RegexExprType& type,
120 shared_ptr<RegexBackrefManager> backrefManager)
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700121 : m_expr(expr)
122 , m_type(type)
123 , m_backrefManager(backrefManager)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800124{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700125 if (!static_cast<bool>(m_backrefManager))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800126 m_backrefManager = make_shared<RegexBackrefManager>();
127}
128
129inline
130RegexMatcher::~RegexMatcher()
131{
132}
133
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700134inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700135RegexMatcher::match(const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800136{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800137 bool result = false;
138
139 m_matchResult.clear();
140
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700141 if (recursiveMatch(0, name, offset, len))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800142 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700143 for (size_t i = offset; i < offset + len ; i++)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800144 m_matchResult.push_back(name.get(i));
145 result = true;
146 }
147 else
148 {
149 result = false;
150 }
151
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800152 return result;
153}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700154
155inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700156RegexMatcher::recursiveMatch(size_t matcherNo, const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800157{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700158 ssize_t tried = len;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800159
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700160 if (matcherNo >= m_matchers.size())
161 return (len == 0);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800162
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700163 shared_ptr<RegexMatcher> matcher = m_matchers[matcherNo];
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700164
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700165 while (tried >= 0)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800166 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700167 if (matcher->match(name, offset, tried) &&
168 recursiveMatch(matcherNo + 1, name, offset + tried, len - tried))
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700169 return true;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800170 tried--;
171 }
172
173 return false;
174}
Yingdi Yu5e974202014-01-29 16:59:06 -0800175
176
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800177} // namespace ndn
178
179
180#endif // NDN_UTIL_REGEX_REGEX_MATCHER_H