Skip to content

Commit 73d7afc

Browse files
author
Michael Mezger
committed
Add feature from request EVerest#75:
- only create xmldsig framgnets which are listed (like other fragments) - remove unused fields for optimization (per default remove "shall not be used" from standard) removed elements are not in structure and will result in en/decoder error NOT_IMPLEMENTED when "isUsed" flag is set. Signed-off-by: Michael Mezger <[email protected]>
1 parent 9f0b060 commit 73d7afc

File tree

8 files changed

+135
-7
lines changed

8 files changed

+135
-7
lines changed

src/cbexigen/SchemaAnalyzer.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,7 @@ def analyze_schema_elements(self):
992992
# Check memory option and make optimization
993993
if self.config['apply_optimizations'] == 1:
994994
self.__apply_array_optimizations()
995+
self.__mark_field_optimizations()
995996

996997
# Do the preparations for type generation
997998
self.__prepare_for_type_generation()
@@ -1552,6 +1553,24 @@ def __apply_array_optimizations(self):
15521553
particle.max_occurs = optimizations[particle.type_short]
15531554
particle.max_occurs_changed = True
15541555

1556+
def __mark_field_optimizations(self):
1557+
config_module = get_config_module()
1558+
parameter = self.__schema_prefix + 'field_optimizations'
1559+
if hasattr(config_module, parameter):
1560+
optimizations = getattr(config_module, parameter)
1561+
else:
1562+
return
1563+
1564+
for element in self.__generate_elements:
1565+
if element.name_short in optimizations.keys() and len(optimizations[element.name_short]) == 0:
1566+
msg_write(f"Optimized element: {element.name_short}")
1567+
1568+
for particle in element.particles:
1569+
if particle.name in optimizations.keys():
1570+
if len(optimizations[particle.name]) == 0 or element.name_short in optimizations[particle.name]:
1571+
particle.is_optimized = True
1572+
msg_write(f"Optimized particle: {particle.name} in element: {element.name}")
1573+
15551574
def __prepare_for_type_generation(self):
15561575
# Sort the list of elements to be generated by level and count
15571576
self.__generate_elements.sort(key=lambda item: item.count, reverse=False)

