diff --git a/src/ifcopenshell-python/ifcopenshell/__init__.py b/src/ifcopenshell-python/ifcopenshell/__init__.py index a0662f24cc..6f68fee18a 100644 --- a/src/ifcopenshell-python/ifcopenshell/__init__.py +++ b/src/ifcopenshell-python/ifcopenshell/__init__.py @@ -301,10 +301,10 @@ def stream2(path: Union[Path, str]): as a dictionary. Args: - path (Union[Path, str]): _description_ + path (Union[Path, str]): input file path Yields: - _type_: _description_ + dict: entity instance dictionaries """ streamer = ifcopenshell_wrapper.InstanceStreamer(str(path)) while streamer: @@ -312,6 +312,22 @@ def stream2(path: Union[Path, str]): yield inst +def stream2_from_string(data: str): + """Streams the content of a file path from string, yielding each instance + as a dictionary. + + Args: + data (str): input data + + Yields: + dict: entity instance dictionaries + """ + streamer = ifcopenshell_wrapper.stream_from_string(data) + while streamer: + if inst := streamer.read_instance_py(): + yield inst + + def convert_path_to_rocksdb(ifcspf_path: Union[Path, str], rocksdb_path: Union[Path, str]): """Converts an IFC-SPF file on disk to the IfcOpenShell-specific RocksDB encoding. RocksDB is an embedded key-value store that allows diff --git a/src/ifcparse/IfcFile.h b/src/ifcparse/IfcFile.h index 961c56f3fe..8e79856bba 100644 --- a/src/ifcparse/IfcFile.h +++ b/src/ifcparse/IfcFile.h @@ -130,6 +130,8 @@ public: InstanceStreamer(const std::string& fn); + InstanceStreamer(void* data, int length); + InstanceStreamer(const IfcParse::schema_definition* schema, IfcParse::IfcSpfLexer* lexer); ~InstanceStreamer() { diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index cdcdfc8f64..8f3b74f4b6 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -1499,6 +1499,33 @@ IfcParse::InstanceStreamer::InstanceStreamer(const std::string& fn) } } +IfcParse::InstanceStreamer::InstanceStreamer(void* data, int length) + : stream_(new IfcSpfStream(data, length)) + , 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_) { + 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(const IfcParse::schema_definition* schema, IfcParse::IfcSpfLexer* lexer) : stream_(nullptr) , lexer_(lexer) diff --git a/src/ifcwrap/IfcParseWrapper.i b/src/ifcwrap/IfcParseWrapper.i index 21148f1cd2..45a617916e 100644 --- a/src/ifcwrap/IfcParseWrapper.i +++ b/src/ifcwrap/IfcParseWrapper.i @@ -708,6 +708,7 @@ private: %newobject open; %newobject read; %newobject parse_ifcxml; +%newobject stream_from_string; %inline %{ IfcParse::IfcFile* open(const std::string& fn, bool readonly=false) { @@ -728,6 +729,12 @@ private: return f; } + IfcParse::InstanceStreamer* stream_from_string(const std::string& data) { + char* copiedData = new char[data.length()]; + memcpy(copiedData, data.c_str(), data.length()); + return new IfcParse::InstanceStreamer((void *)copiedData, data.length()); + } + const char* version() { return IFCOPENSHELL_VERSION; }