Skip to content

Commit

Permalink
app: refactors json archiver/dearchiver use
Browse files Browse the repository at this point in the history
  • Loading branch information
quesnel committed Aug 20, 2024
1 parent 89c25ea commit 54c4de3
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 177 deletions.
291 changes: 219 additions & 72 deletions app/gui/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,61 +349,7 @@ static void application_manage_menu_action(application& app) noexcept
auto id = app.mod.registred_paths.get_id(path);
path.path = str;

app.add_simulation_task([&app, id]() noexcept {
auto* file = app.mod.registred_paths.try_to_get(id);
if (not file)
return;

auto f = file::open(
file->path.c_str(),
open_mode::read,
[&](file::error_code ec) noexcept {
app.notifications.try_insert(
log_level::error,
[&](auto& title, auto& msg) noexcept {
format(title,
"Fail to open project file {}",
file->path.c_str());

switch (ec) {
case file::error_code::memory_error:
msg = "Memory allocation error";
break;
case file::error_code::eof_error:
msg = "The end of the file is "
"reached too quickly.";
break;
case file::error_code::arg_error:
msg = "Internal error";
break;
case file::error_code::open_error:
msg = "Open file error";
break;
}
});
});

if (not f.has_value()) {
app.mod.registred_paths.free(*file);
return;
}

json_dearchiver read;
if (not read(app.pj, app.mod, app.sim, *f)) {
// @TODO improve details in notifications from file
// error callback.
app.mod.registred_paths.free(*file);
return;
}

app.notifications.try_insert(
log_level::info,
[&](auto& title, auto& msg) noexcept {
format(title,
"Project file {} read",
file->path.c_str());
});
});
app.start_load_project(id);
}
}

Expand Down Expand Up @@ -654,8 +600,8 @@ static void show_select_model_box_recursive(application& app,
show_select_model_box_recursive(app, *sibling, access);
}

auto build_unique_component_vector(application& app, tree_node& tn)
-> vector<component_id>
auto build_unique_component_vector(application& app,
tree_node& tn) -> vector<component_id>
{
vector<component_id> ret;
vector<tree_node*> stack;
Expand Down Expand Up @@ -788,30 +734,231 @@ unordered_task_list& application::get_unordered_task_list(int idx) noexcept
return task_mgr.temp_task_lists[idx];
}

std::optional<file> application::try_open_file(const char* filename,
open_mode mode) noexcept
{
debug::ensure(filename);

if (not filename)
return std::nullopt;

auto f = file::open(filename, mode, [&](file::error_code ec) noexcept {
notifications.try_insert(log_level::error,
[&](auto& title, auto& msg) noexcept {
format(title, "Open file {}", filename);
switch (ec) {
case file::error_code::memory_error:
msg = "Memory allocation error";
break;
case file::error_code::eof_error:
msg = "End of file reached to quickly";
break;

case file::error_code::arg_error:
msg = "Internal error (bad argument)";
break;

case file::error_code::open_error:
msg = "Filesystem error";
break;
};
});
});

return f;
}

void application::start_load_project(const registred_path_id id) noexcept
{
add_gui_task([&, id]() noexcept {
std::scoped_lock _(mod.reg_paths_mutex);

auto* file = mod.registred_paths.try_to_get(id);
if (not file)
return;

std::scoped_lock lock(file->mutex);

auto f_opt = try_open_file(file->path.c_str(), open_mode::read);
if (not f_opt)
return;

json_dearchiver dearc;
dearc(
pj,
mod,
sim,
*f_opt,
[&](
json_dearchiver::error_code ec,
std::
variant<std::monostate, sz, int, std::pair<sz, std::string_view>>
v) noexcept {
notifications.try_insert(
log_level::error, [&](auto& title, auto& msg) noexcept {
format(title,
"Loading project file {} error",
file->path.c_str());
switch (ec) {
case json_dearchiver::error_code::memory_error:
if (auto* ptr = std::get_if<sz>(&v); ptr) {
format(msg,
"json de-archiving memory error: not "
"enough memory "
"(requested: {})\n",
*ptr);
} else {
format(msg,
"json de-archiving memory error: not "
"enough memory\n");
}
break;

case json_dearchiver::error_code::arg_error:
format(msg, "json de-archiving internal error\n");
break;

case json_dearchiver::error_code::file_error:
if (auto* ptr = std::get_if<sz>(&v); ptr) {
format(msg,
"json de-archiving file error: file too "
"small {}\n",
*ptr);
} else {
format(msg,
"json de-archiving memory error: not "
"enough memory\n");
}
break;

case json_dearchiver::error_code::read_error:
if (auto* ptr = std::get_if<int>(&v);
ptr and *ptr != 0) {
format(msg,
"json de-archiving read error: internal "
"system {} ({})\n",
*ptr,
std::strerror(*ptr));
} else {
format(msg, "json de-archiving read error\n");
}
break;

case json_dearchiver::error_code::format_error:
if (auto* ptr =
std::get_if<std::pair<sz, std::string_view>>(&v);
ptr) {
if (ptr->second.empty()) {
format(msg,
"json de-archiving json format error at "
"offset "
"{}\n",
ptr->first);

} else {
format(msg,
"json de-archiving json format error "
"`{}' at offset "
"{}\n",
ptr->second,
ptr->first);
}
} else {
format(msg,
"json de-archiving json format error\n");
}
break;

default:
format(msg, "json de-archiving unknown error\n");
}
});
});

notifications.try_insert(
log_level::info, [&](auto& title, auto& /*msg*/) noexcept {
format(
title, "Loading project file {} success", file->path.c_str());
});
});
}

