aboutsummaryrefslogtreecommitdiffstats
path: root/generate_auto_job
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2022-01-31 13:34:40 +0100
committerJay Berkenbilt <ejb@ql.org>2022-01-31 21:57:45 +0100
commit81b6314cb513f3e48c788722b9b024bf7c47a601 (patch)
tree82995960fac0f2f6da34a43850cb0037c9ed7c61 /generate_auto_job
parentf99e0af49c969529f36f287e23d4e178c40e8c4a (diff)
downloadqpdf-81b6314cb513f3e48c788722b9b024bf7c47a601.tar.zst
QPDFJob: fix logic errors in handling arrays
The code was assuming everything was happening inside dictionaries. Instead, make the dictionary key handler creatino explicit only when iterating through dictionary keys.
Diffstat (limited to 'generate_auto_job')
-rwxr-xr-xgenerate_auto_job149
1 files changed, 70 insertions, 79 deletions
diff --git a/generate_auto_job b/generate_auto_job
index d935af8f..6b59debc 100755
--- a/generate_auto_job
+++ b/generate_auto_job
@@ -454,7 +454,7 @@ class Main:
identifier = self.to_identifier(table, 'argEnd', False)
self.decls.append(f'void {identifier}();')
- def handle_json_trivial(self, key, fdata):
+ def handle_json_trivial(self, flag_key, fdata):
config = None
for t, [kind, v] in fdata['tables'].items():
# We have determined that all tables, if multiple, have
@@ -463,106 +463,98 @@ class Main:
config = tdata['config']
if kind == 'bare':
self.json_init.append(
- f'addBare("{key}", [this]() {{ {config}->{key}(); }});')
+ f'addBare([this]() {{ {config}->{flag_key}(); }});')
elif kind == 'optional_parameter' or kind == 'required_parameter':
# No optional parameters in json
self.json_init.append(
- f'addParameter("{key}", [this](char const* p)'
- f' {{ {config}->{key}(p); }});')
+ f'addParameter([this](char const* p)'
+ f' {{ {config}->{flag_key}(p); }});')
elif kind == 'optional_choices' or kind == 'required_choices':
# No optional choices in json
self.json_init.append(
- f'addChoices("{key}", {v}_choices,'
- f' [this](char const* p) {{ {config}->{key}(p); }});')
+ f'addChoices({v}_choices,'
+ f' [this](char const* p) {{ {config}->{flag_key}(p); }});')
- def handle_json_manual(self, key, path):
+ def handle_json_manual(self, path):
method = re.sub(r'\.([a-zA-Z0-9])',
lambda x: x.group(1).upper(),
- f'setup{path}.{key}')
- self.json_decls.append(
- f'void {method}(std::string const&);')
- self.json_init.append(
- f'doSetup("{key}", bindSetup(&Handlers::{method}));')
+ f'setup{path}')
+ self.json_decls.append(f'void {method}();')
+ self.json_init.append(f'{method}();')
def option_to_json_key(self, s):
return self.to_identifier(s, '', False)
- def build_schema(self, j, s, flag, path, expected, options_seen):
- if flag:
+ def flag_to_schema_key(self, k):
+ if k.startswith('_'):
+ schema_key = k[1:]
+ else:
+ schema_key = re.sub(r'[^\.]+\.', '', k)
+ return self.option_to_json_key(schema_key)
+
+ def build_schema(self, j, path, flag, expected, options_seen):
+ if flag in expected:
+ options_seen.add(flag)
+ elif not (flag == '' or flag.startswith('_') or isinstance(j, str)):
+ raise Exception(f'json: unknown key {flag}')
+
+ if isinstance(j, dict):
+ schema_value = {}
+ if flag:
+ identifier = self.to_identifier(path, '', False)
+ self.json_decls.append(f'void begin{identifier}(JSON);')
+ self.json_decls.append(f'void end{identifier}();')
+ self.json_init.append(
+ f'beginDict(bindJSON(&Handlers::begin{identifier}),'
+ f' bindBare(&Handlers::end{identifier})); // {path}')
+ for k, v in j.items():
+ schema_key = self.flag_to_schema_key(k)
+ subpath = f'{path}.{schema_key}'
+ self.json_init.append(f'pushKey("{schema_key}");')
+ schema_value[schema_key] = self.build_schema(
+ v, subpath, k, expected, options_seen)
+ self.json_init.append(f'popHandler(); // key: {schema_key}')
+ elif isinstance(j, list):
+ if len(j) != 1:
+ raise Exception('json contains array with length != 1')
identifier = self.to_identifier(path, '', False)
- self.json_decls.append(f'void begin{identifier}(JSON);')
- self.json_decls.append(f'void end{identifier}();')
+ self.json_decls.append(f'void begin{identifier}Array(JSON);')
+ self.json_decls.append(f'void end{identifier}Array();')
+ self.json_init.append(
+ f'beginArray(bindJSON(&Handlers::begin{identifier}Array),'
+ f' bindBare(&Handlers::end{identifier}Array));'
+ f' // {path}[]')
+ schema_value = [
+ self.build_schema(j[0], path, flag,
+ expected, options_seen)
+ ]
self.json_init.append(
- f'beginDict("{flag}",'
- f' bindJSON(&Handlers::begin{identifier}),'
- f' bindBare(&Handlers::end{identifier})); // {path}')
- for k, v in j.items():
+ f'popHandler(); // array: {path}[]')
+ else:
+ schema_value = j
+ if schema_value is None:
+ schema_value = re.sub(
+ r'--(\S+)',
+ lambda x: self.option_to_json_key(x.group(1)),
+ expected[flag]['help'])
is_trivial = False
- if k in expected:
+ if flag in expected:
is_trivial = True
common_config = None
- for t in expected[k]['tables']:
+ for t in expected[flag]['tables']:
tdata = self.by_table[t]
- if k in tdata['manual']:
+ if flag in tdata['manual']:
is_trivial = False
if common_config is None:
common_config = tdata['config']
elif common_config != tdata['config']:
is_trivial = False
- elif not (k.startswith('_') or isinstance(v, str)):
- raise Exception(f'json: unknown key {k}')
- if k.startswith('_'):
- schema_key = k[1:]
+ config_key = self.flag_to_schema_key(flag)
+ if is_trivial:
+ self.handle_json_trivial(config_key, expected[flag])
else:
- schema_key = re.sub(r'[^\.]+\.', '', k)
- schema_key = self.option_to_json_key(schema_key)
- schema_value = v
- is_dict = False
- if k in expected:
- options_seen.add(re.sub('^_', '', k))
- if v is None:
- schema_value = re.sub(
- r'--(\S+)',
- lambda x: self.option_to_json_key(x.group(1)),
- expected[k]['help'])
- if (isinstance(v, dict)):
- is_dict = True
- schema_value = {}
- self.build_schema(v, schema_value,
- schema_key, f'{path}.{schema_key}',
- expected, options_seen)
- elif (isinstance(v, list)):
- if len(v) != 1:
- raise Exception('json contains array with length != 1')
- if isinstance(v[0], dict):
- is_dict = True
- schema_value = [{}]
- subpath = f'{path}.{schema_key}'
- identifier = self.to_identifier(subpath, '', False)
- self.json_decls.append(
- f'void begin{identifier}Array(JSON);')
- self.json_decls.append(
- f'void end{identifier}Array();')
- self.json_init.append(
- f'beginArray("{flag}",'
- f' bindJSON(&Handlers::begin{identifier}Array),'
- f' bindBare(&Handlers::end{identifier}Array));'
- f' // {subpath}[]')
- self.build_schema(v[0], schema_value[0],
- schema_key, subpath,
- expected, options_seen)
- self.json_init.append(
- f'endContainer(); // {subpath}[]')
- elif schema_value is None:
- raise Exception(f'unknown schema value for {k}')
- s[schema_key] = schema_value
- if not is_dict:
- if is_trivial:
- self.handle_json_trivial(schema_key, expected[k])
- else:
- self.handle_json_manual(schema_key, path)
- if flag:
- self.json_init.append(f'endContainer(); // {path}')
+ self.handle_json_manual(path)
+ return schema_value
def generate_schema(self, data):
# Check to make sure that every command-line option is
@@ -588,9 +580,8 @@ class Main:
# go. This verifies consistency between command-line options
# and the json section of the data and builds up a schema by
# populating with help information as available.
- self.schema = {}
- self.build_schema(data['json'], self.schema, '', '',
- expected, options_seen)
+ self.schema = self.build_schema(
+ data['json'], '', '', expected, options_seen)
if options_seen != set(expected.keys()):
raise Exception('missing from json: ' +
str(set(expected.keys()) - options_seen))