Source code for pyndn.util.regex.ndn_regex_top_matcher
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2017-2019 Regents of the University of California.
# Author: Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
# Author: Jeff Thompson <[email protected]>
#
# This program 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.
#
# This program 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 a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# A copy of the GNU Lesser General Public License is in the file COPYING.
from pyndn.name import Name
from pyndn.util.regex.ndn_regex_matcher_base import NdnRegexMatcherBase
from pyndn.util.regex.ndn_regex_backref_manager import NdnRegexBackrefManager
from pyndn.util.regex.ndn_regex_pattern_list_matcher import NdnRegexPatternListMatcher
[docs]class NdnRegexTopMatcher(NdnRegexMatcherBase):
"""
Create an NdnRegexTopMatcher.
:param str expr: The expression.
:param str expand:
"""
def __init__(self, expr, expand = ""):
super(NdnRegexTopMatcher, self).__init__(
expr, NdnRegexMatcherBase.NdnRegexExprType.TOP)
self._primaryMatcher = None
self._secondaryMatcher = None
self._primaryBackrefManager = NdnRegexBackrefManager()
self._secondaryBackrefManager = NdnRegexBackrefManager()
self._isSecondaryUsed = False
self._expand = expand
self._compile()
[docs] def match(self, name, offset = None, length = None):
"""
:param Name name:
:param int offset: Ignored.
:param int length: Ignored.
:rtype: bool
"""
self._isSecondaryUsed = False
self._matchResult = []
if self._primaryMatcher.match(name, 0, name.size()):
self._matchResult = []
for component in self._primaryMatcher.getMatchResult():
self._matchResult.append(component)
return True
else:
if (self._secondaryMatcher != None and
self._secondaryMatcher.match(name, 0, name.size())):
self._matchResult = []
for component in self._secondaryMatcher.getMatchResult():
self._matchResult.append(component)
self._isSecondaryUsed = True
return True
return False
[docs] def expand(self, expandStr = ""):
"""
:param str expandStr:
:rtype: Name
"""
result = Name()
backrefManager = (self._secondaryBackrefManager if self._isSecondaryUsed
else self._primaryBackrefManager)
backrefNo = backrefManager.size()
if expandStr != "":
usingExpand = expandStr
else:
usingExpand = self._expand
offset = [0]
while offset[0] < len(usingExpand):
item = NdnRegexTopMatcher._getItemFromExpand(usingExpand, offset)
if item[0] == '<':
result.append(item[1 : len(item) - 1])
if item[0] == '\\':
index = int(item[1 : len(item)])
if 0 == index:
for component in self._matchResult:
result.append(component)
elif index <= backrefNo:
for component in backrefManager.getBackref(
index - 1).getMatchResult():
result.append(component)
else:
raise NdnRegexMatcherBase.Error(
"Exceeded the range of back reference")
return result
[docs] @staticmethod
def fromName(name, hasAnchor = False):
"""
:param Name name:
:param bool hasAnchor:
:rtype: NdnRegexTopMatcher
"""
regexStr = "^"
for i in range(name.size()):
regexStr += "<"
regexStr += NdnRegexTopMatcher._convertSpecialChar(
name.get(i).toEscapedString())
regexStr += ">"
if hasAnchor:
regexStr += "$"
return NdnRegexTopMatcher(regexStr)
def _compile(self):
errMsg = "Error: RegexTopMatcher.Compile(): "
expr = self._expr
if '$' != expr[-1]:
expr = expr + "<.*>*"
else:
expr = expr[0 : -1]
if '^' != expr[0]:
self._secondaryMatcher = NdnRegexPatternListMatcher(
"<.*>*" + expr, self._secondaryBackrefManager)
else:
expr = expr[1:]
self._primaryMatcher = NdnRegexPatternListMatcher(
expr, self._primaryBackrefManager)
@staticmethod
def _getItemFromExpand(expand, offset):
"""
:param str expand:
:param Array<int> offset: This updates offset[0].
:rtype: str
"""
begin = offset[0]
if expand[offset[0]] == '\\':
offset[0] += 1
if offset[0] >= len(expand):
raise NdnRegexMatcherBase.Error("Wrong format of expand string!")
while (offset[0] < len(expand) and
expand[offset[0]] <= '9' and expand[offset[0]] >= '0'):
offset[0] += 1
if offset[0] > len(expand):
raise NdnRegexMatcherBase.Error(
"Wrong format of expand string!")
if offset[0] > begin + 1:
return expand[begin : offset[0]]
else:
raise NdnRegexMatcherBase.Error("Wrong format of expand string!")
elif expand[offset[0]] == '<':
offset[0] += 1
if offset[0] >= len(expand):
raise NdnRegexMatcherBase.Error("Wrong format of expand string!")
left = 1
right = 0
while right < left:
if expand[offset[0]] == '<':
left += 1
if expand[offset[0]] == '>':
right += 1
offset[0] += 1
if offset[0] >= len(expand):
raise NdnRegexMatcherBase.Error(
"Wrong format of expand string!")
return expand[begin : offset[0]]
else:
raise NdnRegexMatcherBase.Error("Wrong format of expand string!")
@staticmethod
def _convertSpecialChar(string):
"""
:param str string:
:rtype: str
"""
newStr = ""
for c in string:
if (c == '.' or
c == '[' or
c == '{' or
c == '}' or
c == '(' or
c == ')' or
c == '\\' or
c == '*' or
c == '+' or
c == '?' or
c == '|' or
c == '^' or
c == '$'):
newStr += '\\'
newStr += c
else:
newStr += c
return newStr