// ************************************ // * // * rntviewer // * // * A graphical RNTuple visualizer // * // * @author silverweed, 2024 // * // *********************************** #include #include #include #include #include #include #include #ifdef DEBUG #include #endif #ifndef RNT_NO_GFX #include #include #include #include #define GLFW_INCLUDE_NONE #include #endif #define V_MAJOR "0" #define V_MINOR "2" #include "root/root_inc.h" #include "root/RMicroFileReader.hxx" #include "types.h" #include "defer.hpp" #include "prof.hpp" #include "mem.h" #include "str.h" #include "rntuple.h" #include "window.h" #include "render.h" #include "app_state.h" // @Platform #include "platform_linux.h" namespace chr = std::chrono; #include "mem.cpp" #include "str.cpp" #include "rntuple.cpp" #include "render_term.cpp" #include "argparse.cpp" #ifndef RNT_NO_GFX #include "render.cpp" #include "mainloop.cpp" #endif internal void app_cleanup(App_State &app) { os_stop_file_watch(app); os_unmap_file(app.inspected_file.mem, app.inspected_file.size); if (app.inspected_file.stream) fclose(app.inspected_file.stream); } int main(int argc, char **argv) { // Prepare thread context Thread_Ctx tctx; tctx_init(tctx); defer { tctx_release(); }; // Allocate program memory Arena *arena = arena_alloc(); if (!arena) { fprintf(stderr, "Failed to allocate memory\n"); return 1; } defer { arena_release(arena); }; // Parse cmdline Cmdline_Args args = parse_args(argc, argv); if (args.show_help_and_exit || !args.ntpl_name.size || !args.file_name.size) { print_help(argv[0]); return 1; } #ifdef RNT_NO_GFX if (!args.print_to_terminal) { fprintf(stderr, "rntviewer was compiled without graphics support. Please use -t to enable terminal mode."); return 0; } #endif // Create app state App_State app {}; defer { app_cleanup(app); }; // Open and map the file if (args.file_name.size) { if (!os_open_and_map_file(args.file_name, app)) return 1; // Watch file for changes (to adapt the displayed file size - otherwise // we may try to access invalid memory when the file gets shrunk) if (!args.print_to_terminal) os_start_file_watch(args.file_name, app); } app.ntpl_name = args.ntpl_name; app.base_display_addr = args.start_addr; app.tfile_data = get_tfile_data(app.inspected_file, app.ntpl_name); app.rndata = get_rntuple_data(arena, app.inspected_file, app.ntpl_name); if (args.print_to_terminal) { u64 nbytes_displayed = args.nbytes_displayed; if (!nbytes_displayed) nbytes_displayed = 1000; String8 rendered = render_range_to_string(arena, app, nbytes_displayed, args.n_cols); printf("%s\n", rendered.c()); return 0; } #ifndef RNT_NO_GFX // Init imgui and GLFW GLFWwindow *window = init_glfw(800, 600); if (!window) { fprintf(stderr, "Failed to init GLFW\n"); return 1; } defer { glfwTerminate(); }; if (!init_imgui(window)) { fprintf(stderr, "Failed to init Imgui\n"); return 1; } make_viewer(app, args.n_cols); // Start main loop run_main_loop(window, arena, app); #endif return 0; }