blob: 029bb0399c84281b9422a38ff20fc5eaff8310e6 [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_COMPONENT_MATCHER_HPP
25#define NDN_UTIL_REGEX_REGEX_COMPONENT_MATCHER_HPP
Yingdi Yu5e974202014-01-29 16:59:06 -080026
27#include <boost/regex.hpp>
28
29#include "regex-matcher.hpp"
30#include "regex-pseudo-matcher.hpp"
31
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080032namespace ndn {
33
Yingdi Yu5e974202014-01-29 16:59:06 -080034class RegexComponentMatcher : public RegexMatcher
35{
36public:
37 /**
38 * @brief Create a RegexComponent matcher from expr
39 * @param expr The standard regular expression to match a component
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070040 * @param backrefManager The back reference manager
41 * @param isExactMatch The flag to provide exact match
Yingdi Yu5e974202014-01-29 16:59:06 -080042 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070043 RegexComponentMatcher(const std::string& expr,
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070044 shared_ptr<RegexBackrefManager> backrefManager,
45 bool isExactMatch = true);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070046
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070047 virtual
48 ~RegexComponentMatcher()
49 {
50 };
Yingdi Yu5e974202014-01-29 16:59:06 -080051
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070052 virtual bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070053 match(const Name& name, size_t offset, size_t len = 1);
Yingdi Yu5e974202014-01-29 16:59:06 -080054
55protected:
56 /**
57 * @brief Compile the regular expression to generate the more matchers when necessary
58 * @returns true if compiling succeeds
59 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070060 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080061 compile();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070062
Yingdi Yu5e974202014-01-29 16:59:06 -080063private:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070064 bool m_isExactMatch;
Yingdi Yu5e974202014-01-29 16:59:06 -080065 boost::regex m_componentRegex;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070066 std::vector<shared_ptr<RegexPseudoMatcher> > m_pseudoMatchers;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070067
Yingdi Yu5e974202014-01-29 16:59:06 -080068};
Yingdi Yu5e974202014-01-29 16:59:06 -080069
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080070
71inline
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070072RegexComponentMatcher::RegexComponentMatcher(const std::string& expr,
73 shared_ptr<RegexBackrefManager> backrefManager,
74 bool isExactMatch)
75 : RegexMatcher(expr, EXPR_COMPONENT, backrefManager)
76 , m_isExactMatch(isExactMatch)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080077{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080078 compile();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080079}
80
Alexander Afanasyev680e77a2014-08-14 22:39:17 -070081// Re: http://www.boost.org/users/history/version_1_56_0.html
82//
83// Breaking change: corrected behavior of basic_regex<>::mark_count() to match existing
84// documentation, basic_regex<>::subexpression(n) changed to match, see
85// https://svn.boost.org/trac/boost/ticket/9227
86static const size_t BOOST_REGEXP_MARK_COUNT_CORRECTION =
87#if BOOST_VERSION < 105600
88 1;
89#else
90 0;
91#endif
92
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070093inline void
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070094RegexComponentMatcher::compile()
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080095{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070096 m_componentRegex = boost::regex(m_expr);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080097
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070098 m_pseudoMatchers.clear();
99 m_pseudoMatchers.push_back(make_shared<RegexPseudoMatcher>());
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800100
Alexander Afanasyev680e77a2014-08-14 22:39:17 -0700101 for (size_t i = 1;
102 i <= m_componentRegex.mark_count() - BOOST_REGEXP_MARK_COUNT_CORRECTION; i++)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800103 {
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -0700104 shared_ptr<RegexPseudoMatcher> pMatcher = make_shared<RegexPseudoMatcher>();
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700105 m_pseudoMatchers.push_back(pMatcher);
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -0700106 m_backrefManager->pushRef(static_pointer_cast<RegexMatcher>(pMatcher));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800107 }
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800108}
109
110inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700111RegexComponentMatcher::match(const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800112{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800113 m_matchResult.clear();
114
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700115 if (m_expr.empty())
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800116 {
117 m_matchResult.push_back(name.get(offset));
118 return true;
119 }
120
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700121 if (m_isExactMatch)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800122 {
123 boost::smatch subResult;
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700124 std::string targetStr = name.get(offset).toUri();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700125 if (boost::regex_match(targetStr, subResult, m_componentRegex))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800126 {
Alexander Afanasyev680e77a2014-08-14 22:39:17 -0700127 for (size_t i = 1;
128 i <= m_componentRegex.mark_count() - BOOST_REGEXP_MARK_COUNT_CORRECTION; i++)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800129 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700130 m_pseudoMatchers[i]->resetMatchResult();
131 m_pseudoMatchers[i]->setMatchResult(subResult[i]);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800132 }
133 m_matchResult.push_back(name.get(offset));
134 return true;
135 }
136 }
137 else
138 {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700139 BOOST_THROW_EXCEPTION(RegexMatcher::Error("Non-exact component search is not supported "
140 "yet"));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800141 }
142
143 return false;
144}
145
146
147} // namespace ndn
148
149#endif // NDN_UTIL_REGEX_REGEX_COMPONENT_MATCHER_HPP