Compare commits

...
2 Commits
Author SHA1 Message Date
Qiuhan Ding 699725dae1 regex: move functions out of headers
Change-Id: I6a3ea61a6564195e297288d514c5a805a832e0e6
2015-08-06 15:28:51 -07:00
Yingdi Yu b56c54ebc1 docs: trust schema spec
Refs: #2829

Change-Id: Idd41b49f41ee9e87ded8df2bb800a7a28bb69932
2015-08-06 15:28:49 -07:00
19 changed files with 1340 additions and 808 deletions

No files matched your search

+1
View File
@@ -34,6 +34,7 @@ ndn-cxx Documentation
+ :doc:`tutorials/security-validator-config`
+ :doc:`tutorials/signed-interest`
+ :doc:`tutorials/certificate-format`
+ :doc:`tutorials/security-trust-schema`
- :doc:`manpages`
+1
View File
@@ -9,3 +9,4 @@ Tutorials
tutorials/security-validator-config
tutorials/signed-interest
tutorials/certificate-format
tutorials/security-trust-schema
+423
View File
@@ -0,0 +1,423 @@
Trust Schema Specification
==========================
.. contents::
Trust in NDN is based on name. A data packet is valid only if it is signed with a key whose
name satisfies certain conditions (e.g., sharing the same prefix, containing certain name
components, etc.). Such a relation between data name and key name defines a trust rule. Since
keys are just another type of data, authenticating the signing key of a data packet is the same
as authenticating a normal data packet. The trust model of an NDN application consists of a
set of trust rules that associate data with keys, keys with their signing keys (including some
pre-trusted keys).
Trust schema is a description of a trust model, which can help automate data and interest
packet signing and authentication. A trust schema describes the relationship between packet
and its signing key in terms of name patterns. A trust schema interpreter with the ability to
retrieve public keys (also called *authenticating* *interpreter*) can automatically validate
packets according to the trust model. Similarly, a trust schema interpreter with the ability
to access private keys (also called *signing* *interpreter*) can automatically sign packets
according to the trust model. This specification defines a way to specify a trust model using
the trust schema.
A trust schema consists of three parts: a list of **rules**, one or more
**anchor**, and a **crypto**:
.. table::
+------------+------------------------------------------------------------------------+
| **rule** | Restriction on a packet name and its signing key name |
+------------+------------------------------------------------------------------------+
| **anchor** | A pre-authenticated public key (a data packet carrying the public key) |
+------------+------------------------------------------------------------------------+
| **crypto** | Cryptographic requirements on packet signature: which public key |
| | algorithm to use, which hashing algorithm to use, and what is the |
| | minimum required signature strength |
+------------+------------------------------------------------------------------------+
.. note::
All values in trust schema definition must be quoted if they contain spaces.
Here is an example of the schema configuration file:
::
rule
{
id article
name (<>*)<blog><article><><><>
signer author($1)
}
rule
{
id author
name (<>*)<blog><author>[user]<KEY>[id]
signer admin($1)
}
rule
{
id admin
name (<>*)<blog><admin>[user]<KEY>[id]
signer admin($1)|root($1)
}
anchor
{
id root
name (<>*)<blog><KEY>[id]
file blog-root.cert
}
crypto
{
hash sha256
signing rsa|ecdsa
key-strength 112
}
An authenticating interpreter that loads this trust schema can automatically
validate blog articles, blog author keys, and blog admin keys. When an
authenticating interpreter get an article data packet, the interpreter will
find the first **rule** whose **name** matches the data name and check the
data's KeyLocator against the **signer** in the rule. For example, if the
article is signed by an author key which matches the signer **author**, the
interpreter can fetch the key and validate the key using the author rule which
corresponds to the matched signer. The authentication process can recursively
develop until reaching an **anchor**. At this moment, the interpreter can
trigger the signature verification along the reverse path until eventually
authenticating article.
Similarly, for packet signing, a signing interpreter that loads this trust
schema can construct a chain of signing key to sign packet correctly, so that
the packet can be authenticated by authenticating interpreter using the same
trust schema.
Rule
----
A rule has the following properties:
- **id**: a unique identifier of the rule in the trust schema that can be used to
link rules as part of signer "function." The identifier must start with a
letter, and can only contain letters, digits, and underscores. The identifier
is case-sensitive.
- **name**: name pattern of the packet in terms of :doc:`utils-ndn-regex`
- **type** (optional): type of packet to match against the rule.
Possible values: **data** (default) and **interest**.
- **signer**: one or more invocations of rules or trust anchors, separated by **|**.
Each invocation can take as an input name components that are either explicitly
specified or extracted from the packet name using regular expression sub-groups.
Output of each rule invocation is a name pattern from the corresponding rule or
trust anchor, specialized with the specified input parameters.
Example::
rule
{
id article
name (<>*)<blog><article><><><>
signer author($1)
}
A data/interest packet will be checked by a rule only if the packet **name**
matches the rule's name property.
For a packet that is matched by a rule, the packet's KeyLocator will be checked
against the rule's **signer** property.
The packet's KeyLocator must match a name pattern that is derived from at least
one of the signers to be treated as a valid packet. Note that KeyLocator always
points to a certificate, thus the "functions" in a signer must be data rules.
.. note::
For interest packets, the name property only matches the name components that
exist before the packet is signed. In other words, if the signature signing
process add the signature info and signature value as name components, these
name components will not be matched by the pattern.
.. note::
**ATTENTION: The order of rules MATTERS!** A packet will be check ONLY with
the first matched rule.
Anchor
------
A trust schema must contain at least one **anchor** (a pre-authenticated key) and
all authentication paths must end at an anchor. Each anchor must contain:
- **id**: identifier for the anchor that can be used to link an anchor to a rule
as a signer "function". The identifier must start with a letter, and can only
contain letters, digits, and underscores. The identifier is case-sensitive.
- **name**: name pattern of the packet in terms of :doc:`utils-ndn-regex`
Since an anchor is pre-authenticated, it does not have the **signer** property,
but instead the key directly. Therefore, anchor must specify exactly one of the
following properties:
- **file**: name of a file containing a base64 encoded pre-authenticated public key
certificate.
or
- **raw**: text string in base64 encoding, containing the raw bytes of a pre-authenticated
public key certificate.
or
- **dir**: name of directory under which each file contains a base64 encoded
pre-authenticated public key certificate.
Examples::
anchor
{
id root
name (<>*)<blog><KEY>[id]
file blog-root.cert
}
anchor
{
id another-root
name <KEY>[id]
raw "Bv0DGwdG...amHFvHIMDw=="
}
anchor
{
id root
name (<>*)<blog><KEY>[id]
dir /etc/ndn/trust-anchors
}
When **file** or **dir** is specified and the file(s) can change during the runtime,
additional **refresh** property can be specified to define how often the
pre-authenticated key should be refreshed in the trust model (Three units of time
interval are supported: ``h`` for hour, ``m`` for minute, and ``s`` for second)::
anchor
{
id root
name (<>*)<blog><KEY>[id]
file blog-root.cert
refresh 1h ; refresh the key every hour, other units include
; m (for minutes) and s (for seconds)
}
There is another special anchor **any**. As long as such an anchor is defined
in config file, any signature of any data and interest packet is considered valid::
anchor
{
any true
}
.. note::
Use of ``any`` anchor is highly discouraged and should only be used to
temporarily disable packet validation (e.g., while debugging code).
Crypto (Signature Requirements)
-------------------------------
**crypto** block defines the acceptable packet signature.
**crypto** must contain three properties:
- **hash**: one or more allowed hash algorithms, separated by **|**.
Possible values: **sha256**
- **signing**: one or more allowed signing algorithms, separated by **|**
Possible values: **rsa** (RSA signature algorithm), **ecdsa** (ECDSA signature algorithm)
- **key-strength**: minimum crypto strength of a key (in terms of symmetric key bits)
Recommended values by NIST (`details`_) and their equivalent RSA and ECDSA key sizes:
+---------------------------------------------+-------------------+----------------+
| Key Strength (in symmetric key bits) | RSA key bits | ECDSA key bits |
+=============================================+===================+================+
| 80 (very weak) | 1024 | 160 |
+---------------------------------------------+-------------------+----------------+
| 112 (recommended value) | 2048 | 224 |
+---------------------------------------------+-------------------+----------------+
| 128 | 3072 | 256 |
+---------------------------------------------+-------------------+----------------+
| 192 | 7680 | 384 |
+---------------------------------------------+-------------------+----------------+
| 256 (strong) | 15360 | 521 |
+---------------------------------------------+-------------------+----------------+
.. todo: define key strengths for RSA 4096 (as it is a pretty commonly used value)
.. _details: http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf
..
Any
---
There is another special optional property of trust schema **any**. As long as
such a property is specified with a value **true**, packet validation will be
turned off.
::
any true
.. note::
**ATTENTION: This property is dangerous.** You should used it only when you
want to disable packet validation temporarily (e.g, debugging code, building
a demo).
Examples
--------
Example Configuration For NLSR
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The trust model of NLSR is semi-hierarchical. An example certificate signing hierarchy is:
::
root
|
+--------------+---------------+
site1 site2
| |
+---------+---------+ +
operator1 operator2 operator3
| | |
+-----+-----+ +----+-----+ +-----+-----+--------+
router1 router2 router3 router4 router5 router6 router7
| | | | | | |
+ + + + + + +
NLSR NSLR NSLR NSLR NSLR NSLR NSLR
However, entities name may not follow the signing hierarchy, for
example:
+------------+-------------------------------------------------------------------------------------+
| Entity | Identity name and examples |
+============+=====================================================================================+
| root | ``/<network>`` |
| | |
| | Identity example: ``/ndn`` |
| | |
| | Certificate name example: ``/ndn/KEY/ksk-1/ID-CERT/%01`` |
+------------+-------------------------------------------------------------------------------------+
| site | ``/<network>/<site>`` |
| | |
| | Identity example: ``/ndn/edu/ucla`` |
| | |
| | Certificate name example: ``/ndn/edu/ucla/KEY/ksk-2/ID-CERT/%01`` |
+------------+-------------------------------------------------------------------------------------+
| operator | ``/<network>/<site>/%C1.O.N./<operator-id>`` |
| | |
| | Identity example: ``/ndn/edu/ucla/%C1.O.N./op1`` |
| | |
| | Certificate name example: ``/ndn/edu/ucla/%C1.O.N./op1/KEY/ksk-3/ID-CERT/%01`` |
+------------+-------------------------------------------------------------------------------------+
| router | ``/<network>/<site>/%C1.O.R./<router-id>`` |
| | |
| | Identity example: ``/ndn/edu/ucla/%C1.O.R./rt1`` |
| | |
| | Certificate name example: ``/ndn/edu/ucla/%C1.O.R./rt1/KEY/ksk-4/ID-CERT/%01`` |
+------------+-------------------------------------------------------------------------------------+
| NLSR | ``/<network>/<site>/%C1.O.R./<router-id>/NLSR`` |
| | |
| | Identity example: ``/ndn/edu/ucla/%C1.O.R./rt1/NLSR`` |
| | |
| | Certificate name example: ``/ndn/edu/ucla/%C1.O.R./rt1/NLSR/KEY/ksk-5/ID-CERT/%01`` |
+------------+-------------------------------------------------------------------------------------+
Assume that a typical NLSR data name is
``/ndn/edu/ucla/%C1.O.R./rt1/NLSR/LSA/LSType.1/%01``. Then here is the trust schema:
::
rule
{
id announce
name (<>)(<>*)<%C1.O.R.>(<>)<NLSR><LSA><LSType.1>[id]
signer nlsr($1,$2,$3)
}
rule
{
id nlsr
name (<>)(<>*)<%C1.O.R.>(<>)<NLSR><KEY>[id]<ID-CERT>[version]
signer router($1,$2,$3)
}
rule
{
id router
name (<>)(<>*)<%C1.O.R.>(<>)<KEY>[id]<ID-CERT>[version]
signer operator($1,$2)
}
rule
{
id operator
name (<>)(<>*)<%C1.O.N.>[user]<KEY>[id]<ID-CERT>[version]
signer site($1)
}
rule
{
id site
name (<>)(<>*)<KEY>[id]<ID-CERT>[version]
signer root($1)
}
anchor
{
id root
name (<>)<KEY>[id]<ID-CERT>[version]
file "testbed-trust-anchor.cert"
}
crypto
{
hash sha-256
signing rsa|ecdsa
key-strength 112
}
Example Configuration For NFD RIB Management
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Assume `NFD RIB Management <http://redmine.named-data.net/projects/nfd/wiki/RibMgmt>`_
allows any valid testbed certificate to register prefix, the configuration file could be
written as:
::
rule
{
id localhost-rib-command
type interest
name <localhost><nrd>[<register><unregister><advertise><withdraw>]<><prefix>(<>*)(<>)
signer key($1,$2)
}
rule
{
id key
name (<>*)(<>)<KEY>[id]<ID-CERT>[version]
signer key($1,null)|root()
}
trust-anchor
{
id root
name <KEY>[id]
raw "Bv0DGwdG...amHFvHIMDw=="
}
crypto
{
hash sha-256
signing rsa|ecdsa
key-strength 112
}
+62
View File
@@ -0,0 +1,62 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#include "regex-backref-matcher.hpp"
#include "regex-pattern-list-matcher.hpp"
namespace ndn {
RegexBackrefMatcher::RegexBackrefMatcher(const std::string& expr,
shared_ptr<RegexBackrefManager> backrefManager)
: RegexMatcher(expr, EXPR_BACKREF, backrefManager)
{
}
RegexBackrefMatcher::~RegexBackrefMatcher()
{
}
void
RegexBackrefMatcher::lateCompile()
{
compile();
}
void
RegexBackrefMatcher::compile()
{
if (m_expr.size() < 2)
throw Error("Unrecognized format: " + m_expr);
size_t lastIndex = m_expr.size() - 1;
if ('(' == m_expr[0] && ')' == m_expr[lastIndex]) {
// m_backRefManager->pushRef(this);
auto matcher = make_shared<RegexPatternListMatcher>(m_expr.substr(1, lastIndex - 1),
m_backrefManager);
m_matchers.push_back(matcher);
}
else
throw Error("Unrecognized format: " + m_expr);
}
} // namespace ndn
+4 -44
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -17,8 +17,6 @@
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
*/
#ifndef NDN_UTIL_REGEX_REGEX_BACKREF_MATCHER_HPP
@@ -36,54 +34,16 @@ public:
RegexBackrefMatcher(const std::string& expr, shared_ptr<RegexBackrefManager> backrefManager);
virtual
~RegexBackrefMatcher()
{
}
~RegexBackrefMatcher() NDN_CXX_DECL_FINAL;
void
lateCompile()
{
compile();
}
lateCompile();
protected:
virtual void
compile();
compile() NDN_CXX_DECL_FINAL;
};
} // namespace ndn
#include "regex-pattern-list-matcher.hpp"
namespace ndn {
inline
RegexBackrefMatcher::RegexBackrefMatcher(const std::string& expr,
shared_ptr<RegexBackrefManager> backrefManager)
: RegexMatcher(expr, EXPR_BACKREF, backrefManager)
{
// compile();
}
inline void
RegexBackrefMatcher::compile()
{
if (m_expr.size() < 2)
throw RegexMatcher::Error("Unrecognized format: " + m_expr);
size_t lastIndex = m_expr.size() - 1;
if ('(' == m_expr[0] && ')' == m_expr[lastIndex]) {
// m_backRefManager->pushRef(this);
shared_ptr<RegexMatcher> matcher(new RegexPatternListMatcher(m_expr.substr(1, lastIndex - 1),
m_backrefManager));
m_matchers.push_back(matcher);
}
else
throw RegexMatcher::Error("Unrecognized format: " + m_expr);
}
} // namespace ndn
#endif // NDN_UTIL_REGEX_REGEX_BACKREF_MATCHER_HPP
@@ -0,0 +1,97 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#include "regex-component-matcher.hpp"
namespace ndn {
// Re: http://www.boost.org/users/history/version_1_56_0.html
//
// Breaking change: corrected behavior of basic_regex<>::mark_count() to match existing
// documentation, basic_regex<>::subexpression(n) changed to match, see
// https://svn.boost.org/trac/boost/ticket/9227
static const size_t BOOST_REGEXP_MARK_COUNT_CORRECTION =
#if BOOST_VERSION < 105600
1;
#else
0;
#endif
RegexComponentMatcher::RegexComponentMatcher(const std::string& expr,
shared_ptr<RegexBackrefManager> backrefManager,
bool isExactMatch)
: RegexMatcher(expr, EXPR_COMPONENT, backrefManager)
, m_isExactMatch(isExactMatch)
{
compile();
}
RegexComponentMatcher::~RegexComponentMatcher()
{
}
bool
RegexComponentMatcher::match(const Name& name, size_t offset, size_t len)
{
m_matchResult.clear();
if (m_expr.empty()) {
m_matchResult.push_back(name.get(offset));
return true;
}
if (m_isExactMatch) {
boost::smatch subResult;
std::string targetStr = name.get(offset).toUri();
if (boost::regex_match(targetStr, subResult, m_componentRegex)) {
for (size_t i = 1;
i <= m_componentRegex.mark_count() - BOOST_REGEXP_MARK_COUNT_CORRECTION; i++) {
m_pseudoMatchers[i]->resetMatchResult();
m_pseudoMatchers[i]->setMatchResult(subResult[i]);
}
m_matchResult.push_back(name.get(offset));
return true;
}
}
else {
throw Error("Non-exact component search is not supported yet!");
}
return false;
}
void
RegexComponentMatcher::compile()
{
m_componentRegex = boost::regex(m_expr);
m_pseudoMatchers.clear();
m_pseudoMatchers.push_back(make_shared<RegexPseudoMatcher>());
for (size_t i = 1;
i <= m_componentRegex.mark_count() - BOOST_REGEXP_MARK_COUNT_CORRECTION; i++) {
auto pMatcher = make_shared<RegexPseudoMatcher>();
m_pseudoMatchers.push_back(pMatcher);
m_backrefManager->pushRef(static_pointer_cast<RegexMatcher>(pMatcher));
}
}
} // namespace ndn
+4 -84
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -17,8 +17,6 @@
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
*/
#ifndef NDN_UTIL_REGEX_REGEX_COMPONENT_MATCHER_HPP
@@ -45,12 +43,10 @@ public:
bool isExactMatch = true);
virtual
~RegexComponentMatcher()
{
};
~RegexComponentMatcher() NDN_CXX_DECL_FINAL;
virtual bool
match(const Name& name, size_t offset, size_t len = 1);
match(const Name& name, size_t offset, size_t len = 1) NDN_CXX_DECL_FINAL;
protected:
/**
@@ -58,7 +54,7 @@ protected:
* @returns true if compiling succeeds
*/
virtual void
compile();
compile() NDN_CXX_DECL_FINAL;
private:
bool m_isExactMatch;
@@ -67,82 +63,6 @@ private:
};
inline
RegexComponentMatcher::RegexComponentMatcher(const std::string& expr,
shared_ptr<RegexBackrefManager> backrefManager,
bool isExactMatch)
: RegexMatcher(expr, EXPR_COMPONENT, backrefManager)
, m_isExactMatch(isExactMatch)
{
compile();
}
// Re: http://www.boost.org/users/history/version_1_56_0.html
//
// Breaking change: corrected behavior of basic_regex<>::mark_count() to match existing
// documentation, basic_regex<>::subexpression(n) changed to match, see
// https://svn.boost.org/trac/boost/ticket/9227
static const size_t BOOST_REGEXP_MARK_COUNT_CORRECTION =
#if BOOST_VERSION < 105600
1;
#else
0;
#endif
inline void
RegexComponentMatcher::compile()
{
m_componentRegex = boost::regex(m_expr);
m_pseudoMatchers.clear();
m_pseudoMatchers.push_back(make_shared<RegexPseudoMatcher>());
for (size_t i = 1;
i <= m_componentRegex.mark_count() - BOOST_REGEXP_MARK_COUNT_CORRECTION; i++)
{
shared_ptr<RegexPseudoMatcher> pMatcher = make_shared<RegexPseudoMatcher>();
m_pseudoMatchers.push_back(pMatcher);
m_backrefManager->pushRef(static_pointer_cast<RegexMatcher>(pMatcher));
}
}
inline bool
RegexComponentMatcher::match(const Name& name, size_t offset, size_t len)
{
m_matchResult.clear();
if (m_expr.empty())
{
m_matchResult.push_back(name.get(offset));
return true;
}
if (m_isExactMatch)
{
boost::smatch subResult;
std::string targetStr = name.get(offset).toUri();
if (boost::regex_match(targetStr, subResult, m_componentRegex))
{
for (size_t i = 1;
i <= m_componentRegex.mark_count() - BOOST_REGEXP_MARK_COUNT_CORRECTION; i++)
{
m_pseudoMatchers[i]->resetMatchResult();
m_pseudoMatchers[i]->setMatchResult(subResult[i]);
}
m_matchResult.push_back(name.get(offset));
return true;
}
}
else
{
throw RegexMatcher::Error("Non-exact component search is not supported yet!");
}
return false;
}
} // namespace ndn
#endif // NDN_UTIL_REGEX_REGEX_COMPONENT_MATCHER_HPP
@@ -0,0 +1,161 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#include "regex-component-set-matcher.hpp"
namespace ndn {
RegexComponentSetMatcher::RegexComponentSetMatcher(const std::string& expr,
shared_ptr<RegexBackrefManager> backrefManager)
: RegexMatcher(expr, EXPR_COMPONENT_SET, backrefManager)
, m_isInclusion(true)
{
compile();
}
RegexComponentSetMatcher::~RegexComponentSetMatcher()
{
}
bool
RegexComponentSetMatcher::match(const Name& name, size_t offset, size_t len)
{
bool isMatched = false;
/* componentset only matches one component */
if (len != 1)
{
return false;
}
for (auto& component : m_components) {
if (component->match(name, offset, len)) {
isMatched = true;
break;
}
}
m_matchResult.clear();
if (m_isInclusion ? isMatched : !isMatched) {
m_matchResult.push_back(name.get(offset));
return true;
}
else
return false;
}
void
RegexComponentSetMatcher::compile()
{
if (m_expr.size() < 2)
throw Error("Regexp compile error (cannot parse " + m_expr + ")");
switch (m_expr[0]) {
case '<':
return compileSingleComponent();
case '[':
{
size_t lastIndex = m_expr.size() - 1;
if (']' != m_expr[lastIndex])
throw Error("Regexp compile error (no matching ']' in " + m_expr + ")");
if ('^' == m_expr[1]) {
m_isInclusion = false;
compileMultipleComponents(2, lastIndex);
}
else
compileMultipleComponents(1, lastIndex);
break;
}
default:
throw Error("Regexp compile error (cannot parse " + m_expr + ")");
}
}
void
RegexComponentSetMatcher::compileSingleComponent()
{
size_t end = extractComponent(1);
if (m_expr.size() != end) {
throw Error("Component expr error " + m_expr);
}
else {
auto component = make_shared<RegexComponentMatcher>(m_expr.substr(1, end - 2),
m_backrefManager);
m_components.insert(component);
}
}
void
RegexComponentSetMatcher::compileMultipleComponents(size_t start, size_t lastIndex)
{
size_t index = start;
size_t tempIndex = start;
while (index < lastIndex) {
if ('<' != m_expr[index])
throw Error("Component expr error " + m_expr);
tempIndex = index + 1;
index = extractComponent(tempIndex);
auto component = make_shared<RegexComponentMatcher>(m_expr.substr(tempIndex,
index - tempIndex - 1),
m_backrefManager);
m_components.insert(component);
}
if (index != lastIndex)
throw Error("Not sufficient expr to parse " + m_expr);
}
size_t
RegexComponentSetMatcher::extractComponent(size_t index)
{
size_t lcount = 1;
size_t rcount = 0;
while (lcount > rcount) {
switch (m_expr[index]) {
case '<':
lcount++;
break;
case '>':
rcount++;
break;
case 0:
throw Error("Error: square brackets mismatch");
break;
}
index++;
}
return index;
}
} // namespace ndn
+4 -151
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -17,8 +17,6 @@
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
*/
#ifndef NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP
@@ -44,10 +42,10 @@ public:
RegexComponentSetMatcher(const std::string& expr, shared_ptr<RegexBackrefManager> backrefManager);
virtual
~RegexComponentSetMatcher();
~RegexComponentSetMatcher() NDN_CXX_DECL_FINAL;
virtual bool
match(const Name& name, size_t offset, size_t len = 1);
match(const Name& name, size_t offset, size_t len = 1) NDN_CXX_DECL_FINAL;
protected:
/**
@@ -55,7 +53,7 @@ protected:
* @returns true if compiling succeeds
*/
virtual void
compile();
compile() NDN_CXX_DECL_FINAL;
private:
size_t
@@ -73,151 +71,6 @@ private:
bool m_isInclusion;
};
inline
RegexComponentSetMatcher::RegexComponentSetMatcher(const std::string& expr,
shared_ptr<RegexBackrefManager> backrefManager)
: RegexMatcher(expr, EXPR_COMPONENT_SET, backrefManager)
, m_isInclusion(true)
{
compile();
}
inline
RegexComponentSetMatcher::~RegexComponentSetMatcher()
{
}
inline void
RegexComponentSetMatcher::compile()
{
if (m_expr.size() < 2)
throw RegexMatcher::Error("Regexp compile error (cannot parse " + m_expr + ")");
switch (m_expr[0]) {
case '<':
return compileSingleComponent();
case '[':
{
size_t lastIndex = m_expr.size() - 1;
if (']' != m_expr[lastIndex])
throw RegexMatcher::Error("Regexp compile error (no matching ']' in " + m_expr + ")");
if ('^' == m_expr[1]) {
m_isInclusion = false;
compileMultipleComponents(2, lastIndex);
}
else
compileMultipleComponents(1, lastIndex);
break;
}
default:
throw RegexMatcher::Error("Regexp compile error (cannot parse " + m_expr + ")");
}
}
inline void
RegexComponentSetMatcher::compileSingleComponent()
{
size_t end = extractComponent(1);
if (m_expr.size() != end)
{
throw RegexMatcher::Error("Component expr error " + m_expr);
}
else
{
shared_ptr<RegexComponentMatcher> component =
make_shared<RegexComponentMatcher>(m_expr.substr(1, end - 2), m_backrefManager);
m_components.insert(component);
}
}
inline void
RegexComponentSetMatcher::compileMultipleComponents(size_t start, size_t lastIndex)
{
size_t index = start;
size_t tempIndex = start;
while (index < lastIndex) {
if ('<' != m_expr[index])
throw RegexMatcher::Error("Component expr error " + m_expr);
tempIndex = index + 1;
index = extractComponent(tempIndex);
shared_ptr<RegexComponentMatcher> component =
make_shared<RegexComponentMatcher>(m_expr.substr(tempIndex, index - tempIndex - 1),
m_backrefManager);
m_components.insert(component);
}
if (index != lastIndex)
throw RegexMatcher::Error("Not sufficient expr to parse " + m_expr);
}
inline bool
RegexComponentSetMatcher::match(const Name& name, size_t offset, size_t len)
{
bool isMatched = false;
/* componentset only matches one component */
if (len != 1)
{
return false;
}
for (ComponentsSet::iterator it = m_components.begin();
it != m_components.end();
++it)
{
if ((*it)->match(name, offset, len))
{
isMatched = true;
break;
}
}
m_matchResult.clear();
if (m_isInclusion ? isMatched : !isMatched)
{
m_matchResult.push_back(name.get(offset));
return true;
}
else
return false;
}
inline size_t
RegexComponentSetMatcher::extractComponent(size_t index)
{
size_t lcount = 1;
size_t rcount = 0;
while (lcount > rcount) {
switch (m_expr[index]) {
case '<':
lcount++;
break;
case '>':
rcount++;
break;
case 0:
throw RegexMatcher::Error("Error: square brackets mismatch");
break;
}
index++;
}
return index;
}
} // namespace ndn
#endif // NDN_UTIL_REGEX_COMPONENT_SET_MATCHER_HPP
+80
View File
@@ -0,0 +1,80 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#include "regex-matcher.hpp"
namespace ndn {
RegexMatcher::RegexMatcher(const std::string& expr,
const RegexExprType& type,
shared_ptr<RegexBackrefManager> backrefManager)
: m_expr(expr)
, m_type(type)
, m_backrefManager(backrefManager)
{
if (!static_cast<bool>(m_backrefManager))
m_backrefManager = make_shared<RegexBackrefManager>();
}
RegexMatcher::~RegexMatcher()
{
}
bool
RegexMatcher::match(const Name& name, size_t offset, size_t len)
{
bool result = false;
m_matchResult.clear();
if (recursiveMatch(0, name, offset, len)) {
for (size_t i = offset; i < offset + len ; i++)
m_matchResult.push_back(name.get(i));
result = true;
}
else {
result = false;
}
return result;
}
bool
RegexMatcher::recursiveMatch(size_t matcherNo, const Name& name, size_t offset, size_t len)
{
ssize_t tried = len;
if (matcherNo >= m_matchers.size())
return (len == 0);
shared_ptr<RegexMatcher> matcher = m_matchers[matcherNo];
while (tried >= 0) {
if (matcher->match(name, offset, tried) &&
recursiveMatch(matcherNo + 1, name, offset + tried, len - tried))
return true;
tried--;
}
return false;
}
} // namespace ndn
+3 -73
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -17,8 +17,6 @@
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
*/
#ifndef NDN_UTIL_REGEX_REGEX_MATCHER_H
@@ -26,11 +24,10 @@
#include "../../common.hpp"
#include "../../name.hpp"
#include "regex-backref-manager.hpp"
namespace ndn {
class RegexBackrefManager;
class RegexMatcher
{
public:
@@ -56,7 +53,7 @@ public:
RegexMatcher(const std::string& expr,
const RegexExprType& type,
shared_ptr<RegexBackrefManager> backrefManager = shared_ptr<RegexBackrefManager>());
shared_ptr<RegexBackrefManager> backrefManager = nullptr);
virtual
~RegexMatcher();
@@ -110,71 +107,4 @@ operator<<(std::ostream& os, const RegexMatcher& regex)
} // namespace ndn
#include "regex-backref-manager.hpp"
namespace ndn {
inline
RegexMatcher::RegexMatcher(const std::string& expr,
const RegexExprType& type,
shared_ptr<RegexBackrefManager> backrefManager)
: m_expr(expr)
, m_type(type)
, m_backrefManager(backrefManager)
{
if (!static_cast<bool>(m_backrefManager))
m_backrefManager = make_shared<RegexBackrefManager>();
}
inline
RegexMatcher::~RegexMatcher()
{
}
inline bool
RegexMatcher::match(const Name& name, size_t offset, size_t len)
{
bool result = false;
m_matchResult.clear();
if (recursiveMatch(0, name, offset, len))
{
for (size_t i = offset; i < offset + len ; i++)
m_matchResult.push_back(name.get(i));
result = true;
}
else
{
result = false;
}
return result;
}
inline bool
RegexMatcher::recursiveMatch(size_t matcherNo, const Name& name, size_t offset, size_t len)
{
ssize_t tried = len;
if (matcherNo >= m_matchers.size())
return (len == 0);
shared_ptr<RegexMatcher> matcher = m_matchers[matcherNo];
while (tried >= 0)
{
if (matcher->match(name, offset, tried) &&
recursiveMatch(matcherNo + 1, name, offset + tried, len - tried))
return true;
tried--;
}
return false;
}
} // namespace ndn
#endif // NDN_UTIL_REGEX_REGEX_MATCHER_H
@@ -0,0 +1,159 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#include "regex-pattern-list-matcher.hpp"
#include "regex-repeat-matcher.hpp"
#include "regex-backref-matcher.hpp"
namespace ndn {
RegexPatternListMatcher::RegexPatternListMatcher(const std::string& expr,
shared_ptr<RegexBackrefManager> backrefManager)
: RegexMatcher(expr, EXPR_PATTERN_LIST, backrefManager)
{
compile();
}
RegexPatternListMatcher::~RegexPatternListMatcher()
{
}
void
RegexPatternListMatcher::compile()
{
size_t len = m_expr.size();
size_t index = 0;
size_t subHead = index;
while (index < len) {
subHead = index;
if (!extractPattern(subHead, &index))
throw Error("Compile error");
}
}
bool
RegexPatternListMatcher::extractPattern(size_t index, size_t* next)
{
size_t start = index;
size_t end = index;
size_t indicator = index;
switch (m_expr[index]) {
case '(':
index++;
index = extractSubPattern('(', ')', index);
indicator = index;
end = extractRepetition(index);
if (indicator == end) {
auto matcher = make_shared<RegexBackrefMatcher>(m_expr.substr(start, end - start),
m_backrefManager);
m_backrefManager->pushRef(matcher);
dynamic_pointer_cast<RegexBackrefMatcher>(matcher)->lateCompile();
m_matchers.push_back(matcher);
}
else
m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
m_backrefManager, indicator - start));
break;
case '<':
index++;
index = extractSubPattern('<', '>', index);
indicator = index;
end = extractRepetition(index);
m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
m_backrefManager, indicator - start));
break;
case '[':
index++;
index = extractSubPattern('[', ']', index);
indicator = index;
end = extractRepetition(index);
m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
m_backrefManager, indicator - start));
break;
default:
throw Error("Unexpected syntax");
}
*next = end;
return true;
}
int
RegexPatternListMatcher::extractSubPattern(const char left, const char right, size_t index)
{
size_t lcount = 1;
size_t rcount = 0;
while (lcount > rcount) {
if (index >= m_expr.size())
throw Error("Parenthesis mismatch");
if (left == m_expr[index])
lcount++;
if (right == m_expr[index])
rcount++;
index++;
}
return index;
}
int
RegexPatternListMatcher::extractRepetition(size_t index)
{
size_t exprSize = m_expr.size();
if (index == exprSize)
return index;
if (('+' == m_expr[index] || '?' == m_expr[index] || '*' == m_expr[index])) {
return ++index;
}
if ('{' == m_expr[index]) {
while ('}' != m_expr[index]) {
index++;
if (index == exprSize)
break;
}
if (index == exprSize)
throw Error("Missing right brace bracket");
else
return ++index;
}
else {
return index;
}
}
} // namespace ndn
+3 -141
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -17,8 +17,6 @@
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
*/
#ifndef NDN_UTIL_REGEX_REGEX_PATTERN_LIST_MATCHER_HPP
@@ -38,13 +36,11 @@ public:
RegexPatternListMatcher(const std::string& expr, shared_ptr<RegexBackrefManager> backrefManager);
virtual
~RegexPatternListMatcher()
{
};
~RegexPatternListMatcher() NDN_CXX_DECL_FINAL;
protected:
virtual void
compile();
compile() NDN_CXX_DECL_FINAL;
private:
bool
@@ -60,140 +56,6 @@ private:
};
} // namespace ndn
#include "regex-repeat-matcher.hpp"
#include "regex-backref-matcher.hpp"
namespace ndn {
inline
RegexPatternListMatcher::RegexPatternListMatcher(const std::string& expr,
shared_ptr<RegexBackrefManager> backrefManager)
: RegexMatcher(expr, EXPR_PATTERN_LIST, backrefManager)
{
compile();
}
inline void
RegexPatternListMatcher::compile()
{
size_t len = m_expr.size();
size_t index = 0;
size_t subHead = index;
while (index < len) {
subHead = index;
if (!extractPattern(subHead, &index))
throw RegexMatcher::Error("Compile error");
}
}
inline bool
RegexPatternListMatcher::extractPattern(size_t index, size_t* next)
{
size_t start = index;
size_t end = index;
size_t indicator = index;
switch (m_expr[index]) {
case '(':
index++;
index = extractSubPattern('(', ')', index);
indicator = index;
end = extractRepetition(index);
if (indicator == end) {
shared_ptr<RegexMatcher> matcher =
make_shared<RegexBackrefMatcher>(m_expr.substr(start, end - start), m_backrefManager);
m_backrefManager->pushRef(matcher);
dynamic_pointer_cast<RegexBackrefMatcher>(matcher)->lateCompile();
m_matchers.push_back(matcher);
}
else
m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
m_backrefManager, indicator - start));
break;
case '<':
index++;
index = extractSubPattern('<', '>', index);
indicator = index;
end = extractRepetition(index);
m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
m_backrefManager, indicator - start));
break;
case '[':
index++;
index = extractSubPattern('[', ']', index);
indicator = index;
end = extractRepetition(index);
m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
m_backrefManager, indicator - start));
break;
default:
throw RegexMatcher::Error("Unexpected syntax");
}
*next = end;
return true;
}
inline int
RegexPatternListMatcher::extractSubPattern(const char left, const char right, size_t index)
{
size_t lcount = 1;
size_t rcount = 0;
while (lcount > rcount) {
if (index >= m_expr.size())
throw RegexMatcher::Error("Parenthesis mismatch");
if (left == m_expr[index])
lcount++;
if (right == m_expr[index])
rcount++;
index++;
}
return index;
}
inline int
RegexPatternListMatcher::extractRepetition(size_t index)
{
size_t exprSize = m_expr.size();
if (index == exprSize)
return index;
if (('+' == m_expr[index] || '?' == m_expr[index] || '*' == m_expr[index])) {
return ++index;
}
if ('{' == m_expr[index]) {
while ('}' != m_expr[index]) {
index++;
if (index == exprSize)
break;
}
if (index == exprSize)
throw RegexMatcher::Error("Missing right brace bracket");
else
return ++index;
}
else {
return index;
}
}
} // namespace ndn
#endif // NDN_UTIL_REGEX_REGEX_PATTERN_LIST_MATCHER_HPP
+53
View File
@@ -0,0 +1,53 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#include "regex-pseudo-matcher.hpp"
namespace ndn {
RegexPseudoMatcher::RegexPseudoMatcher()
: RegexMatcher("", EXPR_PSEUDO)
{
}
RegexPseudoMatcher::~RegexPseudoMatcher()
{
}
void
RegexPseudoMatcher::compile()
{
}
void
RegexPseudoMatcher::setMatchResult(const std::string& str)
{
m_matchResult.push_back(name::Component(reinterpret_cast<const uint8_t*>(str.c_str()),
str.size()));
}
void
RegexPseudoMatcher::resetMatchResult()
{
m_matchResult.clear();
}
} // namespace ndn
+3 -29
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -17,8 +17,6 @@
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
*/
#ifndef NDN_UTIL_REGEX_REGEX_PSEUDO_MATCHER_HPP
@@ -35,14 +33,10 @@ public:
RegexPseudoMatcher();
virtual
~RegexPseudoMatcher()
{
}
~RegexPseudoMatcher() NDN_CXX_DECL_FINAL;
virtual void
compile()
{
}
compile() NDN_CXX_DECL_FINAL;
void
setMatchResult(const std::string& str);
@@ -51,26 +45,6 @@ public:
resetMatchResult();
};
inline
RegexPseudoMatcher::RegexPseudoMatcher()
: RegexMatcher("", EXPR_PSEUDO)
{
}
inline void
RegexPseudoMatcher::setMatchResult(const std::string& str)
{
m_matchResult.push_back(name::Component(reinterpret_cast<const uint8_t*>(str.c_str()),
str.size()));
}
inline void
RegexPseudoMatcher::resetMatchResult()
{
m_matchResult.clear();
}
} // namespace ndn
#endif // NDN_UTIL_REGEX_REGEX_PSEUDO_MATCHER_HPP
+178
View File
@@ -0,0 +1,178 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#include "regex-repeat-matcher.hpp"
#include "regex-backref-matcher.hpp"
#include "regex-component-set-matcher.hpp"
namespace ndn {
RegexRepeatMatcher::RegexRepeatMatcher(const std::string& expr,
shared_ptr<RegexBackrefManager> backrefManager,
size_t indicator)
: RegexMatcher(expr, EXPR_REPEAT_PATTERN, backrefManager)
, m_indicator(indicator)
{
compile();
}
RegexRepeatMatcher::~RegexRepeatMatcher()
{
}
bool
RegexRepeatMatcher::match(const Name& name, size_t offset, size_t len)
{
m_matchResult.clear();
if (0 == m_repeatMin)
if (0 == len)
return true;
if (recursiveMatch(0, name, offset, len)) {
for (size_t i = offset; i < offset + len; i++)
m_matchResult.push_back(name.get(i));
return true;
}
else
return false;
}
void
RegexRepeatMatcher::compile()
{
shared_ptr<RegexMatcher> matcher;
if ('(' == m_expr[0]) {
matcher = make_shared<RegexBackrefMatcher>(m_expr.substr(0, m_indicator), m_backrefManager);
m_backrefManager->pushRef(matcher);
dynamic_pointer_cast<RegexBackrefMatcher>(matcher)->lateCompile();
}
else{
matcher = make_shared<RegexComponentSetMatcher>(m_expr.substr(0, m_indicator),
m_backrefManager);
}
m_matchers.push_back(matcher);
parseRepetition();
}
bool
RegexRepeatMatcher::parseRepetition()
{
size_t exprSize = m_expr.size();
const size_t MAX_REPETITIONS = std::numeric_limits<size_t>::max();
if (exprSize == m_indicator) {
m_repeatMin = 1;
m_repeatMax = 1;
return true;
}
else {
if (exprSize == (m_indicator + 1)) {
if ('?' == m_expr[m_indicator]) {
m_repeatMin = 0;
m_repeatMax = 1;
return true;
}
if ('+' == m_expr[m_indicator]) {
m_repeatMin = 1;
m_repeatMax = MAX_REPETITIONS;
return true;
}
if ('*' == m_expr[m_indicator]) {
m_repeatMin = 0;
m_repeatMax = MAX_REPETITIONS;
return true;
}
}
else {
std::string repeatStruct = m_expr.substr(m_indicator, exprSize - m_indicator);
size_t rsSize = repeatStruct.size();
size_t min = 0;
size_t max = 0;
if (boost::regex_match(repeatStruct, boost::regex("\\{[0-9]+,[0-9]+\\}"))) {
size_t separator = repeatStruct.find_first_of(',', 0);
min = atoi(repeatStruct.substr(1, separator - 1).c_str());
max = atoi(repeatStruct.substr(separator + 1, rsSize - separator - 2).c_str());
}
else if (boost::regex_match(repeatStruct, boost::regex("\\{,[0-9]+\\}"))) {
size_t separator = repeatStruct.find_first_of(',', 0);
min = 0;
max = atoi(repeatStruct.substr(separator + 1, rsSize - separator - 2).c_str());
}
else if (boost::regex_match(repeatStruct, boost::regex("\\{[0-9]+,\\}"))) {
size_t separator = repeatStruct.find_first_of(',', 0);
min = atoi(repeatStruct.substr(1, separator).c_str());
max = MAX_REPETITIONS;
}
else if (boost::regex_match(repeatStruct, boost::regex("\\{[0-9]+\\}"))) {
min = atoi(repeatStruct.substr(1, rsSize - 1).c_str());
max = min;
}
else
throw Error("Error: RegexRepeatMatcher.ParseRepetition(): Unrecognized format " + m_expr);
if (min > MAX_REPETITIONS || max > MAX_REPETITIONS || min > max)
throw Error("Error: RegexRepeatMatcher.ParseRepetition(): Wrong number " + m_expr);
m_repeatMin = min;
m_repeatMax = max;
return true;
}
}
return false;
}
bool
RegexRepeatMatcher::recursiveMatch(size_t repeat, const Name& name, size_t offset, size_t len)
{
ssize_t tried = len;
shared_ptr<RegexMatcher> matcher = m_matchers[0];
if (0 < len && repeat >= m_repeatMax) {
return false;
}
if (0 == len && repeat < m_repeatMin) {
return false;
}
if (0 == len && repeat >= m_repeatMin) {
return true;
}
while (tried >= 0) {
if (matcher->match(name, offset, tried) &&
recursiveMatch(repeat + 1, name, offset + tried, len - tried))
return true;
tried--;
}
return false;
}
} // namespace ndn
+4 -168
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -17,8 +17,6 @@
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
*/
#ifndef NDN_UTIL_REGEX_REGEX_REPEAT_MATCHER_HPP
@@ -40,12 +38,10 @@ public:
size_t indicator);
virtual
~RegexRepeatMatcher()
{
}
~RegexRepeatMatcher() NDN_CXX_DECL_FINAL;
virtual bool
match(const Name& name, size_t offset, size_t len);
match(const Name& name, size_t offset, size_t len) NDN_CXX_DECL_FINAL;
protected:
/**
@@ -53,7 +49,7 @@ protected:
* @returns true if compiling succeeds
*/
virtual void
compile();
compile() NDN_CXX_DECL_FINAL;
private:
bool
@@ -70,166 +66,6 @@ private:
size_t m_repeatMax;
};
} // namespace ndn
#include "regex-backref-matcher.hpp"
#include "regex-component-set-matcher.hpp"
namespace ndn {
inline
RegexRepeatMatcher::RegexRepeatMatcher(const std::string& expr,
shared_ptr<RegexBackrefManager> backrefManager,
size_t indicator)
: RegexMatcher(expr, EXPR_REPEAT_PATTERN, backrefManager)
, m_indicator(indicator)
{
compile();
}
inline void
RegexRepeatMatcher::compile()
{
shared_ptr<RegexMatcher> matcher;
if ('(' == m_expr[0]) {
matcher = make_shared<RegexBackrefMatcher>(m_expr.substr(0, m_indicator), m_backrefManager);
m_backrefManager->pushRef(matcher);
dynamic_pointer_cast<RegexBackrefMatcher>(matcher)->lateCompile();
}
else{
matcher = make_shared<RegexComponentSetMatcher>(m_expr.substr(0, m_indicator),
m_backrefManager);
}
m_matchers.push_back(matcher);
parseRepetition();
}
inline bool
RegexRepeatMatcher::parseRepetition()
{
size_t exprSize = m_expr.size();
const size_t MAX_REPETITIONS = std::numeric_limits<size_t>::max();
if (exprSize == m_indicator) {
m_repeatMin = 1;
m_repeatMax = 1;
return true;
}
else {
if (exprSize == (m_indicator + 1)) {
if ('?' == m_expr[m_indicator]) {
m_repeatMin = 0;
m_repeatMax = 1;
return true;
}
if ('+' == m_expr[m_indicator]) {
m_repeatMin = 1;
m_repeatMax = MAX_REPETITIONS;
return true;
}
if ('*' == m_expr[m_indicator]) {
m_repeatMin = 0;
m_repeatMax = MAX_REPETITIONS;
return true;
}
}
else {
std::string repeatStruct = m_expr.substr(m_indicator, exprSize - m_indicator);
size_t rsSize = repeatStruct.size();
size_t min = 0;
size_t max = 0;
if (boost::regex_match(repeatStruct, boost::regex("\\{[0-9]+,[0-9]+\\}"))) {
size_t separator = repeatStruct.find_first_of(',', 0);
min = atoi(repeatStruct.substr(1, separator - 1).c_str());
max = atoi(repeatStruct.substr(separator + 1, rsSize - separator - 2).c_str());
}
else if (boost::regex_match(repeatStruct, boost::regex("\\{,[0-9]+\\}"))) {
size_t separator = repeatStruct.find_first_of(',', 0);
min = 0;
max = atoi(repeatStruct.substr(separator + 1, rsSize - separator - 2).c_str());
}
else if (boost::regex_match(repeatStruct, boost::regex("\\{[0-9]+,\\}"))) {
size_t separator = repeatStruct.find_first_of(',', 0);
min = atoi(repeatStruct.substr(1, separator).c_str());
max = MAX_REPETITIONS;
}
else if (boost::regex_match(repeatStruct, boost::regex("\\{[0-9]+\\}"))) {
min = atoi(repeatStruct.substr(1, rsSize - 1).c_str());
max = min;
}
else
throw RegexMatcher::Error(std::string("Error: RegexRepeatMatcher.ParseRepetition(): ")
+ "Unrecognized format "+ m_expr);
if (min > MAX_REPETITIONS || max > MAX_REPETITIONS || min > max)
throw RegexMatcher::Error(std::string("Error: RegexRepeatMatcher.ParseRepetition(): ")
+ "Wrong number " + m_expr);
m_repeatMin = min;
m_repeatMax = max;
return true;
}
}
return false;
}
inline bool
RegexRepeatMatcher::match(const Name& name, size_t offset, size_t len)
{
m_matchResult.clear();
if (0 == m_repeatMin)
if (0 == len)
return true;
if (recursiveMatch(0, name, offset, len))
{
for (size_t i = offset; i < offset + len; i++)
m_matchResult.push_back(name.get(i));
return true;
}
else
return false;
}
inline bool
RegexRepeatMatcher::recursiveMatch(size_t repeat, const Name& name, size_t offset, size_t len)
{
ssize_t tried = len;
shared_ptr<RegexMatcher> matcher = m_matchers[0];
if (0 < len && repeat >= m_repeatMax)
{
return false;
}
if (0 == len && repeat < m_repeatMin)
{
return false;
}
if (0 == len && repeat >= m_repeatMin)
{
return true;
}
while (tried >= 0)
{
if (matcher->match(name, offset, tried) &&
recursiveMatch(repeat + 1, name, offset + tried, len - tried))
return true;
tried--;
}
return false;
}
} // namespace ndn
#endif // NDN_UTIL_REGEX_REGEX_REPEAT_MATCHER_HPP
+96 -112
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -17,8 +17,6 @@
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
*/
#include "regex-top-matcher.hpp"
@@ -47,8 +45,6 @@ RegexTopMatcher::~RegexTopMatcher()
void
RegexTopMatcher::compile()
{
std::string errMsg = "Error: RegexTopMatcher.Compile(): ";
std::string expr = m_expr;
if ('$' != expr[expr.size() - 1])
@@ -78,21 +74,18 @@ RegexTopMatcher::match(const Name& name)
m_matchResult.clear();
if (m_primaryMatcher->match(name, 0, name.size()))
{
m_matchResult = m_primaryMatcher->getMatchResult();
if (m_primaryMatcher->match(name, 0, name.size())) {
m_matchResult = m_primaryMatcher->getMatchResult();
return true;
}
else {
if (static_cast<bool>(m_secondaryMatcher) && m_secondaryMatcher->match(name, 0, name.size())) {
m_matchResult = m_secondaryMatcher->getMatchResult();
m_isSecondaryUsed = true;
return true;
}
else
{
if (static_cast<bool>(m_secondaryMatcher) && m_secondaryMatcher->match(name, 0, name.size()))
{
m_matchResult = m_secondaryMatcher->getMatchResult();
m_isSecondaryUsed = true;
return true;
}
return false;
}
return false;
}
}
bool
@@ -106,7 +99,7 @@ RegexTopMatcher::expand(const std::string& expandStr)
{
Name result;
shared_ptr<RegexBackrefManager> backrefManager =
auto backrefManager =
(m_isSecondaryUsed ? m_secondaryBackrefManager : m_primaryBackrefManager);
size_t backrefNo = backrefManager->size();
@@ -119,36 +112,32 @@ RegexTopMatcher::expand(const std::string& expandStr)
expand = m_expand;
size_t offset = 0;
while (offset < expand.size())
{
std::string item = getItemFromExpand(expand, offset);
if (item[0] == '<')
{
result.append(item.substr(1, item.size() - 2));
}
if (item[0] == '\\')
{
size_t index = boost::lexical_cast<size_t>(item.substr(1, item.size() - 1));
if (0 == index) {
std::vector<name::Component>::iterator it = m_matchResult.begin();
std::vector<name::Component>::iterator end = m_matchResult.end();
for (; it != end; it++)
result.append(*it);
}
else if (index <= backrefNo)
{
std::vector<name::Component>::const_iterator it =
backrefManager->getBackref(index - 1)->getMatchResult().begin();
std::vector<name::Component>::const_iterator end =
backrefManager->getBackref(index - 1)->getMatchResult().end();
for (; it != end; it++)
result.append(*it);
}
else
throw RegexMatcher::Error("Exceed the range of back reference");
}
while (offset < expand.size()) {
std::string item = getItemFromExpand(expand, offset);
if (item[0] == '<') {
result.append(item.substr(1, item.size() - 2));
}
if (item[0] == '\\') {
size_t index = boost::lexical_cast<size_t>(item.substr(1, item.size() - 1));
if (0 == index) {
std::vector<name::Component>::iterator it = m_matchResult.begin();
std::vector<name::Component>::iterator end = m_matchResult.end();
for (; it != end; it++)
result.append(*it);
}
else if (index <= backrefNo) {
std::vector<name::Component>::const_iterator it =
backrefManager->getBackref(index - 1)->getMatchResult().begin();
std::vector<name::Component>::const_iterator end =
backrefManager->getBackref(index - 1)->getMatchResult().end();
for (; it != end; it++)
result.append(*it);
}
else
throw Error("Exceed the range of back reference");
}
}
return result;
}
@@ -157,44 +146,41 @@ RegexTopMatcher::getItemFromExpand(const std::string& expand, size_t& offset)
{
size_t begin = offset;
if (expand[offset] == '\\')
{
offset++;
if (offset >= expand.size())
throw RegexMatcher::Error("wrong format of expand string!");
if (expand[offset] == '\\') {
offset++;
if (offset >= expand.size())
throw Error("wrong format of expand string!");
while (expand[offset] <= '9' and expand[offset] >= '0') {
offset++;
if (offset > expand.size())
throw RegexMatcher::Error("wrong format of expand string!");
}
if (offset > begin + 1)
return expand.substr(begin, offset - begin);
else
throw RegexMatcher::Error("wrong format of expand string!");
while (expand[offset] <= '9' and expand[offset] >= '0') {
offset++;
if (offset > expand.size())
throw Error("wrong format of expand string!");
}
else if (expand[offset] == '<')
{
offset++;
if (offset >= expand.size())
throw RegexMatcher::Error("wrong format of expand string!");
size_t left = 1;
size_t right = 0;
while (right < left)
{
if (expand[offset] == '<')
left++;
if (expand[offset] == '>')
right++;
offset++;
if (offset >= expand.size())
throw RegexMatcher::Error("wrong format of expand string!");
}
if (offset > begin + 1)
return expand.substr(begin, offset - begin);
else
throw Error("wrong format of expand string!");
}
else if (expand[offset] == '<') {
offset++;
if (offset >= expand.size())
throw Error("wrong format of expand string!");
size_t left = 1;
size_t right = 0;
while (right < left) {
if (expand[offset] == '<')
left++;
if (expand[offset] == '>')
right++;
offset++;
if (offset >= expand.size())
throw Error("wrong format of expand string!");
}
return expand.substr(begin, offset - begin);
}
else
throw RegexMatcher::Error("wrong format of expand string!");
throw Error("wrong format of expand string!");
}
shared_ptr<RegexTopMatcher>
@@ -202,12 +188,11 @@ RegexTopMatcher::fromName(const Name& name, bool hasAnchor)
{
std::string regexStr("^");
for (Name::const_iterator it = name.begin(); it != name.end(); it++)
{
regexStr.append("<");
regexStr.append(convertSpecialChar(it->toUri()));
regexStr.append(">");
}
for (const auto& comp : name) {
regexStr.append("<");
regexStr.append(convertSpecialChar(comp.toUri()));
regexStr.append(">");
}
if (hasAnchor)
regexStr.append("$");
@@ -221,31 +206,30 @@ std::string
RegexTopMatcher::convertSpecialChar(const std::string& str)
{
std::string newStr;
for (size_t i = 0; i < str.size(); i++)
{
char c = str[i];
switch (c)
{
case '.':
case '[':
case '{':
case '}':
case '(':
case ')':
case '\\':
case '*':
case '+':
case '?':
case '|':
case '^':
case '$':
newStr.push_back('\\');
// Fallthrough
default:
newStr.push_back(c);
break;
}
}
for (size_t i = 0; i < str.size(); i++) {
char c = str[i];
switch (c)
{
case '.':
case '[':
case '{':
case '}':
case '(':
case ')':
case '\\':
case '*':
case '+':
case '?':
case '|':
case '^':
case '$':
newStr.push_back('\\');
// Fallthrough
default:
newStr.push_back(c);
break;
}
}
return newStr;
}
+4 -6
View File
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
* Copyright (c) 2013-2015 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -17,8 +17,6 @@
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
*/
#ifndef NDN_UTIL_REGEX_REGEX_TOP_MATCHER_HPP
@@ -39,13 +37,13 @@ public:
RegexTopMatcher(const std::string& expr, const std::string& expand = "");
virtual
~RegexTopMatcher();
~RegexTopMatcher() NDN_CXX_DECL_FINAL;
bool
match(const Name& name);
virtual bool
match(const Name& name, size_t offset, size_t len);
match(const Name& name, size_t offset, size_t len) NDN_CXX_DECL_FINAL;
virtual Name
expand(const std::string& expand = "");
@@ -55,7 +53,7 @@ public:
protected:
virtual void
compile();
compile() NDN_CXX_DECL_FINAL;
private:
std::string