blob: efe906f33c961d6a4ee05962d2012624d6fa2520 [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
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080015#ifndef NDN_UTIL_REGEX_REGEX_MATCHER_H
16#define NDN_UTIL_REGEX_REGEX_MATCHER_H
Yingdi Yu5e974202014-01-29 16:59:06 -080017
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080018#include "../../common.hpp"
Yingdi Yu5e974202014-01-29 16:59:06 -080019#include "../../name.hpp"
Yingdi Yu5e974202014-01-29 16:59:06 -080020
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080021namespace ndn {
22
23class RegexBackrefManager;
Yingdi Yu5e974202014-01-29 16:59:06 -080024
25class RegexMatcher
26{
27public:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070028 class Error : public std::runtime_error
29 {
30 public:
31 explicit
32 Error(const std::string& what)
33 : std::runtime_error(what)
34 {
35 }
36 };
Yingdi Yu5e974202014-01-29 16:59:06 -080037
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070038 enum RegexExprType {
Yingdi Yu5e974202014-01-29 16:59:06 -080039 EXPR_TOP,
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070040 EXPR_PATTERN_LIST,
Yingdi Yu5e974202014-01-29 16:59:06 -080041 EXPR_REPEAT_PATTERN,
Yingdi Yu5e974202014-01-29 16:59:06 -080042 EXPR_BACKREF,
43 EXPR_COMPONENT_SET,
44 EXPR_COMPONENT,
Yingdi Yu5e974202014-01-29 16:59:06 -080045 EXPR_PSEUDO
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070046 };
Yingdi Yu5e974202014-01-29 16:59:06 -080047
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070048 RegexMatcher(const std::string& expr,
49 const RegexExprType& type,
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080050 shared_ptr<RegexBackrefManager> backrefManager = shared_ptr<RegexBackrefManager>());
Yingdi Yu5e974202014-01-29 16:59:06 -080051
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070052 virtual
Yingdi Yu5e974202014-01-29 16:59:06 -080053 ~RegexMatcher();
54
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070055 virtual bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070056 match(const Name& name, size_t offset, size_t len);
Yingdi Yu5e974202014-01-29 16:59:06 -080057
58 /**
59 * @brief get the matched name components
60 * @returns the matched name components
61 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070062 const std::vector<name::Component>&
Yingdi Yu5e974202014-01-29 16:59:06 -080063 getMatchResult() const
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070064 {
65 return m_matchResult;
66 }
Yingdi Yu5e974202014-01-29 16:59:06 -080067
68 const std::string&
69 getExpr() const
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070070 {
71 return m_expr;
72 }
Yingdi Yu5e974202014-01-29 16:59:06 -080073
74protected:
75 /**
76 * @brief Compile the regular expression to generate the more matchers when necessary
77 * @returns true if compiling succeeds
78 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070079 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080080 compile() = 0;
81
82private:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070083 bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070084 recursiveMatch(size_t matcherNo, const Name& name, size_t offset, size_t len);
Yingdi Yu5e974202014-01-29 16:59:06 -080085
86
87protected:
88 const std::string m_expr;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070089 const RegexExprType m_type;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080090 shared_ptr<RegexBackrefManager> m_backrefManager;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070091 std::vector<shared_ptr<RegexMatcher> > m_matchers;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080092 std::vector<name::Component> m_matchResult;
Yingdi Yu5e974202014-01-29 16:59:06 -080093};
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080094
Alexander Afanasyev90164962014-03-06 08:29:59 +000095inline std::ostream&
96operator<<(std::ostream& os, const RegexMatcher& regex)
97{
98 os << regex.getExpr();
99 return os;
100}
101
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800102} // namespace ndn
103
104#include "regex-backref-manager.hpp"
105
106namespace ndn {
107
108inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700109RegexMatcher::RegexMatcher(const std::string& expr,
110 const RegexExprType& type,
111 shared_ptr<RegexBackrefManager> backrefManager)
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700112 : m_expr(expr)
113 , m_type(type)
114 , m_backrefManager(backrefManager)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800115{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700116 if (!static_cast<bool>(m_backrefManager))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800117 m_backrefManager = make_shared<RegexBackrefManager>();
118}
119
120inline
121RegexMatcher::~RegexMatcher()
122{
123}
124
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700125inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700126RegexMatcher::match(const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800127{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800128 bool result = false;
129
130 m_matchResult.clear();
131
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700132 if (recursiveMatch(0, name, offset, len))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800133 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700134 for (size_t i = offset; i < offset + len ; i++)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800135 m_matchResult.push_back(name.get(i));
136 result = true;
137 }
138 else
139 {
140 result = false;
141 }
142
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800143 return result;
144}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700145
146inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700147RegexMatcher::recursiveMatch(size_t matcherNo, const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800148{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700149 ssize_t tried = len;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800150
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700151 if (matcherNo >= m_matchers.size())
152 return (len == 0);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800153
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700154 shared_ptr<RegexMatcher> matcher = m_matchers[matcherNo];
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700155
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700156 while (tried >= 0)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800157 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700158 if (matcher->match(name, offset, tried) &&
159 recursiveMatch(matcherNo + 1, name, offset + tried, len - tried))
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700160 return true;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800161 tried--;
162 }
163
164 return false;
165}
Yingdi Yu5e974202014-01-29 16:59:06 -0800166
167
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800168} // namespace ndn
169
170
171#endif // NDN_UTIL_REGEX_REGEX_MATCHER_H