@@ -99,6 +99,8 @@ def get():
9999selectable_simple_types = set ()
100100argument_count = {}
101101parent_relations = {}
102+ argument_names_and_types = {}
103+ entity_map = {}
102104
103105#
104106# Since inherited arguments of Express entities are placed in sequence before the non-inherited once, we need to keep track of how many inherited arguments exist
@@ -111,6 +113,15 @@ def argument_start(c):
111113 i += argument_count [c ] if c in argument_count else 0
112114 if not (c in parent_relations ): break
113115 return i
116+
117+ def parent_arguments (c ):
118+ if c not in parent_relations : return []
119+ l = []
120+ while True :
121+ c = parent_relations [c ]
122+ i += argument_count [c ] if c in argument_count else 0
123+ if not (c in parent_relations ): break
124+ return []
114125
115126#
116127# Several classes to generate code from Express types and entities
@@ -127,6 +138,7 @@ def __str__(self):
127138 return "SHARED_PTR< IfcTemplatedEntityList<IfcAbstractSelect> >"
128139 else :
129140 return "std::vector<%(type)s> /*[%(lower)s:%(upper)s]*/" % self .__dict__
141+ def is_shared_ptr (self ): return self .type in entity_names or self .type in selections
130142 def type_enum (self ):
131143 if self .type in simple_types :
132144 t = simple_types [self .type ].type_enum ()
@@ -199,12 +211,12 @@ def __init__(self,l):
199211 def __str__ (self ):
200212 global generator_mode
201213 if generator_mode == 'HEADER' and isinstance (self .type ,EnumType ):
202- return ("namespace %(name)s {\n %(comment)stypedef %(type)s %(name)s;\n std::string ToString(%(name)s v);\n %(name)s FromString(const std::string& s);\n }" % self .__dict__ )% self .__dict__
214+ return ("namespace %(name)s {\n %(comment)stypedef %(type)s %(name)s;\n const char* ToString(%(name)s v);\n %(name)s FromString(const std::string& s);\n }" % self .__dict__ )% self .__dict__
203215 elif generator_mode == 'HEADER' :
204216 return "%stypedef %s %s;" % (self .comment ,self .type ,self .name )
205217 elif generator_mode == 'SOURCE' and isinstance (self .type ,EnumType ):
206218 generator_mode = 'SOURCE_TO'
207- s = "std::string %(name)s::ToString(%(name)s v) {\n if ( v < 0 || v >= %(len)d ) throw IfcException(\" Unable to find find keyword in schema\" );\n const char* names[] = %(type)s;\n return names[v];\n }\n " % self .__dict__
219+ s = "const char* %(name)s::ToString(%(name)s v) {\n if ( v < 0 || v >= %(len)d ) throw IfcException(\" Unable to find find keyword in schema\" );\n const char* names[] = %(type)s;\n return names[v];\n }\n " % self .__dict__
208220 generator_mode = 'SOURCE_FROM'
209221 s += ("%(name)s::%(name)s %(name)s::FromString(const std::string& s) {\n %(type)s throw IfcException(\" Unable to find find keyword in schema\" );\n }" % self .__dict__ )% self .__dict__
210222 generator_mode = 'SOURCE'
@@ -214,6 +226,12 @@ def type_enum(self):
214226class Argument (object ):
215227 def __init__ (self ,l ):
216228 self .name , self .optional , self .type = l
229+ def is_enum (self ): return str (self .type ) in enumerations
230+ def type_str (self ):
231+ if str (self .type ) in entity_names :
232+ return "%(type)s*" % self .__dict__
233+ else :
234+ return "%(type)s::%(type)s" % self .__dict__ if self .is_enum () else self .type
217235class ArgumentList :
218236 def __init__ (self ,l ):
219237 self .l = [Argument (a ) for a in l ]
@@ -224,11 +242,12 @@ def __str__(self):
224242 argv = self .argstart
225243 for a in self .l :
226244 class_name = indent = comment = optional_comment = ""
245+ is_array = isinstance (a .type ,ArrayType ) and a .type .is_shared_ptr ()
227246 return_type = str (a .type )
228247 if generator_mode == 'SOURCE' :
229248 class_name = "%(class_name)s::"
230249 if isinstance (a .type ,BinaryType ) or (isinstance (a .type ,ArrayType ) and isinstance (a .type .type ,BinaryType )):
231- function_body = " { throw; /* Not implemented argument 7 */ }"
250+ function_body = " { throw; /* Not implemented argument*/ }"
232251 elif isinstance (a .type ,ArrayType ) and str (a .type .type ) in entity_names :
233252 function_body = " { RETURN_AS_LIST(%s,%d) }" % (a .type .type ,argv )
234253 elif isinstance (a .type ,ArrayType ) and str (a .type .type ) in selections :
@@ -240,9 +259,15 @@ def __str__(self):
240259 else :
241260 function_body = " { return *entity->getArgument(%d); }" % argv
242261 function_body2 = " { return !entity->getArgument(%d)->isNull(); }" % argv
262+ if isinstance (a .type ,BinaryType ) or (isinstance (a .type ,ArrayType ) and isinstance (a .type .type ,BinaryType )):
263+ function_body3 = " { if ( ! entity->isWritable() ) { throw; } }"
264+ elif return_type in enumerations :
265+ function_body3 = " { if ( ! entity->isWritable() ) { entity = new IfcWritableEntity(entity); } ((IfcWritableEntity*)entity)->setArgument(%d,v%s,%s::ToString(v)); }" % (argv ,"->generalize()" if is_array else "" ,return_type )
266+ else :
267+ function_body3 = " { if ( ! entity->isWritable() ) { entity = new IfcWritableEntity(entity); } ((IfcWritableEntity*)entity)->setArgument(%d,v%s); }" % (argv ,"->generalize()" if is_array else "" )
243268 else :
244269 indent = " "
245- function_body = function_body2 = ";"
270+ function_body = function_body2 = function_body3 = ";"
246271 comment = IfcDocumentation .description ((self .class_name ,a .name ))
247272 comment = comment + "\n " if comment else ''
248273 comment = comment .replace ("///" ,"%s///" % indent )
@@ -253,6 +278,7 @@ def __str__(self):
253278 elif ( str (a .type ) in entity_names ):
254279 return_type = "%(type)s*" % a .__dict__
255280 s += "\n %s%s%s %s%s()%s" % (comment ,indent ,return_type ,class_name ,a .name ,function_body )
281+ s += "\n %svoid %sset%s(%s v)%s" % (indent ,class_name ,a .name ,return_type ,function_body3 )
256282 argv += 1
257283
258284 if generator_mode == 'HEADER' :
@@ -304,8 +330,27 @@ def __init__(self,l):
304330 entity_names .add (self .class_name )
305331 parent_relations [self .class_name ] = self .parent_class
306332 argument_count [self .class_name ] = len (self .arguments )
333+ entity_map [self .class_name ] = self
334+ def get_constructor_args (self ):
335+ s = entity_map [self .parent_class ].get_constructor_args () if self .parent_class else []
336+ i = len (s ) + 1
337+ s += ["%s v%d_%s" % (a .type_str (),b + i ,a .name ) for a ,b in zip (self .arguments .l ,range (len (self .arguments )))]
338+ return s
339+ def get_constructor_implementation (self ):
340+ s = entity_map [self .parent_class ].get_constructor_implementation () if self .parent_class else []
341+ i = len (s ) + 1
342+ b = 0
343+ for a in self .arguments .l :
344+ generalize = "->generalize()" if (isinstance (a .type ,ArrayType ) and a .type .is_shared_ptr ()) else ""
345+ if isinstance (a .type ,BinaryType ) or (isinstance (a .type ,ArrayType ) and isinstance (a .type .type ,BinaryType )):
346+ continue
347+ s .append ("e->setArgument(%d,v%d_%s%s)" % (b + i - 1 ,b + i ,a .name ,generalize ))
348+ b += 1
349+ return s #"; ".join(s)
307350 def __str__ (self ):
308- if generator_mode == 'HEADER' :
351+ self .constructor_args_list = self .get_constructor_args ()
352+ self .constructor_args = ", " .join (self .constructor_args_list )
353+ if generator_mode == 'HEADER' :
309354 comment = IfcDocumentation .description (self .class_name )
310355 comment = comment + "\n " if comment else ''
311356 return "%sclass %s : public %s {\n public:%s%s%s\n };" % (comment ,self .class_name ,
@@ -316,18 +361,22 @@ def __str__(self):
316361 "\n Type::Enum type() const;" +
317362 "\n static Type::Enum Class();" +
318363 "\n %(class_name)s (IfcAbstractEntityPtr e = IfcAbstractEntityPtr());" +
364+ ("\n %(class_name)s (%(constructor_args)s);" if len (self .constructor_args_list ) else "" )+
319365 "\n typedef %(class_name)s* ptr;" +
320366 "\n typedef SHARED_PTR< IfcTemplatedEntityList<%(class_name)s> > list;" +
321367 "\n typedef IfcTemplatedEntityList<%(class_name)s>::it it;" )% self .__dict__
322368 )
323369 elif generator_mode == 'SOURCE' :
324370 self .arguments .argstart = argument_start (self .class_name )
371+ self .constructor_implementation = "; " .join (self .get_constructor_implementation ())
325372 return (("\n // Function implementations for %(class_name)s" + str (self .arguments )+ str (self .inverse )+
326373 ("\n bool %(class_name)s::is(Type::Enum v) const { return v == Type::%(class_name)s; }" if self .parent_class is None else
327374 "\n bool %(class_name)s::is(Type::Enum v) const { return v == Type::%(class_name)s || %(parent_class)s::is(v); }" )+
328375 "\n Type::Enum %(class_name)s::type() const { return Type::%(class_name)s; }" +
329376 "\n Type::Enum %(class_name)s::Class() { return Type::%(class_name)s; }" +
330- "\n %(class_name)s::%(class_name)s(IfcAbstractEntityPtr e) { if (!is(Type::%(class_name)s)) throw IfcException(\" Unable to find find keyword in schema\" ); entity = e; }" )% self .__dict__ )% self .__dict__
377+ "\n %(class_name)s::%(class_name)s(IfcAbstractEntityPtr e) { if (!is(Type::%(class_name)s)) throw IfcException(\" Unable to find find keyword in schema\" ); entity = e; }" +
378+ ("\n %(class_name)s::%(class_name)s(%(constructor_args)s) { IfcWritableEntity* e = new IfcWritableEntity(Class()); %(constructor_implementation)s; entity = e; }" if len (self .constructor_args_list ) else "" )
379+ )% self .__dict__ )% self .__dict__
331380
332381
333382from funcparserlib .parser import a , skip , many , maybe , some
@@ -462,6 +511,7 @@ def __str__(self):
462511 Enum Parent(Enum v);
463512 Enum FromString(const std::string& s);
464513 std::string ToString(Enum v);
514+ bool IsSimple(Enum v);
465515}
466516
467517}
@@ -505,9 +555,12 @@ def __str__(self):
505555
506556print >> cpp_file , """#include "%(schema)s.h"
507557#include "IfcException.h"
558+ #include "IfcWrite.h"
559+ #include "IfcWritableEntity.h"
508560
509561using namespace %(schema)s;
510562using namespace IfcParse;
563+ using namespace IfcWrite;
511564
512565IfcSchemaEntity %(schema)s::SchemaEntity(IfcAbstractEntityPtr e) {
513566 switch(e->type()){""" % {'schema' :schema_version }
@@ -552,6 +605,10 @@ def __str__(self):
552605print >> cpp_file , " return (Enum)-1;"
553606print >> cpp_file , "}"
554607
608+ print >> cpp_file , "bool Type::IsSimple(Enum v){"
609+ print >> cpp_file , " return v == Type::%s;" % " || v == Type::" .join (simple_enumerations )
610+ print >> cpp_file , "}"
611+
555612for t in [T for T in types if isinstance (T .type ,EnumType )]:
556613 print >> cpp_file , t
557614for e in entities : print >> cpp_file , e ,
0 commit comments