Skip to content

Commit d0b5310

Browse files
SiebrenWSiebren WeertmanSebaLukas
authored
Use big int for integer type without max value (#65)
* Use big int for integer type without max value * fix decoder for signed datatype with non-strict exi padding * add conversion for byte to/from unsigned (bigint) datatype * const correctness and remove log * increase int buffer and code cleanup --------- Signed-off-by: Siebren Weertman <[email protected]> Signed-off-by: Siebren Weertman <[email protected]> Signed-off-by: Siebren <[email protected]> Co-authored-by: Siebren Weertman <[email protected]> Co-authored-by: Sebastian Lukas <[email protected]>
1 parent 9beaf0f commit d0b5310

12 files changed

+221
-10
lines changed

src/cbexigen/decoder_classes.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,23 @@ def __get_content_decode_long_int(self, element_typename, detail: ElementGrammar
365365

366366
return decode_content
367367

368+
def __get_content_decode_signed(self, element_typename, detail: ElementGrammarDetail, level):
369+
type_value = f'{element_typename}->{detail.particle.name}'
370+
next_grammar_id = detail.next_grammar
371+
372+
template_file = 'DecodeTypeSigned.jinja'
373+
decode_comment = '// decode: signed'
374+
if detail.particle.is_attribute:
375+
decode_comment += ' (Attribute)'
376+
temp = self.generator.get_template(template_file)
377+
decode_content = temp.render(decode_comment=decode_comment,
378+
type_value=type_value,
379+
type_option=detail.particle.is_optional,
380+
next_grammar_id=next_grammar_id,
381+
indent=self.indent, level=level)
382+
383+
return decode_content
384+
368385
def __get_content_decode_string(self, element_typename, detail: ElementGrammarDetail, level):
369386
decode_comment = '// decode: string (len, characters)'
370387
if detail.particle.is_attribute:
@@ -550,6 +567,8 @@ def __get_type_content(self, grammar: ElementGrammar, detail: ElementGrammarDeta
550567
type_content = self.__get_content_decode_int(grammar.element_typename, detail, level)
551568
elif detail.particle.integer_base_type == 'uint64':
552569
type_content = self.__get_content_decode_long_int(grammar.element_typename, detail, level)
570+
elif detail.particle.integer_base_type == 'signed':
571+
type_content = self.__get_content_decode_signed(grammar.element_typename, detail, level)
553572
else:
554573
log_write_error(f"Unhandled numeric type: '{detail.particle.name}': "
555574
f"'{detail.particle.type_short}', " +

src/cbexigen/encoder_classes.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,15 @@ def __get_content_encode_long_int(self, element_typename, detail: ElementGrammar
282282

283283
return content
284284

285+
def __get_content_encode_signed(self, element_typename, detail, level):
286+
value_parameter = f'{element_typename}->{detail.particle.name}'
287+
288+
temp = self.generator.get_template('EncodeTypeSigned.jinja')
289+
content = temp.render(value_parameter=value_parameter,
290+
next_grammar=detail.next_grammar,
291+
indent=self.indent, level=level)
292+
return content
293+
285294
def __get_content_encode_string(self, element_typename, detail: ElementGrammarDetail, level):
286295
length_parameter = f'{element_typename}->{detail.particle.name}.{detail.particle.length_parameter_name}'
287296
value_parameter = f'{element_typename}->{detail.particle.name}.{detail.particle.value_parameter_name}'
@@ -420,6 +429,8 @@ def __get_type_content(self, grammar: ElementGrammar, detail: ElementGrammarDeta
420429
type_content = self.__get_content_encode_int(grammar.element_typename, detail, level)
421430
elif detail.particle.integer_base_type == 'uint64':
422431
type_content = self.__get_content_encode_long_int(grammar.element_typename, detail, level)
432+
elif detail.particle.integer_base_type == 'signed':
433+
type_content = self.__get_content_encode_signed(grammar.element_typename, detail, level)
423434
else:
424435
log_write_error(f"Unhandled numeric type: '{detail.particle.name}': "
425436
f"'{detail.particle.type_short}', " +

src/cbexigen/tools.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
'uint16': 'uint16_t',
2222
'uint32': 'uint32_t',
2323
'uint64': 'uint64_t',
24+
'signed': 'exi_signed_t',
2425
}
2526

2627
TYPE_TRANSLATION = {
@@ -29,7 +30,7 @@
2930
'byte': 'int8',
3031
'short': 'int16',
3132
'int': 'int32',
32-
'integer': 'int32',
33+
'integer': 'signed',
3334
'long': 'int64',
3435
'decimal': 'integer', # FIXME special type
3536
'unsignedByte': 'uint8',
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{{ indent * level }}{{ decode_comment }}
2+
{{ indent * level }}error = exi_basetypes_decoder_nbit_uint(stream, 1, &eventCode);
3+
{{ indent * level }}if (error == 0)
4+
{{ indent * level }}{
5+
{{ indent * (level + 1) }}error = exi_basetypes_decoder_signed(stream, &{{ type_value }});
6+
{{ indent * (level + 1) }}if (error == 0)
7+
{{ indent * (level + 1) }}{
8+
{%- if type_option == 1 %}
9+
{{ indent * (level + 2) }}{{ type_value }}_isUsed = 1u;
10+
{%- endif %}
11+
{{ indent * (level + 2) }}grammar_id = {{ next_grammar_id }};
12+
{{ indent * (level + 1) }}}
13+
{{ indent * (level + 1) }}error = exi_basetypes_decoder_nbit_uint(stream, 1, &eventCode);
14+
{{ indent * level }}}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{{ indent * level }}error = exi_basetypes_encoder_nbit_uint(stream, 1, 0);
2+
{{ indent * level }}if (error == EXI_ERROR__NO_ERROR)
3+
{{ indent * level }}{
4+
{{ indent * (level + 1) }}error = exi_basetypes_encoder_signed(stream, &{{ value_parameter }});
5+
{{ indent * (level + 1) }}if (error == EXI_ERROR__NO_ERROR)
6+
{{ indent * (level + 1) }}{
7+
{{ indent * (level + 2) }}// encode END Element
8+
{{ indent * (level + 2) }}error = exi_basetypes_encoder_nbit_uint(stream, 1, 0);
9+
{{ indent * (level + 2) }}if (error == EXI_ERROR__NO_ERROR)
10+
{{ indent * (level + 2) }}{
11+
{{ indent * (level + 3) }}grammar_id = {{ next_grammar }};
12+
{{ indent * (level + 2) }}}
13+
{{ indent * (level + 1) }}}
14+
{{ indent * level }}}

src/input/code_templates/c/static_code/exi_basetypes.c.jinja

Lines changed: 100 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,34 @@ int exi_basetypes_convert_64_to_unsigned(exi_unsigned_t* exi_unsigned, uint64_t
5858
return (exi_unsigned->octets_count <= EXI_BASETYPES_UINT64_MAX_OCTETS) ? EXI_ERROR__NO_ERROR : EXI_ERROR__OCTET_COUNT_LARGER_THAN_TYPE_SUPPORTS;
5959
}
6060

61-
int exi_basetypes_convert_from_unsigned(exi_unsigned_t* exi_unsigned, uint32_t* value, size_t max_octets)
61+
int exi_basetypes_convert_to_signed(exi_signed_t* exi_signed, int32_t value, size_t max_octets)
62+
{
63+
if (value < 0) {
64+
exi_signed->is_negative = 1;
65+
return exi_basetypes_convert_to_unsigned(&exi_signed->data, -value, max_octets);
66+
}
67+
exi_signed->is_negative = 0;
68+
return exi_basetypes_convert_to_unsigned(&exi_signed->data, value, max_octets);
69+
}
70+
71+
int exi_basetypes_convert_64_to_signed(exi_signed_t* exi_signed, int64_t value)
72+
{
73+
if (value < 0) {
74+
exi_signed->is_negative = 1;
75+
return exi_basetypes_convert_64_to_unsigned(&exi_signed->data, -value);
76+
}
77+
exi_signed->is_negative = 0;
78+
return exi_basetypes_convert_64_to_unsigned(&exi_signed->data, value);
79+
}
80+
81+
int exi_basetypes_convert_from_unsigned(const exi_unsigned_t* exi_unsigned, uint32_t* value, size_t max_octets)
6282
{
6383
if (exi_unsigned->octets_count > max_octets)
6484
{
6585
return EXI_ERROR__OCTET_COUNT_LARGER_THAN_TYPE_SUPPORTS;
6686
}
6787

68-
uint8_t* current_octet = exi_unsigned->octets;
88+
const uint8_t* current_octet = exi_unsigned->octets;
6989
*value = 0;
7090

7191
for (size_t n = 0; n < exi_unsigned->octets_count; n++)
@@ -78,14 +98,14 @@ int exi_basetypes_convert_from_unsigned(exi_unsigned_t* exi_unsigned, uint32_t*
7898
return EXI_ERROR__NO_ERROR;
7999
}
80100

81-
int exi_basetypes_convert_64_from_unsigned(exi_unsigned_t* exi_unsigned, uint64_t* value)
101+
int exi_basetypes_convert_64_from_unsigned(const exi_unsigned_t* exi_unsigned, uint64_t* value)
82102
{
83103
if (exi_unsigned->octets_count > EXI_BASETYPES_UINT64_MAX_OCTETS)
84104
{
85105
return EXI_ERROR__OCTET_COUNT_LARGER_THAN_TYPE_SUPPORTS;
86106
}
87107

88-
uint8_t* current_octet = exi_unsigned->octets;
108+
const uint8_t* current_octet = exi_unsigned->octets;
89109
*value = 0;
90110

91111
for (size_t n = 0; n < exi_unsigned->octets_count; n++)
@@ -97,4 +117,80 @@ int exi_basetypes_convert_64_from_unsigned(exi_unsigned_t* exi_unsigned, uint64_
97117

98118
return EXI_ERROR__NO_ERROR;
99119
}
120+
121+
int exi_basetypes_convert_from_signed(const exi_signed_t* exi_signed, int32_t* value, size_t max_octets)
122+
{
123+
uint32_t u_value = 0;
124+
int res = exi_basetypes_convert_from_unsigned(&exi_signed->data, &u_value, max_octets);
125+
*value = (exi_signed->is_negative == 0) ? u_value : -u_value;
126+
return res;
127+
}
128+
129+
int exi_basetypes_convert_64_from_signed(const exi_signed_t* exi_signed, int64_t* value)
130+
{
131+
uint64_t u_value = 0;
132+
int res = exi_basetypes_convert_64_from_unsigned(&exi_signed->data, &u_value);
133+
*value = (exi_signed->is_negative == 0) ? u_value : -u_value;
134+
return res;
135+
}
136+
137+
int exi_basetypes_convert_bytes_from_unsigned(const exi_unsigned_t* exi_unsigned, uint8_t* data, size_t* data_len, size_t data_size)
138+
{
139+
const uint8_t* current_octet = exi_unsigned->octets;
140+
uint16_t temp = 0;
141+
*data_len = 0;
142+
size_t total_offset = 0;
143+
144+
for (size_t n = 0; n < exi_unsigned->octets_count; n++) {
145+
temp += ((uint16_t)(*current_octet & EXI_BASETYPES_OCTET_SEQ_VALUE_MASK) << total_offset);
146+
total_offset += 7;
147+
if (total_offset >= 8) {
148+
if (data_size == *data_len) {
149+
return EXI_ERROR__ENCODED_INTEGER_SIZE_LARGER_THAN_DESTINATION;
150+
}
151+
total_offset -= 8;
152+
data[(*data_len)++] = temp & 0xFF;
153+
temp >>= 8;
154+
}
155+
current_octet++;
156+
}
157+
if (total_offset != 0) {
158+
if (data_size == *data_len) {
159+
return EXI_ERROR__ENCODED_INTEGER_SIZE_LARGER_THAN_DESTINATION;
160+
}
161+
data[(*data_len)++] = temp & 0xFF;
162+
}
163+
return EXI_ERROR__NO_ERROR;
164+
}
165+
166+
int exi_basetypes_convert_bytes_to_unsigned(exi_unsigned_t* exi_unsigned, const uint8_t* data, size_t data_len)
167+
{
168+
uint8_t *current_octet = &exi_unsigned->octets[0];
169+
uint16_t dummy = 0;
170+
uint8_t dummy_count = 0;
171+
172+
for (size_t n = 0; n != data_len; n++, current_octet++) {
173+
if (dummy_count <= 8) {
174+
dummy |= (data[n] << dummy_count);
175+
dummy_count += 8;
176+
}
177+
exi_unsigned->octets_count++;
178+
*current_octet = (uint8_t)(dummy & EXI_BASETYPES_OCTET_SEQ_VALUE_MASK);
179+
180+
dummy >>= 7u;
181+
dummy_count -= 7;
182+
if (n == data_len) {
183+
break;
184+
}
185+
186+
*current_octet |= EXI_BASETYPES_OCTET_SEQ_FLAG_MASK;
187+
}
188+
if (dummy_count > 0) {
189+
*(current_octet-1) |= EXI_BASETYPES_OCTET_SEQ_FLAG_MASK;
190+
exi_unsigned->octets_count++;
191+
*current_octet = (uint8_t)(dummy & EXI_BASETYPES_OCTET_SEQ_VALUE_MASK);
192+
}
193+
return EXI_ERROR__NO_ERROR;
194+
}
195+
100196
{% endblock %}

src/input/code_templates/c/static_code/exi_basetypes.h.jinja

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#define EXI_STRING_MAX_LEN 64
1717
#define EXI_BYTE_ARRAY_MAX_LEN 350
1818

19-
#define EXI_BASETYPES_MAX_OCTETS_SUPPORTED 10
19+
#define EXI_BASETYPES_MAX_OCTETS_SUPPORTED 29
2020

2121
#define EXI_BASETYPES_OCTET_SEQ_FLAG_MASK 0x80
2222
#define EXI_BASETYPES_OCTET_SEQ_VALUE_MASK 0x7F
@@ -40,11 +40,26 @@ typedef struct
4040
size_t octets_count;
4141
} exi_unsigned_t;
4242

43+
typedef struct exi_signed_t
44+
{
45+
exi_unsigned_t data;
46+
uint8_t is_negative : 1;
47+
} exi_signed_t;
48+
4349
typedef char exi_character_t;
4450

4551
int exi_basetypes_convert_to_unsigned(exi_unsigned_t* exi_unsigned, uint32_t value, size_t max_octets);
4652
int exi_basetypes_convert_64_to_unsigned(exi_unsigned_t* exi_unsigned, uint64_t value);
4753

48-
int exi_basetypes_convert_from_unsigned(exi_unsigned_t* exi_unsigned, uint32_t* value, size_t max_octets);
49-
int exi_basetypes_convert_64_from_unsigned(exi_unsigned_t* exi_unsigned, uint64_t* value);
54+
int exi_basetypes_convert_from_unsigned(const exi_unsigned_t* exi_unsigned, uint32_t* value, size_t max_octets);
55+
int exi_basetypes_convert_64_from_unsigned(const exi_unsigned_t* exi_unsigned, uint64_t* value);
56+
57+
int exi_basetypes_convert_to_signed(exi_signed_t* exi_signed, int32_t value, size_t max_octets);
58+
int exi_basetypes_convert_64_to_signed(exi_signed_t* exi_signed, int64_t value);
59+
60+
int exi_basetypes_convert_from_signed(const exi_signed_t* exi_unsigned, int32_t* value, size_t max_octets);
61+
int exi_basetypes_convert_64_from_signed(const exi_signed_t* exi_unsigned, int64_t* value);
62+
63+
int exi_basetypes_convert_bytes_from_unsigned(const exi_unsigned_t* exi_unsigned, uint8_t* data, size_t* data_len, size_t data_size);
64+
int exi_basetypes_convert_bytes_to_unsigned(exi_unsigned_t* exi_unsigned, const uint8_t* data, size_t data_len);
5065
{% endblock %}

src/input/code_templates/c/static_code/exi_basetypes_decoder.c.jinja

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,11 @@ int exi_basetypes_decoder_uint_64(exi_bitstream_t* stream, uint64_t* value)
224224
return EXI_ERROR__NO_ERROR;
225225
}
226226

227+
int exi_basetypes_decoder_unsigned(exi_bitstream_t* stream, exi_unsigned_t* value)
228+
{
229+
return exi_basetypes_decoder_read_unsigned(stream, value);
230+
}
231+
227232
/*****************************************************************************
228233
* interface functions - integer
229234
*****************************************************************************/
@@ -341,6 +346,21 @@ int exi_basetypes_decoder_integer_64(exi_bitstream_t* stream, int64_t* value)
341346
return error;
342347
}
343348

349+
int exi_basetypes_decoder_signed(exi_bitstream_t* stream, exi_signed_t* value)
350+
{
351+
int sign = 0;
352+
353+
int error = exi_basetypes_decoder_bool(stream, &sign);
354+
if (error != EXI_ERROR__NO_ERROR)
355+
{
356+
return error;
357+
}
358+
value->is_negative = (sign == 0) ? 0 : 1;
359+
360+
error = exi_basetypes_decoder_unsigned(stream, &value->data);
361+
return error;
362+
}
363+
344364
/*****************************************************************************
345365
* interface functions - characters, string
346366
*****************************************************************************/

src/input/code_templates/c/static_code/exi_basetypes_decoder.h.jinja

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ int exi_basetypes_decoder_uint_8(exi_bitstream_t* stream, uint8_t* value);
6262
int exi_basetypes_decoder_uint_16(exi_bitstream_t* stream, uint16_t* value);
6363
int exi_basetypes_decoder_uint_32(exi_bitstream_t* stream, uint32_t* value);
6464
int exi_basetypes_decoder_uint_64(exi_bitstream_t* stream, uint64_t* value);
65+
int exi_basetypes_decoder_unsigned(exi_bitstream_t* stream, exi_unsigned_t* value);
6566

6667
/**
6768
* \brief decoder for type integer
@@ -79,6 +80,7 @@ int exi_basetypes_decoder_integer_8(exi_bitstream_t* stream, int8_t* value);
7980
int exi_basetypes_decoder_integer_16(exi_bitstream_t* stream, int16_t* value);
8081
int exi_basetypes_decoder_integer_32(exi_bitstream_t* stream, int32_t* value);
8182
int exi_basetypes_decoder_integer_64(exi_bitstream_t* stream, int64_t* value);
83+
int exi_basetypes_decoder_signed(exi_bitstream_t* stream, exi_signed_t* value);
8284

8385
/**
8486
* \brief decoder for type character array

src/input/code_templates/c/static_code/exi_basetypes_encoder.c.jinja

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
/*****************************************************************************
1212
* local functions
1313
*****************************************************************************/
14-
static int exi_basetypes_encoder_write_unsigned(exi_bitstream_t* stream, exi_unsigned_t* exi_unsigned)
14+
static int exi_basetypes_encoder_write_unsigned(exi_bitstream_t* stream, const exi_unsigned_t* exi_unsigned)
1515
{
1616
{%- if add_debug_code == 1 %}
1717
if (stream->status_callback)
1818
{
1919
stream->status_callback(EXI_DEBUG__BASETYPES_ENCODE_UNSIGNED, 0, exi_unsigned->octets_count, 0);
2020
}
2121
{% endif %}
22-
uint8_t* current_octet = exi_unsigned->octets;
22+
const uint8_t* current_octet = exi_unsigned->octets;
2323

2424
for (size_t n = 0; n < exi_unsigned->octets_count; n++)
2525
{
@@ -173,6 +173,11 @@ int exi_basetypes_encoder_uint_64(exi_bitstream_t* stream, uint64_t value)
173173
return exi_basetypes_encoder_write_unsigned(stream, &exi_unsigned);
174174
}
175175

176+
int exi_basetypes_encoder_unsigned(exi_bitstream_t* stream, const exi_unsigned_t* value)
177+
{
178+
return exi_basetypes_encoder_write_unsigned(stream, value);
179+
}
180+
176181
/*****************************************************************************
177182
* interface functions - integer
178183
*****************************************************************************/
@@ -278,6 +283,17 @@ int exi_basetypes_encoder_integer_64(exi_bitstream_t* stream, int64_t value)
278283
return exi_basetypes_encoder_uint_64(stream, result);
279284
}
280285

286+
int exi_basetypes_encoder_signed(exi_bitstream_t* stream, const exi_signed_t* value)
287+
{
288+
int error = exi_basetypes_encoder_bool(stream, value->is_negative);
289+
if (error != EXI_ERROR__NO_ERROR)
290+
{
291+
return error;
292+
}
293+
294+
return exi_basetypes_encoder_unsigned(stream, &value->data);
295+
}
296+
281297
/*****************************************************************************
282298
* interface functions - characters, string
283299
*****************************************************************************/

0 commit comments

Comments
 (0)