blob: 3140375572532033b1d38f3b728b80b4185b54ce [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
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
Yingdi Yu5e974202014-01-29 16:59:06 -080027#include "regex-matcher.hpp"
28#include "regex-pseudo-matcher.hpp"
29
Davide Pesavento45ab9a92017-11-05 19:34:31 -050030#include <boost/regex.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
Davide Pesavento45ab9a92017-11-05 19:34:31 -050047 bool
48 match(const Name& name, size_t offset, size_t len = 1) override;
Yingdi Yu5e974202014-01-29 16:59:06 -080049
50protected:
Davide Pesavento45ab9a92017-11-05 19:34:31 -050051 void
52 compile() override;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070053
Yingdi Yu5e974202014-01-29 16:59:06 -080054private:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070055 bool m_isExactMatch;
Yingdi Yu5e974202014-01-29 16:59:06 -080056 boost::regex m_componentRegex;
Davide Pesavento45ab9a92017-11-05 19:34:31 -050057 std::vector<shared_ptr<RegexPseudoMatcher>> m_pseudoMatchers;
Yingdi Yu5e974202014-01-29 16:59:06 -080058};
Yingdi Yu5e974202014-01-29 16:59:06 -080059
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080060inline
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070061RegexComponentMatcher::RegexComponentMatcher(const std::string& expr,
62 shared_ptr<RegexBackrefManager> backrefManager,
63 bool isExactMatch)
Davide Pesavento45ab9a92017-11-05 19:34:31 -050064 : RegexMatcher(expr, EXPR_COMPONENT, std::move(backrefManager))
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070065 , m_isExactMatch(isExactMatch)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080066{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080067 compile();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080068}
69
Alexander Afanasyev680e77a2014-08-14 22:39:17 -070070// Re: http://www.boost.org/users/history/version_1_56_0.html
71//
72// Breaking change: corrected behavior of basic_regex<>::mark_count() to match existing
73// documentation, basic_regex<>::subexpression(n) changed to match, see
74// https://svn.boost.org/trac/boost/ticket/9227
Davide Pesavento45ab9a92017-11-05 19:34:31 -050075//
76static constexpr size_t BOOST_REGEXP_MARK_COUNT_CORRECTION =
Alexander Afanasyev680e77a2014-08-14 22:39:17 -070077#if BOOST_VERSION < 105600
Davide Pesavento45ab9a92017-11-05 19:34:31 -050078 1;
Alexander Afanasyev680e77a2014-08-14 22:39:17 -070079#else
Davide Pesavento45ab9a92017-11-05 19:34:31 -050080 0;
Alexander Afanasyev680e77a2014-08-14 22:39:17 -070081#endif
82
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070083inline void
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070084RegexComponentMatcher::compile()
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080085{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070086 m_componentRegex = boost::regex(m_expr);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080087
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070088 m_pseudoMatchers.clear();
89 m_pseudoMatchers.push_back(make_shared<RegexPseudoMatcher>());
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080090
Davide Pesavento45ab9a92017-11-05 19:34:31 -050091 for (size_t i = 1; i <= m_componentRegex.mark_count() - BOOST_REGEXP_MARK_COUNT_CORRECTION; i++) {
92 m_pseudoMatchers.push_back(make_shared<RegexPseudoMatcher>());
93 m_backrefManager->pushRef(m_pseudoMatchers.back());
94 }
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080095}
96
97inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070098RegexComponentMatcher::match(const Name& name, size_t offset, size_t len)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080099{
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800100 m_matchResult.clear();
101
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500102 if (m_expr.empty()) {
103 m_matchResult.push_back(name.get(offset));
104 return true;
105 }
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800106
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500107 if (!m_isExactMatch)
108 BOOST_THROW_EXCEPTION(Error("Non-exact component search is not supported yet"));
109
110 boost::smatch subResult;
111 std::string targetStr = name.get(offset).toUri();
112 if (boost::regex_match(targetStr, subResult, m_componentRegex)) {
113 for (size_t i = 1; i <= m_componentRegex.mark_count() - BOOST_REGEXP_MARK_COUNT_CORRECTION; i++) {
114 m_pseudoMatchers[i]->resetMatchResult();
115 m_pseudoMatchers[i]->setMatchResult(subResult[i]);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800116 }
Davide Pesavento45ab9a92017-11-05 19:34:31 -0500117 m_matchResult.push_back(name.get(offset));
118 return true;
119 }
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800120
121 return false;
122}
123
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800124} // namespace ndn
125
126#endif // NDN_UTIL_REGEX_REGEX_COMPONENT_MATCHER_HPP