From 3e816ba5958f7985b3a27008ec1770a8e4b406a7 Mon Sep 17 00:00:00 2001 From: Gabriel Dos Reis Date: Sun, 27 Jul 2025 20:04:08 -0700 Subject: [PATCH] Use `ifc::tool::InputFile` in IFC printer This patch makes the IFC printer use memory mapping for input IFC files via `ifc::tool::InputFile` --- src/ifc-printer/main.cxx | 191 +++++++++++++++++++-------------------- 1 file changed, 93 insertions(+), 98 deletions(-) diff --git a/src/ifc-printer/main.cxx b/src/ifc-printer/main.cxx index 16844f5..0463bfe 100644 --- a/src/ifc-printer/main.cxx +++ b/src/ifc-printer/main.cxx @@ -29,98 +29,90 @@ auto& std_error = std::cerr; using namespace ifc::util; using namespace std::literals; -struct Arguments { - PrintOptions options = PrintOptions::None; +namespace { + struct Arguments { + PrintOptions options = PrintOptions::None; - // Files to process. - std::vector files; -}; + // Files to process. + std::vector files; + }; -void print_help(const ifc::fs::path& path) -{ - auto name = path.stem().string(); - std::cout << "Usage:\n\n"; - std::cout << name << " ifc-file1 [ifc-file2 ...] [--color/-c]\n"; - std::cout << name << " --help/-h\n"; -} + void print_help(const ifc::fs::path& path) + { + auto name = path.stem().string(); + std::cout << "Usage:\n\n"; + std::cout << name << " ifc-file1 [ifc-file2 ...] [--color/-c]\n"; + std::cout << name << " --help/-h\n"; + } -Arguments process_args(int argc, ifc::tool::NativeChar* argv[]) -{ - Arguments result; - for (int i = 1; i < argc; ++i) + Arguments process_args(int argc, ifc::tool::NativeChar* argv[]) { - if (argv[i] == NSV("--help")) + Arguments result; + for (int i = 1; i < argc; ++i) { - print_help(argv[0]); - exit(0); - } - else if (argv[i] == NSV("--color")) - { - result.options |= PrintOptions::Use_color; + if (argv[i] == NSV("--help")) + { + print_help(argv[0]); + exit(0); + } + else if (argv[i] == NSV("--color")) + { + result.options |= PrintOptions::Use_color; + } + // Future flags to add as needed + // --location: print locations + // --header: print module header + // etc. + + else if (argv[i][0] != '-') + { + result.files.emplace_back(argv[i]); + } + else + { + std_error << NSV("Unknown command line argument '") << argv[i] << NSV("'\n"); + print_help(argv[0]); + std::exit(1); + } } - // Future flags to add as needed - // --location: print locations - // --header: print module header - // etc. - else if (argv[i][0] != '-') - { - result.files.emplace_back(argv[i]); - } - else + if (result.files.empty()) { - std_error << NSV("Unknown command line argument '") << argv[i] << NSV("'\n"); + std_error << NSV("Specify filepath of an ifc file\n"); print_help(argv[0]); std::exit(1); } - } - if (result.files.empty()) - { - std_error << NSV("Specify filepath of an ifc file\n"); - print_help(argv[0]); - std::exit(1); + return result; } - return result; -} - -std::vector load_file(const ifc::fs::path& path) -{ - auto size = std::filesystem::file_size(path); - std::vector v; - v.resize(size); - std::ifstream file(path.string(), std::ios::binary); - file.read(reinterpret_cast(v.data()), static_cast(v.size())); - return v; -} - -void process_ifc(const ifc::fs::path& path, PrintOptions options) -{ - auto contents = load_file(path); - - ifc::InputIfc file{gsl::span(contents)}; - ifc::Pathname name{path.u8string().c_str()}; - file.validate(name, ifc::Architecture::Unknown, ifc::Pathname{}, - ifc::IfcOptions::IntegrityCheck); - - ifc::Reader reader(file); - ifc::util::Loader loader(reader); - auto& gs = loader.get(reader.ifc.header()->global_scope); - print(gs, std::cout, options); - - // Make sure that we resolve and print all - // referenced nodes. - options |= PrintOptions::Top_level_index; - while (not loader.referenced_nodes.empty()) + void process_ifc(const ifc::fs::path& path, PrintOptions options) { - auto it = loader.referenced_nodes.begin(); - const auto node_key = *it; - loader.referenced_nodes.erase(it); + ifc::tool::InputFile container { path }; + + ifc::InputIfc file { container.contents() }; + ifc::Pathname name{path.u8string().c_str()}; + file.validate(name, ifc::Architecture::Unknown, ifc::Pathname{}, + ifc::IfcOptions::IntegrityCheck); + + ifc::Reader reader(file); + ifc::util::Loader loader(reader); + auto& gs = loader.get(reader.ifc.header()->global_scope); + print(gs, std::cout, options); + + // Make sure that we resolve and print all + // referenced nodes. + options |= PrintOptions::Top_level_index; + while (not loader.referenced_nodes.empty()) + { + auto it = loader.referenced_nodes.begin(); + const auto node_key = *it; + loader.referenced_nodes.erase(it); - auto& item = loader.get(node_key); - print(item, std::cout, options); + auto& item = loader.get(node_key); + print(item, std::cout, options); + } } } @@ -130,32 +122,35 @@ int wmain(int argc, wchar_t* argv[]) int main(int argc, char* argv[]) #endif { - Arguments arguments = process_args(argc, argv); + std::size_t error_count = 0; - try + Arguments arguments = process_args(argc, argv); + for (const auto& file : arguments.files) { - for (const auto& file : arguments.files) + try { process_ifc(file, arguments.options); - - return EXIT_SUCCESS; - } - catch (const ifc::IfcArchMismatch&) - { - std::cerr << "ifc architecture mismatch\n"; - } - catch(ifc::error_condition::UnexpectedVisitor& e) - { - std::cerr << "visit unexpected " << e.category << ": " - << e.sort << '\n'; - } - catch(const ifc::InputIfc::MissingIfcHeader&) - { - std::cerr << "Missing ifc binary file header\n"; - } - catch (...) - { - std::cerr << "unknown exception caught\n"; + continue; + } + catch (const ifc::IfcArchMismatch&) + { + std::cerr << file.string() << ": ifc architecture mismatch\n"; + } + catch(const ifc::error_condition::UnexpectedVisitor& e) + { + std::cerr << file.string() + << ": visit unexpected " << e.category << ", " + << e.sort << "\n"; + } + catch(const ifc::InputIfc::MissingIfcHeader&) + { + std::cerr << file.string() << ": Missing ifc binary file header\n"; + } + catch (...) + { + std::cerr << file.string() << ": unknown exception caught\n"; + } + ++error_count; } - return EXIT_FAILURE; + return error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }