diff options
-rw-r--r-- | compat/strerror.cpp | 31 | ||||
-rw-r--r-- | compat/strerror.hpp | 9 | ||||
-rw-r--r-- | loader/texture.cpp | 4 | ||||
-rw-r--r-- | loader/wall-atlas.cpp | 2 | ||||
-rw-r--r-- | serialize/json-helper.cpp | 47 | ||||
-rw-r--r-- | serialize/wall-atlas.cpp | 5 | ||||
-rw-r--r-- | serialize/world-reader.cpp | 10 | ||||
-rw-r--r-- | serialize/world-writer.cpp | 16 |
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 |