mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-18 19:30:25 +00:00
Auto-detect filetype
This commit is contained in:
@@ -206,7 +206,7 @@ size_t read_filters_from_file(const std::string&, inclusion_filter&, inclusion_t
|
|||||||
void parse_filter(geom_filter &, const std::vector<std::string>&);
|
void parse_filter(geom_filter &, const std::vector<std::string>&);
|
||||||
std::vector<IfcGeom::filter_t> setup_filters(const std::vector<geom_filter>&, const std::string&);
|
std::vector<IfcGeom::filter_t> setup_filters(const std::vector<geom_filter>&, const std::string&);
|
||||||
|
|
||||||
bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file, bool no_progress, bool mmap, bool rocksdb);
|
bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file, bool no_progress, bool mmap);
|
||||||
|
|
||||||
// from https://stackoverflow.com/questions/31696328/boost-program-options-using-zero-parameter-options-multiple-times
|
// from https://stackoverflow.com/questions/31696328/boost-program-options-using-zero-parameter-options-multiple-times
|
||||||
struct verbosity_counter {
|
struct verbosity_counter {
|
||||||
@@ -239,7 +239,6 @@ int main(int argc, char** argv) {
|
|||||||
path_t cache_file;
|
path_t cache_file;
|
||||||
std::string log_format;
|
std::string log_format;
|
||||||
std::string geometry_kernel;
|
std::string geometry_kernel;
|
||||||
std::string input_format;
|
|
||||||
|
|
||||||
po::options_description generic_options("Command line options");
|
po::options_description generic_options("Command line options");
|
||||||
verbosity_counter vcounter;
|
verbosity_counter vcounter;
|
||||||
@@ -255,7 +254,6 @@ int main(int argc, char** argv) {
|
|||||||
("yes,y", "answer 'yes' automatically to possible confirmation queries (e.g. overwriting an existing output file)")
|
("yes,y", "answer 'yes' automatically to possible confirmation queries (e.g. overwriting an existing output file)")
|
||||||
("no-progress", "suppress possible progress bar type of prints that use carriage return")
|
("no-progress", "suppress possible progress bar type of prints that use carriage return")
|
||||||
("log-format", po::value<std::string>(&log_format), "log format: plain or json")
|
("log-format", po::value<std::string>(&log_format), "log format: plain or json")
|
||||||
("input-format", po::value<std::string>(&input_format), "input format: ifcspf, ifcxml, rocksdb")
|
|
||||||
("log-file", new po::typed_value<path_t, char_t>(&log_file), "redirect log output to file");
|
("log-file", new po::typed_value<path_t, char_t>(&log_file), "redirect log output to file");
|
||||||
|
|
||||||
po::options_description fileio_options;
|
po::options_description fileio_options;
|
||||||
@@ -662,7 +660,7 @@ int main(int argc, char** argv) {
|
|||||||
if (output_extension == XML) {
|
if (output_extension == XML) {
|
||||||
int exit_code = EXIT_FAILURE;
|
int exit_code = EXIT_FAILURE;
|
||||||
try {
|
try {
|
||||||
if (init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap, input_format=="rocksdb")) {
|
if (init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap)) {
|
||||||
time_t start, end;
|
time_t start, end;
|
||||||
time(&start);
|
time(&start);
|
||||||
XmlSerializer s(ifc_file, IfcUtil::path::to_utf8(output_temp_filename));
|
XmlSerializer s(ifc_file, IfcUtil::path::to_utf8(output_temp_filename));
|
||||||
@@ -682,7 +680,7 @@ int main(int argc, char** argv) {
|
|||||||
} else if (output_extension == IFC) {
|
} else if (output_extension == IFC) {
|
||||||
int exit_code = EXIT_FAILURE;
|
int exit_code = EXIT_FAILURE;
|
||||||
try {
|
try {
|
||||||
if (init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap, input_format == "rocksdb")) {
|
if (init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap)) {
|
||||||
time_t start, end;
|
time_t start, end;
|
||||||
time(&start);
|
time(&start);
|
||||||
std::ofstream fs(output_filename.c_str());
|
std::ofstream fs(output_filename.c_str());
|
||||||
@@ -708,7 +706,7 @@ int main(int argc, char** argv) {
|
|||||||
else if (output_extension == RDB) {
|
else if (output_extension == RDB) {
|
||||||
int exit_code = EXIT_FAILURE;
|
int exit_code = EXIT_FAILURE;
|
||||||
try {
|
try {
|
||||||
if (init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap, input_format == "rocksdb")) {
|
if (init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap)) {
|
||||||
time_t start, end;
|
time_t start, end;
|
||||||
time(&start);
|
time(&start);
|
||||||
RocksDbSerializer s(ifc_file, IfcUtil::path::to_utf8(output_filename));
|
RocksDbSerializer s(ifc_file, IfcUtil::path::to_utf8(output_filename));
|
||||||
@@ -941,7 +939,7 @@ int main(int argc, char** argv) {
|
|||||||
time_t start,end;
|
time_t start,end;
|
||||||
time(&start);
|
time(&start);
|
||||||
|
|
||||||
if (!init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap, input_format == "rocksdb")) {
|
if (!init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap)) {
|
||||||
write_log(!quiet);
|
write_log(!quiet);
|
||||||
serializer.reset();
|
serializer.reset();
|
||||||
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename)); /**< @todo Windows Unicode support */
|
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename)); /**< @todo Windows Unicode support */
|
||||||
@@ -1274,7 +1272,7 @@ void write_log(bool header) {
|
|||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
|
||||||
bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file, bool no_progress, bool mmap, bool rocksdb) {
|
bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file, bool no_progress, bool mmap) {
|
||||||
time_t start, end;
|
time_t start, end;
|
||||||
|
|
||||||
// Prevent IfcFile::Init() prints by setting output to null temporarily
|
// Prevent IfcFile::Init() prints by setting output to null temporarily
|
||||||
@@ -1293,7 +1291,7 @@ bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file,
|
|||||||
ifc_file = new IfcParse::IfcFile(filename, mmap);
|
ifc_file = new IfcParse::IfcFile(filename, mmap);
|
||||||
#else
|
#else
|
||||||
(void)mmap;
|
(void)mmap;
|
||||||
ifc_file = new IfcParse::IfcFile(filename, rocksdb ? IfcParse::rocksdb : IfcParse::ifcspf);
|
ifc_file = new IfcParse::IfcFile(filename);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -499,3 +499,43 @@ IfcParse::IfcFile::~IfcFile() {
|
|||||||
delete p.second;
|
delete p.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
IfcParse::filetype IfcParse::guess_file_type(const std::string& fn) {
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
if (!fs::exists(fn)) {
|
||||||
|
// @todo this is just weird, but for consistency with earlier behaviour
|
||||||
|
// for now the only intent for this function is to auto-detect RocksDB
|
||||||
|
return FT_IFCSPF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs::is_directory(fn)) {
|
||||||
|
// Typical RocksDB file to look for
|
||||||
|
auto currentFile = fs::path(fn) / "CURRENT";
|
||||||
|
|
||||||
|
if (!fs::exists(currentFile) || !fs::is_regular_file(currentFile)) {
|
||||||
|
return FT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream infile(currentFile);
|
||||||
|
if (!infile) {
|
||||||
|
return FT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
if (!std::getline(infile, line)) {
|
||||||
|
return FT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RocksDB's CURRENT file typically contains a line like "MANIFEST-000001".
|
||||||
|
if (line.find("MANIFEST-") == 0) {
|
||||||
|
return FT_ROCKSDB;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// @todo just return SPF for now, but ideally this will be augmented with all other options
|
||||||
|
return FT_IFCSPF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+10
-6
@@ -572,12 +572,16 @@ namespace impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum filetype {
|
enum filetype {
|
||||||
ifcspf,
|
FT_IFCSPF,
|
||||||
ifcxml,
|
FT_IFCXML,
|
||||||
rocksdb,
|
FT_IFCZIP,
|
||||||
autodetect
|
FT_ROCKSDB,
|
||||||
|
FT_UNKNOWN,
|
||||||
|
FT_AUTODETECT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
filetype guess_file_type(const std::string& fn);
|
||||||
|
|
||||||
/// This class provides access to the entity instances in an IFC file
|
/// This class provides access to the entity instances in an IFC file
|
||||||
/// The file takes ownership of instances added to this file and deletes them when the file is deleted.
|
/// The file takes ownership of instances added to this file and deletes them when the file is deleted.
|
||||||
class IFC_PARSE_API IfcFile {
|
class IFC_PARSE_API IfcFile {
|
||||||
@@ -623,13 +627,13 @@ private:
|
|||||||
#ifdef USE_MMAP
|
#ifdef USE_MMAP
|
||||||
IfcFile(const std::string& path, bool mmap = false);
|
IfcFile(const std::string& path, bool mmap = false);
|
||||||
#else
|
#else
|
||||||
IfcFile(const std::string& path, filetype ty=ifcspf);
|
IfcFile(const std::string& path, filetype ty=FT_AUTODETECT);
|
||||||
#endif
|
#endif
|
||||||
IfcFile(std::istream& stream, int length);
|
IfcFile(std::istream& stream, int length);
|
||||||
IfcFile(void* data, int length);
|
IfcFile(void* data, int length);
|
||||||
IfcFile(IfcParse::IfcSpfStream* stream);
|
IfcFile(IfcParse::IfcSpfStream* stream);
|
||||||
// @nb path is only used in rocksdb mode, for spf file is in-memory only until write() is called
|
// @nb path is only used in rocksdb mode, for spf file is in-memory only until write() is called
|
||||||
IfcFile(const IfcParse::schema_definition* schema = IfcParse::schema_by_name("IFC4"), filetype ty = ifcspf, const std::string& path = "");
|
IfcFile(const IfcParse::schema_definition* schema = IfcParse::schema_by_name("IFC4"), filetype ty = FT_AUTODETECT, const std::string& path = "");
|
||||||
|
|
||||||
~IfcFile();
|
~IfcFile();
|
||||||
|
|
||||||
|
|||||||
@@ -1296,7 +1296,10 @@ IfcFile::IfcFile(const std::string& fn, bool mmap) {
|
|||||||
#else
|
#else
|
||||||
IfcFile::IfcFile(const std::string& path, filetype ty) {
|
IfcFile::IfcFile(const std::string& path, filetype ty) {
|
||||||
// @todo allow for rocksdb from path
|
// @todo allow for rocksdb from path
|
||||||
if (ty == ifcspf) {
|
if (ty == FT_AUTODETECT) {
|
||||||
|
ty = guess_file_type(path);
|
||||||
|
}
|
||||||
|
if (ty == FT_IFCSPF) {
|
||||||
IfcSpfStream s(path);
|
IfcSpfStream s(path);
|
||||||
storage_.emplace<1>(); // impl::in_memory_file_storage{};
|
storage_.emplace<1>(); // impl::in_memory_file_storage{};
|
||||||
// @todo assign in constructor
|
// @todo assign in constructor
|
||||||
@@ -1307,7 +1310,7 @@ IfcFile::IfcFile(const std::string& path, filetype ty) {
|
|||||||
byid_ = decltype(byid_)(&std::get<impl::in_memory_file_storage>(storage_).byid_);
|
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_);
|
byref_excl_ = decltype(byref_excl_)(&std::get<impl::in_memory_file_storage>(storage_).byref_excl_);
|
||||||
// byidentity_ = decltype(byidentity_)(&std::get<impl::in_memory_file_storage>(storage_).byidentity_);
|
// byidentity_ = decltype(byidentity_)(&std::get<impl::in_memory_file_storage>(storage_).byidentity_);
|
||||||
} else {
|
} else if (ty == FT_ROCKSDB) {
|
||||||
// @todo this can only be used for databases that already exist, because otherwise there is no way to specify the schema
|
// @todo this can only be used for databases that already exist, because otherwise there is no way to specify the schema
|
||||||
storage_.emplace<2>(path, this);
|
storage_.emplace<2>(path, this);
|
||||||
std::get<impl::rocks_db_file_storage>(storage_).read_schema(schema_);
|
std::get<impl::rocks_db_file_storage>(storage_).read_schema(schema_);
|
||||||
@@ -1315,6 +1318,8 @@ IfcFile::IfcFile(const std::string& path, filetype ty) {
|
|||||||
byid_ = decltype(byid_)(&std::get<impl::rocks_db_file_storage>(storage_).instance_by_name_);
|
byid_ = decltype(byid_)(&std::get<impl::rocks_db_file_storage>(storage_).instance_by_name_);
|
||||||
byref_excl_ = decltype(byref_excl_)(&std::get<impl::rocks_db_file_storage>(storage_).byref_excl_);
|
byref_excl_ = decltype(byref_excl_)(&std::get<impl::rocks_db_file_storage>(storage_).byref_excl_);
|
||||||
// byidentity_ = decltype(byidentity_)(&std::get<impl::rocks_db_file_storage>(storage_).instance_cache_);
|
// byidentity_ = decltype(byidentity_)(&std::get<impl::rocks_db_file_storage>(storage_).instance_cache_);
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Unsupported file format");
|
||||||
}
|
}
|
||||||
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
|
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
|
||||||
}
|
}
|
||||||
@@ -1344,21 +1349,26 @@ IfcFile::IfcFile(const IfcParse::schema_definition* schema, filetype ty, const s
|
|||||||
: schema_(schema)
|
: schema_(schema)
|
||||||
, ifcroot_type_(schema_->declaration_by_name("IfcRoot"))
|
, ifcroot_type_(schema_->declaration_by_name("IfcRoot"))
|
||||||
, max_id_(0)
|
, max_id_(0)
|
||||||
, _header(ty == rocksdb ? this : nullptr)
|
, _header(ty == FT_ROCKSDB ? this : nullptr)
|
||||||
{
|
{
|
||||||
if (ty == ifcspf) {
|
if (ty == FT_AUTODETECT) {
|
||||||
|
ty = guess_file_type(path);
|
||||||
|
}
|
||||||
|
if (ty == FT_IFCSPF) {
|
||||||
storage_.emplace<1>();
|
storage_.emplace<1>();
|
||||||
std::get<impl::in_memory_file_storage>(storage_).file = this;
|
std::get<impl::in_memory_file_storage>(storage_).file = this;
|
||||||
|
|
||||||
byid_ = decltype(byid_)(&std::get<impl::in_memory_file_storage>(storage_).byid_);
|
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_);
|
byref_excl_ = decltype(byref_excl_)(&std::get<impl::in_memory_file_storage>(storage_).byref_excl_);
|
||||||
// byidentity_ = decltype(byidentity_)(&std::get<impl::in_memory_file_storage>(storage_).byidentity_);
|
// byidentity_ = decltype(byidentity_)(&std::get<impl::in_memory_file_storage>(storage_).byidentity_);
|
||||||
} else {
|
} else if (ty == FT_ROCKSDB) {
|
||||||
storage_.emplace<2>(path, this);
|
storage_.emplace<2>(path, this);
|
||||||
|
|
||||||
byid_ = decltype(byid_)(&std::get<impl::rocks_db_file_storage>(storage_).instance_by_name_);
|
byid_ = decltype(byid_)(&std::get<impl::rocks_db_file_storage>(storage_).instance_by_name_);
|
||||||
byref_excl_ = decltype(byref_excl_)(&std::get<impl::rocks_db_file_storage>(storage_).byref_excl_);
|
byref_excl_ = decltype(byref_excl_)(&std::get<impl::rocks_db_file_storage>(storage_).byref_excl_);
|
||||||
// byidentity_ = decltype(byidentity_)(&std::get<impl::rocks_db_file_storage>(storage_).instance_cache_);
|
// byidentity_ = decltype(byidentity_)(&std::get<impl::rocks_db_file_storage>(storage_).instance_cache_);
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Unsupported file format");
|
||||||
}
|
}
|
||||||
setDefaultHeaderValues();
|
setDefaultHeaderValues();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user