blob: 5916565703ee85e01cdb0d1f3c8f1b584f3cae0a [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento45ab9a92017-11-05 19:34:31 -05002/*
3 * Copyright (c) 2013-2017 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
Davide Pesavento45ab9a92017-11-05 19:34:31 -050024#ifndef NDN_UTIL_REGEX_REGEX_MATCHER_HPP
25#define NDN_UTIL_REGEX_REGEX_MATCHER_HPP
Yingdi Yu5e974202014-01-29 16:59:06 -080026
Davide Pesavento45ab9a92017-11-05 19:34:31 -050027#include "regex-backref-manager.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
Yingdi Yu5e974202014-01-29 16:59:06 -080032class RegexMatcher
33{
34public:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070035 class Error : public std::runtime_error
36 {
37 public:
38 explicit
39 Error(const std::string& what)
40 : std::runtime_error(what)
41 {
42 }
43 };
Yingdi Yu5e974202014-01-29 16:59:06 -080044
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070045 enum RegexExprType {
Yingdi Yu5e974202014-01-29 16:59:06 -080046 EXPR_TOP,
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070047 EXPR_PATTERN_LIST,
Yingdi Yu5e974202014-01-29 16:59:06 -080048 EXPR_REPEAT_PATTERN,
Yingdi Yu5e974202014-01-29 16:59:06 -080049 EXPR_BACKREF,
50 EXPR_COMPONENT_SET,
51 EXPR_COMPONENT,
Yingdi Yu5e974202014-01-29 16:59:06 -080052 EXPR_PSEUDO
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070053 };
Yingdi Yu5e974202014-01-29 16:59:06 -080054
Davide Pesavento45ab9a92017-11-05 19:34:31 -050055 RegexMatcher(const std::string& expr, const RegexExprType& type,
56 shared_ptr<RegexBackrefManager> backrefManager = nullptr);
Yingdi Yu5e974202014-01-29 16:59:06 -080057
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070058 virtual
Davide Pesavento45ab9a92017-11-05 19:34:31 -050059 ~RegexMatcher() = default;
Yingdi Yu5e974202014-01-29 16:59:06 -080060
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070061 virtual bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070062 match(const Name& name, size_t offset, size_t len);
Yingdi Yu5e974202014-01-29 16:59:06 -080063
64 /**
65 * @brief get the matched name components
66 * @returns the matched name components
67 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070068 const std::vector<name::Component>&
Yingdi Yu5e974202014-01-29 16:59:06 -080069 getMatchResult() const
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070070 {
71 return m_matchResult;
72 }
Yingdi Yu5e974202014-01-29 16:59:06 -080073
74 const std::string&
75 getExpr() const
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070076 {
77 return m_expr;
78 }
Yingdi Yu5e974202014-01-29 16:59:06 -080079
80protected:
81 /**
82 * @brief Compile the regular expression to generate the more matchers when necessary
Yingdi Yu5e974202014-01-29 16:59:06 -080083 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070084 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080085 compile() = 0;
86
87private:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070088 bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070089 recursiveMatch(size_t matcherNo, const Name& name, size_t offset, size_t len);
Yingdi Yu5e974202014-01-29 16:59:06 -080090
Yingdi Yu5e974202014-01-29 16:59:06 -080091protected:
92 const std::string m_expr;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070093 const RegexExprType m_type;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080094 shared_ptr<RegexBackrefManager> m_backrefManager;
Davide Pesavento45ab9a92017-11-05 19:34:31 -050095 std::vector<shared_ptr<RegexMatcher>> m_matchers;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080096 std::vector<name::Component> m_matchResult;
Yingdi Yu5e974202014-01-29 16:59:06 -080097};
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080098
Alexander Afanasyev90164962014-03-06 08:29:59 +000099inline std::ostream&
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500100operator<<(std::ostream& os, const RegexMatcher& rm)
Alexander Afanasyev90164962014-03-06 08:29:59 +0000101{
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500102 return os << rm.getExpr();
Alexander Afanasyev90164962014-03-06 08:29:59 +0000103}
104
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800105inline
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500106RegexMatcher::RegexMatcher(const std::string& expr, const RegexExprType& type,
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700107 shared_ptr<RegexBackrefManager> backrefManager)
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700108 : m_expr(expr)
109 , m_type(type)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800110{
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500111 if (backrefManager)
112 m_backrefManager = std::move(backrefManager);
113 else
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800114 m_backrefManager = make_shared<RegexBackrefManager>();
115}
116
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700117inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700118RegexMatcher::match(const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800119{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800120 m_matchResult.clear();
121
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500122 if (recursiveMatch(0, name, offset, len)) {
123 for (size_t i = offset; i < offset + len; i++)
124 m_matchResult.push_back(name.get(i));
125 return true;
126 }
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800127
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500128 return false;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800129}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700130
131inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700132RegexMatcher::recursiveMatch(size_t matcherNo, const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800133{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700134 if (matcherNo >= m_matchers.size())
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500135 return len == 0;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800136
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500137 ssize_t tried = len;
138 auto matcher = m_matchers[matcherNo];
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700139
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500140 while (tried >= 0) {
141 if (matcher->match(name, offset, tried) &&
142 recursiveMatch(matcherNo + 1, name, offset + tried, len - tried))
143 return true;
144 tried--;
145 }
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800146
147 return false;
148}
Yingdi Yu5e974202014-01-29 16:59:06 -0800149
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800150} // namespace ndn
151
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500152#endif // NDN_UTIL_REGEX_REGEX_MATCHER_HPP