|
| 1 | +@# Included from rosidl_generator_c/resource/idl__description.c.em |
| 2 | +@{ |
| 3 | +from rosidl_generator_c import escape_string |
| 4 | +from rosidl_generator_c import idl_structure_type_to_c_include_prefix |
| 5 | +from rosidl_generator_c import type_hash_to_c_definition |
| 6 | +from rosidl_parser.definition import NamespacedType |
| 7 | +from rosidl_generator_type_description import FIELD_TYPE_ID_TO_NAME |
| 8 | +from rosidl_generator_type_description import GET_DESCRIPTION_FUNC |
| 9 | +from rosidl_generator_type_description import GET_HASH_FUNC |
| 10 | +from rosidl_generator_type_description import GET_INDIVIDUAL_SOURCE_FUNC |
| 11 | +from rosidl_generator_type_description import GET_SOURCES_FUNC |
| 12 | + |
| 13 | +def typename_to_c(typename): |
| 14 | + return typename.replace('/', '__') |
| 15 | + |
| 16 | +def static_seq_n(varname, n): |
| 17 | + """Statically define a runtime Sequence or String type.""" |
| 18 | + if n > 0: |
| 19 | + return f'{{{varname}, {n}, {n}}}' |
| 20 | + return '{NULL, 0, 0}' |
| 21 | + |
| 22 | +def static_seq(varname, values): |
| 23 | + """Statically define a runtime Sequence or String type.""" |
| 24 | + if values: |
| 25 | + return f'{{{varname}, {len(values)}, {len(values)}}}' |
| 26 | + return '{NULL, 0, 0}' |
| 27 | + |
| 28 | +def utf8_encode(value_string): |
| 29 | + from rosidl_generator_c import escape_string |
| 30 | + # Slice removes the b'' from the representation. |
| 31 | + return escape_string(repr(value_string.encode('utf-8'))[2:-1]) |
| 32 | + |
| 33 | +implicit_type_names = set(td['type_description']['type_name'] for td, _ in implicit_type_descriptions) |
| 34 | +includes = set() |
| 35 | +toplevel_msg, _ = toplevel_type_description |
| 36 | + |
| 37 | +for referenced_td in toplevel_msg['referenced_type_descriptions']: |
| 38 | + if referenced_td['type_name'] in implicit_type_names: |
| 39 | + continue |
| 40 | + names = referenced_td['type_name'].split('/') |
| 41 | + _type = NamespacedType(names[:-1], names[-1]) |
| 42 | + include_prefix = idl_structure_type_to_c_include_prefix(_type, 'detail') |
| 43 | + includes.add(include_prefix + '__functions.h') |
| 44 | + |
| 45 | +full_type_descriptions = [toplevel_type_description] + implicit_type_descriptions |
| 46 | +full_type_names = [t['type_description']['type_name'] for t, _ in full_type_descriptions] |
| 47 | +all_type_descriptions = [toplevel_msg['type_description']] + toplevel_msg['referenced_type_descriptions'] |
| 48 | + |
| 49 | +toplevel_encoding = type_source_file.suffix[1:] |
| 50 | +with open(type_source_file, 'r', encoding='utf-8') as f: |
| 51 | + raw_source_content = f.read() |
| 52 | +}@ |
| 53 | +@ |
| 54 | +#include <assert.h> |
| 55 | +#include <string.h> |
| 56 | + |
| 57 | +// Include directives for referenced types |
| 58 | +@[for header_file in includes]@ |
| 59 | +#include "@(header_file)" |
| 60 | +@[end for]@ |
| 61 | + |
| 62 | +@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
| 63 | +@# Cache expected hashes for externally referenced types, for error checking |
| 64 | +// Hashes for external referenced types |
| 65 | +#ifndef NDEBUG |
| 66 | +@[for referenced_type_description in toplevel_msg['referenced_type_descriptions']]@ |
| 67 | +@{ |
| 68 | +type_name = referenced_type_description['type_name'] |
| 69 | +c_typename = type_name.replace('/', '__') |
| 70 | +}@ |
| 71 | +@[ if type_name not in full_type_names]@ |
| 72 | +static const rosidl_type_hash_t @(c_typename)__EXPECTED_HASH = @(type_hash_to_c_definition(hash_lookup[type_name])); |
| 73 | +@[ end if]@ |
| 74 | +@[end for]@ |
| 75 | +#endif |
| 76 | +@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
| 77 | + |
| 78 | +@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
| 79 | +@# Names for all types |
| 80 | +@[for itype_description in all_type_descriptions]@ |
| 81 | +static char @(typename_to_c(itype_description['type_name']))__TYPE_NAME[] = "@(itype_description['type_name'])"; |
| 82 | +@[end for]@ |
| 83 | +@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
| 84 | + |
| 85 | +@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
| 86 | +@# Define all values going into each local type |
| 87 | +@ |
| 88 | +@[for msg, interface_type in full_type_descriptions]@ |
| 89 | +@{ |
| 90 | +itype_description = msg['type_description'] |
| 91 | +td_typename = itype_description['type_name'] |
| 92 | +td_c_typename = typename_to_c(td_typename) |
| 93 | +ref_tds = msg['referenced_type_descriptions'] |
| 94 | +}@ |
| 95 | +@ |
| 96 | +// Define type names, field names, and default values |
| 97 | +@[ for field in itype_description['fields']]@ |
| 98 | +static char @(td_c_typename)__FIELD_NAME__@(field['name'])[] = "@(field['name'])"; |
| 99 | +@[ if field['default_value']]@ |
| 100 | +static char @(td_c_typename)__DEFAULT_VALUE__@(field['name'])[] = "@(utf8_encode(field['default_value']))"; |
| 101 | +@[ end if]@ |
| 102 | +@[ end for]@ |
| 103 | + |
| 104 | +@ |
| 105 | +@[ if itype_description['fields']]@ |
| 106 | +static rosidl_runtime_c__type_description__Field @(td_c_typename)__FIELDS[] = { |
| 107 | +@[ for field in itype_description['fields']]@ |
| 108 | + { |
| 109 | + @(static_seq(f"{td_c_typename}__FIELD_NAME__{field['name']}", field['name'])), |
| 110 | + { |
| 111 | + rosidl_runtime_c__type_description__FieldType__@(FIELD_TYPE_ID_TO_NAME[field['type']['type_id']]), |
| 112 | + @(field['type']['capacity']), |
| 113 | + @(field['type']['string_capacity']), |
| 114 | + @(static_seq(f"{typename_to_c(field['type']['nested_type_name'])}__TYPE_NAME", field['type']['nested_type_name'])), |
| 115 | + }, |
| 116 | + @(static_seq(f"{td_c_typename}__DEFAULT_VALUE__{field['name']}", field['default_value'])), |
| 117 | + }, |
| 118 | +@[ end for]@ |
| 119 | +}; |
| 120 | +@[ end if]@ |
| 121 | +@ |
| 122 | +@[ if ref_tds]@ |
| 123 | + |
| 124 | +static rosidl_runtime_c__type_description__IndividualTypeDescription @(td_c_typename)__REFERENCED_TYPE_DESCRIPTIONS[] = { |
| 125 | +@[ for ref_td in ref_tds]@ |
| 126 | + { |
| 127 | + @(static_seq(f"{typename_to_c(ref_td['type_name'])}__TYPE_NAME", ref_td['type_name'])), |
| 128 | + {NULL, 0, 0}, |
| 129 | + }, |
| 130 | +@[ end for]@ |
| 131 | +}; |
| 132 | +@[ end if]@ |
| 133 | + |
| 134 | +const rosidl_runtime_c__type_description__TypeDescription * |
| 135 | +@(td_c_typename)__@(GET_DESCRIPTION_FUNC)( |
| 136 | + const rosidl_@(interface_type)_type_support_t * type_support) |
| 137 | +{ |
| 138 | + (void)type_support; |
| 139 | + static bool constructed = false; |
| 140 | + static const rosidl_runtime_c__type_description__TypeDescription description = { |
| 141 | + { |
| 142 | + @(static_seq(f'{td_c_typename}__TYPE_NAME', td_typename)), |
| 143 | + @(static_seq(f'{td_c_typename}__FIELDS', msg['type_description']['fields'])), |
| 144 | + }, |
| 145 | + @(static_seq(f'{td_c_typename}__REFERENCED_TYPE_DESCRIPTIONS', ref_tds)), |
| 146 | + }; |
| 147 | + if (!constructed) { |
| 148 | +@[ for idx, ref_td in enumerate(ref_tds)]@ |
| 149 | +@{ |
| 150 | +c_typename = typename_to_c(ref_td['type_name']) |
| 151 | +}@ |
| 152 | +@[ if ref_td['type_name'] not in full_type_names]@ |
| 153 | + assert(0 == memcmp(&@(c_typename)__EXPECTED_HASH, @(c_typename)__@(GET_HASH_FUNC)(NULL), sizeof(rosidl_type_hash_t))); |
| 154 | +@[ end if]@ |
| 155 | + description.referenced_type_descriptions.data[@(idx)].fields = @(c_typename)__@(GET_DESCRIPTION_FUNC)(NULL)->type_description.fields; |
| 156 | +@[ end for]@ |
| 157 | + constructed = true; |
| 158 | + } |
| 159 | + return &description; |
| 160 | +} |
| 161 | +@[end for]@ |
| 162 | +@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
| 163 | + |
| 164 | +@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
| 165 | +@# Define individual raw sources |
| 166 | +@[if raw_source_content]@ |
| 167 | +static char toplevel_type_raw_source[] =@ |
| 168 | +@[ for line in raw_source_content.splitlines()[:-1]] |
| 169 | + "@(utf8_encode(line))\n"@ |
| 170 | +@[ end for] |
| 171 | + "@(utf8_encode(raw_source_content.splitlines()[-1]))"; |
| 172 | +@[end if]@ |
| 173 | + |
| 174 | +static char @(toplevel_encoding)_encoding[] = "@(toplevel_encoding)"; |
| 175 | +@[if implicit_type_descriptions]@ |
| 176 | +static char implicit_encoding[] = "implicit"; |
| 177 | +@[end if]@ |
| 178 | + |
| 179 | +// Define all individual source functions |
| 180 | +@[for type_description_msg, interface_type in full_type_descriptions]@ |
| 181 | +@{ |
| 182 | +itype_description = type_description_msg['type_description'] |
| 183 | +td_typename = itype_description['type_name'] |
| 184 | +td_c_typename = typename_to_c(td_typename) |
| 185 | +if td_typename in implicit_type_names: |
| 186 | + encoding = 'implicit' |
| 187 | + contents_var = None |
| 188 | + contents = None |
| 189 | +else: |
| 190 | + encoding = toplevel_encoding |
| 191 | + contents_var = 'toplevel_type_raw_source' |
| 192 | + contents = raw_source_content |
| 193 | +}@ |
| 194 | + |
| 195 | +const rosidl_runtime_c__type_description__TypeSource * |
| 196 | +@(td_c_typename)__@(GET_INDIVIDUAL_SOURCE_FUNC)( |
| 197 | + const rosidl_@(interface_type)_type_support_t * type_support) |
| 198 | +{ |
| 199 | + (void)type_support; |
| 200 | + static const rosidl_runtime_c__type_description__TypeSource source = { |
| 201 | + @(static_seq(f'{td_c_typename}__TYPE_NAME', td_typename)), |
| 202 | + @(static_seq(f'{encoding}_encoding', encoding)), |
| 203 | + @(static_seq(contents_var, contents)), |
| 204 | + }; |
| 205 | + return &source; |
| 206 | +} |
| 207 | +@[end for]@ |
| 208 | +@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
| 209 | +@ |
| 210 | +@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
| 211 | +@# Define full raw source sequences |
| 212 | +@[for type_description_msg, interface_type in full_type_descriptions]@ |
| 213 | +@{ |
| 214 | +ref_tds = type_description_msg['referenced_type_descriptions'] |
| 215 | +num_sources = len(ref_tds) + 1 |
| 216 | +td_c_typename = typename_to_c(type_description_msg['type_description']['type_name']) |
| 217 | +}@ |
| 218 | + |
| 219 | +const rosidl_runtime_c__type_description__TypeSource__Sequence * |
| 220 | +@(td_c_typename)__@(GET_SOURCES_FUNC)( |
| 221 | + const rosidl_@(interface_type)_type_support_t * type_support) |
| 222 | +{ |
| 223 | + (void)type_support; |
| 224 | + static rosidl_runtime_c__type_description__TypeSource sources[@(num_sources)]; |
| 225 | + static const rosidl_runtime_c__type_description__TypeSource__Sequence source_sequence = @(static_seq_n('sources', num_sources)); |
| 226 | + static bool constructed = false; |
| 227 | + if (!constructed) { |
| 228 | + sources[0] = *@(td_c_typename)__@(GET_INDIVIDUAL_SOURCE_FUNC)(NULL), |
| 229 | +@[ for idx, ref_td in enumerate(ref_tds)]@ |
| 230 | + sources[@(idx + 1)] = *@(typename_to_c(ref_td['type_name']))__@(GET_INDIVIDUAL_SOURCE_FUNC)(NULL); |
| 231 | +@[ end for]@ |
| 232 | + constructed = true; |
| 233 | + } |
| 234 | + return &source_sequence; |
| 235 | +} |
| 236 | +@[end for]@ |
| 237 | +@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
0 commit comments