2014-02-17 22:13:55 +00:00
|
|
|
###############################################################################
|
|
|
|
|
# #
|
|
|
|
|
# This file is part of IfcOpenShell. #
|
|
|
|
|
# #
|
|
|
|
|
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
|
|
|
|
# it under the terms of the Lesser GNU General Public License as published by #
|
|
|
|
|
# the Free Software Foundation, either version 3.0 of the License, or #
|
|
|
|
|
# (at your option) any later version. #
|
|
|
|
|
# #
|
|
|
|
|
# IfcOpenShell is distributed in the hope that it will be useful, #
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
|
|
|
# Lesser GNU General Public License for more details. #
|
|
|
|
|
# #
|
|
|
|
|
# You should have received a copy of the Lesser GNU General Public License #
|
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
|
|
|
|
# #
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
2016-02-18 13:17:15 +01:00
|
|
|
import codegen
|
2014-02-17 22:13:55 +00:00
|
|
|
import templates
|
|
|
|
|
|
2016-04-08 23:23:29 +02:00
|
|
|
from schema import OrderedCaseInsensitiveDict
|
|
|
|
|
|
2016-02-18 13:17:15 +01:00
|
|
|
class Implementation(codegen.Base):
|
2014-02-17 22:13:55 +00:00
|
|
|
def __init__(self, mapping):
|
|
|
|
|
enumeration_functions = []
|
|
|
|
|
entity_implementations = []
|
|
|
|
|
schema_entity_statements = []
|
|
|
|
|
|
|
|
|
|
schema_name = mapping.schema.name.capitalize()
|
2017-12-18 15:25:09 +01:00
|
|
|
schema_name_upper = mapping.schema.name.upper()
|
2014-02-17 22:13:55 +00:00
|
|
|
|
|
|
|
|
stringify = lambda s: '"%s"'%s
|
|
|
|
|
cat = lambda vs: "".join(vs)
|
|
|
|
|
catc = lambda vs: ", ".join(vs)
|
|
|
|
|
catnl = lambda vs: "\n".join(vs)
|
|
|
|
|
cator = lambda vs: " || ".join(vs)
|
|
|
|
|
nl = lambda s: "%s\n"%s if len(s) else s
|
|
|
|
|
|
|
|
|
|
write = lambda str, **kwargs: enumeration_functions.append(str%kwargs)
|
|
|
|
|
|
|
|
|
|
for name, enum in mapping.schema.enumerations.items():
|
|
|
|
|
short_name = name[:-4] if name.endswith("Enum") else name
|
|
|
|
|
context = locals()
|
|
|
|
|
write(
|
|
|
|
|
templates.enumeration_function,
|
|
|
|
|
max_id = len(enum.values),
|
|
|
|
|
name = name,
|
2017-12-13 18:05:10 +01:00
|
|
|
schema_name = schema_name,
|
2017-12-18 15:25:09 +01:00
|
|
|
schema_name_upper = schema_name_upper,
|
2014-02-17 22:13:55 +00:00
|
|
|
values = catc(map(stringify, enum.values)),
|
|
|
|
|
from_string_statements = catnl(templates.enum_from_string_stmt%dict(context,**locals()) for value in enum.values)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
write = lambda str, **kwargs: entity_implementations.append(str%kwargs)
|
|
|
|
|
|
2020-08-29 10:23:59 +02:00
|
|
|
for name, type in mapping.schema.entities.items():
|
2014-02-17 22:13:55 +00:00
|
|
|
parent_type_test = "" if not type.supertypes or len(type.supertypes) != 1 \
|
|
|
|
|
else templates.parent_type_test%(type.supertypes[0])
|
2017-12-13 18:05:10 +01:00
|
|
|
|
2014-02-17 22:13:55 +00:00
|
|
|
constructor_arguments = mapping.get_assignable_arguments(type, include_derived = True)
|
|
|
|
|
constructor_arguments_str = catc("%(full_type)s v%(index)d_%(name)s"%a for a in constructor_arguments if not a['is_derived'])
|
|
|
|
|
attributes = []
|
|
|
|
|
constructor_implementations = []
|
|
|
|
|
write_attr = lambda str, **kwargs: attributes.append(str%kwargs)
|
|
|
|
|
for arg in constructor_arguments:
|
|
|
|
|
if not arg['is_inherited'] and not arg['is_derived']:
|
|
|
|
|
if arg['is_optional']:
|
|
|
|
|
write_attr(
|
2014-05-04 14:42:55 +00:00
|
|
|
templates.const_function,
|
2014-02-17 22:13:55 +00:00
|
|
|
class_name = name,
|
2017-12-13 18:05:10 +01:00
|
|
|
schema_name = schema_name,
|
2017-12-18 15:25:09 +01:00
|
|
|
schema_name_upper = schema_name_upper,
|
2014-02-17 22:13:55 +00:00
|
|
|
name = 'has%s'%arg['name'],
|
|
|
|
|
arguments = '',
|
|
|
|
|
return_type = 'bool',
|
|
|
|
|
body = templates.optional_attr_stmt % {'index':arg['index']-1}
|
|
|
|
|
)
|
2014-05-04 14:42:55 +00:00
|
|
|
|
|
|
|
|
def find_template(arg):
|
|
|
|
|
simple = mapping.schema.is_simpletype(arg['list_instance_type'])
|
2015-01-05 14:11:42 +00:00
|
|
|
select = arg['list_instance_type'] == "IfcUtil::IfcBaseClass"
|
2015-05-21 12:09:57 +00:00
|
|
|
express = mapping.flatten_type_string(arg['list_instance_type']) in mapping.express_to_cpp_typemapping
|
2014-05-04 14:42:55 +00:00
|
|
|
if arg['is_enum']: return templates.get_attr_stmt_enum
|
2015-06-16 12:58:07 +00:00
|
|
|
elif arg['is_nested'] and arg['is_templated_list']: return templates.get_attr_stmt_nested_array
|
2015-05-21 12:09:57 +00:00
|
|
|
elif arg['is_templated_list'] and not (select or simple or express): return templates.get_attr_stmt_array
|
2014-05-04 14:42:55 +00:00
|
|
|
elif arg['non_optional_type'].endswith('*'): return templates.get_attr_stmt_entity
|
|
|
|
|
else: return templates.get_attr_stmt
|
|
|
|
|
|
|
|
|
|
tmpl = find_template(arg)
|
2014-02-17 22:13:55 +00:00
|
|
|
write_attr(
|
2014-05-04 14:42:55 +00:00
|
|
|
templates.const_function,
|
2014-02-17 22:13:55 +00:00
|
|
|
class_name = name,
|
|
|
|
|
name = arg['name'],
|
|
|
|
|
arguments = '',
|
2017-12-13 18:05:10 +01:00
|
|
|
schema_name = schema_name,
|
2017-12-18 15:25:09 +01:00
|
|
|
schema_name_upper = schema_name_upper,
|
2014-02-17 22:13:55 +00:00
|
|
|
return_type = arg['non_optional_type'],
|
|
|
|
|
body = tmpl % {'index': arg['index']-1,
|
2017-12-13 18:05:10 +01:00
|
|
|
'type' : arg['non_optional_type'].replace('::Value', ''),
|
2014-02-17 22:13:55 +00:00
|
|
|
'list_instance_type' : arg['list_instance_type']}
|
|
|
|
|
)
|
2015-01-05 14:11:42 +00:00
|
|
|
|
|
|
|
|
def find_template(arg):
|
|
|
|
|
simple = mapping.schema.is_simpletype(arg['list_instance_type'])
|
|
|
|
|
select = arg['list_instance_type'] == "IfcUtil::IfcBaseClass"
|
|
|
|
|
express = arg['list_instance_type'] in mapping.express_to_cpp_typemapping
|
|
|
|
|
if arg['is_enum']: return templates.set_attr_stmt_enum
|
2015-05-21 12:09:57 +00:00
|
|
|
elif arg['is_templated_list'] and not (select or simple or express): return templates.set_attr_stmt_array
|
2015-01-05 14:11:42 +00:00
|
|
|
else: return templates.set_attr_stmt
|
2014-02-17 22:13:55 +00:00
|
|
|
|
2015-01-05 14:11:42 +00:00
|
|
|
tmpl = find_template(arg)
|
2014-02-17 22:13:55 +00:00
|
|
|
write_attr(
|
|
|
|
|
templates.function,
|
|
|
|
|
class_name = name,
|
|
|
|
|
name = 'set%s'%arg['name'],
|
|
|
|
|
arguments = '%s v'%arg['non_optional_type'],
|
|
|
|
|
return_type = 'void',
|
2017-12-13 18:05:10 +01:00
|
|
|
schema_name = schema_name,
|
2017-12-18 15:25:09 +01:00
|
|
|
schema_name_upper = schema_name_upper,
|
2014-02-17 22:13:55 +00:00
|
|
|
body = tmpl % {'index': arg['index']-1,
|
2017-12-13 18:05:10 +01:00
|
|
|
'type' : arg['non_optional_type'].replace('::Value', '')}
|
2014-02-17 22:13:55 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if arg['is_derived']:
|
|
|
|
|
constructor_implementations.append(templates.constructor_stmt_derived % {'index' : arg['index']-1})
|
|
|
|
|
else:
|
|
|
|
|
is_optional_non_naked_ptr = arg['is_optional'] and not arg['non_optional_type'].endswith('*')
|
|
|
|
|
arg_name = "v%(index)d_%(name)s"%arg
|
|
|
|
|
deref_name = ("*%s"%arg_name) if is_optional_non_naked_ptr else arg_name
|
|
|
|
|
|
|
|
|
|
tmpl = templates.constructor_stmt_array if arg['is_templated_list'] \
|
|
|
|
|
else templates.constructor_stmt_enum if arg['is_enum'] \
|
|
|
|
|
else templates.constructor_stmt
|
|
|
|
|
impl = tmpl % {'name' : deref_name,
|
|
|
|
|
'index' : arg['index']-1,
|
2017-12-13 18:05:10 +01:00
|
|
|
'type' : arg['non_optional_type'].replace('::Value', '')}
|
2014-02-17 22:13:55 +00:00
|
|
|
if is_optional_non_naked_ptr:
|
|
|
|
|
impl = templates.constructor_stmt_optional%{'name' : arg_name,
|
|
|
|
|
'index' : arg['index']-1,
|
|
|
|
|
'stmt' : impl}
|
|
|
|
|
constructor_implementations.append(impl)
|
2015-01-10 22:13:52 +00:00
|
|
|
|
|
|
|
|
def get_attribute_index(entity, attr_name):
|
|
|
|
|
related_entity = mapping.schema.entities[entity]
|
2016-04-08 23:23:29 +02:00
|
|
|
return [a['name'].lower() for a in mapping.get_assignable_arguments(related_entity, include_derived=True)].index(attr_name.lower())
|
2014-02-17 22:13:55 +00:00
|
|
|
|
2014-05-04 14:42:55 +00:00
|
|
|
inverse = [templates.const_function % {
|
2014-02-17 22:13:55 +00:00
|
|
|
'class_name' : name,
|
2017-12-13 18:05:10 +01:00
|
|
|
'schema_name' : schema_name,
|
2017-12-18 15:25:09 +01:00
|
|
|
'schema_name_upper' : schema_name_upper,
|
2014-02-17 22:13:55 +00:00
|
|
|
'name' : i.name,
|
|
|
|
|
'arguments' : '',
|
2017-12-13 18:05:10 +01:00
|
|
|
'return_type' : '::%s::%s::list::ptr' % (schema_name, i.entity),
|
2017-12-18 15:25:09 +01:00
|
|
|
'body' : templates.get_inverse % {'type': i.entity, 'index':get_attribute_index(i.entity, i.attribute), 'schema_name' : schema_name, 'schema_name_upper': schema_name_upper}
|
2020-08-29 10:23:59 +02:00
|
|
|
} for i in type.inverse]
|
2014-02-17 22:13:55 +00:00
|
|
|
|
2017-06-05 17:26:58 +02:00
|
|
|
superclass = "%s((IfcEntityInstanceData*)0)" % type.supertypes[0] if len(type.supertypes) == 1 else 'IfcUtil::IfcBaseEntity()'
|
2014-02-17 22:13:55 +00:00
|
|
|
|
|
|
|
|
write(
|
|
|
|
|
templates.entity_implementation,
|
|
|
|
|
name = name,
|
|
|
|
|
parent_type_test = parent_type_test,
|
|
|
|
|
constructor_arguments = constructor_arguments_str,
|
|
|
|
|
constructor_implementation = cat(constructor_implementations),
|
|
|
|
|
attributes = nl(catnl(attributes)),
|
|
|
|
|
inverse = nl(catnl(inverse)),
|
2017-12-13 18:05:10 +01:00
|
|
|
superclass = superclass,
|
2017-12-18 15:25:09 +01:00
|
|
|
schema_name = schema_name,
|
|
|
|
|
schema_name_upper = schema_name_upper
|
2014-02-17 22:13:55 +00:00
|
|
|
)
|
|
|
|
|
|
2016-04-08 23:23:45 +02:00
|
|
|
selectable_simple_types = sorted(set(sum([b.values for a,b in mapping.schema.selects.items()], [])) & set(map(str, mapping.schema.types.keys())))
|
2015-01-05 14:11:42 +00:00
|
|
|
schema_entity_statements += [templates.schema_entity_stmt%locals() for name, type in mapping.schema.simpletypes.items()]
|
2014-02-17 22:13:55 +00:00
|
|
|
schema_entity_statements += [templates.schema_entity_stmt%locals() for name, type in mapping.schema.entities.items()]
|
|
|
|
|
|
2015-01-05 14:11:42 +00:00
|
|
|
enumerable_types = sorted(set([name for name, type in mapping.schema.types.items()] + [name for name, type in mapping.schema.entities.items()]))
|
2014-02-17 22:13:55 +00:00
|
|
|
max_len = max(map(len, enumerable_types))
|
|
|
|
|
type_name_strings = catc(map(stringify, enumerable_types))
|
|
|
|
|
string_map_statements = [templates.string_map_statement % {
|
|
|
|
|
'uppercase_name' : name.upper(),
|
|
|
|
|
'name' : name,
|
|
|
|
|
'padding' : ' ' * (max_len - len(name))
|
|
|
|
|
} for name in enumerable_types]
|
2016-03-18 11:14:14 +01:00
|
|
|
|
2016-04-08 23:23:29 +02:00
|
|
|
enumeration_index_by_str = OrderedCaseInsensitiveDict((j,i) for i,j in enumerate(enumerable_types))
|
2016-03-18 11:14:14 +01:00
|
|
|
def get_parent_id(s):
|
|
|
|
|
e = mapping.schema.entities.get(s)
|
2016-04-08 23:23:29 +02:00
|
|
|
if e and e.supertypes:
|
2016-03-18 11:14:14 +01:00
|
|
|
return enumeration_index_by_str[e.supertypes[0]]
|
|
|
|
|
else: return -1
|
2014-02-17 22:13:55 +00:00
|
|
|
|
2016-03-18 11:14:14 +01:00
|
|
|
parent_type_statements = ",".join(map(str, map(get_parent_id, enumerable_types)))
|
2014-02-17 22:13:55 +00:00
|
|
|
|
2015-01-05 14:11:42 +00:00
|
|
|
max_id = len(enumerable_types)
|
2014-02-17 22:13:55 +00:00
|
|
|
|
|
|
|
|
simple_type_statements = cator("v == Type::%s"%name for name in selectable_simple_types)
|
2015-01-05 14:11:42 +00:00
|
|
|
|
|
|
|
|
simple_type_impl = []
|
|
|
|
|
for class_name, type in mapping.schema.simpletypes.items():
|
|
|
|
|
type_str = mapping.make_type_string(mapping.flatten_type_string(type))
|
|
|
|
|
attr_type = mapping.make_argument_type(type)
|
|
|
|
|
superclass = mapping.simple_type_parent(class_name)
|
|
|
|
|
|
|
|
|
|
simpletype_impl_is = templates.simpletype_impl_is_with_supertype if superclass \
|
|
|
|
|
else templates.simpletype_impl_is_without_supertype
|
|
|
|
|
|
|
|
|
|
constructor = templates.constructor_single_initlist if superclass \
|
|
|
|
|
else templates.constructor
|
|
|
|
|
|
2015-05-21 12:09:57 +00:00
|
|
|
simpletype_impl_cast = templates.simpletype_impl_cast_templated if mapping.is_templated_list(type) \
|
|
|
|
|
else templates.simpletype_impl_cast
|
|
|
|
|
|
|
|
|
|
simpletype_impl_constructor = templates.simpletype_impl_constructor_templated if mapping.is_templated_list(type) \
|
|
|
|
|
else templates.simpletype_impl_constructor
|
|
|
|
|
|
2017-12-18 15:25:09 +01:00
|
|
|
def compose(params, schema_name=schema_name, schema_name_upper=schema_name_upper):
|
2015-01-05 14:11:42 +00:00
|
|
|
class_name, attr_type, superclass, superclass_init, name, tmpl, return_type, args, body = params
|
2015-05-21 12:09:57 +00:00
|
|
|
underlying_type = mapping.list_instance_type(type)
|
2015-01-05 14:11:42 +00:00
|
|
|
arguments = ",".join(args)
|
|
|
|
|
body = body % locals()
|
|
|
|
|
return tmpl % locals()
|
|
|
|
|
|
|
|
|
|
simple_type_impl.append(templates.simpletype_impl_comment % {'name': class_name})
|
2017-06-05 17:26:58 +02:00
|
|
|
simple_type_impl.extend(map(compose, map(lambda x: (class_name, attr_type, superclass, "(IfcEntityInstanceData*)0")+x, (
|
2017-12-13 13:16:49 +01:00
|
|
|
('Class', templates.function, 'const IfcParse::type_declaration&', (), templates.simpletype_impl_class ),
|
2017-12-11 13:43:06 +01:00
|
|
|
('declaration', templates.const_function, 'const IfcParse::type_declaration&', (), templates.simpletype_impl_declaration ),
|
2017-06-05 17:26:58 +02:00
|
|
|
('', constructor, '', ('IfcEntityInstanceData* e',), templates.simpletype_impl_explicit_constructor),
|
|
|
|
|
('', constructor, '', ("%s v" % type_str,), simpletype_impl_constructor ),
|
|
|
|
|
('', templates.cast_function, type_str, (), simpletype_impl_cast )
|
2015-01-05 14:11:42 +00:00
|
|
|
))))
|
|
|
|
|
simple_type_impl.append('')
|
2015-09-08 20:40:54 +02:00
|
|
|
|
2017-12-18 15:25:09 +01:00
|
|
|
external_definitions = [("extern entity* %s_%%s_type;" % schema_name_upper) % n for n in mapping.schema.entities.keys() ] + \
|
|
|
|
|
[("extern type_declaration* %s_%%s_type;" % schema_name_upper) % n for n in mapping.schema.simpletypes.keys()]
|
2014-02-17 22:13:55 +00:00
|
|
|
|
|
|
|
|
self.str = templates.implementation % {
|
2017-12-18 15:25:09 +01:00
|
|
|
'schema_name_upper' : schema_name_upper,
|
|
|
|
|
'schema_name' : schema_name,
|
2014-02-17 22:13:55 +00:00
|
|
|
'max_id' : max_id,
|
|
|
|
|
'enumeration_functions' : cat(enumeration_functions),
|
|
|
|
|
'schema_entity_statements' : catnl(schema_entity_statements),
|
|
|
|
|
'type_name_strings' : type_name_strings,
|
|
|
|
|
'string_map_statements' : catnl(string_map_statements),
|
|
|
|
|
'simple_type_statement' : simple_type_statements,
|
2016-03-18 11:14:14 +01:00
|
|
|
'parent_type_statements' : parent_type_statements,
|
2015-01-05 14:11:42 +00:00
|
|
|
'entity_implementations' : catnl(entity_implementations),
|
2015-09-08 20:40:54 +02:00
|
|
|
'simple_type_impl' : catnl(simple_type_impl),
|
|
|
|
|
'external_definitions' : catnl(external_definitions)
|
2014-02-17 22:13:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.schema_name = mapping.schema.name.capitalize()
|
2016-02-18 13:17:15 +01:00
|
|
|
|
|
|
|
|
self.file_name = '%s.cpp'%self.schema_name
|
|
|
|
|
|
|
|
|
|
|
2014-02-17 22:13:55 +00:00
|
|
|
def __repr__(self):
|
|
|
|
|
return self.str
|
2020-03-17 11:55:28 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Generator = Implementation
|