void application::start_save_project(const registred_path_id id) noexcept
{
add_gui_task([&, id]() noexcept {
std::scoped_lock _(mod.reg_paths_mutex);

if (auto* file = mod.registred_paths.try_to_get(id); file) {
std::scoped_lock lock(file->mutex);
auto* file = mod.registred_paths.try_to_get(id);
if (not file)
return;

std::scoped_lock lock(file->mutex);

auto f_opt = try_open_file(file->path.c_str(), open_mode::write);
if (not f_opt)
return;

json_archiver arc;
arc(
pj,
mod,
sim,
*f_opt,
json_archiver::print_option::indent_2_one_line_array,
[&](json_archiver::error_code ec,
std::variant<std::monostate, sz, int> v) noexcept {
notifications.try_insert(
log_level::error, [&](auto& title, auto& msg) noexcept {
format(title,
"Saving project file {} error",
file->path.c_str());

switch (ec) {
case json_archiver::error_code::memory_error:
if (auto* ptr = std::get_if<sz>(&v); ptr) {
format(
msg,
"json archiving memory error: not enough memory "
"(requested: {})\n",
*ptr);
} else {
format(msg,
"json archiving memory error: not "
"enough memory\n");
}
break;

auto& n = notifications.alloc();
n.title = "Save project";
case json_archiver::error_code::arg_error:
format(msg, "json archiving internal error\n");
break;

attempt_all(
[&]() -> status {
return pj.save(mod, sim, cache, file->path.c_str());
},
case json_archiver::error_code::empty_project:
format(msg, "json archiving empty project error\n");
break;

[&]() -> void {
format(
n.message, "Error writing file {}", file->path.c_str());
});
case json_archiver::error_code::file_error:
format(msg, "json archiving file access error\n");
break;

mod.registred_paths.free(*file);
notifications.enable(n);
}
case json_archiver::error_code::format_error:
format(msg, "json archiving format error\n");
break;

case json_archiver::error_code::dependency_error:
format(msg, "json archiving format error\n");
break;

default:
format(msg, "json de-archiving unknown error\n");
}
});
});

notifications.try_insert(
log_level::info, [&](auto& title, auto& /*msg*/) noexcept {
format(
title, "Saving project file {} success", file->path.c_str());
});
});
}

Expand Down
13 changes: 7 additions & 6 deletions app/gui/application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define ORG_VLEPROJECT_IRRITATOR_APP_APPLICATION_2021

#include <irritator/core.hpp>
#include <irritator/file.hpp>
#include <irritator/helpers.hpp>
#include <irritator/modeling.hpp>
#include <irritator/observation.hpp>
Expand All @@ -24,7 +25,7 @@
namespace irt {

template<class T, class M>
constexpr std::ptrdiff_t offset_of(const M T::*member)
constexpr std::ptrdiff_t offset_of(const M T::* member)
{
return reinterpret_cast<std::ptrdiff_t>(
&(reinterpret_cast<T*>(0)->*member));
Expand All @@ -44,7 +45,7 @@ constexpr std::ptrdiff_t offset_of(const M T::*member)
//! }
//! @endcode
template<class T, class M>
constexpr T& container_of(M* ptr, const M T::*member)
constexpr T& container_of(M* ptr, const M T::* member)
{
return *reinterpret_cast<T*>(reinterpret_cast<intptr_t>(ptr) -
offset_of(member));
Expand Down Expand Up @@ -709,10 +710,6 @@ class project_window
public:
project_window() noexcept = default;

void load(const char* filename) noexcept;

void save(const char* filename) noexcept;

//! Display the window if the @c application::pj head is defined.
void show() noexcept;

Expand Down Expand Up @@ -987,6 +984,7 @@ struct application {
//! list is available.
unordered_task_list& get_unordered_task_list(int idx) noexcept;

void start_load_project(const registred_path_id file) noexcept;
void start_save_project(const registred_path_id file) noexcept;
void start_save_component(const component_id id) noexcept;
void start_init_source(const u64 id,
Expand All @@ -998,6 +996,9 @@ struct application {
void start_file_remove(const registred_path_id r,
const dir_path_id d,
const file_path_id f) noexcept;

std::optional<file> try_open_file(const char* filename,
open_mode mode) noexcept;
};

/// Display dialog box to choose a @c model in a hierarchy of a @c tree_node
Expand Down
Loading

0 comments on commit 54c4de3

Please sign in to comment.