mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 14:41:25 +00:00
Parse the spf header and check schema_identifiers against compiled schema
This commit is contained in:
@@ -133,6 +133,7 @@ ADD_LIBRARY(IfcParse STATIC
|
|||||||
../src/ifcparse/IfcHierarchyHelper.cpp
|
../src/ifcparse/IfcHierarchyHelper.cpp
|
||||||
../src/ifcparse/IfcLateBoundEntity.cpp
|
../src/ifcparse/IfcLateBoundEntity.cpp
|
||||||
../src/ifcparse/IfcParse.cpp
|
../src/ifcparse/IfcParse.cpp
|
||||||
|
../src/ifcparse/IfcSpfHeader.cpp
|
||||||
../src/ifcparse/IfcUtil.cpp
|
../src/ifcparse/IfcUtil.cpp
|
||||||
../src/ifcparse/IfcWrite.cpp
|
../src/ifcparse/IfcWrite.cpp
|
||||||
)
|
)
|
||||||
@@ -220,6 +221,7 @@ SET(include_files_parse
|
|||||||
../src/ifcparse/IfcHierarchyHelper.h
|
../src/ifcparse/IfcHierarchyHelper.h
|
||||||
../src/ifcparse/IfcLateBoundEntity.h
|
../src/ifcparse/IfcLateBoundEntity.h
|
||||||
../src/ifcparse/IfcParse.h
|
../src/ifcparse/IfcParse.h
|
||||||
|
../src/ifcparse/IfcSpfHeader.h
|
||||||
../src/ifcparse/IfcSpfStream.h
|
../src/ifcparse/IfcSpfStream.h
|
||||||
../src/ifcparse/IfcUtil.h
|
../src/ifcparse/IfcUtil.h
|
||||||
../src/ifcparse/IfcWritableEntity.h
|
../src/ifcparse/IfcWritableEntity.h
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ header = """
|
|||||||
|
|
||||||
namespace %(schema_name)s {
|
namespace %(schema_name)s {
|
||||||
|
|
||||||
|
const char* const Identifier = "%(schema_name_upper)s";
|
||||||
|
|
||||||
// Forward definitions
|
// Forward definitions
|
||||||
%(forward_definitions)s
|
%(forward_definitions)s
|
||||||
|
|
||||||
|
|||||||
@@ -80,8 +80,9 @@ class file(object):
|
|||||||
self.wrapped_data.add(e.wrapped_data)
|
self.wrapped_data.add(e.wrapped_data)
|
||||||
self.instances.append(e)
|
self.instances.append(e)
|
||||||
return e
|
return e
|
||||||
def __getattr__(self,attr):
|
def __getattr__(self, attr):
|
||||||
if attr[0:6] == 'create': return functools.partial(self.create_entity,attr[6:])
|
if attr[0:6] == 'create': return functools.partial(self.create_entity,attr[6:])
|
||||||
|
else: return getattr(self.wrapped_data, attr)
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if isinstance(key, int):
|
if isinstance(key, int):
|
||||||
return entity_instance(self.wrapped_data.by_id(key))
|
return entity_instance(self.wrapped_data.by_id(key))
|
||||||
@@ -89,8 +90,6 @@ class file(object):
|
|||||||
return entity_instance(self.wrapped_data.by_guid(key))
|
return entity_instance(self.wrapped_data.by_guid(key))
|
||||||
def by_type(self, type):
|
def by_type(self, type):
|
||||||
return [entity_instance(e) for e in self.wrapped_data.by_type(type)]
|
return [entity_instance(e) for e in self.wrapped_data.by_type(type)]
|
||||||
def write(self, fn):
|
|
||||||
self.wrapped_data.write(fn)
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter(self[id] for id in self.wrapped_data.entity_names())
|
return iter(self[id] for id in self.wrapped_data.entity_names())
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
* *
|
* *
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef USE_IFC4
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "../ifcparse/Ifc2x3.h"
|
#include "../ifcparse/Ifc2x3.h"
|
||||||
@@ -4253,3 +4255,5 @@ void Type::PopulateDerivedFields(IfcWrite::IfcWritableEntity* e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -24,6 +24,8 @@
|
|||||||
* *
|
* *
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifdef USE_IFC4
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "../ifcparse/Ifc4.h"
|
#include "../ifcparse/Ifc4.h"
|
||||||
@@ -4943,3 +4945,5 @@ void Type::PopulateDerivedFields(IfcWrite::IfcWritableEntity* e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -23,6 +23,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "../ifcparse/IfcParse.h"
|
#include "../ifcparse/IfcParse.h"
|
||||||
|
#include "../ifcparse/IfcSpfHeader.h"
|
||||||
|
|
||||||
namespace IfcParse {
|
namespace IfcParse {
|
||||||
|
|
||||||
@@ -48,6 +49,8 @@ private:
|
|||||||
unsigned int lastId;
|
unsigned int lastId;
|
||||||
unsigned int MaxId;
|
unsigned int MaxId;
|
||||||
|
|
||||||
|
IfcSpfHeader _header;
|
||||||
|
|
||||||
std::string _filename;
|
std::string _filename;
|
||||||
std::string _timestamp;
|
std::string _timestamp;
|
||||||
std::string _author;
|
std::string _author;
|
||||||
@@ -56,7 +59,7 @@ private:
|
|||||||
|
|
||||||
void initTimestamp();
|
void initTimestamp();
|
||||||
public:
|
public:
|
||||||
IfcParse::Tokens* tokens;
|
IfcParse::IfcSpfLexer* tokens;
|
||||||
IfcParse::IfcSpfStream* stream;
|
IfcParse::IfcSpfStream* stream;
|
||||||
|
|
||||||
IfcFile(bool create_latebound_entities = false);
|
IfcFile(bool create_latebound_entities = false);
|
||||||
@@ -116,6 +119,8 @@ public:
|
|||||||
std::string authorEmail() const;
|
std::string authorEmail() const;
|
||||||
std::string authorOrganisation() const;
|
std::string authorOrganisation() const;
|
||||||
|
|
||||||
|
const IfcSpfHeader& header() const { return _header; }
|
||||||
|
|
||||||
bool create_latebound_entities() const { return _create_latebound_entities; }
|
bool create_latebound_entities() const { return _create_latebound_entities; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+35
-20
@@ -210,17 +210,17 @@ void IfcSpfStream::Inc() {
|
|||||||
if ( current == '\n' || current == '\r' ) IfcSpfStream::Inc();
|
if ( current == '\n' || current == '\r' ) IfcSpfStream::Inc();
|
||||||
}
|
}
|
||||||
|
|
||||||
Tokens::Tokens(IfcParse::IfcSpfStream *s, IfcParse::IfcFile* f) {
|
IfcSpfLexer::IfcSpfLexer(IfcParse::IfcSpfStream *s, IfcParse::IfcFile* f) {
|
||||||
file = f;
|
file = f;
|
||||||
stream = s;
|
stream = s;
|
||||||
decoder = new IfcCharacterDecoder(s);
|
decoder = new IfcCharacterDecoder(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tokens::~Tokens() {
|
IfcSpfLexer::~IfcSpfLexer() {
|
||||||
delete decoder;
|
delete decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Tokens::skipWhitespace() {
|
unsigned int IfcSpfLexer::skipWhitespace() {
|
||||||
unsigned int n = 0;
|
unsigned int n = 0;
|
||||||
while ( !stream->eof ) {
|
while ( !stream->eof ) {
|
||||||
char c = stream->Peek();
|
char c = stream->Peek();
|
||||||
@@ -233,7 +233,7 @@ unsigned int Tokens::skipWhitespace() {
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Tokens::skipComment() {
|
unsigned int IfcSpfLexer::skipComment() {
|
||||||
char c = stream->Peek();
|
char c = stream->Peek();
|
||||||
if (c != '/') return 0;
|
if (c != '/') return 0;
|
||||||
stream->Inc();
|
stream->Inc();
|
||||||
@@ -257,7 +257,7 @@ unsigned int Tokens::skipComment() {
|
|||||||
//
|
//
|
||||||
// Returns the offset of the current Token and moves cursor to next
|
// Returns the offset of the current Token and moves cursor to next
|
||||||
//
|
//
|
||||||
Token Tokens::Next() {
|
Token IfcSpfLexer::Next() {
|
||||||
|
|
||||||
if ( stream->eof ) return TokenPtr();
|
if ( stream->eof ) return TokenPtr();
|
||||||
|
|
||||||
@@ -298,7 +298,7 @@ Token Tokens::Next() {
|
|||||||
// Reads a std::string from the file at specified offset
|
// Reads a std::string from the file at specified offset
|
||||||
// Omits whitespace and comments
|
// Omits whitespace and comments
|
||||||
//
|
//
|
||||||
std::string Tokens::TokenString(unsigned int offset) {
|
std::string IfcSpfLexer::TokenString(unsigned int offset) {
|
||||||
const bool was_eof = stream->eof;
|
const bool was_eof = stream->eof;
|
||||||
unsigned int old_offset = stream->Tell();
|
unsigned int old_offset = stream->Tell();
|
||||||
stream->Seek(offset);
|
stream->Seek(offset);
|
||||||
@@ -323,9 +323,9 @@ std::string Tokens::TokenString(unsigned int offset) {
|
|||||||
// Functions for creating Tokens from an arbitary file offset.
|
// Functions for creating Tokens from an arbitary file offset.
|
||||||
// The first 4 bits are reserved for Tokens of type ()=,;$*
|
// The first 4 bits are reserved for Tokens of type ()=,;$*
|
||||||
//
|
//
|
||||||
Token IfcParse::TokenPtr(Tokens* tokens, unsigned int offset) { return Token(tokens,offset); }
|
Token IfcParse::TokenPtr(IfcSpfLexer* tokens, unsigned int offset) { return Token(tokens,offset); }
|
||||||
Token IfcParse::TokenPtr(char c) { return Token((Tokens*)0,(unsigned) c); }
|
Token IfcParse::TokenPtr(char c) { return Token((IfcSpfLexer*)0,(unsigned) c); }
|
||||||
Token IfcParse::TokenPtr() { return Token((Tokens*)0,0); }
|
Token IfcParse::TokenPtr() { return Token((IfcSpfLexer*)0,0); }
|
||||||
|
|
||||||
//
|
//
|
||||||
// Functions to convert Tokens to binary data
|
// Functions to convert Tokens to binary data
|
||||||
@@ -345,8 +345,9 @@ bool TokenFunc::isString(const Token& t) {
|
|||||||
bool TokenFunc::isEnumeration(const Token& t) {
|
bool TokenFunc::isEnumeration(const Token& t) {
|
||||||
return ! isOperator(t) && startsWith(t, '.');
|
return ! isOperator(t) && startsWith(t, '.');
|
||||||
}
|
}
|
||||||
bool TokenFunc::isDatatype(const Token& t) {
|
bool TokenFunc::isKeyword(const Token& t) {
|
||||||
return ! isOperator(t) && startsWith(t, 'I');
|
// bool is a subtype of enumeration, no need to test for that
|
||||||
|
return !isOperator(t) && !isIdentifier(t) && !isString(t) && !isEnumeration(t) && !isInt(t) && !isFloat(t);
|
||||||
}
|
}
|
||||||
bool TokenFunc::isInt(const Token& t) {
|
bool TokenFunc::isInt(const Token& t) {
|
||||||
if (isOperator(t)) return false;
|
if (isOperator(t)) return false;
|
||||||
@@ -419,7 +420,7 @@ EntityArgument::EntityArgument(const Token& t) {
|
|||||||
// Reads the arguments from a list of token
|
// Reads the arguments from a list of token
|
||||||
// Aditionally, stores the ids (i.e. #[\d]+) in a vector
|
// Aditionally, stores the ids (i.e. #[\d]+) in a vector
|
||||||
//
|
//
|
||||||
ArgumentList::ArgumentList(Tokens* t, std::vector<unsigned int>& ids) {
|
ArgumentList::ArgumentList(IfcSpfLexer* t, std::vector<unsigned int>& ids) {
|
||||||
IfcParse::IfcFile* file = t->file;
|
IfcParse::IfcFile* file = t->file;
|
||||||
|
|
||||||
Token next = t->Next();
|
Token next = t->Next();
|
||||||
@@ -429,7 +430,7 @@ ArgumentList::ArgumentList(Tokens* t, std::vector<unsigned int>& ids) {
|
|||||||
else if ( TokenFunc::isOperator(next,'(') ) Push( new ArgumentList(t,ids) );
|
else if ( TokenFunc::isOperator(next,'(') ) Push( new ArgumentList(t,ids) );
|
||||||
else {
|
else {
|
||||||
if ( TokenFunc::isIdentifier(next) ) ids.push_back(TokenFunc::asInt(next));
|
if ( TokenFunc::isIdentifier(next) ) ids.push_back(TokenFunc::asInt(next));
|
||||||
if ( TokenFunc::isDatatype(next) ) {
|
if ( TokenFunc::isKeyword(next) ) {
|
||||||
t->Next();
|
t->Next();
|
||||||
try {
|
try {
|
||||||
Push ( new EntityArgument(next) );
|
Push ( new EntityArgument(next) );
|
||||||
@@ -619,7 +620,7 @@ EntityArgument::~EntityArgument() { delete entity; }
|
|||||||
Entity::Entity(unsigned int i, IfcFile* f) : _id(i), args(0) {
|
Entity::Entity(unsigned int i, IfcFile* f) : _id(i), args(0) {
|
||||||
file = f;
|
file = f;
|
||||||
Token datatype = f->tokens->Next();
|
Token datatype = f->tokens->Next();
|
||||||
if ( ! TokenFunc::isDatatype(datatype)) throw IfcException("Unexpected token while parsing entity");
|
if ( ! TokenFunc::isKeyword(datatype)) throw IfcException("Unexpected token while parsing entity");
|
||||||
_type = IfcSchema::Type::FromString(TokenFunc::asString(datatype));
|
_type = IfcSchema::Type::FromString(TokenFunc::asString(datatype));
|
||||||
offset = datatype.second;
|
offset = datatype.second;
|
||||||
}
|
}
|
||||||
@@ -661,7 +662,7 @@ void Entity::Load(std::vector<unsigned int>& ids, bool seek) const {
|
|||||||
if ( seek ) {
|
if ( seek ) {
|
||||||
file->tokens->stream->Seek(offset);
|
file->tokens->stream->Seek(offset);
|
||||||
Token datatype = file->tokens->Next();
|
Token datatype = file->tokens->Next();
|
||||||
if ( ! TokenFunc::isDatatype(datatype)) throw IfcException("Unexpected token while parsing entity");
|
if ( ! TokenFunc::isKeyword(datatype)) throw IfcException("Unexpected token while parsing entity");
|
||||||
_type = IfcSchema::Type::FromString(TokenFunc::asString(datatype));
|
_type = IfcSchema::Type::FromString(TokenFunc::asString(datatype));
|
||||||
}
|
}
|
||||||
Token open = file->tokens->Next();
|
Token open = file->tokens->Next();
|
||||||
@@ -760,13 +761,27 @@ bool IfcFile::Init(std::istream& f, int len) {
|
|||||||
bool IfcFile::Init(void* data, int len) {
|
bool IfcFile::Init(void* data, int len) {
|
||||||
return IfcFile::Init(new IfcSpfStream(data,len));
|
return IfcFile::Init(new IfcSpfStream(data,len));
|
||||||
}
|
}
|
||||||
bool IfcFile::Init(IfcParse::IfcSpfStream* f) {
|
bool IfcFile::Init(IfcParse::IfcSpfStream* s) {
|
||||||
IfcSchema::InitStringMap();
|
stream = s;
|
||||||
stream = f;
|
if (!stream->valid) {
|
||||||
if ( ! stream->valid ) return false;
|
return false;
|
||||||
tokens = new Tokens (stream,this);
|
}
|
||||||
|
|
||||||
|
tokens = new IfcSpfLexer(stream, this);
|
||||||
|
_header.lexer(tokens);
|
||||||
|
_header.tryRead();
|
||||||
|
|
||||||
|
std::vector<std::string> schemas;
|
||||||
|
try {
|
||||||
|
schemas = _header.file_schema().schema_identifiers();
|
||||||
|
} catch (...) {}
|
||||||
|
if (schemas.size() != 1 || schemas[0] != IfcSchema::Identifier) {
|
||||||
|
Logger::Message(Logger::LOG_WARNING, std::string("File schema encountered that is different from expected value of '") + IfcSchema::Identifier + "'");
|
||||||
|
}
|
||||||
|
|
||||||
Token token = TokenPtr();
|
Token token = TokenPtr();
|
||||||
Token previous = TokenPtr();
|
Token previous = TokenPtr();
|
||||||
|
|
||||||
unsigned int currentId = 0;
|
unsigned int currentId = 0;
|
||||||
lastId = 0;
|
lastId = 0;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
|
|||||||
@@ -53,9 +53,9 @@ namespace IfcParse {
|
|||||||
|
|
||||||
class Entity;
|
class Entity;
|
||||||
class IfcFile;
|
class IfcFile;
|
||||||
class Tokens;
|
class IfcSpfLexer;
|
||||||
|
|
||||||
typedef std::pair<Tokens*,unsigned> Token;
|
typedef std::pair<IfcSpfLexer*, unsigned> Token;
|
||||||
|
|
||||||
/// Provides functions to convert Tokens to binary data
|
/// Provides functions to convert Tokens to binary data
|
||||||
/// Tokens are merely offsets to where they can be read in the file
|
/// Tokens are merely offsets to where they can be read in the file
|
||||||
@@ -74,7 +74,7 @@ namespace IfcParse {
|
|||||||
/// Returns whether the token can be interpreted as an enumerated value
|
/// Returns whether the token can be interpreted as an enumerated value
|
||||||
static bool isEnumeration(const Token& t);
|
static bool isEnumeration(const Token& t);
|
||||||
/// Returns whether the token can be interpreted as a datatype name
|
/// Returns whether the token can be interpreted as a datatype name
|
||||||
static bool isDatatype(const Token& t);
|
static bool isKeyword(const Token& t);
|
||||||
/// Returns whether the token can be interpreted as an integer
|
/// Returns whether the token can be interpreted as an integer
|
||||||
static bool isInt(const Token& t);
|
static bool isInt(const Token& t);
|
||||||
/// Returns whether the token can be interpreted as a boolean
|
/// Returns whether the token can be interpreted as a boolean
|
||||||
@@ -97,12 +97,12 @@ namespace IfcParse {
|
|||||||
// Functions for creating Tokens from an arbitary file offset
|
// Functions for creating Tokens from an arbitary file offset
|
||||||
// The first 4 bits are reserved for Tokens of type ()=,;$*
|
// The first 4 bits are reserved for Tokens of type ()=,;$*
|
||||||
//
|
//
|
||||||
Token TokenPtr(Tokens* tokens, unsigned int offset);
|
Token TokenPtr(IfcSpfLexer* tokens, unsigned int offset);
|
||||||
Token TokenPtr(char c);
|
Token TokenPtr(char c);
|
||||||
Token TokenPtr();
|
Token TokenPtr();
|
||||||
|
|
||||||
/// A stream of tokens to be read from a IfcSpfStream.
|
/// A stream of tokens to be read from a IfcSpfStream.
|
||||||
class Tokens {
|
class IfcSpfLexer {
|
||||||
private:
|
private:
|
||||||
IfcCharacterDecoder* decoder;
|
IfcCharacterDecoder* decoder;
|
||||||
unsigned int skipWhitespace();
|
unsigned int skipWhitespace();
|
||||||
@@ -110,9 +110,9 @@ namespace IfcParse {
|
|||||||
public:
|
public:
|
||||||
IfcSpfStream* stream;
|
IfcSpfStream* stream;
|
||||||
IfcFile* file;
|
IfcFile* file;
|
||||||
Tokens(IfcSpfStream* s, IfcFile* f);
|
IfcSpfLexer(IfcSpfStream* s, IfcFile* f);
|
||||||
Token Next();
|
Token Next();
|
||||||
~Tokens();
|
~IfcSpfLexer();
|
||||||
std::string TokenString(unsigned int offset);
|
std::string TokenString(unsigned int offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ namespace IfcParse {
|
|||||||
std::vector<Argument*> list;
|
std::vector<Argument*> list;
|
||||||
void Push(Argument* l);
|
void Push(Argument* l);
|
||||||
public:
|
public:
|
||||||
ArgumentList(Tokens* t, std::vector<unsigned int>& ids);
|
ArgumentList(IfcSpfLexer* t, std::vector<unsigned int>& ids);
|
||||||
~ArgumentList();
|
~ArgumentList();
|
||||||
|
|
||||||
IfcUtil::ArgumentType type() const;
|
IfcUtil::ArgumentType type() const;
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
/********************************************************************************
|
||||||
|
* *
|
||||||
|
* 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/>. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#include "../ifcparse/IfcParse.h"
|
||||||
|
|
||||||
|
#include "IfcSpfHeader.h"
|
||||||
|
|
||||||
|
static const char * const ISO_10303_21 = "ISO-10303-21";
|
||||||
|
static const char * const HEADER = "HEADER";
|
||||||
|
static const char * const FILE_DESCRIPTION = "FILE_DESCRIPTION";
|
||||||
|
static const char * const FILE_NAME = "FILE_NAME";
|
||||||
|
static const char * const FILE_SCHEMA = "FILE_SCHEMA";
|
||||||
|
static const char * const FILE_POPULATION = "FILE_POPULATION";
|
||||||
|
static const char * const SECTION_LANGUAGE = "SECTION_LANGUAGE";
|
||||||
|
static const char * const SECTION_CONTEXT = "SECTION_CONTEXT";
|
||||||
|
static const char * const ENDSEC = "ENDSEC";
|
||||||
|
static const char * const DATA = "DATA";
|
||||||
|
|
||||||
|
using namespace IfcParse;
|
||||||
|
|
||||||
|
void IfcSpfHeader::readSemicolon() {
|
||||||
|
if (!TokenFunc::isOperator(_lexer->Next(), ';')) {
|
||||||
|
throw IfcException(std::string("Expected ;"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IfcSpfHeader::readParen() {
|
||||||
|
if (!TokenFunc::isOperator(_lexer->Next(), '(')) {
|
||||||
|
throw IfcException(std::string("Expected ("));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IfcSpfHeader::readTerminal(const std::string& term, Trail trail) {
|
||||||
|
if (TokenFunc::asString(_lexer->Next()) != term) {
|
||||||
|
throw IfcException(std::string("Expected " + term));
|
||||||
|
}
|
||||||
|
if (trail == TRAILING_SEMICOLON) {
|
||||||
|
readSemicolon();
|
||||||
|
} else if (trail == TRAILING_PAREN) {
|
||||||
|
readParen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IfcSpfHeader::read() {
|
||||||
|
readTerminal(ISO_10303_21, TRAILING_SEMICOLON);
|
||||||
|
readTerminal(HEADER, TRAILING_SEMICOLON);
|
||||||
|
|
||||||
|
readTerminal(FILE_DESCRIPTION, TRAILING_PAREN);
|
||||||
|
_file_description = new FileDescription(_lexer);
|
||||||
|
readSemicolon();
|
||||||
|
|
||||||
|
readTerminal(FILE_NAME, TRAILING_PAREN);
|
||||||
|
_file_name = new FileName(_lexer);
|
||||||
|
readSemicolon();
|
||||||
|
|
||||||
|
readTerminal(FILE_SCHEMA, TRAILING_PAREN);
|
||||||
|
_file_schema = new FileSchema(_lexer);
|
||||||
|
readSemicolon();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IfcSpfHeader::tryRead() {
|
||||||
|
try {
|
||||||
|
read();
|
||||||
|
return true;
|
||||||
|
} catch(const IfcException&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileDescription& IfcSpfHeader::file_description() {
|
||||||
|
if (_file_description) {
|
||||||
|
return *_file_description;
|
||||||
|
} else {
|
||||||
|
throw IfcException("File description not read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileName& IfcSpfHeader::file_name() {
|
||||||
|
if (_file_name) {
|
||||||
|
return *_file_name;
|
||||||
|
} else {
|
||||||
|
throw IfcException("File name not read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileSchema& IfcSpfHeader::file_schema() {
|
||||||
|
if (_file_schema) {
|
||||||
|
return *_file_schema;
|
||||||
|
} else {
|
||||||
|
throw IfcException("File schema not read");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/********************************************************************************
|
||||||
|
* *
|
||||||
|
* 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/>. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef IFCSPFHEADER_H
|
||||||
|
#define IFCSPFHEADER_H
|
||||||
|
|
||||||
|
#include "../ifcparse/IfcSpfStream.h"
|
||||||
|
|
||||||
|
namespace IfcParse {
|
||||||
|
|
||||||
|
class HeaderEntity {
|
||||||
|
private:
|
||||||
|
ArgumentList* list;
|
||||||
|
protected:
|
||||||
|
HeaderEntity(IfcSpfLexer* lexer) {
|
||||||
|
std::vector<unsigned int> ids;
|
||||||
|
list = new ArgumentList(lexer, ids);
|
||||||
|
};
|
||||||
|
Argument* getArgument(unsigned int i) const {
|
||||||
|
return (*list)[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileDescription : private HeaderEntity {
|
||||||
|
public:
|
||||||
|
FileDescription(IfcSpfLexer* lexer) : HeaderEntity(lexer) {}
|
||||||
|
std::vector<std::string> description() const { return *getArgument(0); }
|
||||||
|
std::string implementation_level() const { return *getArgument(1); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileName : private HeaderEntity {
|
||||||
|
public:
|
||||||
|
FileName(IfcSpfLexer* lexer) : HeaderEntity(lexer) {}
|
||||||
|
std::string name() const { return *getArgument(0); }
|
||||||
|
std::string time_stamp() const { return *getArgument(1); }
|
||||||
|
std::vector<std::string> author() const { return *getArgument(2); }
|
||||||
|
std::vector<std::string> organization() const { return *getArgument(3); }
|
||||||
|
std::string preprocessor_version() const { return *getArgument(4); }
|
||||||
|
std::string originating_system() const { return *getArgument(5); }
|
||||||
|
std::string authorization()const { return *getArgument(6); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileSchema : private HeaderEntity {
|
||||||
|
public:
|
||||||
|
FileSchema(IfcSpfLexer* lexer) : HeaderEntity(lexer) {}
|
||||||
|
std::vector<std::string> schema_identifiers() const { return *getArgument(0); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class IfcSpfHeader {
|
||||||
|
private:
|
||||||
|
IfcSpfLexer* _lexer;
|
||||||
|
FileDescription* _file_description;
|
||||||
|
FileName* _file_name;
|
||||||
|
FileSchema* _file_schema;
|
||||||
|
void readParen();
|
||||||
|
void readSemicolon();\
|
||||||
|
enum Trail {
|
||||||
|
TRAILING_SEMICOLON,
|
||||||
|
TRAILING_PAREN,
|
||||||
|
NONE
|
||||||
|
};
|
||||||
|
void readTerminal(const std::string& term, Trail trail);
|
||||||
|
public:
|
||||||
|
IfcSpfHeader() : _lexer(0), _file_description(0), _file_name(0), _file_schema(0) {}
|
||||||
|
explicit IfcSpfHeader(IfcSpfLexer* lexer) : _lexer(lexer) {}
|
||||||
|
|
||||||
|
IfcSpfLexer* lexer() { return _lexer; }
|
||||||
|
void lexer(IfcSpfLexer* l) { _lexer = l; }
|
||||||
|
|
||||||
|
void read();
|
||||||
|
bool tryRead();
|
||||||
|
|
||||||
|
const FileDescription& file_description();
|
||||||
|
const FileName& file_name();
|
||||||
|
const FileSchema& file_schema();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -28,6 +28,14 @@
|
|||||||
%ignore IfcParse::IfcFile::AddEntity;
|
%ignore IfcParse::IfcFile::AddEntity;
|
||||||
%ignore operator<<;
|
%ignore operator<<;
|
||||||
|
|
||||||
|
%ignore IfcParse::FileDescription::FileDescription;
|
||||||
|
%ignore IfcParse::FileName::FileName;
|
||||||
|
%ignore IfcParse::FileSchema::FileSchema;
|
||||||
|
%ignore IfcParse::IfcFile::tokens;
|
||||||
|
%ignore IfcParse::IfcSpfHeader::IfcSpfHeader(IfcSpfLexer*);
|
||||||
|
%ignore IfcParse::IfcSpfHeader::lexer;
|
||||||
|
%ignore IfcParse::IfcSpfHeader::stream;
|
||||||
|
|
||||||
%rename("by_type") EntitiesByType;
|
%rename("by_type") EntitiesByType;
|
||||||
%rename("__len__") getArgumentCount;
|
%rename("__len__") getArgumentCount;
|
||||||
%rename("get_argument_type") getArgumentType;
|
%rename("get_argument_type") getArgumentType;
|
||||||
@@ -156,6 +164,11 @@
|
|||||||
std::ofstream f(fn.c_str());
|
std::ofstream f(fn.c_str());
|
||||||
f << (*$self);
|
f << (*$self);
|
||||||
}
|
}
|
||||||
|
%pythoncode %{
|
||||||
|
if _newclass:
|
||||||
|
# Hide the getters with read-only property implementations
|
||||||
|
header = property(header)
|
||||||
|
%}
|
||||||
}
|
}
|
||||||
|
|
||||||
%extend IfcParse::IfcLateBoundEntity {
|
%extend IfcParse::IfcLateBoundEntity {
|
||||||
@@ -164,6 +177,48 @@
|
|||||||
%}
|
%}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%extend IfcParse::IfcSpfHeader {
|
||||||
|
%pythoncode %{
|
||||||
|
if _newclass:
|
||||||
|
# Hide the getters with read-only property implementations
|
||||||
|
file_description = property(file_description)
|
||||||
|
file_name = property(file_name)
|
||||||
|
file_schema = property(file_schema)
|
||||||
|
%}
|
||||||
|
};
|
||||||
|
|
||||||
|
%extend IfcParse::FileDescription {
|
||||||
|
%pythoncode %{
|
||||||
|
if _newclass:
|
||||||
|
# Hide the getters with read-only property implementations
|
||||||
|
description = property(description)
|
||||||
|
implementation_level = property(implementation_level)
|
||||||
|
%}
|
||||||
|
};
|
||||||
|
|
||||||
|
%extend IfcParse::FileName {
|
||||||
|
%pythoncode %{
|
||||||
|
if _newclass:
|
||||||
|
# Hide the getters with read-only property implementations
|
||||||
|
name = property(name)
|
||||||
|
time_stamp = property(time_stamp)
|
||||||
|
author = property(author)
|
||||||
|
organization = property(organization)
|
||||||
|
preprocessor_version = property(preprocessor_version)
|
||||||
|
originating_system = property(originating_system)
|
||||||
|
authorization = property(authorization)
|
||||||
|
%}
|
||||||
|
};
|
||||||
|
|
||||||
|
%extend IfcParse::FileSchema {
|
||||||
|
%pythoncode %{
|
||||||
|
if _newclass:
|
||||||
|
# Hide the getters with read-only property implementations
|
||||||
|
schema_identifiers = property(schema_identifiers)
|
||||||
|
%}
|
||||||
|
};
|
||||||
|
|
||||||
|
%include "../ifcparse/IfcSpfHeader.h"
|
||||||
%include "../ifcparse/IfcFile.h"
|
%include "../ifcparse/IfcFile.h"
|
||||||
%include "../ifcparse/IfcLateBoundEntity.h"
|
%include "../ifcparse/IfcLateBoundEntity.h"
|
||||||
|
|
||||||
|
|||||||
@@ -213,6 +213,10 @@
|
|||||||
RelativePath="..\src\ifcparse\IfcWrite.cpp"
|
RelativePath="..\src\ifcparse\IfcWrite.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\ifcparse\IfcSpfHeader.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\src\ifcparse\IfcGuidHelper.cpp"
|
RelativePath="..\src\ifcparse\IfcGuidHelper.cpp"
|
||||||
>
|
>
|
||||||
@@ -283,6 +287,10 @@
|
|||||||
RelativePath="..\src\ifcparse\IfcParse.h"
|
RelativePath="..\src\ifcparse\IfcParse.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\ifcparse\IfcSpfHeader.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\src\ifcparse\IfcSpfStream.h"
|
RelativePath="..\src\ifcparse\IfcSpfStream.h"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user