blob: 9b5d26f8bc18782f096cb0cad411fc761de3b9e3 [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
Yingdi Yu5e974202014-01-29 16:59:06 -080086 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070087 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080088 compile() = 0;
89
90private:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070091 bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070092 recursiveMatch(size_t matcherNo, const Name& name, size_t offset, size_t len);
Yingdi Yu5e974202014-01-29 16:59:06 -080093
94
95protected:
96 const std::string m_expr;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070097 const RegexExprType m_type;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080098 shared_ptr<RegexBackrefManager> m_backrefManager;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070099 std::vector<shared_ptr<RegexMatcher> > m_matchers;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800100 std::vector<name::Component> m_matchResult;
Yingdi Yu5e974202014-01-29 16:59:06 -0800101};
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800102
Alexander Afanasyev90164962014-03-06 08:29:59 +0000103inline std::ostream&
104operator<<(std::ostream& os, const RegexMatcher& regex)
105{
106 os << regex.getExpr();
107 return os;
108}
109
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800110} // namespace ndn
111
112#include "regex-backref-manager.hpp"
113
114namespace ndn {
115
116inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700117RegexMatcher::RegexMatcher(const std::string& expr,
118 const RegexExprType& type,
119 shared_ptr<RegexBackrefManager> backrefManager)
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700120 : m_expr(expr)
121 , m_type(type)
122 , m_backrefManager(backrefManager)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800123{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700124 if (!static_cast<bool>(m_backrefManager))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800125 m_backrefManager = make_shared<RegexBackrefManager>();
126}
127
128inline
129RegexMatcher::~RegexMatcher()
130{
131}
132
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700133inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700134RegexMatcher::match(const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800135{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800136 bool result = false;
137
138 m_matchResult.clear();
139
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700140 if (recursiveMatch(0, name, offset, len))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800141 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700142 for (size_t i = offset; i < offset + len ; i++)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800143 m_matchResult.push_back(name.get(i));
144 result = true;
145 }
146 else
147 {
148 result = false;
149 }
150
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800151 return result;
152}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700153
154inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700155RegexMatcher::recursiveMatch(size_t matcherNo, const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800156{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700157 ssize_t tried = len;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800158
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700159 if (matcherNo >= m_matchers.size())
160 return (len == 0);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800161
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700162 shared_ptr<RegexMatcher> matcher = m_matchers[matcherNo];
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700163
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700164 while (tried >= 0)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800165 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700166 if (matcher->match(name, offset, tried) &&
167 recursiveMatch(matcherNo + 1, name, offset + tried, len - tried))
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700168 return true;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800169 tried--;
170 }
171
172 return false;
173}
Yingdi Yu5e974202014-01-29 16:59:06 -0800174
175
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800176} // namespace ndn
177
178
179#endif // NDN_UTIL_REGEX_REGEX_MATCHER_H