blob: 08cefdb46b608adb237072d13e252ac7d280b944 [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 Afanasyev73e30042015-09-17 17:09:51 -07003 * Copyright (c) 2013-2015 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 {
Davide Pesavento18cf81b2015-09-12 23:36:43 +020050 }
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
Yingdi Yu5e974202014-01-29 16:59:06 -080058 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070059 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080060 compile();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070061
Yingdi Yu5e974202014-01-29 16:59:06 -080062private:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070063 bool m_isExactMatch;
Yingdi Yu5e974202014-01-29 16:59:06 -080064 boost::regex m_componentRegex;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070065 std::vector<shared_ptr<RegexPseudoMatcher> > m_pseudoMatchers;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070066
Yingdi Yu5e974202014-01-29 16:59:06 -080067};
Yingdi Yu5e974202014-01-29 16:59:06 -080068
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080069
70inline
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070071RegexComponentMatcher::RegexComponentMatcher(const std::string& expr,
72 shared_ptr<RegexBackrefManager> backrefManager,
73 bool isExactMatch)
74 : RegexMatcher(expr, EXPR_COMPONENT, backrefManager)
75 , m_isExactMatch(isExactMatch)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080076{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080077 compile();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080078}
79
Alexander Afanasyev680e77a2014-08-14 22:39:17 -070080// Re: http://www.boost.org/users/history/version_1_56_0.html
81//
82// Breaking change: corrected behavior of basic_regex<>::mark_count() to match existing
83// documentation, basic_regex<>::subexpression(n) changed to match, see
84// https://svn.boost.org/trac/boost/ticket/9227
85static const size_t BOOST_REGEXP_MARK_COUNT_CORRECTION =
86#if BOOST_VERSION < 105600
87 1;
88#else
89 0;
90#endif
91
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070092inline void
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070093RegexComponentMatcher::compile()
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080094{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070095 m_componentRegex = boost::regex(m_expr);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080096
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070097 m_pseudoMatchers.clear();
98 m_pseudoMatchers.push_back(make_shared<RegexPseudoMatcher>());
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080099
Alexander Afanasyev680e77a2014-08-14 22:39:17 -0700100 for (size_t i = 1;
101 i <= m_componentRegex.mark_count() - BOOST_REGEXP_MARK_COUNT_CORRECTION; i++)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800102 {
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -0700103 shared_ptr<RegexPseudoMatcher> pMatcher = make_shared<RegexPseudoMatcher>();
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700104 m_pseudoMatchers.push_back(pMatcher);
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -0700105 m_backrefManager->pushRef(static_pointer_cast<RegexMatcher>(pMatcher));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800106 }
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800107}
108
109inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700110RegexComponentMatcher::match(const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800111{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800112 m_matchResult.clear();
113
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700114 if (m_expr.empty())
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800115 {
116 m_matchResult.push_back(name.get(offset));
117 return true;
118 }
119
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700120 if (m_isExactMatch)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800121 {
122 boost::smatch subResult;
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700123 std::string targetStr = name.get(offset).toUri();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700124 if (boost::regex_match(targetStr, subResult, m_componentRegex))
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800125 {
Alexander Afanasyev680e77a2014-08-14 22:39:17 -0700126 for (size_t i = 1;
127 i <= m_componentRegex.mark_count() - BOOST_REGEXP_MARK_COUNT_CORRECTION; i++)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800128 {
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700129 m_pseudoMatchers[i]->resetMatchResult();
130 m_pseudoMatchers[i]->setMatchResult(subResult[i]);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800131 }
132 m_matchResult.push_back(name.get(offset));
133 return true;
134 }
135 }
136 else
137 {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700138 BOOST_THROW_EXCEPTION(RegexMatcher::Error("Non-exact component search is not supported "
139 "yet"));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800140 }
141
142 return false;
143}
144
145
146} // namespace ndn
147
148#endif // NDN_UTIL_REGEX_REGEX_COMPONENT_MATCHER_HPP