src/cbexigen/datatype_classes.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ def __init__(self, current_scheme: XMLSchema11, parameters, analyzer_data: Analy
3636
self.__fragments = get_fragment_parameter_for_schema(self.__schema_prefix)
3737
self.__generate_fragment = len(self.__fragments) > 0
3838

39+
self.__xmldsigfragments = []
40+
self.__generate_all_xmldsig_fragment = True
41+
if self.config['generate_fragments'] == 1:
42+
self.__xmldsigfragments = get_fragment_parameter_for_schema('xmldsig_')
43+
self.__generate_all_xmldsig_fragment = len(self.__xmldsigfragments) == 0
44+
3945
if self.logging_enabled:
4046
self.logger_name = str(self.h_params['filename'])
4147
if self.logger_name.casefold().endswith('.h') or self.logger_name.casefold().endswith('.c'):
@@ -276,12 +282,19 @@ def __generate_sequence_content(self, name, comment, content, indent_level=1):
276282
return temp.render(indent=indent, level=indent_level,
277283
sequence_comment=comment, sequence_name=name, sequence_content=content)
278284

285+
def __generate_optimized_struct(self, name, comment, indent_level=1):
286+
indent = ' ' * self.config['c_code_indent_chars']
287+
temp = self.generator.get_template('SubStructOptimized.jinja')
288+
return temp.render(indent=indent, level=indent_level, name=name, comment=comment)
289+
279290
def __get_particle_content(self, particle: Particle, elements, indent_level=1):
280291
content = ''
281292
last = None
282293

294+
if particle.is_optimized is True:
295+
content += self.__generate_optimized_struct(particle.name, ": Optimized out element", indent_level)
283296
# particle type is in list, so a separate type is generated
284-
if particle.type in self.analyzer_data.known_elements:
297+
elif particle.type in self.analyzer_data.known_elements:
285298
if particle.max_occurs > 1:
286299
# generate struct for array with length variable
287300
if particle.is_enum:
@@ -449,7 +462,7 @@ def __get_xmldsig_fragment_content(self):
449462

450463
fragment: FragmentData
451464
for fragment in self.analyzer_data.known_fragments.values():
452-
if 'xmldsig' in fragment.namespace.casefold():
465+
if 'xmldsig' in fragment.namespace.casefold() and (fragment.name in self.__xmldsigfragments or self.__generate_all_xmldsig_fragment is True):
453466
fragment_type = fragment.type
454467
if fragment.type == 'AnonType':
455468
fragment_type = fragment.name
@@ -460,6 +473,8 @@ def __get_xmldsig_fragment_content(self):
460473
else:
461474
self.log(f'xmldsig Fragment {fragment.name} ({fragment.type}) '
462475
f'is not in the list of known elements.')
476+
else:
477+
self.log(f"Skipped xmlsigFragment: {fragment.name}")
463478

464479
temp = self.generator.get_template('BaseStructWithUnionAndUsed.jinja')
465480
content = temp.render(struct_name=name,
@@ -657,6 +672,12 @@ def __init__(self, current_scheme, parameters, analyzer_data: AnalyzerData, enab
657672
self.__fragments = get_fragment_parameter_for_schema(self.__schema_prefix)
658673
self.__generate_fragment = len(self.__fragments) > 0
659674

675+
self.__xmldsigfragments = []
676+
self.__generate_all_xmldsig_fragment = True
677+
if self.config['generate_fragments'] == 1:
678+
self.__xmldsigfragments = get_fragment_parameter_for_schema('xmldsig_')
679+
self.__generate_all_xmldsig_fragment = len(self.__xmldsigfragments) == 0
680+
660681
if self.logging_enabled:
661682
self.logger_name = str(self.c_params['filename'])
662683
if self.logger_name.casefold().endswith('.h') or self.logger_name.casefold().endswith('.c'):
@@ -789,7 +810,7 @@ def __get_xmldsig_fragment_content(self):
789810

790811
fragment: FragmentData
791812
for fragment in self.analyzer_data.known_fragments.values():
792-
if 'xmldsig' in fragment.namespace.casefold():
813+
if 'xmldsig' in fragment.namespace.casefold() and (fragment.name in self.__xmldsigfragments or self.__generate_all_xmldsig_fragment is True):
793814
fragment_type = fragment.type
794815
if fragment.type == 'AnonType':
795816
fragment_type = fragment.name

src/cbexigen/decoder_classes.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ def __init__(self, parameters, enable_logging=True):
2828
self.__fragments = get_fragment_parameter_for_schema(self.__schema_prefix)
2929
self.__generate_fragment = len(self.__fragments) > 0
3030

31+
self.__xmldsigfragments = []
32+
self.__generate_all_xmldsig_fragment = True
33+
if self.config['generate_fragments'] == 1:
34+
self.__xmldsigfragments = get_fragment_parameter_for_schema('xmldsig_')
35+
self.__generate_all_xmldsig_fragment = len(self.__xmldsigfragments) == 0
36+
3137
self.__include_content = ''
3238
self.__code_content = ''
3339

@@ -102,6 +108,11 @@ def __init__(self, parameters, analyzer_data, enable_logging=True):
102108
if self.config['generate_fragments'] == 1:
103109
self.__fragments = get_fragment_parameter_for_schema(self.__schema_prefix)
104110
self.__generate_fragment = len(self.__fragments) > 0
111+
self.__xmldsigfragments = []
112+
self.__generate_all_xmldsig_fragment = True
113+
if self.config['generate_fragments'] == 1:
114+
self.__xmldsigfragments = get_fragment_parameter_for_schema('xmldsig_')
115+
self.__generate_all_xmldsig_fragment = len(self.__xmldsigfragments) == 0
105116

106117
self.__include_content = ''
107118
self.__code_content = ''
@@ -511,6 +522,14 @@ def __get_content_decode_not_implemented(self, element_typename, detail: Element
511522

512523
return decode_content
513524

525+
def __get_content_decode_optimized_out(self, element_typename, detail: ElementGrammarDetail, level):
526+
decode_comment = f"// decode removed with optimization: '{detail.particle.type_short}', base type '{detail.particle.typename}"
527+
temp = self.generator.get_template('DecodeTypeNotImplemented.jinja')
528+
decode_content = temp.render(decode_comment=decode_comment,
529+
indent=self.indent, level=level)
530+
531+
return decode_content
532+
514533
def __get_type_content(self, grammar: ElementGrammar, detail: ElementGrammarDetail, level):
515534
if detail.particle is None:
516535
temp = self.generator.get_template('BaseDecodeEndElement.jinja')
@@ -519,7 +538,10 @@ def __get_type_content(self, grammar: ElementGrammar, detail: ElementGrammarDeta
519538
# default content for types not covered below
520539
type_content = self.__get_content_decode_not_implemented(grammar.element_typename, detail, level)
521540

522-
if detail.is_any and detail.any_is_dummy:
541+
if detail.particle.is_optimized is True:
542+
# use "not implemented" content when optimized
543+
type_content = self.__get_content_decode_optimized_out(grammar.element_typename, detail, level)
544+
elif detail.is_any and detail.any_is_dummy:
523545
type_content = self.__get_content_decode_no_event(grammar.element_typename, detail, level)
524546
elif detail.particle.is_enum:
525547
if detail.particle.is_array:
@@ -870,7 +892,7 @@ def __get_xmldsig_fragment_content(self):
870892

871893
decode_fn = []
872894
for fragment in self.analyzer_data.known_fragments.values():
873-
if 'xmldsig' in fragment.namespace.casefold():
895+
if 'xmldsig' in fragment.namespace.casefold() and (fragment.name in self.__xmldsigfragments or self.__generate_all_xmldsig_fragment is True):
874896
if fragment.type in self.analyzer_data.known_elements.values():
875897
function = f'{CONFIG_PARAMS["decode_function_prefix"]}{self.__schema_prefix}{fragment.type}'
876898
parameter = f'{parameter_name}->{fragment.name}'

src/cbexigen/elementData.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class Particle:
3535
is_enum: bool = False
3636
is_attribute: bool = False
3737
is_simple_content: bool = False
38+
is_optimized: bool = False
3839
enum_count: int = -1
3940
# additional flag if content model is choice and changed min occurrence
4041
content_model_changed_restrictions: bool = False

src/cbexigen/encoder_classes.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ def __init__(self, parameters, enable_logging=True):
2828
self.__fragments = get_fragment_parameter_for_schema(self.__schema_prefix)
2929
self.__generate_fragment = len(self.__fragments) > 0
3030

31+
self.__xmldsigfragments = []
32+
self.__generate_all_xmldsig_fragment = True
33+
if self.config['generate_fragments'] == 1:
34+
self.__xmldsigfragments = get_fragment_parameter_for_schema('xmldsig_')
35+
self.__generate_all_xmldsig_fragment = len(self.__xmldsigfragments) == 0
36+
3137
self.__include_content = ''
3238
self.__code_content = ''
3339

@@ -103,6 +109,12 @@ def __init__(self, parameters, analyzer_data, enable_logging=True):
103109
self.__fragments = get_fragment_parameter_for_schema(self.__schema_prefix)
104110
self.__generate_fragment = len(self.__fragments) > 0
105111

112+
self.__xmldsigfragments = []
113+
self.__generate_all_xmldsig_fragment = True
114+
if self.config['generate_fragments'] == 1:
115+
self.__xmldsigfragments = get_fragment_parameter_for_schema('xmldsig_')
116+
self.__generate_all_xmldsig_fragment = len(self.__xmldsigfragments) == 0
117+
106118
self.__include_content = ''
107119
self.__code_content = ''
108120
self.__function_content = ''
@@ -531,7 +543,7 @@ def __get_event_content_for_optional_element(self, detail: ElementGrammarDetail,
531543
if detail.flag == GrammarFlag.END:
532544
content += self.__get_event_content_for_end_element(detail, grammar.bits_to_write, False, level)
533545
else:
534-
if detail.particle is not None and not (detail.is_any and detail.any_is_dummy):
546+
if detail.particle is not None and not (detail.is_any and detail.any_is_dummy) and detail.particle.is_optimized is False:
535547
if detail.is_extra_grammar:
536548
option = -2
537549

@@ -557,6 +569,15 @@ def __get_event_content_for_optional_element(self, detail: ElementGrammarDetail,
557569
add_debug_code=self.get_status_for_add_debug_code(detail.particle.prefixed_name),
558570
type_parameter=type_parameter,
559571
indent=self.indent, level=level)
572+
elif detail.particle.is_optimized is True:
573+
parameter = grammar.element_typename + '->' + detail.particle.name
574+
event_comment = f'// Event optimized out: {detail.particle_name} (index={detail.event_index}); next={detail.next_grammar}'
575+
temp = self.generator.get_template('EncodeEventOptionalElementOptimized.jinja')
576+
content += temp.render(option=option,
577+
parameter=parameter,
578+
event_comment=event_comment,
579+
indent=self.indent, level=level)
580+
560581
else:
561582
# unsupported particle which appears in the event list
562583
if detail.is_any and detail.any_is_dummy:
@@ -885,7 +906,7 @@ def __get_xmldsig_fragment_content(self):
885906

886907
encode_fn = []
887908
for fragment in self.analyzer_data.known_fragments.values():
888-
if 'xmldsig' in fragment.namespace.casefold():
909+
if 'xmldsig' in fragment.namespace.casefold() and (fragment.name in self.__xmldsigfragments or self.__generate_all_xmldsig_fragment is True):
889910
if fragment.type in self.analyzer_data.known_elements.values():
890911
function = f'{CONFIG_PARAMS["encode_function_prefix"]}{self.__schema_prefix}{fragment.type}'
891912
parameter = f'{parameter_name}->{fragment.name}'

src/config.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,28 @@
7676
'ParameterType': 8
7777
}
7878

79+
# optimizations for fields, which shall be excluded. The name to exclude and a list of parent elements [V2G2-771]
80+
# - Id (attribute in SignedInfo)
81+
# - ##any in SignedInfo – CanonicalizationMethod
82+
# - HMACOutputLength in SignedInfo – SignatureMethod
83+
# - ##other in SignedInfo – SignatureMethod
84+
# - Type (attribute in SignedInfo-Reference)
85+
# - ##other in SignedInfo – Reference – Transforms – Transform
86+
# - XPath in SignedInfo – Reference – Transforms – Transform
87+
# - ##other in SignedInfo – Reference – DigestMethod
88+
# - Id (attribute in SignatureValue)
89+
# - Object (in Signature)
90+
# - KeyInfo
91+
iso2_field_optimizations = {
92+
'Id': ['SignedInfo', 'SignatureValue'], # remove Id from SignedInfo and SignatureValue
93+
'ANY': ['CanonicalizationMethod', 'SignatureMethod', 'Transform', 'DigestMethod'], # remove ##any from these elements
94+
'HMACOutputLength': ['SignatureMethod'], # remove HMACOutputLength from SignatureMethod
95+
'Type': ['Reference'], # remove Type from Reference
96+
'XPath': ['Transform'], # remove XPath from Transform
97+
'Object': ['Signature'], # remove Object from Signature
98+
'KeyInfo': [] # remove generally
99+
}
100+
79101
# if fragment de- and encoder should be generated, set this value to 1.
80102
# Currently only complex elements can be added to the fragment coders.
81103
# NOTE! There may be problems when comparing the signature of the eMAID.
@@ -121,6 +143,11 @@
121143
'DC_ChargeParameterDiscoveryRes',
122144
]
123145

146+
# mxldsig fragments which should be generated
147+
xmldsig_fragments = [
148+
'SignedInfo' # creates only signedInfo fragment
149+
]
150+
124151
# general C code style
125152
c_code_indent_chars = 4
126153
# these characters will be replaced by an underscore in generated code
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
{{ indent * level }}// {{ name }} {{ comment }}
3+
{{ indent * level }}unsigned int {{ name }}_isUsed:1;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{%- if option == -2 %}
2+
{{ indent * level }}if (1 == 0)
3+
{%- elif option == 0 %}
4+
{{ indent * level }}if ({{ parameter }}_isUsed == 1u)
5+
{%- elif option > 0 %}
6+
{{ indent * level }}else if ({{ parameter }}_isUsed == 1u)
7+
{%- else %}
8+
{{ indent * level }}else
9+
{%- endif %}
10+
{{ indent * level }}{
11+
{{ indent * (level + 1) }}{{ event_comment }}
12+
{{ indent * (level + 1) }}error = EXI_ERROR__ENCODER_NOT_IMPLEMENTED;
13+
{{ indent * (level + 1) }}done = 1;
14+
{{ indent * level }}}

0 commit comments

Comments
 (0)