@@ -107,6 +107,64 @@ if constexpr (std::endian::native == std::endian::little) {
107107
108108{# ------------------------------------ #}
109109
110+ {% macro decl_calc_args_class(group) %}
111+ {% set va_args_count = group.fields | selectattr('token', 'in', ['group', 'data']) | list | length %}
112+ {% if va_args_count > 0 -%}
113+ std::tuple<
114+ {% for field in group.fields | selectattr('token', 'in', ['group', 'data']) %}
115+ {% if field.token == 'group' %}
116+ {% if field.fields | selectattr('token', 'in', ['group', 'data' ]) | list | length > 0 %}
117+ std::vector<
118+ {{ decl_calc_args_class(field) | indent(8) }}
119+ > /* {{ field.name }} */ {% if not loop.last %},{% endif +%}
120+ {% else %}
121+ std::size_t /* {{ field.name }} */ {% if not loop.last %},{% endif +%}
122+ {% endif %}
123+ {% elif field.token == 'data' %}
124+ std::size_t /* {{ field.name }} */ {% if not loop.last %},{% endif +%}
125+ {% endif %}
126+ {% endfor %}
127+ >
128+ {%- endif %}
129+ {%- endmacro %}
130+
131+ {% macro decl_calc_args(group, argName) %}
132+ {% set va_args_count = group.fields | selectattr('token', 'in', ['group', 'data']) | list | length %}
133+ {% if va_args_count > 0 -%}
134+ std::apply([](
135+ {%- for field in group.fields | selectattr('token', 'in', ['group', 'data']) -%}
136+ auto const& field_{{ field.name -}}{%- if not loop.last %}, {% endif -%}
137+ {%- endfor -%}
138+ ) -> std::size_t {
139+ std::size_t result{0};
140+ {% for field in group.fields | selectattr('token', 'in', ['group', 'data']) %}
141+ // {{ field.name }} ({{ field.token }})
142+ {% if field.token == 'group' %}
143+ {% if field.fields | selectattr('token', 'in', ['group', 'data' ]) | list | length > 0 %}
144+ result += {{ field.dimension_type.encoded_length }};
145+ for (auto const& entry : field_{{ field.name }}) {
146+ result += {{ field.block_length }} + {{ decl_calc_args(field, 'entry') | indent(8) }};
147+ }
148+ {% else %}
149+ result += field_{{ field.name }} * {{ field.block_length }} + {{ field.dimension_type.encoded_length }};
150+ {% endif %}
151+ {% elif field.token == 'data' %}
152+ {% set length = (field.type.contained_types | selectattr('reference_name', 'equalto', 'length') | first) %}
153+ {% set varData = (field.type.contained_types | selectattr('reference_name', 'equalto', 'varData') | first) %}
154+ {% if varData.primitive_type.size > 1 %}
155+ result += field_{{ field.name }} * {{ varData.primitive_type.size }} + {{ length.encoded_length }};
156+ {% else %}
157+ result += field_{{ field.name }} + {{ length.encoded_length }};
158+ {% endif %}
159+ {% endif %}
160+ {% endfor %}
161+ return result;
162+ }, {{ argName }})
163+ {%- endif %}
164+ {%- endmacro %}
165+
166+ {# ------------------------------------ #}
167+
110168{% macro decl_enum(type) %}
111169{% set class_cpp_t = type.name | fmt_class_type %}
112170{% set enc_cpp_t = type.encoding_type | to_cpp_type %}
@@ -271,6 +329,8 @@ public:
271329
272330{% macro decl_message(message) %}
273331{% set class_cpp_t = message.name | fmt_class_message %}
332+ {# count of variable-length fields (groups and data)#}
333+ {% set va_args_count = message.fields | selectattr('token', 'in', ['group', 'data']) | list | length %}
274334class {{ class_cpp_t }} {
275335private:
276336 std::span<std::byte> buffer_;
@@ -447,6 +507,24 @@ public:
447507 static_assert(static_cast<std::string_view>(N).size () + 1 < 0, " Field not found ({{ class_cpp_t }})" );
448508 }
449509{% endif %}
510+
511+ {% if va_args_count > 0 %}
512+
513+ using CalcArgsHelper = {{ decl_calc_args_class(message) | indent(4) }};
514+
515+ [[nodiscard]] static constexpr auto calcBufferSize(CalcArgsHelper const& info) noexcept -> std::size_t {
516+ std::size_t bufferSize{ {{- message.block_length -}} };
517+
518+ bufferSize += {{ decl_calc_args(message, 'info') | indent(8) }};
519+
520+ return bufferSize;
521+ }
522+ {% else %}
523+
524+ [[nodiscard]] static constexpr auto calcBufferSize() noexcept -> std::size_t {
525+ return {{ message.block_length }};
526+ }
527+ {% endif %}
450528};
451529{%- endmacro %}
452530
0 commit comments