Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use big int for integer type without max value #65

Merged
merged 5 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/cbexigen/decoder_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,23 @@ def __get_content_decode_long_int(self, element_typename, detail: ElementGrammar

return decode_content

def __get_content_decode_signed(self, element_typename, detail: ElementGrammarDetail, level):
type_value = f'{element_typename}->{detail.particle.name}'
next_grammar_id = detail.next_grammar

template_file = 'DecodeTypeSigned.jinja'
decode_comment = '// decode: signed'
if detail.particle.is_attribute:
decode_comment += ' (Attribute)'
temp = self.generator.get_template(template_file)
decode_content = temp.render(decode_comment=decode_comment,
type_value=type_value,
type_option=detail.particle.is_optional,
next_grammar_id=next_grammar_id,
indent=self.indent, level=level)

return decode_content

def __get_content_decode_string(self, element_typename, detail: ElementGrammarDetail, level):
decode_comment = '// decode: string (len, characters)'
if detail.particle.is_attribute:
Expand Down Expand Up @@ -550,6 +567,8 @@ def __get_type_content(self, grammar: ElementGrammar, detail: ElementGrammarDeta
type_content = self.__get_content_decode_int(grammar.element_typename, detail, level)
elif detail.particle.integer_base_type == 'uint64':
type_content = self.__get_content_decode_long_int(grammar.element_typename, detail, level)
elif detail.particle.integer_base_type == 'signed':
type_content = self.__get_content_decode_signed(grammar.element_typename, detail, level)
else:
log_write_error(f"Unhandled numeric type: '{detail.particle.name}': "
f"'{detail.particle.type_short}', " +
Expand Down
11 changes: 11 additions & 0 deletions src/cbexigen/encoder_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,15 @@ def __get_content_encode_long_int(self, element_typename, detail: ElementGrammar

return content

def __get_content_encode_signed(self, element_typename, detail, level):
value_parameter = f'{element_typename}->{detail.particle.name}'

temp = self.generator.get_template('EncodeTypeSigned.jinja')
content = temp.render(value_parameter=value_parameter,
next_grammar=detail.next_grammar,
indent=self.indent, level=level)
return content

def __get_content_encode_string(self, element_typename, detail: ElementGrammarDetail, level):
length_parameter = f'{element_typename}->{detail.particle.name}.{detail.particle.length_parameter_name}'
value_parameter = f'{element_typename}->{detail.particle.name}.{detail.particle.value_parameter_name}'
Expand Down Expand Up @@ -420,6 +429,8 @@ def __get_type_content(self, grammar: ElementGrammar, detail: ElementGrammarDeta
type_content = self.__get_content_encode_int(grammar.element_typename, detail, level)
elif detail.particle.integer_base_type == 'uint64':
type_content = self.__get_content_encode_long_int(grammar.element_typename, detail, level)
elif detail.particle.integer_base_type == 'signed':
type_content = self.__get_content_encode_signed(grammar.element_typename, detail, level)
else:
log_write_error(f"Unhandled numeric type: '{detail.particle.name}': "
f"'{detail.particle.type_short}', " +
Expand Down
3 changes: 2 additions & 1 deletion src/cbexigen/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
'uint16': 'uint16_t',
'uint32': 'uint32_t',
'uint64': 'uint64_t',
'signed': 'exi_signed_t',
}

TYPE_TRANSLATION = {
Expand All @@ -29,7 +30,7 @@
'byte': 'int8',
'short': 'int16',
'int': 'int32',
'integer': 'int32',
'integer': 'signed',
'long': 'int64',
'decimal': 'integer', # FIXME special type
'unsignedByte': 'uint8',
Expand Down
14 changes: 14 additions & 0 deletions src/input/code_templates/c/decoder/DecodeTypeSigned.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{{ indent * level }}{{ decode_comment }}
{{ indent * level }}error = exi_basetypes_decoder_nbit_uint(stream, 1, &eventCode);
{{ indent * level }}if (error == 0)
{{ indent * level }}{
{{ indent * (level + 1) }}error = exi_basetypes_decoder_signed(stream, &{{ type_value }});
{{ indent * (level + 1) }}if (error == 0)
{{ indent * (level + 1) }}{
{%- if type_option == 1 %}
{{ indent * (level + 2) }}{{ type_value }}_isUsed = 1u;
{%- endif %}
{{ indent * (level + 2) }}grammar_id = {{ next_grammar_id }};
{{ indent * (level + 1) }}}
{{ indent * (level + 1) }}error = exi_basetypes_decoder_nbit_uint(stream, 1, &eventCode);
{{ indent * level }}}
14 changes: 14 additions & 0 deletions src/input/code_templates/c/encoder/EncodeTypeSigned.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{{ indent * level }}error = exi_basetypes_encoder_nbit_uint(stream, 1, 0);
{{ indent * level }}if (error == EXI_ERROR__NO_ERROR)
{{ indent * level }}{
{{ indent * (level + 1) }}error = exi_basetypes_encoder_signed(stream, &{{ value_parameter }});
{{ indent * (level + 1) }}if (error == EXI_ERROR__NO_ERROR)
{{ indent * (level + 1) }}{
{{ indent * (level + 2) }}// encode END Element
{{ indent * (level + 2) }}error = exi_basetypes_encoder_nbit_uint(stream, 1, 0);
{{ indent * (level + 2) }}if (error == EXI_ERROR__NO_ERROR)
{{ indent * (level + 2) }}{
{{ indent * (level + 3) }}grammar_id = {{ next_grammar }};
{{ indent * (level + 2) }}}
{{ indent * (level + 1) }}}
{{ indent * level }}}
104 changes: 100 additions & 4 deletions src/input/code_templates/c/static_code/exi_basetypes.c.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,34 @@ int exi_basetypes_convert_64_to_unsigned(exi_unsigned_t* exi_unsigned, uint64_t
return (exi_unsigned->octets_count <= EXI_BASETYPES_UINT64_MAX_OCTETS) ? EXI_ERROR__NO_ERROR : EXI_ERROR__OCTET_COUNT_LARGER_THAN_TYPE_SUPPORTS;
}

int exi_basetypes_convert_from_unsigned(exi_unsigned_t* exi_unsigned, uint32_t* value, size_t max_octets)
int exi_basetypes_convert_to_signed(exi_signed_t* exi_signed, int32_t value, size_t max_octets)
{
if (value < 0) {
exi_signed->is_negative = 1;
return exi_basetypes_convert_to_unsigned(&exi_signed->data, -value, max_octets);
}
exi_signed->is_negative = 0;
return exi_basetypes_convert_to_unsigned(&exi_signed->data, value, max_octets);
}

int exi_basetypes_convert_64_to_signed(exi_signed_t* exi_signed, int64_t value)
{
if (value < 0) {
exi_signed->is_negative = 1;
return exi_basetypes_convert_64_to_unsigned(&exi_signed->data, -value);
}
exi_signed->is_negative = 0;
return exi_basetypes_convert_64_to_unsigned(&exi_signed->data, value);
}

int exi_basetypes_convert_from_unsigned(const exi_unsigned_t* exi_unsigned, uint32_t* value, size_t max_octets)
{
if (exi_unsigned->octets_count > max_octets)
{
return EXI_ERROR__OCTET_COUNT_LARGER_THAN_TYPE_SUPPORTS;
}

uint8_t* current_octet = exi_unsigned->octets;
const uint8_t* current_octet = exi_unsigned->octets;
*value = 0;

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

int exi_basetypes_convert_64_from_unsigned(exi_unsigned_t* exi_unsigned, uint64_t* value)
int exi_basetypes_convert_64_from_unsigned(const exi_unsigned_t* exi_unsigned, uint64_t* value)
{
if (exi_unsigned->octets_count > EXI_BASETYPES_UINT64_MAX_OCTETS)
{
return EXI_ERROR__OCTET_COUNT_LARGER_THAN_TYPE_SUPPORTS;
}

uint8_t* current_octet = exi_unsigned->octets;
const uint8_t* current_octet = exi_unsigned->octets;
*value = 0;

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

return EXI_ERROR__NO_ERROR;
}

int exi_basetypes_convert_from_signed(const exi_signed_t* exi_signed, int32_t* value, size_t max_octets)
{
uint32_t u_value = 0;
int res = exi_basetypes_convert_from_unsigned(&exi_signed->data, &u_value, max_octets);
*value = (exi_signed->is_negative == 0) ? u_value : -u_value;
return res;
}

int exi_basetypes_convert_64_from_signed(const exi_signed_t* exi_signed, int64_t* value)
{
uint64_t u_value = 0;
int res = exi_basetypes_convert_64_from_unsigned(&exi_signed->data, &u_value);
*value = (exi_signed->is_negative == 0) ? u_value : -u_value;
return res;
}

int exi_basetypes_convert_bytes_from_unsigned(const exi_unsigned_t* exi_unsigned, uint8_t* data, size_t* data_len, size_t data_size)
barsnick marked this conversation as resolved.
Show resolved Hide resolved
{
const uint8_t* current_octet = exi_unsigned->octets;
uint16_t temp = 0;
*data_len = 0;
size_t total_offset = 0;

for (size_t n = 0; n < exi_unsigned->octets_count; n++) {
temp += ((uint16_t)(*current_octet & EXI_BASETYPES_OCTET_SEQ_VALUE_MASK) << total_offset);
total_offset += 7;
if (total_offset >= 8) {
if (data_size == *data_len) {
return EXI_ERROR__ENCODED_INTEGER_SIZE_LARGER_THAN_DESTINATION;
}
total_offset -= 8;
data[(*data_len)++] = temp & 0xFF;
temp >>= 8;
}
current_octet++;
}
if (total_offset != 0) {
if (data_size == *data_len) {
return EXI_ERROR__ENCODED_INTEGER_SIZE_LARGER_THAN_DESTINATION;
}
data[(*data_len)++] = temp & 0xFF;
}
return EXI_ERROR__NO_ERROR;
}

int exi_basetypes_convert_bytes_to_unsigned(exi_unsigned_t* exi_unsigned, const uint8_t* data, size_t data_len)
barsnick marked this conversation as resolved.
Show resolved Hide resolved
{
uint8_t *current_octet = &exi_unsigned->octets[0];
uint16_t dummy = 0;
uint8_t dummy_count = 0;

for (size_t n = 0; n != data_len; n++, current_octet++) {
if (dummy_count <= 8) {
dummy |= (data[n] << dummy_count);
dummy_count += 8;
}
exi_unsigned->octets_count++;
*current_octet = (uint8_t)(dummy & EXI_BASETYPES_OCTET_SEQ_VALUE_MASK);

dummy >>= 7u;
dummy_count -= 7;
if (n == data_len) {
break;
}

*current_octet |= EXI_BASETYPES_OCTET_SEQ_FLAG_MASK;
}
if (dummy_count > 0) {
*(current_octet-1) |= EXI_BASETYPES_OCTET_SEQ_FLAG_MASK;
exi_unsigned->octets_count++;
*current_octet = (uint8_t)(dummy & EXI_BASETYPES_OCTET_SEQ_VALUE_MASK);
}
return EXI_ERROR__NO_ERROR;
}

{% endblock %}
21 changes: 18 additions & 3 deletions src/input/code_templates/c/static_code/exi_basetypes.h.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#define EXI_STRING_MAX_LEN 64
#define EXI_BYTE_ARRAY_MAX_LEN 350

#define EXI_BASETYPES_MAX_OCTETS_SUPPORTED 10
#define EXI_BASETYPES_MAX_OCTETS_SUPPORTED 29

#define EXI_BASETYPES_OCTET_SEQ_FLAG_MASK 0x80
#define EXI_BASETYPES_OCTET_SEQ_VALUE_MASK 0x7F
Expand All @@ -40,11 +40,26 @@ typedef struct
size_t octets_count;
} exi_unsigned_t;

typedef struct exi_signed_t
{
exi_unsigned_t data;
uint8_t is_negative : 1;
} exi_signed_t;

typedef char exi_character_t;

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

int exi_basetypes_convert_from_unsigned(exi_unsigned_t* exi_unsigned, uint32_t* value, size_t max_octets);
int exi_basetypes_convert_64_from_unsigned(exi_unsigned_t* exi_unsigned, uint64_t* value);
int exi_basetypes_convert_from_unsigned(const exi_unsigned_t* exi_unsigned, uint32_t* value, size_t max_octets);
int exi_basetypes_convert_64_from_unsigned(const exi_unsigned_t* exi_unsigned, uint64_t* value);

int exi_basetypes_convert_to_signed(exi_signed_t* exi_signed, int32_t value, size_t max_octets);
int exi_basetypes_convert_64_to_signed(exi_signed_t* exi_signed, int64_t value);

int exi_basetypes_convert_from_signed(const exi_signed_t* exi_unsigned, int32_t* value, size_t max_octets);
int exi_basetypes_convert_64_from_signed(const exi_signed_t* exi_unsigned, int64_t* value);

int exi_basetypes_convert_bytes_from_unsigned(const exi_unsigned_t* exi_unsigned, uint8_t* data, size_t* data_len, size_t data_size);
int exi_basetypes_convert_bytes_to_unsigned(exi_unsigned_t* exi_unsigned, const uint8_t* data, size_t data_len);
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,11 @@ int exi_basetypes_decoder_uint_64(exi_bitstream_t* stream, uint64_t* value)
return EXI_ERROR__NO_ERROR;
}

int exi_basetypes_decoder_unsigned(exi_bitstream_t* stream, exi_unsigned_t* value)
{
return exi_basetypes_decoder_read_unsigned(stream, value);
}

/*****************************************************************************
* interface functions - integer
*****************************************************************************/
Expand Down Expand Up @@ -341,6 +346,21 @@ int exi_basetypes_decoder_integer_64(exi_bitstream_t* stream, int64_t* value)
return error;
}

int exi_basetypes_decoder_signed(exi_bitstream_t* stream, exi_signed_t* value)
{
int sign = 0;

int error = exi_basetypes_decoder_bool(stream, &sign);
if (error != EXI_ERROR__NO_ERROR)
{
return error;
}
value->is_negative = (sign == 0) ? 0 : 1;

error = exi_basetypes_decoder_unsigned(stream, &value->data);
barsnick marked this conversation as resolved.
Show resolved Hide resolved
return error;
}

/*****************************************************************************
* interface functions - characters, string
*****************************************************************************/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ int exi_basetypes_decoder_uint_8(exi_bitstream_t* stream, uint8_t* value);
int exi_basetypes_decoder_uint_16(exi_bitstream_t* stream, uint16_t* value);
int exi_basetypes_decoder_uint_32(exi_bitstream_t* stream, uint32_t* value);
int exi_basetypes_decoder_uint_64(exi_bitstream_t* stream, uint64_t* value);
int exi_basetypes_decoder_unsigned(exi_bitstream_t* stream, exi_unsigned_t* value);

/**
* \brief decoder for type integer
Expand All @@ -79,6 +80,7 @@ int exi_basetypes_decoder_integer_8(exi_bitstream_t* stream, int8_t* value);
int exi_basetypes_decoder_integer_16(exi_bitstream_t* stream, int16_t* value);
int exi_basetypes_decoder_integer_32(exi_bitstream_t* stream, int32_t* value);
int exi_basetypes_decoder_integer_64(exi_bitstream_t* stream, int64_t* value);
int exi_basetypes_decoder_signed(exi_bitstream_t* stream, exi_signed_t* value);

/**
* \brief decoder for type character array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
/*****************************************************************************
* local functions
*****************************************************************************/
static int exi_basetypes_encoder_write_unsigned(exi_bitstream_t* stream, exi_unsigned_t* exi_unsigned)
static int exi_basetypes_encoder_write_unsigned(exi_bitstream_t* stream, const exi_unsigned_t* exi_unsigned)
{
{%- if add_debug_code == 1 %}
if (stream->status_callback)
{
stream->status_callback(EXI_DEBUG__BASETYPES_ENCODE_UNSIGNED, 0, exi_unsigned->octets_count, 0);
}
{% endif %}
uint8_t* current_octet = exi_unsigned->octets;
const uint8_t* current_octet = exi_unsigned->octets;

for (size_t n = 0; n < exi_unsigned->octets_count; n++)
{
Expand Down Expand Up @@ -173,6 +173,11 @@ int exi_basetypes_encoder_uint_64(exi_bitstream_t* stream, uint64_t value)
return exi_basetypes_encoder_write_unsigned(stream, &exi_unsigned);
}

int exi_basetypes_encoder_unsigned(exi_bitstream_t* stream, const exi_unsigned_t* value)
{
return exi_basetypes_encoder_write_unsigned(stream, value);
barsnick marked this conversation as resolved.
Show resolved Hide resolved
}

/*****************************************************************************
* interface functions - integer
*****************************************************************************/
Expand Down Expand Up @@ -278,6 +283,17 @@ int exi_basetypes_encoder_integer_64(exi_bitstream_t* stream, int64_t value)
return exi_basetypes_encoder_uint_64(stream, result);
}

int exi_basetypes_encoder_signed(exi_bitstream_t* stream, const exi_signed_t* value)
{
int error = exi_basetypes_encoder_bool(stream, value->is_negative);
if (error != EXI_ERROR__NO_ERROR)
{
return error;
}

return exi_basetypes_encoder_unsigned(stream, &value->data);
}

/*****************************************************************************
* interface functions - characters, string
*****************************************************************************/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ int exi_basetypes_encoder_uint_8(exi_bitstream_t* stream, uint8_t value);
int exi_basetypes_encoder_uint_16(exi_bitstream_t* stream, uint16_t value);
int exi_basetypes_encoder_uint_32(exi_bitstream_t* stream, uint32_t value);
int exi_basetypes_encoder_uint_64(exi_bitstream_t* stream, uint64_t value);
int exi_basetypes_encoder_unsigned(exi_bitstream_t* stream, const exi_unsigned_t* value);

/**
* \brief encoder for type integer
Expand All @@ -79,6 +80,7 @@ int exi_basetypes_encoder_integer_8(exi_bitstream_t* stream, int8_t value);
int exi_basetypes_encoder_integer_16(exi_bitstream_t* stream, int16_t value);
int exi_basetypes_encoder_integer_32(exi_bitstream_t* stream, int32_t value);
int exi_basetypes_encoder_integer_64(exi_bitstream_t* stream, int64_t value);
int exi_basetypes_encoder_signed(exi_bitstream_t* stream, const exi_signed_t* value);

/**
* \brief encoder for type exi_character array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#define EXI_ERROR__ARRAY_OUT_OF_BOUNDS -110
#define EXI_ERROR__CHARACTER_BUFFER_TOO_SMALL -111
#define EXI_ERROR__BYTE_BUFFER_TOO_SMALL -112
#define EXI_ERROR__ENCODED_INTEGER_SIZE_LARGER_THAN_DESTINATION -113

// grammar errors -130 to -149
#define EXI_ERROR__UNKNOWN_GRAMMAR_ID -130
Expand Down