summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--compat/strerror.cpp31
-rw-r--r--compat/strerror.hpp9
-rw-r--r--loader/texture.cpp4
-rw-r--r--loader/wall-atlas.cpp2
-rw-r--r--serialize/json-helper.cpp47
-rw-r--r--serialize/wall-atlas.cpp5
-rw-r--r--serialize/world-reader.cpp10
-rw-r--r--serialize/world-writer.cpp16
8 files changed, 78 insertions, 46 deletions
diff --git a/compat/strerror.cpp b/compat/strerror.cpp
new file mode 100644
index 00000000..67b87e2f
--- /dev/null
+++ b/compat/strerror.cpp
@@ -0,0 +1,31 @@
+#include "strerror.hpp"
+#include <errno.h>
+#include <string.h>
+
+namespace floormat {
+
+StringView get_error_string(ArrayView<char> buf)
+{
+#ifndef _WIN32
+ if constexpr(std::is_same_v<char*, std::decay_t<decltype(::strerror_r(errno, buf.data(), buf.size()))>>)
+ {
+ const char* str { ::strerror_r(errno, buf.data(), buf.size()) };
+ if (str)
+ return str;
+ }
+ else
+ {
+ const int status { ::strerror_r(errno, buf.data(), buf.size()) };
+ if (status == 0)
+ return buf;
+ }
+#else
+ ::strerror_s(buf.data(), buf.size(), errno);
+ if (buf[0])
+ return buf;
+#endif
+
+ return "Unknown error"_s;
+};
+
+} // namespace floormat
diff --git a/compat/strerror.hpp b/compat/strerror.hpp
new file mode 100644
index 00000000..1929d97d
--- /dev/null
+++ b/compat/strerror.hpp
@@ -0,0 +1,9 @@
+#pragma once
+#include <Corrade/Containers/ArrayView.h>
+#include <Corrade/Containers/StringView.h>
+
+namespace floormat {
+
+StringView get_error_string(ArrayView<char> buf);
+
+} // namespace floormat
diff --git a/loader/texture.cpp b/loader/texture.cpp
index ce72a29c..28b903c2 100644
--- a/loader/texture.cpp
+++ b/loader/texture.cpp
@@ -2,6 +2,7 @@
#include "compat/assert.hpp"
#include "compat/exception.hpp"
#include "compat/defs.hpp"
+#include "compat/strerror.hpp"
#include <cstring>
#include <cstdio>
#include <Corrade/Containers/StringStlView.h>
@@ -46,7 +47,8 @@ Trade::ImageData2D loader_impl::texture(StringView prefix, StringView filename_)
}
const auto path = Path::currentDirectory();
buf[len] = '\0';
- fm_throw("can't open image '{}' (cwd '{}')"_cf, buf, path ? StringView{*path} : "(null)"_s);
+ char errbuf[128];
+ fm_throw("can't open image '{}' (cwd '{}'): {}"_cf, buf, path ? StringView{*path} : "(null)"_s, get_error_string(errbuf));
}
} // namespace floormat::loader_detail
diff --git a/loader/wall-atlas.cpp b/loader/wall-atlas.cpp
index 4ade3fbb..1784f4e2 100644
--- a/loader/wall-atlas.cpp
+++ b/loader/wall-atlas.cpp
@@ -38,7 +38,7 @@ const wall_info& loader_impl::wall_atlas(StringView name, StringView dir)
auto it = wall_atlas_map.find(path);
if (it == wall_atlas_map.end())
- fm_throw("no such wall atlas '{}'"_cf, fmt::string_view{path.data(), path.size()});
+ fm_throw("no such wall atlas '{}'"_cf, path);
fm_assert(it->second != nullptr);
if (!it->second->atlas)
{
diff --git a/serialize/json-helper.cpp b/serialize/json-helper.cpp
index 695b76ef..b9853794 100644
--- a/serialize/json-helper.cpp
+++ b/serialize/json-helper.cpp
@@ -1,47 +1,54 @@
#include "json-helper.hpp"
#include "compat/exception.hpp"
-#include <cerrno>
-#include <cstring>
+#include "compat/strerror.hpp"
+#include <concepts>
#include <fstream>
#include <Corrade/Containers/StringStlView.h>
namespace floormat {
-template<typename T, std::ios_base::openmode mode>
-static T open_stream(StringView filename)
+namespace {
+
+template<std::derived_from<std::basic_ios<char>> T, std::ios_base::openmode mode>
+T open_stream(StringView filename)
{
T s;
- s.exceptions(std::ios_base::failbit | std::ios_base::badbit);
+ errno = 0;
s.open(filename.data(), mode);
- if (!s)
+ if (!s.good())
{
+ const auto mode_str = (mode & std::ios_base::out) == std::ios_base::out ? "writing"_s : "reading"_s;
char errbuf[128];
- constexpr auto get_error_string = []<size_t N> (char (&buf)[N])
- {
- buf[0] = '\0';
-#ifndef _WIN32
- (void)::strerror_r(errno, buf, std::size(buf));
-#else
- (void)::strerror_s(buf, std::size(buf), errno);
-#endif
- };
- const char* mode_str = (mode & std::ios_base::out) == std::ios_base::out ? "writing" : "reading";
- (void)get_error_string(errbuf);
- fm_throw("can't open file '{}' for {}: {}"_cf, filename, mode_str, errbuf);
+ fm_throw("can't open file '{}' for {}: {}"_cf, filename, mode_str, get_error_string(errbuf));
}
return s;
}
+} // namespace
+
auto json_helper::from_json_(StringView filename) noexcept(false) -> json
{
json j;
- open_stream<std::ifstream, std::ios_base::in>(filename) >> j;
+ auto s = open_stream<std::ifstream, std::ios_base::in>(filename);
+ s >> j;
+ if (s.bad() || !s.eof() && s.fail())
+ {
+ char errbuf[128];
+ fm_throw("input/output error while {} '{}': {}"_cf, filename, "reading"_s, get_error_string(errbuf));
+ }
return j;
}
void json_helper::to_json_(const json& j, StringView filename) noexcept(false)
{
- (open_stream<std::ofstream, std::ios_base::out>(filename) << j.dump(2, ' ') << '\n').flush();
+ auto s = open_stream<std::ofstream, std::ios_base::out>(filename);
+ s << j.dump(2, ' ') << "\n";
+ s.flush();
+ if (!s.good())
+ {
+ char errbuf[128];
+ fm_throw("input/output error while {} '{}': {}"_cf, filename, "writing"_s, get_error_string(errbuf));
+ }
}
} // namespace floormat
diff --git a/serialize/wall-atlas.cpp b/serialize/wall-atlas.cpp
index 2d8dd7a4..b8c2eb7a 100644
--- a/serialize/wall-atlas.cpp
+++ b/serialize/wall-atlas.cpp
@@ -89,8 +89,7 @@ void wall_atlas_def::serialize(StringView filename) const
void wall_atlas::serialize(StringView filename) const
{
- return wall_atlas_def::serialize(filename, _info, _frame_array,
- _dir_array, _direction_map);
+ return wall_atlas_def::serialize(filename, _info, _frame_array, _dir_array, _direction_map);
}
} // namespace floormat
@@ -105,7 +104,7 @@ uint8_t direction_index_from_name(StringView s)
else
i++;
- fm_throw("bad rotation name '{}'"_cf, fmt::string_view{s.data(), s.size()});
+ fm_throw("bad rotation name '{}'"_cf, s);
}
StringView direction_index_to_name(size_t i)
diff --git a/serialize/world-reader.cpp b/serialize/world-reader.cpp
index b912b5d7..555785ff 100644
--- a/serialize/world-reader.cpp
+++ b/serialize/world-reader.cpp
@@ -10,6 +10,7 @@
#include "src/tile-atlas.hpp"
#include "src/anim-atlas.hpp"
#include "src/chunk-scenery.hpp"
+#include "compat/strerror.hpp"
#include <cstring>
#include <memory>
@@ -469,15 +470,6 @@ namespace floormat {
world world::deserialize(StringView filename)
{
char errbuf[128];
- constexpr auto get_error_string = []<size_t N> (char (&buf)[N]) -> const char* {
- buf[0] = '\0';
-#ifndef _WIN32
- (void)::strerror_r(errno, buf, std::size(buf));
-#else
- (void)::strerror_s(buf, std::size(buf), errno);
-#endif
- return buf;
- };
fm_soft_assert(filename.flags() & StringViewFlag::NullTerminated);
FILE_raii f = ::fopen(filename.data(), "rb");
if (!f)
diff --git a/serialize/world-writer.cpp b/serialize/world-writer.cpp
index 78ce3ac2..9fb65e3d 100644
--- a/serialize/world-writer.cpp
+++ b/serialize/world-writer.cpp
@@ -13,6 +13,7 @@
#include "loader/scenery.hpp"
#include "src/anim-atlas.hpp"
#include "src/light.hpp"
+#include "compat/strerror.hpp"
#include <concepts>
#include <cstring>
#include <vector>
@@ -624,27 +625,18 @@ void world::serialize(StringView filename)
{
collect(true);
char errbuf[128];
- constexpr auto get_error_string = []<size_t N> (char (&buf)[N]) -> const char* {
- buf[0] = '\0';
-#ifndef _WIN32
- (void)::strerror_r(errno, buf, std::size(buf));
-#else
- (void)::strerror_s(buf, std::size(buf), errno);
-#endif
- return buf;
- };
fm_assert(filename.flags() & StringViewFlag::NullTerminated);
if (Path::exists(filename))
Path::remove(filename);
FILE_raii file = ::fopen(filename.data(), "wb");
if (!file)
- fm_abort("fopen(\"%s\", \"w\"): %s", filename.data(), get_error_string(errbuf));
+ fm_abort("fopen(\"%s\", \"w\"): %s", filename.data(), get_error_string(errbuf).data());
writer_state s{*this};
const auto array = s.serialize_world();
if (auto len = ::fwrite(array.data(), array.size(), 1, file); len != 1)
- fm_abort("fwrite: %s", get_error_string(errbuf));
+ fm_abort("fwrite: %s", get_error_string(errbuf).data());
if (int ret = ::fflush(file); ret != 0)
- fm_abort("fflush: %s", get_error_string(errbuf));
+ fm_abort("fflush: %s", get_error_string(errbuf).data());
}
} // namespace floormat