blob: 88cefe0be92c9ec5219a7efc37f7e5977ba18c05 [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
95} // namespace ndn
96
97#include "regex-backref-manager.hpp"
98
99namespace ndn {
100
101inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700102RegexMatcher::RegexMatcher(const std::string& expr,
103 const RegexExprType& type,
104 shared_ptr<RegexBackrefManager> backrefManager)
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700105 : m_expr(expr)
106 , m_type(type)
107 , m_backrefManager(backrefManager)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800108{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700109 if (!static_cast<bool>(m_backrefManager))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800110 m_backrefManager = make_shared<RegexBackrefManager>();
111}
112
113inline
114RegexMatcher::~RegexMatcher()
115{
116}
117
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700118inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700119RegexMatcher::match(const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800120{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800121 bool result = false;
122
123 m_matchResult.clear();
124
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700125 if (recursiveMatch(0, name, offset, len))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800126 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700127 for (size_t i = offset; i < offset + len ; i++)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800128 m_matchResult.push_back(name.get(i));
129 result = true;
130 }
131 else
132 {
133 result = false;
134 }
135
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800136 return result;
137}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700138
139inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700140RegexMatcher::recursiveMatch(size_t matcherNo, const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800141{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700142 ssize_t tried = len;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800143
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700144 if (matcherNo >= m_matchers.size())
145 return (len == 0);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800146
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700147 shared_ptr<RegexMatcher> matcher = m_matchers[matcherNo];
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700148
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700149 while (tried >= 0)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800150 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700151 if (matcher->match(name, offset, tried) &&
152 recursiveMatch(matcherNo + 1, name, offset + tried, len - tried))
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700153 return true;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800154 tried--;
155 }
156
157 return false;
158}
Yingdi Yu5e974202014-01-29 16:59:06 -0800159
160
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800161} // namespace ndn
162
163
164#endif // NDN_UTIL_REGEX_REGEX_MATCHER_H