Skip to content

Commit 7b17c2d

Browse files
committed
Make header values writable
1 parent f6f541e commit 7b17c2d

10 files changed

Lines changed: 370 additions & 165 deletions

File tree

src/examples/IfcOpenHouse.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ int main(int argc, char** argv) {
5555
// The IfcHierarchyHelper is a subclass of the regular IfcFile that provides several
5656
// convenience functions for working with geometry in IFC files.
5757
IfcHierarchyHelper file;
58-
file.filename("IfcOpenHouse.ifc");
58+
file.header().file_name().name("IfcOpenHouse.ifc");
5959

6060
// Start by adding a wall to the file, initially leaving most attributes blank.
6161
IfcSchema::IfcWallStandardCase* south_wall = new IfcSchema::IfcWallStandardCase(

src/ifcparse/IfcFile.h

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,7 @@ class IfcFile {
5151

5252
IfcSpfHeader _header;
5353

54-
std::string _filename;
55-
std::string _timestamp;
56-
std::string _author;
57-
std::string _author_email;
58-
std::string _author_organisation;
59-
60-
void initTimestamp();
54+
void setDefaultHeaderValues();
6155
public:
6256
IfcParse::IfcSpfLexer* tokens;
6357
IfcParse::IfcSpfStream* stream;
@@ -76,7 +70,11 @@ class IfcFile {
7670
template <class T>
7771
typename T::list::ptr EntitiesByType() {
7872
IfcEntityList::ptr untyped_list = EntitiesByType(T::Class());
79-
return untyped_list->as<T>();
73+
if (untyped_list) {
74+
return untyped_list->as<T>();
75+
} else {
76+
return typename T::list::ptr(new typename T::list);
77+
}
8078
}
8179

8280
/// Returns all entities in the file that match the positional argument.
@@ -110,16 +108,10 @@ class IfcFile {
110108
void AddEntity(IfcUtil::IfcBaseClass* entity);
111109
void AddEntities(IfcEntityList::ptr es);
112110

113-
void filename(const std::string& s);
114-
std::string filename() const;
115-
void timestamp(const std::string& s);
116-
std::string timestamp() const;
117-
void author(const std::string& name, const std::string& email, const std::string& organisation);
118-
std::string authorName() const;
119-
std::string authorEmail() const;
120-
std::string authorOrganisation() const;
121-
122111
const IfcSpfHeader& header() const { return _header; }
112+
IfcSpfHeader& header() { return _header; }
113+
114+
std::string createTimestamp() const;
123115

124116
bool create_latebound_entities() const { return _create_latebound_entities; }
125117
};

src/ifcparse/IfcParse.cpp

Lines changed: 73 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -420,25 +420,31 @@ EntityArgument::EntityArgument(const Token& t) {
420420
// Reads the arguments from a list of token
421421
// Aditionally, stores the ids (i.e. #[\d]+) in a vector
422422
//
423-
ArgumentList::ArgumentList(IfcSpfLexer* t, std::vector<unsigned int>& ids) {
423+
void ArgumentList::read(IfcSpfLexer* t, std::vector<unsigned int>& ids) {
424424
IfcParse::IfcFile* file = t->file;
425425

426426
Token next = t->Next();
427427
while( next.second || next.first ) {
428-
if ( TokenFunc::isOperator(next,',') ) {}
429-
else if ( TokenFunc::isOperator(next,')') ) break;
430-
else if ( TokenFunc::isOperator(next,'(') ) Push( new ArgumentList(t,ids) );
431-
else {
432-
if ( TokenFunc::isIdentifier(next) ) ids.push_back(TokenFunc::asInt(next));
433-
if ( TokenFunc::isKeyword(next) ) {
428+
if ( TokenFunc::isOperator(next,',') ) {
429+
// do nothing
430+
} else if ( TokenFunc::isOperator(next,')') ) {
431+
break;
432+
} else if ( TokenFunc::isOperator(next,'(') ) {
433+
ArgumentList* list = new ArgumentList();
434+
list->read(t, ids);
435+
push(list);
436+
} else {
437+
if ( TokenFunc::isIdentifier(next) ) {
438+
ids.push_back(TokenFunc::asInt(next));
439+
} if ( TokenFunc::isKeyword(next) ) {
434440
t->Next();
435441
try {
436-
Push ( new EntityArgument(next) );
442+
push ( new EntityArgument(next) );
437443
} catch ( IfcException& e ) {
438444
Logger::Message(Logger::LOG_ERROR,e.what());
439445
}
440446
} else {
441-
Push ( new TokenArgument(next) );
447+
push ( new TokenArgument(next) );
442448
}
443449
}
444450
next = t->Next();
@@ -461,7 +467,7 @@ IfcUtil::ArgumentType ArgumentList::type() const {
461467
}
462468
}
463469

464-
void ArgumentList::Push(Argument* l) {
470+
void ArgumentList::push(Argument* l) {
465471
list.push_back(l);
466472
}
467473

@@ -523,10 +529,22 @@ ArgumentList::operator IfcEntityListList::ptr() const {
523529
}
524530
unsigned int ArgumentList::size() const { return (unsigned int) list.size(); }
525531
Argument* ArgumentList::operator [] (unsigned int i) const {
526-
if ( i >= list.size() )
532+
if ( i >= list.size() ) {
527533
throw IfcException("Argument index out of range");
534+
}
528535
return list[i];
529536
}
537+
void ArgumentList::set(unsigned int i, Argument* argument) {
538+
while (size() < i) {
539+
push(new TokenArgument(Token(static_cast<IfcSpfLexer*>(0), '$')));
540+
}
541+
if (i < size()) {
542+
delete list[i];
543+
list[i] = argument;
544+
} else {
545+
list.push_back(argument);
546+
}
547+
}
530548
std::string ArgumentList::toString(bool upper) const {
531549
std::stringstream ss;
532550
ss << "(";
@@ -666,7 +684,8 @@ void Entity::Load(std::vector<unsigned int>& ids, bool seek) const {
666684
_type = IfcSchema::Type::FromString(TokenFunc::asString(datatype));
667685
}
668686
Token open = file->tokens->Next();
669-
args = new ArgumentList(file->tokens, ids);
687+
args = new ArgumentList();
688+
args->read(file->tokens, ids);
670689
unsigned int old_offset = file->tokens->stream->Tell();
671690
Token semilocon = file->tokens->Next();
672691
if ( ! TokenFunc::isOperator(semilocon,';') ) file->tokens->stream->Seek(old_offset);
@@ -697,7 +716,10 @@ std::string Entity::toString(bool upper) const {
697716
if ( upper ) {
698717
for (std::string::iterator p = dt.begin(); p != dt.end(); ++p ) *p = toupper(*p);
699718
}
700-
ss << "#" << _id << "=" << dt << args->toString(upper);
719+
if (!IfcSchema::Type::IsSimple(type()) || _id != 0) {
720+
ss << "#" << _id << "=";
721+
}
722+
ss << dt << args->toString(upper);
701723
return ss.str();
702724
}
703725

@@ -721,12 +743,12 @@ IfcWrite::IfcWritableEntity* Entity::isWritable() {
721743

722744
IfcFile::IfcFile(bool create_latebound_entities)
723745
: _create_latebound_entities(create_latebound_entities)
746+
, stream(0)
747+
, lastId(0)
748+
, tokens(0)
749+
, MaxId(0)
724750
{
725-
stream = 0;
726-
lastId = 0;
727-
tokens = 0;
728-
MaxId = 0;
729-
initTimestamp();
751+
setDefaultHeaderValues();
730752
}
731753

732754
//
@@ -998,25 +1020,7 @@ IfcFile::entity_by_id_t::const_iterator IfcFile::end() const {
9981020
}
9991021

10001022
std::ostream& operator<< (std::ostream& os, const IfcParse::IfcFile& f) {
1001-
os << "ISO-10303-21;" << std::endl;
1002-
os << "HEADER;" << std::endl;
1003-
os << "FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');" << std::endl;
1004-
os << "FILE_NAME("
1005-
<< static_cast<std::string>(IfcWrite::IfcCharacterEncoder(f.filename())) << ","
1006-
<< static_cast<std::string>(IfcWrite::IfcCharacterEncoder(f.timestamp())) << ",("
1007-
<< static_cast<std::string>(IfcWrite::IfcCharacterEncoder(f.authorOrganisation())) << "),("
1008-
<< static_cast<std::string>(IfcWrite::IfcCharacterEncoder(f.authorName())) << ","
1009-
<< static_cast<std::string>(IfcWrite::IfcCharacterEncoder(f.authorEmail()))
1010-
<< "),'IfcOpenShell " << IFCOPENSHELL_VERSION
1011-
<< "','IfcOpenShell " << IFCOPENSHELL_VERSION
1012-
<< "','');" << std::endl;
1013-
#ifdef USE_IFC4
1014-
os << "FILE_SCHEMA(('IFC4'));" << std::endl;
1015-
#else
1016-
os << "FILE_SCHEMA(('IFC2X3'));" << std::endl;
1017-
#endif
1018-
os << "ENDSEC;" << std::endl;
1019-
os << "DATA;" << std::endl;
1023+
f.header().write(os);
10201024

10211025
for ( IfcFile::entity_by_id_t::const_iterator it = f.begin(); it != f.end(); ++ it ) {
10221026
const IfcUtil::IfcBaseClass* e = it->second;
@@ -1029,26 +1033,20 @@ std::ostream& operator<< (std::ostream& os, const IfcParse::IfcFile& f) {
10291033
return os;
10301034
}
10311035

1032-
void IfcFile::filename(const std::string& s) { _filename = s; }
1033-
std::string IfcFile::filename() const { return _filename; }
1034-
void IfcFile::timestamp(const std::string& s) { _timestamp = s; }
1035-
std::string IfcFile::timestamp() const { return _timestamp; }
1036-
void IfcFile::author(const std::string& name, const std::string& email, const std::string& organisation) {
1037-
_author = name;
1038-
_author_email = email;
1039-
_author_organisation = organisation;
1040-
}
1041-
std::string IfcFile::authorName() const { return _author; }
1042-
std::string IfcFile::authorEmail() const { return _author_email; }
1043-
std::string IfcFile::authorOrganisation() const { return _author_organisation; }
1044-
void IfcFile::initTimestamp() {
1036+
std::string IfcFile::createTimestamp() const {
10451037
char buf[255];
1038+
10461039
time_t t;
10471040
time(&t);
1048-
struct tm * ti = localtime (&t);
1041+
1042+
struct tm* ti = localtime (&t);
1043+
1044+
std::string result = "";
10491045
if (strftime(buf,255,"%Y-%m-%dT%H:%M:%S",ti)) {
1050-
_timestamp = std::string(buf);
1046+
result = std::string(buf);
10511047
}
1048+
1049+
return result;
10521050
}
10531051

10541052
IfcEntityList::ptr IfcFile::getInverse(int instance_id, IfcSchema::Type::Enum type, int attribute_index) {
@@ -1078,4 +1076,26 @@ IfcEntityList::ptr IfcFile::getInverse(int instance_id, IfcSchema::Type::Enum ty
10781076
}
10791077

10801078
return l;
1081-
}
1079+
}
1080+
1081+
void IfcFile::setDefaultHeaderValues() {
1082+
const std::string empty_string = "";
1083+
std::vector<std::string> file_description, schema_identifiers, empty_vector;
1084+
1085+
file_description.push_back("ViewDefinition [CoordinationView]");
1086+
schema_identifiers.push_back(IfcSchema::Identifier);
1087+
1088+
header().file_description().description(file_description);
1089+
header().file_description().implementation_level("2;1");
1090+
1091+
header().file_name().name(empty_string);
1092+
header().file_name().time_stamp(createTimestamp());
1093+
header().file_name().author(empty_vector);
1094+
header().file_name().organization(empty_vector);
1095+
header().file_name().preprocessor_version("IfcOpenShell " IFCOPENSHELL_VERSION);
1096+
header().file_name().originating_system("IfcOpenShell " IFCOPENSHELL_VERSION);
1097+
header().file_name().authorization(empty_string);
1098+
1099+
header().file_schema().schema_identifiers(schema_identifiers);
1100+
}
1101+

src/ifcparse/IfcParse.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,12 @@ namespace IfcParse {
122122
class ArgumentList: public Argument {
123123
private:
124124
std::vector<Argument*> list;
125-
void Push(Argument* l);
125+
void push(Argument* l);
126126
public:
127-
ArgumentList(IfcSpfLexer* t, std::vector<unsigned int>& ids);
128127
~ArgumentList();
129128

129+
void read(IfcSpfLexer* t, std::vector<unsigned int>& ids);
130+
130131
IfcUtil::ArgumentType type() const;
131132

132133
operator int() const;
@@ -140,7 +141,10 @@ namespace IfcParse {
140141
operator IfcEntityList::ptr() const;
141142
operator IfcEntityListList::ptr() const;
142143
unsigned int size() const;
144+
143145
Argument* operator [] (unsigned int i) const;
146+
void set(unsigned int i, Argument*);
147+
144148
std::string toString(bool upper=false) const;
145149
bool isNull() const;
146150
};
@@ -206,7 +210,7 @@ namespace IfcParse {
206210
/// ============================
207211
class Entity : public IfcAbstractEntity {
208212
private:
209-
mutable Argument* args;
213+
mutable ArgumentList* args;
210214
mutable IfcSchema::Type::Enum _type;
211215
public:
212216
/// The EXPRESS ENTITY_INSTANCE_NAME

src/ifcparse/IfcSpfHeader.cpp

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,17 @@ void IfcSpfHeader::read() {
6262
readTerminal(HEADER, TRAILING_SEMICOLON);
6363

6464
readTerminal(FILE_DESCRIPTION, TRAILING_PAREN);
65+
delete _file_description;
6566
_file_description = new FileDescription(_lexer);
6667
readSemicolon();
6768

6869
readTerminal(FILE_NAME, TRAILING_PAREN);
70+
delete _file_name;
6971
_file_name = new FileName(_lexer);
7072
readSemicolon();
7173

7274
readTerminal(FILE_SCHEMA, TRAILING_PAREN);
75+
delete _file_schema;
7376
_file_schema = new FileSchema(_lexer);
7477
readSemicolon();
7578
}
@@ -83,26 +86,65 @@ bool IfcSpfHeader::tryRead() {
8386
}
8487
}
8588

86-
const FileDescription& IfcSpfHeader::file_description() {
89+
void IfcSpfHeader::write(std::ostream& os) const {
90+
os << ISO_10303_21 << ";" << "\n";
91+
os << HEADER << ";" << "\n";
92+
os << file_description().toString(true) << "\n";
93+
os << file_name().toString(true) << "\n";
94+
os << file_schema().toString(true) << "\n";
95+
os << ENDSEC << ";" << "\n";
96+
os << DATA << ";" << "\n";
97+
}
98+
99+
100+
const FileDescription& IfcSpfHeader::file_description() const {
101+
if (_file_description) {
102+
return *_file_description;
103+
} else {
104+
throw IfcException("File description not set");
105+
}
106+
}
107+
108+
const FileName& IfcSpfHeader::file_name() const {
109+
if (_file_name) {
110+
return *_file_name;
111+
} else {
112+
throw IfcException("File name not set");
113+
}
114+
}
115+
116+
const FileSchema& IfcSpfHeader::file_schema() const {
117+
if (_file_schema) {
118+
return *_file_schema;
119+
} else {
120+
throw IfcException("File schema not set");
121+
}
122+
}
123+
124+
FileDescription& IfcSpfHeader::file_description() {
87125
if (_file_description) {
88126
return *_file_description;
89127
} else {
90-
throw IfcException("File description not read");
128+
throw IfcException("File description not set");
91129
}
92130
}
93131

94-
const FileName& IfcSpfHeader::file_name() {
132+
FileName& IfcSpfHeader::file_name() {
95133
if (_file_name) {
96134
return *_file_name;
97135
} else {
98-
throw IfcException("File name not read");
136+
throw IfcException("File name not set");
99137
}
100138
}
101139

102-
const FileSchema& IfcSpfHeader::file_schema() {
140+
FileSchema& IfcSpfHeader::file_schema() {
103141
if (_file_schema) {
104142
return *_file_schema;
105143
} else {
106-
throw IfcException("File schema not read");
144+
throw IfcException("File schema not set");
107145
}
108146
}
147+
148+
FileDescription::FileDescription(IfcSpfLexer* lexer) : HeaderEntity(FILE_DESCRIPTION, lexer) {}
149+
FileName::FileName(IfcSpfLexer* lexer) : HeaderEntity(FILE_NAME, lexer) {}
150+
FileSchema::FileSchema(IfcSpfLexer* lexer) : HeaderEntity(FILE_SCHEMA, lexer) {}

0 commit comments

Comments
 (0)