Version 1.0
Copyright © 2023 Lowell D. Thomas
python-ini
 … powered by Python APG
parser_callbacks.py
Go to the documentation of this file.
1 ''' @file python_ini/parser_callbacks.py
2 @brief The parser call back functions for the IniFile class.
3 '''
4 import sys
5 import os
6 # add the current working directory to the path
7 # DO NOT MOVE THE FOLLOWING STATEMENT
8 # if using autopep8 formatter, for example, set argument '--ignore=E402'
9 sys.path.append(os.getcwd())
10 from apg_py.lib import identifiers as id
11 
12 
13 def line_end(cb):
14  if(cb['state'] == id.MATCH):
15  cb['user_data']['line_no'] += 1
16 
17 
19  if(cb['state'] == id.MATCH):
20  cb['user_data']['errors'].append({'line': cb['user_data']['line_no'],
21  'message': 'bad section definition'})
22 
23 
25  if(cb['state'] == id.MATCH):
26  if(cb['user_data']['skip_bad_key']):
27  cb['user_data']['skip_bad_key'] = False
28  else:
29  cb['user_data']['errors'].append({'line': cb['user_data']['line_no'] - 1,
30  'message': 'bad key/value definition'})
31 
32 
34  if(cb['state'] == id.MATCH):
35  msg = 'invalid blank line, only white space and comments allowed'
36  cb['user_data']['errors'].append({'line': cb['user_data']['line_no'],
37  'message': msg})
38 
39 
40 def hex_digit(d):
41  if(d >= 48 and d <= 57):
42  return d - 48
43  if(d >= 65 and d <= 72):
44  return d - 55
45  if(d >= 97 and d <= 102):
46  return d - 87
47  return None
48 
49 
50 def unicode8(cb):
51  cb['state'] = id.NOMATCH
52  cb['phrase_length'] = 0
53  d = cb['input'][cb['phrase_index']]
54  if(d != 85):
55  return
56  c = 0
57  for i in range(1, 9):
58  d = cb['input'][cb['phrase_index'] + i]
59  v = hex_digit(d)
60  if(v is None):
61  msg = 'Unicode-32 value(\\Uhhhhhhhh) has invalid hex digit - char code(' + \
62  str(d) + ')'
63  cb['user_data']['errors'].append({'line': cb['user_data']['line_no'],
64  'message': msg})
65  cb['user_data']['skip_escaped_error'] = True
66  cb['user_data']['skip_bad_key'] = True
67  return
68  c = 16 * c + v
69  if(c >= 0xd800 and c <= 0xdfff):
70  msg = 'Unicode-32 value(\\Uhhhhhhhh) - surrogates not allowed - x' + \
71  hex(c)
72  cb['user_data']['errors'].append({'line': cb['user_data']['line_no'],
73  'message': msg})
74  cb['user_data']['skip_escaped_error'] = True
75  cb['user_data']['skip_bad_key'] = True
76  elif(c > 0x10ffff):
77  msg = 'Unicode-32 value(\\Uhhhhhhhh) - value out of range - ' + \
78  hex(c)
79  cb['user_data']['errors'].append({'line': cb['user_data']['line_no'],
80  'message': msg})
81  cb['user_data']['skip_escaped_error'] = True
82  cb['user_data']['skip_bad_key'] = True
83  else:
84  # successful match
85  cb['state'] = id.MATCH
86  cb['phrase_length'] = 9
87 
88 
89 def unicode4(cb):
90  cb['state'] = id.NOMATCH
91  cb['phrase_length'] = 0
92  d = cb['input'][cb['phrase_index']]
93  if(d != 117):
94  return
95  c = 0
96  for i in range(1, 5):
97  d = cb['input'][cb['phrase_index'] + i]
98  v = hex_digit(d)
99  if(v is None):
100  msg = 'Unicode-16 value(\\uhhhh) has invalid hex digit - char code(' + \
101  str(d) + ')'
102  cb['user_data']['errors'].append({'line': cb['user_data']['line_no'],
103  'message': msg})
104  cb['user_data']['skip_escaped_error'] = True
105  cb['user_data']['skip_bad_key'] = True
106  return
107  # validate the value
108  c = 16 * c + v
109  if(c >= 0xd800 and c <= 0xdfff):
110  msg = 'Unicode-16 value(\\uhhhh) - surrogates not allowed - ' + \
111  hex(c)
112  cb['user_data']['errors'].append({'line': cb['user_data']['line_no'],
113  'message': msg})
114  cb['user_data']['skip_bad_key'] = True
115  cb['user_data']['skip_escaped_error'] = True
116  else:
117  # successful match
118  cb['state'] = id.MATCH
119  cb['phrase_length'] = 5
120 
121 
122 def hexadecimal(cb):
123  cb['state'] = id.NOMATCH
124  cb['phrase_length'] = 0
125  d = cb['input'][cb['phrase_index']]
126  if(d != 120):
127  return
128  for i in range(1, 3):
129  d = cb['input'][cb['phrase_index'] + i]
130  v = hex_digit(d)
131  if(v is None):
132  msg = 'hexadecimal value(\\xhh) has invalid hex digit - char code(' + \
133  str(d) + ')'
134  cb['user_data']['errors'].append({'line': cb['user_data']['line_no'],
135  'message': msg})
136  cb['user_data']['skip_bad_key'] = True
137  cb['user_data']['skip_escaped_error'] = True
138  return
139  # successful match
140  cb['state'] = id.MATCH
141  cb['phrase_length'] = 3
142 
143 
145  cb['state'] = id.NOMATCH
146  cb['phrase_length'] = 0
147  if(cb['user_data']['skip_escaped_error']):
148  cb['user_data']['skip_escaped_error'] = False
149  else:
150  d = cb['input'][cb['phrase_index']]
151  msg = 'unrecognized escaped character(\\c) - char code c(' + \
152  str(d) + ')'
153  cb['user_data']['errors'].append({'line': cb['user_data']['line_no'],
154  'message': msg})
155  cb['user_data']['skip_bad_key'] = True
Python APG, Version 1.0, is licensed under the 2-Clause BSD License,
an Open Source Initiative Approved License.