mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-15 18:14:08 +00:00
String pooling and modern initialization in schema
This commit is contained in:
@@ -117,8 +117,26 @@ class LateBoundSchemaInstantiator:
|
|||||||
elem.this.disown()
|
elem.this.disown()
|
||||||
|
|
||||||
|
|
||||||
|
class string_pool:
|
||||||
|
def __init__(self, fn):
|
||||||
|
self.di = {}
|
||||||
|
self.fn = fn
|
||||||
|
def append(self, v):
|
||||||
|
def _():
|
||||||
|
if i := self.di.get(v):
|
||||||
|
return i
|
||||||
|
else:
|
||||||
|
i = len(self.di)
|
||||||
|
self.di[v] = i
|
||||||
|
return i
|
||||||
|
return self.fn(_())
|
||||||
|
def __iter__(self):
|
||||||
|
return iter(self.di.keys())
|
||||||
|
|
||||||
|
|
||||||
class EarlyBoundCodeWriter:
|
class EarlyBoundCodeWriter:
|
||||||
def __init__(self, schema_name):
|
def __init__(self, schema_name):
|
||||||
|
self.strings = string_pool(lambda i: "strings[%d]" % i)
|
||||||
self.schema_name = schema_name
|
self.schema_name = schema_name
|
||||||
self.schema_name_title = schema_name.capitalize()
|
self.schema_name_title = schema_name.capitalize()
|
||||||
|
|
||||||
@@ -126,7 +144,9 @@ class EarlyBoundCodeWriter:
|
|||||||
"",
|
"",
|
||||||
'#include "../ifcparse/IfcSchema.h"',
|
'#include "../ifcparse/IfcSchema.h"',
|
||||||
'#include "../ifcparse/%(schema_name_title)s.h"' % self.__dict__,
|
'#include "../ifcparse/%(schema_name_title)s.h"' % self.__dict__,
|
||||||
|
'#include <string>',
|
||||||
"",
|
"",
|
||||||
|
'using namespace std::string_literals;',
|
||||||
"using namespace IfcParse;",
|
"using namespace IfcParse;",
|
||||||
"",
|
"",
|
||||||
]
|
]
|
||||||
@@ -156,6 +176,8 @@ class EarlyBoundCodeWriter:
|
|||||||
num_names = len(self.names)
|
num_names = len(self.names)
|
||||||
self.statements.append("declaration* %(schema_name)s_types[%(num_names)d] = {nullptr};" % locals())
|
self.statements.append("declaration* %(schema_name)s_types[%(num_names)d] = {nullptr};" % locals())
|
||||||
|
|
||||||
|
self.statements.append("{string_pool_placeholder}")
|
||||||
|
|
||||||
self.statements.append("{factory_placeholder}")
|
self.statements.append("{factory_placeholder}")
|
||||||
|
|
||||||
self.statements.append(
|
self.statements.append(
|
||||||
@@ -175,117 +197,97 @@ __attribute__((optnone))
|
|||||||
def typedef(self, name, declared_type):
|
def typedef(self, name, declared_type):
|
||||||
schema_name = self.schema_name
|
schema_name = self.schema_name
|
||||||
index_in_schema = self.names.index(name)
|
index_in_schema = self.names.index(name)
|
||||||
|
ref = self.strings.append(name)
|
||||||
self.statements.append(
|
self.statements.append(
|
||||||
' %(schema_name)s_types[%(index_in_schema)d] = new type_declaration("%(name)s", %(index_in_schema)d, %(declared_type)s);'
|
' %(schema_name)s_types[%(index_in_schema)d] = new type_declaration(%(ref)s, %(index_in_schema)d, %(declared_type)s);'
|
||||||
% locals()
|
% locals()
|
||||||
)
|
)
|
||||||
|
|
||||||
def enumeration(self, name, enum):
|
def enumeration(self, name, enum):
|
||||||
schema_name = self.schema_name
|
schema_name = self.schema_name
|
||||||
index_in_schema = self.names.index(name)
|
index_in_schema = self.names.index(name)
|
||||||
self.statements.append(" {")
|
ref = self.strings.append(name)
|
||||||
self.statements.append(" std::vector<std::string> items; items.reserve(%d);" % len(enum.values))
|
items = ",".join(self.strings.append(v) for v in sorted(enum.values))
|
||||||
self.statements.extend(map(lambda v: ' items.push_back("%s");' % v, sorted(enum.values)))
|
|
||||||
self.statements.append(
|
self.statements.append(
|
||||||
' %(schema_name)s_types[%(index_in_schema)d] = new enumeration_type("%(name)s", %(index_in_schema)d, items);'
|
' %(schema_name)s_types[%(index_in_schema)d] = new enumeration_type(%(ref)s, %(index_in_schema)d, {%(items)s});'
|
||||||
% locals()
|
% locals()
|
||||||
)
|
)
|
||||||
self.statements.append(" }")
|
|
||||||
|
|
||||||
def entity(self, name, type):
|
def entity(self, name, type):
|
||||||
schema_name = self.schema_name
|
schema_name = self.schema_name
|
||||||
index_in_schema = self.names.index(name)
|
index_in_schema = self.names.index(name)
|
||||||
|
ref = self.strings.append(name)
|
||||||
supertype = "0" if len(type.supertypes) == 0 else "%s_types[%d]" % (self.schema_name, self.names.index(type.supertypes[0]))
|
supertype = "0" if len(type.supertypes) == 0 else "%s_types[%d]" % (self.schema_name, self.names.index(type.supertypes[0]))
|
||||||
is_abstract = "true" if type.abstract else "false"
|
is_abstract = "true" if type.abstract else "false"
|
||||||
self.statements.append(
|
self.statements.append(
|
||||||
' %(schema_name)s_types[%(index_in_schema)d] = new entity("%(name)s", %(is_abstract)s, %(index_in_schema)d, (entity*) %(supertype)s);'
|
' %(schema_name)s_types[%(index_in_schema)d] = new entity(%(ref)s, %(is_abstract)s, %(index_in_schema)d, (entity*) %(supertype)s);'
|
||||||
% locals()
|
% locals()
|
||||||
)
|
)
|
||||||
|
|
||||||
def select(self, name, type):
|
def select(self, name, type):
|
||||||
schema_name = self.schema_name
|
schema_name = self.schema_name
|
||||||
index_in_schema = self.names.index(name)
|
index_in_schema = self.names.index(name)
|
||||||
self.statements.append(" {")
|
ref = self.strings.append(name)
|
||||||
self.statements.append(" std::vector<const declaration*> items; items.reserve(%d);" % len(type.values))
|
items = ",".join(
|
||||||
self.statements.extend(
|
map(lambda v: "%s_types[%d]" % (self.schema_name, self.names.index(v)), sorted(map(str, type.values)))
|
||||||
map(lambda v: " items.push_back(%s_types[%d]);" % (self.schema_name, self.names.index(v)), sorted(map(str, type.values)))
|
|
||||||
)
|
)
|
||||||
self.statements.append(
|
self.statements.append(
|
||||||
' %(schema_name)s_types[%(index_in_schema)d] = new select_type("%(name)s", %(index_in_schema)d, items);'
|
' %(schema_name)s_types[%(index_in_schema)d] = new select_type(%(ref)s, %(index_in_schema)d, {%(items)s});'
|
||||||
% locals()
|
% locals()
|
||||||
)
|
)
|
||||||
self.statements.append(" }")
|
|
||||||
|
|
||||||
def entity_attributes(self, name, attribute_definitions, is_derived):
|
def entity_attributes(self, name, attribute_definitions, is_derived):
|
||||||
index_in_schema = self.names.index(name)
|
|
||||||
schema_name = self.schema_name
|
schema_name = self.schema_name
|
||||||
self.statements.append(" {")
|
index_in_schema = self.names.index(name)
|
||||||
self.statements.append(
|
def _():
|
||||||
" std::vector<const attribute*> attributes; attributes.reserve(%d);" % len(attribute_definitions)
|
index_in_schema = self.names.index(name)
|
||||||
)
|
schema_name = self.schema_name
|
||||||
for attr_name, decl_type, optional in attribute_definitions:
|
for attr_name, decl_type, optional in attribute_definitions:
|
||||||
optional_cpp = str(optional).lower()
|
attr_name_ref = self.strings.append(attr_name)
|
||||||
self.statements.append(
|
optional_cpp = str(optional).lower()
|
||||||
' attributes.push_back(new attribute("%(attr_name)s", %(decl_type)s, %(optional_cpp)s));'
|
yield 'new attribute(%(attr_name_ref)s, %(decl_type)s, %(optional_cpp)s)' % locals()
|
||||||
% locals()
|
attributes = ",".join(_())
|
||||||
)
|
derived = ",".join(map(lambda b: str(b).lower(), is_derived))
|
||||||
self.statements.append(" std::vector<bool> derived; derived.reserve(%d);" % len(is_derived))
|
self.statements.append(" ((entity*)%(schema_name)s_types[%(index_in_schema)d])->set_attributes({%(attributes)s}, {%(derived)s});" % locals())
|
||||||
self.statements.append(
|
|
||||||
" " + " ".join(map(lambda b: "derived.push_back(%s);" % str(b).lower(), is_derived))
|
|
||||||
)
|
|
||||||
self.statements.append(" ((entity*)%(schema_name)s_types[%(index_in_schema)d])->set_attributes(attributes, derived);" % locals())
|
|
||||||
self.statements.append(" }")
|
|
||||||
|
|
||||||
def inverse_attributes(self, name, inv_attrs):
|
def inverse_attributes(self, name, inv_attrs):
|
||||||
schema_name = self.schema_name
|
schema_name = self.schema_name
|
||||||
index_in_schema = self.names.index(name)
|
index_in_schema = self.names.index(name)
|
||||||
self.statements.append(" {")
|
def _():
|
||||||
self.statements.append(
|
schema_name = self.schema_name
|
||||||
" std::vector<const inverse_attribute*> attributes; attributes.reserve(%d);" % len(inv_attrs)
|
index_in_schema = self.names.index(name)
|
||||||
)
|
for attr_name, aggr_type, bound1, bound2, entity_ref, attribute_entity, attribute_entity_index in inv_attrs:
|
||||||
for attr_name, aggr_type, bound1, bound2, entity_ref, attribute_entity, attribute_entity_index in inv_attrs:
|
attr_name_ref = self.strings.append(attr_name)
|
||||||
opposite_index_in_schema = self.names.index(entity_ref)
|
opposite_index_in_schema = self.names.index(entity_ref)
|
||||||
opposite1 = '%(schema_name)s_types[%(opposite_index_in_schema)d]' % locals()
|
opposite1 = '%(schema_name)s_types[%(opposite_index_in_schema)d]' % locals()
|
||||||
opposite_index_in_schema = self.names.index(attribute_entity)
|
opposite_index_in_schema = self.names.index(attribute_entity)
|
||||||
opposite2 = '%(schema_name)s_types[%(opposite_index_in_schema)d]' % locals()
|
opposite2 = '%(schema_name)s_types[%(opposite_index_in_schema)d]' % locals()
|
||||||
self.statements.append(
|
yield 'new inverse_attribute(%(attr_name_ref)s, inverse_attribute::%(aggr_type)s_type, %(bound1)d, %(bound2)d, ((entity*) %(opposite1)s), ((entity*) %(opposite2)s)->attributes()[%(attribute_entity_index)d])' % locals()
|
||||||
' attributes.push_back(new inverse_attribute("%(attr_name)s", inverse_attribute::%(aggr_type)s_type, %(bound1)d, %(bound2)d, ((entity*) %(opposite1)s), ((entity*) %(opposite2)s)->attributes()[%(attribute_entity_index)d]));'
|
attributes = ",".join(_())
|
||||||
% locals()
|
self.statements.append(" ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_inverse_attributes({%(attributes)s});" % locals())
|
||||||
)
|
|
||||||
self.statements.append(" ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_inverse_attributes(attributes);" % locals())
|
|
||||||
self.statements.append(" }")
|
|
||||||
|
|
||||||
def entity_subtypes(self, name, tys):
|
def entity_subtypes(self, name, tys):
|
||||||
schema_name = self.schema_name
|
schema_name = self.schema_name
|
||||||
index_in_schema = self.names.index(name)
|
index_in_schema = self.names.index(name)
|
||||||
self.statements.append(" {")
|
subtypes = ",".join(map(lambda t: ("((entity*) %%(schema_name)s_types[%d])" % self.names.index(t)), tys)) % locals()
|
||||||
self.statements.append(" std::vector<const entity*> defs; defs.reserve(%d);" % len(tys))
|
self.statements.append(" ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_subtypes({%(subtypes)s});" % locals())
|
||||||
self.statements.append(
|
|
||||||
(" " + "".join(map(lambda t: ("defs.push_back(((entity*) %%(schema_name)s_types[%d]));" % self.names.index(t)), tys))) % locals()
|
|
||||||
)
|
|
||||||
self.statements.append(" ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_subtypes(defs);" % locals())
|
|
||||||
self.statements.append(" }")
|
|
||||||
|
|
||||||
def finalize(self, can_be_instantiated_set):
|
def finalize(self, can_be_instantiated_set):
|
||||||
schema_name = self.schema_name
|
schema_name = self.schema_name
|
||||||
schema_name_title = self.schema_name.capitalize()
|
schema_name_title = self.schema_name.capitalize()
|
||||||
|
def _():
|
||||||
num_declarations = len(self.names)
|
schema_name = self.schema_name
|
||||||
|
schema_name_title = self.schema_name.capitalize()
|
||||||
self.statements.append("")
|
for type_name in self.names:
|
||||||
|
index_in_schema = self.names.index(type_name)
|
||||||
|
yield "%(schema_name)s_types[%(index_in_schema)d]" % locals()
|
||||||
|
declarations = ",".join(_())
|
||||||
|
schema_name_ref = self.strings.append(schema_name)
|
||||||
self.statements.append(
|
self.statements.append(
|
||||||
" std::vector<const declaration*> declarations; declarations.reserve(%(num_declarations)d);" % locals()
|
' return new schema_definition(%(schema_name_ref)s, {%(declarations)s}, new %(schema_name)s_instance_factory());'
|
||||||
)
|
|
||||||
for type_name in self.names:
|
|
||||||
index_in_schema = self.names.index(type_name)
|
|
||||||
self.statements.append(" declarations.push_back(%(schema_name)s_types[%(index_in_schema)d]);" % locals())
|
|
||||||
|
|
||||||
self.statements.append(
|
|
||||||
' return new schema_definition("%(schema_name)s", declarations, new %(schema_name)s_instance_factory());'
|
|
||||||
% locals()
|
% locals()
|
||||||
)
|
)
|
||||||
|
self.statements.append("}");
|
||||||
self.statements.extend(("}", ""))
|
|
||||||
|
|
||||||
self.statements.append(
|
self.statements.append(
|
||||||
"""
|
"""
|
||||||
@@ -348,6 +350,14 @@ class %(schema_name)s_instance_factory : public IfcParse::instance_factory {
|
|||||||
% locals()
|
% locals()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
""
|
||||||
|
self.statements[self.statements.index("{string_pool_placeholder}")] = (
|
||||||
|
"""
|
||||||
|
const std::string strings[] = {%s};
|
||||||
|
"""
|
||||||
|
% ",".join(map(lambda s: '"%s"s' % s, self.strings))
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "\n".join(self.statements)
|
return "\n".join(self.statements)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user