1# Copyright 2015-2021 Espressif Systems (Shanghai) CO LTD
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import re
16
17
18class LineMatcher(object):
19    """
20    Assembles a dictionary of filtering rules based on the --print_filter
21    argument of idf_monitor. Then later it is used to match lines and
22    determine whether they should be shown on screen or not.
23    """
24    LEVEL_N = 0
25    LEVEL_E = 1
26    LEVEL_W = 2
27    LEVEL_I = 3
28    LEVEL_D = 4
29    LEVEL_V = 5
30
31    level = {'N': LEVEL_N, 'E': LEVEL_E, 'W': LEVEL_W, 'I': LEVEL_I, 'D': LEVEL_D,
32             'V': LEVEL_V, '*': LEVEL_V, '': LEVEL_V}
33
34    def __init__(self, print_filter):
35        # type: (str) -> None
36        self._dict = dict()
37        self._re = re.compile(r'^(?:\033\[[01];?[0-9]+m?)?([EWIDV]) \([0-9]+\) ([^:]+): ')
38        items = print_filter.split()
39        if len(items) == 0:
40            self._dict['*'] = self.LEVEL_V  # default is to print everything
41        for f in items:
42            s = f.split(r':')
43            if len(s) == 1:
44                # specifying no warning level defaults to verbose level
45                lev = self.LEVEL_V
46            elif len(s) == 2:
47                if len(s[0]) == 0:
48                    raise ValueError('No tag specified in filter ' + f)
49                try:
50                    lev = self.level[s[1].upper()]
51                except KeyError:
52                    raise ValueError('Unknown warning level in filter ' + f)
53            else:
54                raise ValueError('Missing ":" in filter ' + f)
55            self._dict[s[0]] = lev
56
57    def match(self, line):
58        # type: (str) -> bool
59        try:
60            m = self._re.search(line)
61            if m:
62                lev = self.level[m.group(1)]
63                if m.group(2) in self._dict:
64                    return self._dict[m.group(2)] >= lev
65                return self._dict.get('*', self.LEVEL_N) >= lev
66        except (KeyError, IndexError):
67            # Regular line written with something else than ESP_LOG*
68            # or an empty line.
69            pass
70        # We need something more than "*.N" for printing.
71        return self._dict.get('*', self.LEVEL_N) > self.LEVEL_N
72