mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 18:43:26 +00:00
Storage rework WIP
This commit is contained in:
+189
-286
@@ -26,7 +26,7 @@
|
||||
#include "IfcLogger.h"
|
||||
#include "IfcSchema.h"
|
||||
#include "IfcSIPrefix.h"
|
||||
#include "IfcSpfStream.h"
|
||||
#include "FileReader.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -102,167 +102,7 @@ void init_locale() {
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// Opens the file and gets the filesize
|
||||
//
|
||||
#ifdef USE_MMAP
|
||||
IfcSpfStream::IfcSpfStream(const std::string& path, bool mmap)
|
||||
#else
|
||||
IfcSpfStream::IfcSpfStream(const std::string& path)
|
||||
#endif
|
||||
: stream_(0),
|
||||
buffer_(0),
|
||||
valid(false),
|
||||
eof(false) {
|
||||
#ifdef _MSC_VER
|
||||
std::wstring fn_ws = IfcUtil::path::from_utf8(path);
|
||||
const wchar_t* fn_wide = fn_ws.c_str();
|
||||
|
||||
#ifdef USE_MMAP
|
||||
if (mmap) {
|
||||
mfs = boost::iostreams::mapped_file_source(boost::filesystem::wpath(fn_wide));
|
||||
} else {
|
||||
#endif
|
||||
stream_ = _wfopen(fn_wide, L"rb");
|
||||
#ifdef USE_MMAP
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifdef USE_MMAP
|
||||
if (mmap) {
|
||||
mfs = boost::iostreams::mapped_file_source(path);
|
||||
} else {
|
||||
#endif
|
||||
stream_ = fopen(path.c_str(), "rb");
|
||||
#ifdef USE_MMAP
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_MMAP
|
||||
if (mmap) {
|
||||
if (!mfs.is_open()) {
|
||||
return;
|
||||
}
|
||||
|
||||
valid = true;
|
||||
buffer_ = mfs.data();
|
||||
ptr_ = 0;
|
||||
len_ = mfs.size();
|
||||
} else {
|
||||
#endif
|
||||
if (stream_ == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
valid = true;
|
||||
fseek(stream_, 0, SEEK_END);
|
||||
size = (unsigned int)ftell(stream_);
|
||||
rewind(stream_);
|
||||
char* buffer_rw = new char[size];
|
||||
len_ = (unsigned int)fread(buffer_rw, 1, size, stream_);
|
||||
buffer_ = buffer_rw;
|
||||
eof = len_ == 0;
|
||||
ptr_ = 0;
|
||||
fclose(stream_);
|
||||
stream_ = nullptr;
|
||||
#ifdef USE_MMAP
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
IfcSpfStream::IfcSpfStream(std::istream& stream, int length)
|
||||
: stream_(0),
|
||||
buffer_(0) {
|
||||
eof = false;
|
||||
size = length;
|
||||
char* buffer_rw = new char[size];
|
||||
stream.read(buffer_rw, size);
|
||||
buffer_ = buffer_rw;
|
||||
valid = stream.gcount() == size;
|
||||
ptr_ = 0;
|
||||
len_ = length;
|
||||
}
|
||||
|
||||
IfcSpfStream::IfcSpfStream(void* data, int length)
|
||||
: stream_(0),
|
||||
buffer_(0) {
|
||||
eof = false;
|
||||
size = length;
|
||||
buffer_ = (char*)data;
|
||||
valid = true;
|
||||
ptr_ = 0;
|
||||
len_ = length;
|
||||
}
|
||||
|
||||
IfcSpfStream::~IfcSpfStream() {
|
||||
Close();
|
||||
}
|
||||
|
||||
void IfcSpfStream::Close() {
|
||||
#ifdef USE_MMAP
|
||||
if (mfs.is_open()) {
|
||||
mfs.close();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
delete[] buffer_;
|
||||
if (stream_ != nullptr) {
|
||||
fclose(stream_);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Seeks an arbitrary position in the file
|
||||
//
|
||||
void IfcSpfStream::Seek(unsigned int offset) {
|
||||
ptr_ = offset;
|
||||
if (ptr_ >= len_) {
|
||||
throw IfcException("Reading outside of file limits");
|
||||
}
|
||||
eof = false;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the character at the cursor
|
||||
//
|
||||
char IfcSpfStream::Peek() {
|
||||
return buffer_[ptr_];
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the character at specified offset
|
||||
//
|
||||
char IfcSpfStream::Read(unsigned int offset) {
|
||||
return buffer_[offset];
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the cursor position
|
||||
//
|
||||
unsigned int IfcSpfStream::Tell() const {
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
//
|
||||
// Increments cursor and reads new chunk if necessary
|
||||
//
|
||||
void IfcSpfStream::Inc() {
|
||||
if (++ptr_ == len_) {
|
||||
eof = true;
|
||||
return;
|
||||
}
|
||||
const char current = IfcSpfStream::Peek();
|
||||
if (current == '\n' || current == '\r') {
|
||||
// NB this is recursive. It might as well be a loop.
|
||||
IfcSpfStream::Inc();
|
||||
}
|
||||
}
|
||||
|
||||
IfcSpfLexer::IfcSpfLexer(IfcParse::IfcSpfStream* stream_) {
|
||||
IfcSpfLexer::IfcSpfLexer(IfcParse::FileReader* stream_) {
|
||||
stream = stream_;
|
||||
decoder_ = new IfcCharacterDecoder(stream_);
|
||||
}
|
||||
@@ -271,12 +111,12 @@ IfcSpfLexer::~IfcSpfLexer() {
|
||||
delete decoder_;
|
||||
}
|
||||
|
||||
unsigned int IfcSpfLexer::skipWhitespace() const {
|
||||
unsigned int index = 0;
|
||||
while (!stream->eof) {
|
||||
char character = stream->Peek();
|
||||
size_t IfcSpfLexer::skipWhitespace() const {
|
||||
size_t index = 0;
|
||||
while (!stream->eof()) {
|
||||
char character = stream->peek();
|
||||
if ((character == ' ' || character == '\r' || character == '\n' || character == '\t')) {
|
||||
stream->Inc();
|
||||
stream->increment();
|
||||
++index;
|
||||
} else {
|
||||
break;
|
||||
@@ -285,22 +125,22 @@ unsigned int IfcSpfLexer::skipWhitespace() const {
|
||||
return index;
|
||||
}
|
||||
|
||||
unsigned int IfcSpfLexer::skipComment() const {
|
||||
char character = stream->Peek();
|
||||
size_t IfcSpfLexer::skipComment() const {
|
||||
char character = stream->peek();
|
||||
if (character != '/') {
|
||||
return 0;
|
||||
}
|
||||
stream->Inc();
|
||||
character = stream->Peek();
|
||||
stream->increment();
|
||||
character = stream->peek();
|
||||
if (character != '*') {
|
||||
stream->Seek(stream->Tell() - 1);
|
||||
stream->seek(stream->tell() - 1);
|
||||
return 0;
|
||||
}
|
||||
unsigned int index = 2;
|
||||
size_t index = 2;
|
||||
char intermediate = 0;
|
||||
while (!stream->eof) {
|
||||
character = stream->Peek();
|
||||
stream->Inc();
|
||||
while (!stream->eof()) {
|
||||
character = stream->peek();
|
||||
stream->increment();
|
||||
++index;
|
||||
if (character == '/' && intermediate == '*') {
|
||||
break;
|
||||
@@ -315,19 +155,20 @@ unsigned int IfcSpfLexer::skipComment() const {
|
||||
//
|
||||
Token IfcSpfLexer::Next() {
|
||||
|
||||
if (stream->eof) {
|
||||
if (stream->eof()) {
|
||||
return Token{};
|
||||
}
|
||||
|
||||
while ((skipWhitespace() != 0U) || (skipComment() != 0U)) {
|
||||
}
|
||||
|
||||
if (stream->eof) {
|
||||
if (stream->eof()) {
|
||||
return Token{};
|
||||
}
|
||||
unsigned int pos = stream->Tell();
|
||||
|
||||
char character = stream->Peek();
|
||||
auto& str = GetTempString();
|
||||
auto pos = stream->tell();
|
||||
char character = stream->read();
|
||||
|
||||
// If the cursor is at [()=,;$*] we know token consists of single char
|
||||
if (character == '(' ||
|
||||
@@ -336,69 +177,45 @@ Token IfcSpfLexer::Next() {
|
||||
character == ',' ||
|
||||
character == ';' ||
|
||||
character == '$' ||
|
||||
character == '*') {
|
||||
stream->Inc();
|
||||
return OperatorTokenPtr(this, pos, pos + 1);
|
||||
character == '*')
|
||||
{
|
||||
return OperatorTokenPtr(this, pos, character);
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
|
||||
while (!stream->eof) {
|
||||
|
||||
// Read character and increment pointer if not starting a new token
|
||||
character = stream->Peek();
|
||||
if ((len != 0) && (character == '(' ||
|
||||
character == ')' ||
|
||||
character == '=' ||
|
||||
character == ',' ||
|
||||
character == ';' ||
|
||||
character == '/')) {
|
||||
break;
|
||||
}
|
||||
stream->Inc();
|
||||
len++;
|
||||
|
||||
if (character == '\'') {
|
||||
// If a string is encountered defer processing to the IfcCharacterDecoder
|
||||
if (character == '\'') {
|
||||
decoder_->skip();
|
||||
str = *decoder_;
|
||||
} else {
|
||||
str.assign(&character, 1);
|
||||
|
||||
while (!stream->eof()) {
|
||||
// Read character and increment pointer if not starting a new token
|
||||
character = stream->peek();
|
||||
if (character == '(' ||
|
||||
character == ')' ||
|
||||
character == '=' ||
|
||||
character == ',' ||
|
||||
character == ';' ||
|
||||
character == '/') {
|
||||
break;
|
||||
}
|
||||
str.push_back(character);
|
||||
stream->increment();
|
||||
}
|
||||
}
|
||||
Token t;
|
||||
if (len != 0) {
|
||||
t = GeneralTokenPtr(this, pos, stream->Tell());
|
||||
} else {
|
||||
t = Token{};
|
||||
}
|
||||
// std::wcout << "token: " << pos << " " << TokenFunc::asStringRef(t).c_str() << std::endl;
|
||||
return t;
|
||||
}
|
||||
|
||||
bool IfcSpfStream::is_eof_at(unsigned int local_ptr) const {
|
||||
return local_ptr >= len_;
|
||||
}
|
||||
|
||||
void IfcSpfStream::increment_at(unsigned int& local_ptr) {
|
||||
if (++local_ptr == len_) {
|
||||
return;
|
||||
}
|
||||
const char current = IfcSpfStream::peek_at(local_ptr);
|
||||
if (current == '\n' || current == '\r') {
|
||||
IfcSpfStream::increment_at(local_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
char IfcSpfStream::peek_at(unsigned int local_ptr) {
|
||||
return buffer_[local_ptr];
|
||||
return GeneralTokenPtr(this, pos, str);
|
||||
}
|
||||
|
||||
//
|
||||
// Reads a std::string from the file at specified offset
|
||||
// Omits whitespace and comments
|
||||
//
|
||||
void IfcSpfLexer::TokenString(unsigned int offset, std::string& buffer) {
|
||||
void IfcSpfLexer::TokenString(size_t offset, std::string& buffer) {
|
||||
buffer.clear();
|
||||
while (!stream->is_eof_at(offset)) {
|
||||
char character = stream->peek_at(offset);
|
||||
auto local_stream = *this->stream;
|
||||
local_stream.seek(offset);
|
||||
while (!local_stream.eof()) {
|
||||
char character = local_stream.peek();
|
||||
if (!buffer.empty() && (character == '(' ||
|
||||
character == ')' ||
|
||||
character == '=' ||
|
||||
@@ -407,7 +224,7 @@ void IfcSpfLexer::TokenString(unsigned int offset, std::string& buffer) {
|
||||
character == '/')) {
|
||||
break;
|
||||
}
|
||||
stream->increment_at(offset);
|
||||
local_stream.increment();
|
||||
if (character == ' ' ||
|
||||
character == '\r' ||
|
||||
character == '\n' ||
|
||||
@@ -416,6 +233,7 @@ void IfcSpfLexer::TokenString(unsigned int offset, std::string& buffer) {
|
||||
}
|
||||
if (character == '\'') {
|
||||
// todo, make decoder use local offset ptr
|
||||
auto offset = local_stream.tell();
|
||||
buffer = decoder_->get(offset);
|
||||
break;
|
||||
}
|
||||
@@ -424,10 +242,11 @@ void IfcSpfLexer::TokenString(unsigned int offset, std::string& buffer) {
|
||||
}
|
||||
|
||||
//Note: according to STEP standard, there may be newlines in tokens
|
||||
inline void RemoveTokenSeparators(IfcSpfStream* stream, unsigned start, unsigned end, std::string& oDestination) {
|
||||
/*
|
||||
inline void RemoveTokenSeparators(FileReader* stream, size_t start, size_t end, std::string& oDestination) {
|
||||
oDestination.clear();
|
||||
for (unsigned i = start; i < end; i++) {
|
||||
char character = stream->Read(i);
|
||||
char character = stream->get(i);
|
||||
if (character == ' ' ||
|
||||
character == '\r' ||
|
||||
character == '\n' ||
|
||||
@@ -437,6 +256,7 @@ inline void RemoveTokenSeparators(IfcSpfStream* stream, unsigned start, unsigned
|
||||
oDestination += character;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
bool ParseInt(const char* pStart, int& val) {
|
||||
char* pEnd;
|
||||
@@ -481,22 +301,17 @@ bool ParseBool(const char* pStart, int& val) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Token IfcParse::OperatorTokenPtr(IfcSpfLexer* lexer, unsigned start, unsigned end) {
|
||||
char first = lexer->stream->Read(start);
|
||||
Token token(lexer, start, end, Token_OPERATOR);
|
||||
token.value_char = first;
|
||||
Token IfcParse::OperatorTokenPtr(IfcSpfLexer* lexer, size_t start, char data) {
|
||||
Token token(lexer, start, Token_OPERATOR);
|
||||
token.value_char = data;
|
||||
return token;
|
||||
}
|
||||
|
||||
Token IfcParse::GeneralTokenPtr(IfcSpfLexer* lexer, unsigned start, unsigned end) {
|
||||
Token token(lexer, start, end, Token_NONE);
|
||||
|
||||
//extract token into temp buffer (remove eol-s, no encoding changes)
|
||||
std::string& tokenStr = lexer->GetTempString();
|
||||
RemoveTokenSeparators(lexer->stream, start, end, tokenStr);
|
||||
Token IfcParse::GeneralTokenPtr(IfcSpfLexer* lexer, size_t start, const std::string& tokenStr) {
|
||||
Token token(lexer, start, Token_NONE);
|
||||
|
||||
//determine type of the token
|
||||
char first = lexer->stream->Read(start);
|
||||
const char& first = tokenStr.front();
|
||||
if (first == '#') {
|
||||
token.type = Token_IDENTIFIER;
|
||||
if (!ParseInt(tokenStr.c_str() + 1, token.value_int)) {
|
||||
@@ -521,6 +336,11 @@ Token IfcParse::GeneralTokenPtr(IfcSpfLexer* lexer, unsigned start, unsigned end
|
||||
token.type = Token_KEYWORD;
|
||||
}
|
||||
|
||||
// todo STRING/BINARY/ENUM/KEYWORD not stored
|
||||
// tokenStr is gone after this.
|
||||
// Orrrr we could only free pages when after a full instance is formed because after that no
|
||||
// references to prior token ranges exist anymore.
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
@@ -676,7 +496,25 @@ boost::dynamic_bitset<> TokenFunc::asBinary(const Token& token) {
|
||||
|
||||
std::string TokenFunc::toString(const Token& token) {
|
||||
std::string result;
|
||||
token.lexer->TokenString(token.startPos, result);
|
||||
if (token.type == Token_OPERATOR) {
|
||||
result.push_back(token.value_char);
|
||||
} else if (token.type == Token_INT) {
|
||||
result = std::to_string(token.value_int);
|
||||
} else if (token.type == Token_BOOL) {
|
||||
if (token.value_int == 1) {
|
||||
result = ".T.";
|
||||
} else if (token.value_int == 0) {
|
||||
result = ".F.";
|
||||
} else {
|
||||
result = ".U.";
|
||||
}
|
||||
} else if (token.type == Token_FLOAT) {
|
||||
std::ostringstream oss;
|
||||
oss << std::setprecision(15) << token.value_double;
|
||||
result = oss.str();
|
||||
} else {
|
||||
token.lexer->TokenString(token.startPos, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -684,7 +522,7 @@ std::string TokenFunc::toString(const Token& token) {
|
||||
// Reads the arguments from a list of token
|
||||
// Aditionally, registers the ids (i.e. #[\d]+) in the inverse map
|
||||
//
|
||||
void IfcParse::impl::in_memory_file_storage::load(unsigned entity_instance_name, const IfcParse::entity* entity, parse_context& context, int attribute_index) {
|
||||
void IfcParse::impl::in_memory_file_storage::load(boost::optional<size_t> entity_instance_name, const IfcParse::entity* entity, parse_context& context, int attribute_index) {
|
||||
Token next = tokens->Next();
|
||||
|
||||
/*
|
||||
@@ -708,8 +546,8 @@ void IfcParse::impl::in_memory_file_storage::load(unsigned entity_instance_name,
|
||||
load(entity_instance_name, entity, context.push(), attribute_index == -1 ? (int) attribute_index_within_data : attribute_index);
|
||||
} else {
|
||||
return_value++;
|
||||
if (TokenFunc::isIdentifier(next) && entity) {
|
||||
register_inverse(entity_instance_name, entity, next.value_int, attribute_index == -1 ? attribute_index_within_data : attribute_index);
|
||||
if (TokenFunc::isIdentifier(next) && entity && entity_instance_name) {
|
||||
register_inverse(*entity_instance_name, entity, next.value_int, attribute_index == -1 ? (int) attribute_index_within_data : attribute_index);
|
||||
}
|
||||
|
||||
if (TokenFunc::isKeyword(next)) {
|
||||
@@ -758,10 +596,10 @@ IfcEntityInstanceData IfcParse::impl::in_memory_file_storage::read(unsigned int
|
||||
}
|
||||
|
||||
void IfcParse::impl::in_memory_file_storage::try_read_semicolon() const {
|
||||
unsigned int old_offset = tokens->stream->Tell();
|
||||
auto old_offset = tokens->stream->tell();
|
||||
Token semilocon = tokens->Next();
|
||||
if (!TokenFunc::isOperator(semilocon, ';')) {
|
||||
tokens->stream->Seek(old_offset);
|
||||
tokens->stream->seek(old_offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,7 +621,7 @@ void IfcParse::impl::in_memory_file_storage::unregister_inverse(unsigned id_from
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
std::string to_string_fixed_width(const T& t, size_t w) {
|
||||
std::string to_string_fixed_width(const T& t, size_t) {
|
||||
// @todo currently inactive
|
||||
std::ostringstream oss;
|
||||
oss << /*std::setfill('0') << std::setw(w) <<*/ t;
|
||||
@@ -1345,11 +1183,27 @@ IfcUtil::IfcBaseClass::set_attribute_value(const std::string& s, const T& t) {
|
||||
//
|
||||
#ifdef USE_MMAP
|
||||
IfcFile::IfcFile(const std::string& fn, bool mmap) {
|
||||
IfcSpfStream s(fn, mmap);
|
||||
storage_ = impl::in_memory_file_storage{};
|
||||
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s);
|
||||
std::unique_ptr<FileReader> s;
|
||||
if (mmap) {
|
||||
s = std::make_unique<FileReader>(fn, FileReader::mmap_tag{});
|
||||
} else {
|
||||
s = std::make_unique<FileReader>(fn);
|
||||
}
|
||||
|
||||
storage_.emplace<1>(this);
|
||||
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&*s, schema_, max_id_);
|
||||
|
||||
if ((good_ = std::get<impl::in_memory_file_storage>(storage_).good_)) {
|
||||
// @todo unify these names, it's already confusing enough as it stands
|
||||
byid_ = decltype(byid_)(&std::get<impl::in_memory_file_storage>(storage_).byid_);
|
||||
byref_excl_ = decltype(byref_excl_)(&std::get<impl::in_memory_file_storage>(storage_).byref_excl_);
|
||||
byguid_ = decltype(byguid_)(&std::get<impl::in_memory_file_storage>(storage_).byguid_);
|
||||
}
|
||||
|
||||
ifcroot_type_ = schema_ ? schema_->declaration_by_name("IfcRoot") : nullptr;
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
IfcFile::IfcFile(const std::string& path, filetype ty, bool readonly)
|
||||
: schema_(nullptr)
|
||||
, max_id_(0)
|
||||
@@ -1360,11 +1214,11 @@ IfcFile::IfcFile(const std::string& path, filetype ty, bool readonly)
|
||||
ty = guess_file_type(path);
|
||||
}
|
||||
if (ty == FT_IFCSPF) {
|
||||
IfcSpfStream s(path);
|
||||
FileReader s(path);
|
||||
storage_.emplace<1>(this);
|
||||
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_);
|
||||
|
||||
if (good_ = std::get<impl::in_memory_file_storage>(storage_).good_) {
|
||||
if ((good_ = std::get<impl::in_memory_file_storage>(storage_).good_)) {
|
||||
// @todo unify these names, it's already confusing enough as it stands
|
||||
byid_ = decltype(byid_)(&std::get<impl::in_memory_file_storage>(storage_).byid_);
|
||||
byref_excl_ = decltype(byref_excl_)(&std::get<impl::in_memory_file_storage>(storage_).byref_excl_);
|
||||
@@ -1398,13 +1252,18 @@ IfcFile::IfcFile(const std::string& path, filetype ty, bool readonly)
|
||||
}
|
||||
ifcroot_type_ = schema_ ? schema_->declaration_by_name("IfcRoot") : nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
IfcFile::IfcFile(std::istream& stream, int length)
|
||||
: schema_(nullptr)
|
||||
, max_id_(0)
|
||||
{
|
||||
IfcSpfStream s(stream, length);
|
||||
FileReader s(FileReader::caller_fed_tag{});
|
||||
|
||||
std::string string_data;
|
||||
string_data.resize(length);
|
||||
stream.read(string_data.data(), length);
|
||||
s.push_next_page(string_data);
|
||||
|
||||
storage_.emplace<1>(this);
|
||||
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_);
|
||||
good_ = std::get<impl::in_memory_file_storage>(storage_).good_;
|
||||
@@ -1419,7 +1278,8 @@ IfcFile::IfcFile(void* data, int length)
|
||||
: schema_(nullptr)
|
||||
, max_id_(0)
|
||||
{
|
||||
IfcSpfStream s(data, length);
|
||||
FileReader s(std::string((char*)data, length), FileReader::caller_fed_tag{});
|
||||
|
||||
storage_.emplace<1>(this);
|
||||
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_);
|
||||
good_ = std::get<impl::in_memory_file_storage>(storage_).good_;
|
||||
@@ -1430,7 +1290,7 @@ IfcFile::IfcFile(void* data, int length)
|
||||
byguid_ = decltype(byguid_)(&std::get<impl::in_memory_file_storage>(storage_).byguid_);
|
||||
}
|
||||
|
||||
IfcFile::IfcFile(IfcParse::IfcSpfStream* s)
|
||||
IfcFile::IfcFile(IfcParse::FileReader* s)
|
||||
: schema_(nullptr)
|
||||
, max_id_(0)
|
||||
{
|
||||
@@ -1475,18 +1335,65 @@ IfcFile::IfcFile(const IfcParse::schema_definition* schema, filetype ty, const s
|
||||
setDefaultHeaderValues();
|
||||
}
|
||||
|
||||
IfcParse::InstanceStreamer::InstanceStreamer(const std::string& fn)
|
||||
: stream_(new IfcSpfStream(fn))
|
||||
bool IfcParse::InstanceStreamer::has_semicolon() const
|
||||
{
|
||||
auto local_stream = stream_->clone();
|
||||
auto local_lexer = IfcSpfLexer(&local_stream);
|
||||
Token t = local_lexer.Next();
|
||||
while (t.type != Token_NONE) {
|
||||
if (TokenFunc::isOperator(t, ';')) {
|
||||
return true;
|
||||
}
|
||||
// probably the issue is that this moves the cursor past the page boundary on the local stream which also affects the global one
|
||||
// 'freeze' the stream so that no pages are cleared
|
||||
t = local_lexer.Next();
|
||||
}
|
||||
std::cout << "local: " << local_stream.tell() << " global: " << stream_->tell() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void IfcParse::InstanceStreamer::push_page(const std::string& page)
|
||||
{
|
||||
std::cout << "global: " << stream_->tell() << std::endl;
|
||||
stream_->push_next_page(page);
|
||||
if (good_ == file_open_status::NO_HEADER) {
|
||||
header_ = new IfcParse::IfcSpfHeader(lexer_);
|
||||
if (header_->tryRead() && header_->file_schema()->schema_identifiers().size() == 1) {
|
||||
try {
|
||||
schema_ = IfcParse::schema_by_name(header_->file_schema()->schema_identifiers().front());
|
||||
good_ = file_open_status::SUCCESS;
|
||||
} catch (const IfcParse::IfcException&) {
|
||||
}
|
||||
}
|
||||
storage_.file = nullptr;
|
||||
storage_.schema = schema_;
|
||||
storage_.tokens = lexer_;
|
||||
storage_.references_to_resolve = &references_to_resolve_;
|
||||
}
|
||||
}
|
||||
|
||||
IfcParse::InstanceStreamer::InstanceStreamer()
|
||||
: stream_(new FileReader(FileReader::caller_fed_tag{}))
|
||||
, lexer_(new IfcSpfLexer(stream_))
|
||||
, token_stream_(3, Token{})
|
||||
, schema_(nullptr)
|
||||
, progress_(0)
|
||||
{
|
||||
init_locale();
|
||||
good_ = file_open_status::NO_HEADER;
|
||||
}
|
||||
|
||||
IfcParse::InstanceStreamer::InstanceStreamer(const std::string& fn, bool mmap)
|
||||
: stream_(mmap ? new FileReader(fn, FileReader::mmap_tag{}) : new FileReader(fn))
|
||||
, lexer_(new IfcSpfLexer(stream_))
|
||||
, token_stream_(3, Token{})
|
||||
, schema_(nullptr)
|
||||
, ifcroot_type_(nullptr)
|
||||
, progress_(0)
|
||||
{
|
||||
init_locale();
|
||||
|
||||
good_ = file_open_status::NO_HEADER;
|
||||
if (*stream_) {
|
||||
if (stream_->size() && !stream_->eof()) {
|
||||
header_ = new IfcParse::IfcSpfHeader(lexer_);
|
||||
if (header_->tryRead() && header_->file_schema()->schema_identifiers().size() == 1) {
|
||||
try {
|
||||
@@ -1503,17 +1410,16 @@ IfcParse::InstanceStreamer::InstanceStreamer(const std::string& fn)
|
||||
}
|
||||
|
||||
IfcParse::InstanceStreamer::InstanceStreamer(void* data, int length)
|
||||
: stream_(new IfcSpfStream(data, length))
|
||||
: stream_(new FileReader(std::string((char*) data, length), FileReader::caller_fed_tag{}))
|
||||
, lexer_(new IfcSpfLexer(stream_))
|
||||
, token_stream_(3, Token{})
|
||||
, schema_(nullptr)
|
||||
, ifcroot_type_(nullptr)
|
||||
, progress_(0)
|
||||
{
|
||||
init_locale();
|
||||
|
||||
good_ = file_open_status::NO_HEADER;
|
||||
if (*stream_) {
|
||||
if (stream_->size() && !stream_->eof()) {
|
||||
header_ = new IfcParse::IfcSpfHeader(lexer_);
|
||||
if (header_->tryRead() && header_->file_schema()->schema_identifiers().size() == 1) {
|
||||
try {
|
||||
@@ -1535,7 +1441,6 @@ IfcParse::InstanceStreamer::InstanceStreamer(const IfcParse::schema_definition*
|
||||
, header_(nullptr)
|
||||
, token_stream_(3, Token{})
|
||||
, schema_(schema)
|
||||
, ifcroot_type_(schema->declaration_by_name("IfcRoot"))
|
||||
, progress_(0)
|
||||
{
|
||||
init_locale();
|
||||
@@ -1546,14 +1451,14 @@ IfcParse::InstanceStreamer::InstanceStreamer(const IfcParse::schema_definition*
|
||||
storage_.references_to_resolve = &references_to_resolve_;
|
||||
}
|
||||
|
||||
void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::IfcSpfStream* s, const IfcParse::schema_definition*& schema, unsigned int& max_id) {
|
||||
void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::FileReader* s, const IfcParse::schema_definition*& schema, unsigned int& max_id) {
|
||||
// Initialize a "C" locale for locale-independent
|
||||
// number parsing. See comment above on line 41.
|
||||
init_locale();
|
||||
|
||||
tokens = nullptr;
|
||||
|
||||
if (!s->valid) {
|
||||
if (!s->size() || s->eof()) {
|
||||
// @todo set good on parent file
|
||||
good_ = file_open_status::READ_ERROR;
|
||||
return;
|
||||
@@ -1608,7 +1513,7 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::IfcSpfSt
|
||||
|
||||
auto instance = schema->instantiate(std::get<1>(*inst), std::move(std::get<2>(*inst)));
|
||||
instance->file_ = file;
|
||||
instance->id_ = current_id;
|
||||
instance->id_ = (uint32_t) current_id;
|
||||
|
||||
if (instance->declaration().is(*ifcroot_type_)) {
|
||||
try {
|
||||
@@ -1641,7 +1546,7 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::IfcSpfSt
|
||||
}
|
||||
|
||||
// byidentity_[instance->identity()] = instance;
|
||||
byid_.insert({ current_id, instance });
|
||||
byid_.insert({(uint32_t) current_id, instance });
|
||||
|
||||
// @nb cannot assign to byid_;
|
||||
// byid_[current_id] = instance;
|
||||
@@ -1693,10 +1598,10 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::IfcSpfSt
|
||||
} else if (auto* inst = std::get_if<IfcUtil::IfcBaseClass*>(v)) {
|
||||
byid_[p.first.name_]->data().set_attribute_value(nullptr, nullptr, 0, p.first.index_, *inst);
|
||||
}
|
||||
} else if (auto* v = std::get_if<std::vector<reference_or_simple_type>>(&p.second)) {
|
||||
} else if (auto* vv = std::get_if<std::vector<reference_or_simple_type>>(&p.second)) {
|
||||
aggregate_of_instance::ptr instances(new aggregate_of_instance);
|
||||
instances->reserve(v->size());
|
||||
for (const auto& vi : *v) {
|
||||
instances->reserve(vv->size());
|
||||
for (const auto& vi : *vv) {
|
||||
if (auto* name = std::get_if<InstanceReference>(&vi)) {
|
||||
auto it = byid_.find(*name);
|
||||
if (it == byid_.end()) {
|
||||
@@ -1726,9 +1631,9 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::IfcSpfSt
|
||||
} else {
|
||||
Logger::Error("Duplicate definition for instance reference");
|
||||
}
|
||||
} else if (auto* v = std::get_if<std::vector<std::vector<reference_or_simple_type>>>(&p.second)) {
|
||||
} else if (auto* vvv = std::get_if<std::vector<std::vector<reference_or_simple_type>>>(&p.second)) {
|
||||
aggregate_of_aggregate_of_instance::ptr instances(new aggregate_of_aggregate_of_instance);
|
||||
for (const auto& vi : *v) {
|
||||
for (const auto& vi : *vvv) {
|
||||
std::vector<IfcUtil::IfcBaseClass*> inner;
|
||||
for (const auto& vii : vi) {
|
||||
if (auto* name = std::get_if<InstanceReference>(&vii)) {
|
||||
@@ -2003,15 +1908,15 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
|
||||
auto attr = entity->get_attribute_value(i);
|
||||
IfcUtil::ArgumentType attr_type = attr.type();
|
||||
|
||||
IfcParse::declaration* decl = 0;
|
||||
IfcParse::declaration* potentially_length_measure_decl = 0;
|
||||
if (entity->declaration().as_entity() != nullptr) {
|
||||
decl = 0;
|
||||
potentially_length_measure_decl = 0;
|
||||
const parameter_type* pt = entity->declaration().as_entity()->attribute_by_index(i)->type_of_attribute();
|
||||
while (pt->as_aggregation_type() != nullptr) {
|
||||
pt = pt->as_aggregation_type()->type_of_element();
|
||||
}
|
||||
if (pt->as_named_type() != nullptr) {
|
||||
decl = pt->as_named_type()->declared_type();
|
||||
potentially_length_measure_decl = pt->as_named_type()->declared_type();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2050,7 +1955,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
|
||||
}
|
||||
|
||||
new_entity->set_attribute_value(i, new_instances);
|
||||
} else if ((decl != nullptr) && decl->is(*schema()->declaration_by_name("IfcLengthMeasure"))) {
|
||||
} else if ((potentially_length_measure_decl != nullptr) && potentially_length_measure_decl->is(*schema()->declaration_by_name("IfcLengthMeasure"))) {
|
||||
if (boost::math::isnan(conversion_factor)) {
|
||||
std::pair<IfcUtil::IfcBaseClass*, double> this_file_unit = {nullptr, 1.0};
|
||||
std::pair<IfcUtil::IfcBaseClass*, double> other_file_unit = {nullptr, 1.0};
|
||||
@@ -2283,8 +2188,6 @@ void IfcFile::process_deletion_(IfcUtil::IfcBaseClass* entity) {
|
||||
|
||||
byid_.erase(entity->id());
|
||||
|
||||
const IfcParse::declaration* ty = &entity->declaration();
|
||||
|
||||
remove_type_ref(entity);
|
||||
|
||||
// entity_file_map is in place to prevent duplicate definitions with usage of add().
|
||||
@@ -2891,7 +2794,7 @@ AttributeValue IfcEntityInstanceData::get_attribute_value(void* storage, const I
|
||||
if (storage_) {
|
||||
return AttributeValue(storage_, (uint8_t)index);
|
||||
} else {
|
||||
return AttributeValue((IfcParse::impl::rocks_db_file_storage*)storage, identity, decl, index);
|
||||
return AttributeValue((IfcParse::impl::rocks_db_file_storage*)storage, identity, decl, (uint8_t) index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user