xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/json/scanner.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker"""JSON token scanner
2*cda5da8dSAndroid Build Coastguard Worker"""
3*cda5da8dSAndroid Build Coastguard Workerimport re
4*cda5da8dSAndroid Build Coastguard Workertry:
5*cda5da8dSAndroid Build Coastguard Worker    from _json import make_scanner as c_make_scanner
6*cda5da8dSAndroid Build Coastguard Workerexcept ImportError:
7*cda5da8dSAndroid Build Coastguard Worker    c_make_scanner = None
8*cda5da8dSAndroid Build Coastguard Worker
9*cda5da8dSAndroid Build Coastguard Worker__all__ = ['make_scanner']
10*cda5da8dSAndroid Build Coastguard Worker
11*cda5da8dSAndroid Build Coastguard WorkerNUMBER_RE = re.compile(
12*cda5da8dSAndroid Build Coastguard Worker    r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?',
13*cda5da8dSAndroid Build Coastguard Worker    (re.VERBOSE | re.MULTILINE | re.DOTALL))
14*cda5da8dSAndroid Build Coastguard Worker
15*cda5da8dSAndroid Build Coastguard Workerdef py_make_scanner(context):
16*cda5da8dSAndroid Build Coastguard Worker    parse_object = context.parse_object
17*cda5da8dSAndroid Build Coastguard Worker    parse_array = context.parse_array
18*cda5da8dSAndroid Build Coastguard Worker    parse_string = context.parse_string
19*cda5da8dSAndroid Build Coastguard Worker    match_number = NUMBER_RE.match
20*cda5da8dSAndroid Build Coastguard Worker    strict = context.strict
21*cda5da8dSAndroid Build Coastguard Worker    parse_float = context.parse_float
22*cda5da8dSAndroid Build Coastguard Worker    parse_int = context.parse_int
23*cda5da8dSAndroid Build Coastguard Worker    parse_constant = context.parse_constant
24*cda5da8dSAndroid Build Coastguard Worker    object_hook = context.object_hook
25*cda5da8dSAndroid Build Coastguard Worker    object_pairs_hook = context.object_pairs_hook
26*cda5da8dSAndroid Build Coastguard Worker    memo = context.memo
27*cda5da8dSAndroid Build Coastguard Worker
28*cda5da8dSAndroid Build Coastguard Worker    def _scan_once(string, idx):
29*cda5da8dSAndroid Build Coastguard Worker        try:
30*cda5da8dSAndroid Build Coastguard Worker            nextchar = string[idx]
31*cda5da8dSAndroid Build Coastguard Worker        except IndexError:
32*cda5da8dSAndroid Build Coastguard Worker            raise StopIteration(idx) from None
33*cda5da8dSAndroid Build Coastguard Worker
34*cda5da8dSAndroid Build Coastguard Worker        if nextchar == '"':
35*cda5da8dSAndroid Build Coastguard Worker            return parse_string(string, idx + 1, strict)
36*cda5da8dSAndroid Build Coastguard Worker        elif nextchar == '{':
37*cda5da8dSAndroid Build Coastguard Worker            return parse_object((string, idx + 1), strict,
38*cda5da8dSAndroid Build Coastguard Worker                _scan_once, object_hook, object_pairs_hook, memo)
39*cda5da8dSAndroid Build Coastguard Worker        elif nextchar == '[':
40*cda5da8dSAndroid Build Coastguard Worker            return parse_array((string, idx + 1), _scan_once)
41*cda5da8dSAndroid Build Coastguard Worker        elif nextchar == 'n' and string[idx:idx + 4] == 'null':
42*cda5da8dSAndroid Build Coastguard Worker            return None, idx + 4
43*cda5da8dSAndroid Build Coastguard Worker        elif nextchar == 't' and string[idx:idx + 4] == 'true':
44*cda5da8dSAndroid Build Coastguard Worker            return True, idx + 4
45*cda5da8dSAndroid Build Coastguard Worker        elif nextchar == 'f' and string[idx:idx + 5] == 'false':
46*cda5da8dSAndroid Build Coastguard Worker            return False, idx + 5
47*cda5da8dSAndroid Build Coastguard Worker
48*cda5da8dSAndroid Build Coastguard Worker        m = match_number(string, idx)
49*cda5da8dSAndroid Build Coastguard Worker        if m is not None:
50*cda5da8dSAndroid Build Coastguard Worker            integer, frac, exp = m.groups()
51*cda5da8dSAndroid Build Coastguard Worker            if frac or exp:
52*cda5da8dSAndroid Build Coastguard Worker                res = parse_float(integer + (frac or '') + (exp or ''))
53*cda5da8dSAndroid Build Coastguard Worker            else:
54*cda5da8dSAndroid Build Coastguard Worker                res = parse_int(integer)
55*cda5da8dSAndroid Build Coastguard Worker            return res, m.end()
56*cda5da8dSAndroid Build Coastguard Worker        elif nextchar == 'N' and string[idx:idx + 3] == 'NaN':
57*cda5da8dSAndroid Build Coastguard Worker            return parse_constant('NaN'), idx + 3
58*cda5da8dSAndroid Build Coastguard Worker        elif nextchar == 'I' and string[idx:idx + 8] == 'Infinity':
59*cda5da8dSAndroid Build Coastguard Worker            return parse_constant('Infinity'), idx + 8
60*cda5da8dSAndroid Build Coastguard Worker        elif nextchar == '-' and string[idx:idx + 9] == '-Infinity':
61*cda5da8dSAndroid Build Coastguard Worker            return parse_constant('-Infinity'), idx + 9
62*cda5da8dSAndroid Build Coastguard Worker        else:
63*cda5da8dSAndroid Build Coastguard Worker            raise StopIteration(idx)
64*cda5da8dSAndroid Build Coastguard Worker
65*cda5da8dSAndroid Build Coastguard Worker    def scan_once(string, idx):
66*cda5da8dSAndroid Build Coastguard Worker        try:
67*cda5da8dSAndroid Build Coastguard Worker            return _scan_once(string, idx)
68*cda5da8dSAndroid Build Coastguard Worker        finally:
69*cda5da8dSAndroid Build Coastguard Worker            memo.clear()
70*cda5da8dSAndroid Build Coastguard Worker
71*cda5da8dSAndroid Build Coastguard Worker    return scan_once
72*cda5da8dSAndroid Build Coastguard Worker
73*cda5da8dSAndroid Build Coastguard Workermake_scanner = c_make_scanner or py_make_scanner
74