Commit 73130e7e authored by Gauthier Quesnel's avatar Gauthier Quesnel
Browse files

io: use c++ stream to fix Win32 FS API

parent 33871967
......@@ -6,6 +6,7 @@
#include "imnodes.hpp"
#include <filesystem>
#include <fstream>
#include <future>
#include <mutex>
#include <string>
......@@ -733,13 +734,15 @@ struct editor
if (!path.empty() && ImGui::MenuItem("Save")) {
log_w.log(3, "Write into file %s\n", path.string().c_str());
writer w(std::fopen(path.string().c_str(), "w"));
if (auto os = std::ofstream(path); os.is_open()) {
writer w(os);
auto ret = w(sim);
if (is_success(ret))
log_w.log(5, "success\n");
else
log_w.log(4, "error writing\n");
}
}
if (ImGui::MenuItem("Save as..."))
show_save_file_dialog = true;
......@@ -788,7 +791,8 @@ struct editor
if (load_file_dialog(path)) {
show_load_file_dialog = false;
log_w.log(5, "Load file from %s\n", path.string().c_str());
reader r(std::fopen(path.string().c_str(), "r"));
if (auto is = std::ifstream(path); is.is_open()) {
reader r(is);
auto ret = r(sim);
if (is_success(ret))
log_w.log(5, "success\n");
......@@ -796,6 +800,7 @@ struct editor
log_w.log(4, "error writing\n");
}
}
}
if (show_save_file_dialog) {
static std::string out;
......@@ -809,7 +814,8 @@ struct editor
log_w.log(5, "Save file to %s\n", path.string().c_str());
log_w.log(3, "Write into file %s\n", path.string().c_str());
writer w(std::fopen(path.string().c_str(), "w"));
if (auto os = std::ofstream(path); os.is_open()) {
writer w(os);
auto ret = w(sim);
if (is_success(ret))
log_w.log(5, "success\n");
......@@ -817,6 +823,7 @@ struct editor
log_w.log(4, "error writing\n");
}
}
}
ImGui::Text("X -- delete selected nodes and/or connections /"
" D -- duplicate selected nodes");
......
......@@ -8,37 +8,35 @@
#include <irritator/core.hpp>
#include <algorithm>
#include <cstdio>
#include <istream>
#include <ostream>
namespace irt {
class reader
{
private:
::std::FILE* file = stdin;
std::istream& is;
array<model_id> map;
int model_error = 0;
int connection_error = 0;
char temp_1[32];
char temp_2[32];
public:
reader(::std::FILE* file_ = stdin) noexcept
: file(file_ == nullptr ? stdin : file_)
reader(std::istream& is_) noexcept
: is(is_)
{}
~reader() noexcept
{
if (file && file != stdin)
::std::fclose(file);
}
~reader() noexcept = default;
status operator()(simulation& sim) noexcept
{
int model_number = 0;
irt_return_if_fail(std::fscanf(file, "%d", &model_number) == 1,
status::io_file_format_error);
irt_return_if_fail((is >> model_number), status::io_file_format_error);
irt_return_if_fail(model_number > 0,
status::io_file_format_model_number_error);
......@@ -47,130 +45,119 @@ public:
std::fill_n(std::begin(map), std::size(map), static_cast<model_id>(0));
int id;
char name[8];
char dynamics[11];
for (int i = 0; i != model_number; ++i, ++model_error) {
irt_return_if_fail(
3 == std::fscanf(file, "%d %7s %10s", &id, name, dynamics),
irt_return_if_fail((is >> id >> temp_1 >> temp_2),
status::io_file_format_model_error);
irt_return_if_fail(0 <= id && id < model_number,
status::io_file_format_model_error);
irt_return_if_bad(read(sim, id, name, dynamics));
irt_return_if_bad(read(sim, id, temp_1, temp_2));
}
while (!std::feof(file)) {
while (is) {
int mdl_src_index, port_src_index, mdl_dst_index, port_dst_index;
int read = std::fscanf(file,
"%d %d %d %d",
&mdl_src_index,
&port_src_index,
&mdl_dst_index,
&port_dst_index);
irt_return_if_fail(read == -1 || read == 0 || read == 4,
status::io_file_format_error);
if (read == -1)
if (!(is >> mdl_src_index >> port_src_index >> mdl_dst_index >>
port_dst_index)) {
if (is.eof())
break;
if (read == 4) {
irt_bad_return(status::io_file_format_error);
}
auto* mdl_src = sim.models.try_to_get(mdl_src_index);
irt_return_if_fail(mdl_src,
status::io_file_format_model_unknown);
irt_return_if_fail(mdl_src, status::io_file_format_model_unknown);
auto* mdl_dst = sim.models.try_to_get(mdl_dst_index);
irt_return_if_fail(mdl_dst,
status::io_file_format_model_unknown);
irt_return_if_fail(mdl_dst, status::io_file_format_model_unknown);
output_port_id output_port;
input_port_id input_port;
irt_return_if_bad(sim.get_output_port_id(
*mdl_src, port_src_index, &output_port));
irt_return_if_bad(
sim.get_output_port_id(*mdl_src, port_src_index, &output_port));
irt_return_if_bad(
sim.get_input_port_id(*mdl_dst, port_dst_index, &input_port));
irt_return_if_bad(sim.connect(output_port, input_port));
++connection_error;
}
}
return status::success;
}
private:
bool convert(const char* dynamics_name, dynamics_type* type) noexcept
bool convert(const std::string_view dynamics_name,
dynamics_type* type) noexcept
{
if (std::strcmp(dynamics_name, "none") == 0) {
if (dynamics_name == "none") {
*type = dynamics_type::none;
return true;
}
if (std::strcmp(dynamics_name, "integrator") == 0) {
if (dynamics_name == "integrator") {
*type = dynamics_type::integrator;
return true;
}
if (std::strcmp(dynamics_name, "quantifier") == 0) {
if (dynamics_name == "quantifier") {
*type = dynamics_type::quantifier;
return true;
}
if (std::strcmp(dynamics_name, "adder_2") == 0) {
if (dynamics_name == "adder_2") {
*type = dynamics_type::adder_2;
return true;
}
if (std::strcmp(dynamics_name, "adder_3") == 0) {
if (dynamics_name == "adder_3") {
*type = dynamics_type::adder_3;
return true;
}
if (std::strcmp(dynamics_name, "adder_4") == 0) {
if (dynamics_name == "adder_4") {
*type = dynamics_type::adder_4;
return true;
}
if (std::strcmp(dynamics_name, "mult_2") == 0) {
if (dynamics_name == "mult_2") {
*type = dynamics_type::mult_2;
return true;
}
if (std::strcmp(dynamics_name, "mult_3") == 0) {
if (dynamics_name == "mult_3") {
*type = dynamics_type::mult_3;
return true;
}
if (std::strcmp(dynamics_name, "mult_4") == 0) {
if (dynamics_name == "mult_4") {
*type = dynamics_type::mult_4;
return true;
}
if (std::strcmp(dynamics_name, "counter") == 0) {
if (dynamics_name == "counter") {
*type = dynamics_type::counter;
return true;
}
if (std::strcmp(dynamics_name, "generator") == 0) {
if (dynamics_name == "generator") {
*type = dynamics_type::generator;
return true;
}
if (std::strcmp(dynamics_name, "constant") == 0) {
if (dynamics_name == "constant") {
*type = dynamics_type::constant;
return true;
}
if (std::strcmp(dynamics_name, "cross") == 0) {
if (dynamics_name == "cross") {
*type = dynamics_type::cross;
return true;
}
if (std::strcmp(dynamics_name, "time_func") == 0) {
if (dynamics_name == "time_func") {
*type = dynamics_type::time_func;
return true;
}
......@@ -217,39 +204,27 @@ private:
bool read(integrator& dyn) noexcept
{
return 2 == std::fscanf(file,
"%lf %lf",
&dyn.default_current_value,
&dyn.default_reset_value);
return !!(is >> dyn.default_current_value >> dyn.default_reset_value);
}
bool read(quantifier& dyn) noexcept
{
char state[16];
char init[8];
int ret = std::fscanf(file,
"%lf %d %15s %7s",
&dyn.default_step_size,
&dyn.default_past_length,
state,
init);
if (ret != 4)
if (!(is >> dyn.default_step_size >> dyn.default_past_length >>
temp_1 >> temp_2))
return false;
if (std::strcmp(state, "possible") == 0)
if (std::strcmp(temp_1, "possible") == 0)
dyn.default_adapt_state = quantifier::adapt_state::possible;
else if (std::strcmp(state, "impossible") == 0)
else if (std::strcmp(temp_1, "impossible") == 0)
dyn.default_adapt_state = quantifier::adapt_state::impossible;
else if (std::strcmp(state, "done") == 0)
else if (std::strcmp(temp_1, "done") == 0)
dyn.default_adapt_state = quantifier::adapt_state::done;
else
return false;
if (std::strcmp(init, "true") == 0)
if (std::strcmp(temp_2, "true") == 0)
dyn.default_zero_init_offset = true;
else if (std::strcmp(init, "false") == 0)
else if (std::strcmp(temp_2, "false") == 0)
dyn.default_zero_init_offset = false;
else
return false;
......@@ -259,74 +234,44 @@ private:
bool read(adder_2& dyn) noexcept
{
return 4 == std::fscanf(file,
"%lf %lf %lf %lf",
&dyn.default_values[0],
&dyn.default_values[1],
&dyn.default_input_coeffs[0],
&dyn.default_input_coeffs[1]);
return !!(is >> dyn.default_values[0] >> dyn.default_values[1] >>
dyn.default_input_coeffs[0] >> dyn.default_input_coeffs[1]);
}
bool read(adder_3& dyn) noexcept
{
return 6 == std::fscanf(file,
"%lf %lf %lf %lf %lf %lf",
&dyn.default_values[0],
&dyn.default_values[1],
&dyn.default_values[2],
&dyn.default_input_coeffs[0],
&dyn.default_input_coeffs[1],
&dyn.default_input_coeffs[2]);
return !!(is >> dyn.default_values[0] >> dyn.default_values[1] >>
dyn.default_values[2] >> dyn.default_input_coeffs[0] >>
dyn.default_input_coeffs[1] >> dyn.default_input_coeffs[2]);
}
bool read(adder_4& dyn) noexcept
{
return 8 == std::fscanf(file,
"%lf %lf %lf %lf %lf %lf %lf %lf",
&dyn.default_values[0],
&dyn.default_values[1],
&dyn.default_values[2],
&dyn.default_values[3],
&dyn.default_input_coeffs[0],
&dyn.default_input_coeffs[1],
&dyn.default_input_coeffs[2],
&dyn.default_input_coeffs[3]);
return !!(is >> dyn.default_values[0] >> dyn.default_values[1] >>
dyn.default_values[2] >> dyn.default_values[3] >>
dyn.default_input_coeffs[0] >> dyn.default_input_coeffs[1] >>
dyn.default_input_coeffs[2] >> dyn.default_input_coeffs[3]);
}
bool read(mult_2& dyn) noexcept
{
return 4 == std::fscanf(file,
"%lf %lf %lf %lf",
&dyn.default_values[0],
&dyn.default_values[1],
&dyn.default_input_coeffs[0],
&dyn.default_input_coeffs[1]);
return !!(is >> dyn.default_values[0] >> dyn.default_values[1] >>
dyn.default_input_coeffs[0] >> dyn.default_input_coeffs[1]);
}
bool read(mult_3& dyn) noexcept
{
return 6 == std::fscanf(file,
"%lf %lf %lf %lf %lf %lf",
&dyn.default_values[0],
&dyn.default_values[1],
&dyn.default_values[2],
&dyn.default_input_coeffs[0],
&dyn.default_input_coeffs[1],
&dyn.default_input_coeffs[2]);
return !!(is >> dyn.default_values[0] >> dyn.default_values[1] >>
dyn.default_values[2] >> dyn.default_input_coeffs[0] >>
dyn.default_input_coeffs[1] >> dyn.default_input_coeffs[2]);
}
bool read(mult_4& dyn) noexcept
{
return 8 == std::fscanf(file,
"%lf %lf %lf %lf %lf %lf %lf %lf",
&dyn.default_values[0],
&dyn.default_values[1],
&dyn.default_values[2],
&dyn.default_values[3],
&dyn.default_input_coeffs[0],
&dyn.default_input_coeffs[1],
&dyn.default_input_coeffs[2],
&dyn.default_input_coeffs[3]);
return !!(is >> dyn.default_values[0] >> dyn.default_values[1] >>
dyn.default_values[2] >> dyn.default_values[3] >>
dyn.default_input_coeffs[0] >> dyn.default_input_coeffs[1] >>
dyn.default_input_coeffs[2] >> dyn.default_input_coeffs[3]);
}
bool read(counter& /*dyn*/) noexcept
......@@ -341,22 +286,20 @@ private:
bool read(constant& dyn) noexcept
{
return 1 == std::fscanf(file, "%lf", &dyn.default_value);
return !!(is >> dyn.default_value);
}
bool read(cross& dyn) noexcept
{
return 1 == std::fscanf(file, "%lf", &dyn.default_threshold);
return !!(is >> dyn.default_threshold);
}
bool read(time_func& dyn) noexcept
{
char fn[10];
if (1 != std::fscanf(file, "%9s", fn))
if (!(is >> temp_1))
return false;
if (std::strcmp(fn, "square") == 0)
if (std::strcmp(temp_1, "square") == 0)
dyn.default_f = &square_time_function;
else
dyn.default_f = &time_function;
......@@ -367,24 +310,17 @@ private:
struct writer
{
std::FILE* file = stdout;
std::ostream& os;
array<model_id> map;
writer(std::FILE* file_ = stdout) noexcept
: file(file_)
writer(std::ostream& os_) noexcept
: os(os_)
{}
~writer() noexcept
{
if (file && file != stderr && file != stdout)
std::fclose(file);
}
status operator()(const simulation& sim) noexcept
{
std::fprintf(
file, "%lu\n", static_cast<long unsigned>(sim.models.size()));
os << sim.models.size() << '\n';
irt_return_if_bad(map.init(sim.models.size()));
......@@ -395,7 +331,7 @@ struct writer
while (sim.models.next(mdl)) {
const auto mdl_id = sim.models.get_id(mdl);
std::fprintf(file, "%d %s ", id, mdl->name.c_str());
os << id << ' ' << mdl->name.c_str() << ' ';
map[id] = mdl_id;
sim.dispatch(mdl->type, [this, mdl](auto& dyn_models) {
......@@ -431,12 +367,9 @@ struct writer
assert(it_out != map.end());
assert(it_in != map.end());
std::fprintf(file,
"%d %d %d %d\n",
static_cast<int>(std::distance(map.begin(), it_out)),
src_index,
static_cast<int>(std::distance(map.begin(), it_in)),
dst_index);
os << std::distance(map.begin(), it_out) << ' ' << src_index
<< std::distance(map.begin(), it_in) << ' ' << dst_index
<< '\n';
}
}
}
......@@ -447,148 +380,113 @@ struct writer
private:
void write(const none& /*dyn*/) noexcept
{
std::fprintf(file, "none\n");
os << "none\n";
}
void write(const integrator& dyn) noexcept
{
std::fprintf(file,
"integrator %f %f\n",
dyn.default_current_value,
dyn.default_reset_value);
os << "integrator " << dyn.default_current_value << ' '
<< dyn.default_reset_value << '\n';
}
void write(const quantifier& dyn) noexcept
{
std::fprintf(
file,
"quantifier %f %d %s %s\n",
dyn.default_step_size,
dyn.default_past_length,
dyn.default_adapt_state == quantifier::adapt_state::possible
? "possible"
: dyn.default_adapt_state == quantifier::adapt_state::impossible
? "impossibe"
: "done",
dyn.default_zero_init_offset == true ? "true" : "false");
os << "quantifier " << dyn.default_step_size << ' '
<< dyn.default_past_length << ' '
<< ((dyn.default_adapt_state == quantifier::adapt_state::possible)
? "possible "
: dyn.default_adapt_state ==
quantifier::adapt_state::impossible
? "impossibe "
: "done ")
<< (dyn.default_zero_init_offset == true ? "true\n" : "false\n");
}
void write(const adder_2& dyn) noexcept
{
std::fprintf(file,
"adder_2 %f %f %f %f\n",
dyn.default_values[0],
dyn.default_values[1],
dyn.default_input_coeffs[0],
dyn.default_input_coeffs[1]);
os << "adder_2 " << dyn.default_values[0] << ' '
<< dyn.default_values[1] << ' ' << dyn.default_input_coeffs[0] << ' '
<< dyn.default_input_coeffs[1] << '\n';
}
void write(const adder_3& dyn) noexcept
{
std::fprintf(file,
"adder_3 %f %f %f %f %f %f\n",
dyn.default_values[0],
dyn.default_values[1],
dyn.default_values[2],
dyn.default_input_coeffs[0],
dyn.default_input_coeffs[1],
dyn.default_input_coeffs[2]);
os << "adder_3 " << dyn.default_values[0] << ' '
<< dyn.default_values[1] << ' ' << dyn.default_values[2] << ' '
<< dyn.default_input_coeffs[0] << ' ' << dyn.default_input_coeffs[1]
<< ' ' << dyn.default_input_coeffs[2] << '\n';
}
void write(const adder_4& dyn) noexcept
{
std::fprintf(file,
"adder_4 %f %f %f %f %f %f %f %f\n",
dyn.default_values[0],
dyn.default_values[1],
dyn.default_values[2],
dyn.default_values[3],
dyn.default_input_coeffs[0],
dyn.default_input_coeffs[1],
dyn.default_input_coeffs[2],
dyn.default_input_coeffs[3]);
os << "adder_4 " << dyn.default_values[0] << ' '
<< dyn.default_values[1] << ' ' << dyn.default_values[2] << ' '
<< dyn.default_values[3] << ' ' << dyn.default_input_coeffs[0] << ' '
<< dyn.default_input_coeffs[1] << ' ' << dyn.default_input_coeffs[2]
<< ' ' << dyn.default_input_coeffs[3] << '\n';
}
void write(const mult_2& dyn) noexcept
{
std::fprintf(file,
"mult_2 %f %f %f %f\n",
dyn.default_values[0],
dyn.default_values[1],
dyn.default_input_coeffs[0],
dyn.default_input_coeffs[1]);
os << "mult_2 " << dyn.default_values[0] << ' ' << dyn.default_values[1]
<< ' ' << dyn.default_input_coeffs[0] << ' '
<< dyn.default_input_coeffs[1] << '\n';
}
void write(const mult_3& dyn) noexcept
{
std::fprintf(file,
"mult_3 %f %f %f %f %f %f\n",
dyn.default_values[0],
dyn.default_values[1],
dyn.default_values[2],
dyn.default_input_coeffs[0],
<