Huge refactor: use util::exception everywhere instead of std exceptions
This commit is contained in:
parent
2bff6d6cf3
commit
85d7a0ca33
59 changed files with 357 additions and 326 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <psemek/util/function.hpp>
|
#include <psemek/util/function.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
@ -60,15 +61,19 @@ namespace psemek::async
|
||||||
}
|
}
|
||||||
|
|
||||||
struct empty_future_error
|
struct empty_future_error
|
||||||
: std::exception
|
: util::exception
|
||||||
{
|
{
|
||||||
char const * what() const noexcept { return "future is empty"; }
|
empty_future_error(boost::stacktrace::stacktrace stacktrace = {})
|
||||||
|
: util::exception("Future is empty", std::move(stacktrace))
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct canceled_task_error
|
struct canceled_task_error
|
||||||
: std::exception
|
: util::exception
|
||||||
{
|
{
|
||||||
char const * what() const noexcept { return "task canceled"; }
|
canceled_task_error(boost::stacktrace::stacktrace stacktrace = {})
|
||||||
|
: util::exception("Task canceled", std::move(stacktrace))
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct auto_cancel_tag{};
|
struct auto_cancel_tag{};
|
||||||
|
|
@ -177,15 +182,19 @@ namespace psemek::async
|
||||||
};
|
};
|
||||||
|
|
||||||
struct empty_promise_error
|
struct empty_promise_error
|
||||||
: std::exception
|
: util::exception
|
||||||
{
|
{
|
||||||
char const * what() const noexcept { return "promise is empty"; }
|
empty_promise_error(boost::stacktrace::stacktrace stacktrace = {})
|
||||||
|
: util::exception("Promise is empty", std::move(stacktrace))
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct satisfied_promise_error
|
struct satisfied_promise_error
|
||||||
: std::exception
|
: util::exception
|
||||||
{
|
{
|
||||||
char const * what() const noexcept { return "promise already contains a value or exception"; }
|
satisfied_promise_error(boost::stacktrace::stacktrace stacktrace = {})
|
||||||
|
: util::exception("Promise already contains a value or exception", std::move(stacktrace))
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include <psemek/async/synchronous_executor.hpp>
|
#include <psemek/async/synchronous_executor.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
@ -12,7 +13,7 @@ namespace psemek::async
|
||||||
|
|
||||||
void synchronous_executor::post_at(clock::time_point, task)
|
void synchronous_executor::post_at(clock::time_point, task)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("synchronous_executor doesn't support executor::post_at");
|
throw util::exception("Synchronous_executor doesn't support executor::post_at");
|
||||||
}
|
}
|
||||||
|
|
||||||
void synchronous_executor::stop()
|
void synchronous_executor::stop()
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include <psemek/audio/recorder.hpp>
|
#include <psemek/audio/recorder.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -78,7 +79,7 @@ namespace psemek::audio
|
||||||
std::shared_ptr<track> record(stream_ptr stream)
|
std::shared_ptr<track> record(stream_ptr stream)
|
||||||
{
|
{
|
||||||
if (!stream->length())
|
if (!stream->length())
|
||||||
throw std::runtime_error("cannot record an infinite stream");
|
throw util::exception("Cannot record an infinite stream");
|
||||||
return record(stream, *stream->length());
|
return record(stream, *stream->length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include <psemek/audio/track.hpp>
|
#include <psemek/audio/track.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
|
|
@ -82,14 +83,14 @@ namespace psemek::audio
|
||||||
track_ptr load_raw(util::span<float const> samples)
|
track_ptr load_raw(util::span<float const> samples)
|
||||||
{
|
{
|
||||||
if ((samples.size() % 2) != 0)
|
if ((samples.size() % 2) != 0)
|
||||||
throw std::runtime_error("bad sample count");
|
throw util::exception("Sample count must be even");
|
||||||
return std::make_shared<raw_track_impl>(std::make_shared<data_holder>(samples));
|
return std::make_shared<raw_track_impl>(std::make_shared<data_holder>(samples));
|
||||||
}
|
}
|
||||||
|
|
||||||
track_ptr load_raw(std::vector<float> samples)
|
track_ptr load_raw(std::vector<float> samples)
|
||||||
{
|
{
|
||||||
if ((samples.size() % 2) != 0)
|
if ((samples.size() % 2) != 0)
|
||||||
throw std::runtime_error("bad sample count");
|
throw util::exception("Sample count must be even");
|
||||||
return std::make_shared<raw_track_impl>(std::make_shared<data_holder>(std::move(samples)));
|
return std::make_shared<raw_track_impl>(std::make_shared<data_holder>(std::move(samples)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include <psemek/audio/detail/resampler.hpp>
|
#include <psemek/audio/detail/resampler.hpp>
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
#include <psemek/util/at_scope_exit.hpp>
|
#include <psemek/util/at_scope_exit.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
|
|
@ -24,7 +25,7 @@ namespace psemek::audio
|
||||||
std::vector<float> convert_audio(std::vector<std::vector<float>> const & channels, int frequency)
|
std::vector<float> convert_audio(std::vector<std::vector<float>> const & channels, int frequency)
|
||||||
{
|
{
|
||||||
if (channels.empty() || channels.size() > 2)
|
if (channels.empty() || channels.size() > 2)
|
||||||
throw std::runtime_error(util::to_string("Can't convert audio with ", static_cast<int>(channels.size()), " channels"));
|
throw util::exception(util::to_string("Can't convert audio with ", static_cast<int>(channels.size()), " channels"));
|
||||||
|
|
||||||
std::vector<float> result(channels[0].size() * 2);
|
std::vector<float> result(channels[0].size() * 2);
|
||||||
auto out = result.begin();
|
auto out = result.begin();
|
||||||
|
|
@ -66,7 +67,7 @@ namespace psemek::audio
|
||||||
AudioFile<float> audio_file;
|
AudioFile<float> audio_file;
|
||||||
audio_file.shouldLogErrorsToConsole(false);
|
audio_file.shouldLogErrorsToConsole(false);
|
||||||
audio_file.onError = [](std::string const & error) {
|
audio_file.onError = [](std::string const & error) {
|
||||||
throw std::runtime_error("failed to load WAV file: " + error);
|
throw util::exception("Failed to load WAV file: " + error);
|
||||||
};
|
};
|
||||||
audio_file.loadFromMemory(data_u8);
|
audio_file.loadFromMemory(data_u8);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
#include <psemek/fonts/bmfont.hpp>
|
#include <psemek/fonts/bmfont.hpp>
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <boost/preprocessor/stringize.hpp>
|
#include <boost/preprocessor/stringize.hpp>
|
||||||
|
|
||||||
#define RAPIDJSON_ASSERT(x) if (!(x)) throw ::std::runtime_error("Error parsing font description: " BOOST_PP_STRINGIZE(x));
|
#define RAPIDJSON_ASSERT(x) if (!(x)) throw ::psemek::util::exception("Error parsing font description: " BOOST_PP_STRINGIZE(x));
|
||||||
#define RAPIDJSON_NOEXCEPT_ASSERT(x)
|
#define RAPIDJSON_NOEXCEPT_ASSERT(x)
|
||||||
|
|
||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
|
|
@ -53,7 +54,7 @@ namespace psemek::fonts
|
||||||
document.ParseInsitu(description_str.data());
|
document.ParseInsitu(description_str.data());
|
||||||
|
|
||||||
if (document.HasParseError())
|
if (document.HasParseError())
|
||||||
throw std::runtime_error(util::to_string("Error msdf font description: ", to_string(document.GetParseError()), " at ", document.GetErrorOffset()));
|
throw util::exception(util::to_string("Error msdf font description: ", to_string(document.GetParseError()), " at ", document.GetErrorOffset()));
|
||||||
|
|
||||||
bmfont_data result;
|
bmfont_data result;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <psemek/fonts/kerned_font.hpp>
|
#include <psemek/fonts/kerned_font.hpp>
|
||||||
|
|
||||||
#include <psemek/util/unicode.hpp>
|
#include <psemek/util/unicode.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
namespace psemek::fonts
|
namespace psemek::fonts
|
||||||
{
|
{
|
||||||
|
|
@ -10,9 +11,9 @@ namespace psemek::fonts
|
||||||
, atlas_{std::move(atlas)}
|
, atlas_{std::move(atlas)}
|
||||||
{
|
{
|
||||||
if (!supports_character('?'))
|
if (!supports_character('?'))
|
||||||
throw std::runtime_error("Kerned font must support '?' character");
|
throw util::exception("Kerned font must support '?' character");
|
||||||
if (!supports_character(' '))
|
if (!supports_character(' '))
|
||||||
throw std::runtime_error("Kerned font must support ' ' character");
|
throw util::exception("Kerned font must support ' ' character");
|
||||||
|
|
||||||
std::vector<char32_t> chars;
|
std::vector<char32_t> chars;
|
||||||
for (auto const & g : data_.glyphs)
|
for (auto const & g : data_.glyphs)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <psemek/fonts/monospace_font.hpp>
|
#include <psemek/fonts/monospace_font.hpp>
|
||||||
|
|
||||||
#include <psemek/util/unicode.hpp>
|
#include <psemek/util/unicode.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
namespace psemek::fonts
|
namespace psemek::fonts
|
||||||
{
|
{
|
||||||
|
|
@ -13,10 +14,10 @@ namespace psemek::fonts
|
||||||
, texcoords_{std::move(texcoords)}
|
, texcoords_{std::move(texcoords)}
|
||||||
{
|
{
|
||||||
if (range_.end - range_.begin != texcoords_.size())
|
if (range_.end - range_.begin != texcoords_.size())
|
||||||
throw std::runtime_error("Wrong number of texture coordinates");
|
throw util::exception("Wrong number of texture coordinates");
|
||||||
|
|
||||||
if (!supports_character('?'))
|
if (!supports_character('?'))
|
||||||
throw std::runtime_error("Monospace font must support '?' character");
|
throw util::exception("Monospace font must support '?' character");
|
||||||
}
|
}
|
||||||
|
|
||||||
static geom::vector<float, 2> advance_dir(shape_options::direction_t direction)
|
static geom::vector<float, 2> advance_dir(shape_options::direction_t direction)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <psemek/geom/point.hpp>
|
#include <psemek/geom/point.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
@ -30,7 +31,7 @@ namespace psemek::geom
|
||||||
: points_(std::move(points))
|
: points_(std::move(points))
|
||||||
{
|
{
|
||||||
if (points_.empty())
|
if (points_.empty())
|
||||||
throw std::runtime_error("Points array should be non-empty");
|
throw util::exception("Points array should be non-empty");
|
||||||
temp_.resize(points_.size());
|
temp_.resize(points_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <exception>
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
namespace psemek::geom::detail
|
namespace psemek::geom::detail
|
||||||
{
|
{
|
||||||
|
|
||||||
struct empty_array_exception
|
struct empty_array_exception
|
||||||
: std::exception
|
: util::exception
|
||||||
{
|
{
|
||||||
char const * what() const noexcept
|
empty_array_exception(boost::stacktrace::stacktrace stacktrace = {})
|
||||||
{
|
: util::exception("Indexing an empty array", std::move(stacktrace))
|
||||||
return "Attempt to index a zero vector";
|
{}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include <psemek/geom/scale.hpp>
|
#include <psemek/geom/scale.hpp>
|
||||||
#include <psemek/geom/rotation.hpp>
|
#include <psemek/geom/rotation.hpp>
|
||||||
#include <psemek/geom/translation.hpp>
|
#include <psemek/geom/translation.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
@ -149,7 +150,7 @@ namespace psemek::gfx
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("unsupported glTF animation interpolation type");
|
throw util::exception("Unknown glTF animation interpolation type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include <psemek/gfx/dither.hpp>
|
#include <psemek/gfx/dither.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
namespace psemek::gfx
|
namespace psemek::gfx
|
||||||
{
|
{
|
||||||
|
|
@ -25,7 +26,7 @@ namespace psemek::gfx
|
||||||
basic_pixmap<std::uint8_t> ordered_dither(std::size_t size)
|
basic_pixmap<std::uint8_t> ordered_dither(std::size_t size)
|
||||||
{
|
{
|
||||||
if (size > 16)
|
if (size > 16)
|
||||||
throw std::runtime_error("8-bit dither map cannot be larger than 16x16");
|
throw util::exception("8-bit dither map cannot be larger than 16x16");
|
||||||
|
|
||||||
basic_pixmap<std::uint8_t> result({size, size});
|
basic_pixmap<std::uint8_t> result({size, size});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <psemek/gfx/error.hpp>
|
#include <psemek/gfx/error.hpp>
|
||||||
#include <psemek/gfx/gl.hpp>
|
#include <psemek/gfx/gl.hpp>
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
@ -31,8 +32,8 @@ namespace psemek::gfx
|
||||||
|
|
||||||
auto e = gl::GetError();
|
auto e = gl::GetError();
|
||||||
|
|
||||||
if (e != gl::GetError())
|
if (e != gl::NO_ERROR)
|
||||||
throw std::runtime_error(util::to_string(context, gl_error_str(e)));
|
throw util::exception(util::to_string(context, gl_error_str(e)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <psemek/gfx/framebuffer.hpp>
|
#include <psemek/gfx/framebuffer.hpp>
|
||||||
|
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
namespace psemek::gfx
|
namespace psemek::gfx
|
||||||
{
|
{
|
||||||
|
|
@ -209,7 +210,7 @@ namespace psemek::gfx
|
||||||
void framebuffer::assert_complete(std::string_view name) const
|
void framebuffer::assert_complete(std::string_view name) const
|
||||||
{
|
{
|
||||||
if (auto s = status(); s != gl::FRAMEBUFFER_COMPLETE)
|
if (auto s = status(); s != gl::FRAMEBUFFER_COMPLETE)
|
||||||
throw std::runtime_error(util::to_string("Framebuffer ", name, name.empty() ? "" : " ", "incomplete: ", framebuffer_status_string(s)));
|
throw util::exception(util::to_string("Framebuffer ", name, name.empty() ? "" : " ", "incomplete: ", framebuffer_status_string(s)));
|
||||||
}
|
}
|
||||||
|
|
||||||
framebuffer::framebuffer(std::nullptr_t)
|
framebuffer::framebuffer(std::nullptr_t)
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,12 @@
|
||||||
#include <psemek/geom/rotation.hpp>
|
#include <psemek/geom/rotation.hpp>
|
||||||
#include <psemek/geom/translation.hpp>
|
#include <psemek/geom/translation.hpp>
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
#include <psemek/log/log.hpp>
|
#include <psemek/log/log.hpp>
|
||||||
|
|
||||||
#include <boost/preprocessor/stringize.hpp>
|
#include <boost/preprocessor/stringize.hpp>
|
||||||
|
|
||||||
#define RAPIDJSON_ASSERT(x) if (!(x)) throw ::std::runtime_error("Error parsing glTF: " BOOST_PP_STRINGIZE(x));
|
#define RAPIDJSON_ASSERT(x) if (!(x)) throw ::psemek::util::exception("Error parsing glTF: " BOOST_PP_STRINGIZE(x));
|
||||||
#define RAPIDJSON_NOEXCEPT_ASSERT(x)
|
#define RAPIDJSON_NOEXCEPT_ASSERT(x)
|
||||||
|
|
||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
|
|
@ -65,7 +66,7 @@ namespace psemek::gfx
|
||||||
return gltf_asset::accessor::mat3;
|
return gltf_asset::accessor::mat3;
|
||||||
if (type == "MAT4")
|
if (type == "MAT4")
|
||||||
return gltf_asset::accessor::mat4;
|
return gltf_asset::accessor::mat4;
|
||||||
throw std::runtime_error(util::to_string("Unknown accessor component type: ", type));
|
throw util::exception(util::to_string("Unknown accessor component type: ", type));
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::unordered_set<std::string> supported_extensions =
|
static std::unordered_set<std::string> supported_extensions =
|
||||||
|
|
@ -126,14 +127,14 @@ namespace psemek::gfx
|
||||||
document.ParseInsitu(description_str.data());
|
document.ParseInsitu(description_str.data());
|
||||||
|
|
||||||
if (document.HasParseError())
|
if (document.HasParseError())
|
||||||
throw std::runtime_error(util::to_string("Error parsing glTF: ", to_string(document.GetParseError()), " at ", document.GetErrorOffset()));
|
throw util::exception(util::to_string("Error parsing glTF: ", to_string(document.GetParseError()), " at ", document.GetErrorOffset()));
|
||||||
|
|
||||||
gltf_asset result;
|
gltf_asset result;
|
||||||
|
|
||||||
if (document.HasMember("extensionsRequired"))
|
if (document.HasMember("extensionsRequired"))
|
||||||
for (auto const & extension : document["extensionsRequired"].GetArray())
|
for (auto const & extension : document["extensionsRequired"].GetArray())
|
||||||
if (!supported_extensions.contains(extension.GetString()))
|
if (!supported_extensions.contains(extension.GetString()))
|
||||||
throw std::runtime_error("glTF extension " + std::string(extension.GetString()) + " is not supported");
|
throw util::exception("glTF extension " + std::string(extension.GetString()) + " is not supported");
|
||||||
|
|
||||||
if (document.HasMember("nodes")) for (auto const & node : document["nodes"].GetArray())
|
if (document.HasMember("nodes")) for (auto const & node : document["nodes"].GetArray())
|
||||||
{
|
{
|
||||||
|
|
@ -323,7 +324,7 @@ namespace psemek::gfx
|
||||||
else if (path == "translation")
|
else if (path == "translation")
|
||||||
channel_target.path = gltf_asset::animation::channel::translation;
|
channel_target.path = gltf_asset::animation::channel::translation;
|
||||||
else
|
else
|
||||||
throw std::runtime_error("Unknown glTF animation target path: " + path);
|
throw util::exception("Unknown glTF animation target path: " + path);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const & sampler : animation["samplers"].GetArray())
|
for (auto const & sampler : animation["samplers"].GetArray())
|
||||||
|
|
@ -341,7 +342,7 @@ namespace psemek::gfx
|
||||||
else if (interpolation == "CUBICSPLINE")
|
else if (interpolation == "CUBICSPLINE")
|
||||||
sampler_target.interpolation = geom::easing_type::cubic;
|
sampler_target.interpolation = geom::easing_type::cubic;
|
||||||
else
|
else
|
||||||
throw std::runtime_error("Unknown glTF animation interpolation type: " + interpolation);
|
throw util::exception("Unknown glTF animation interpolation type: " + interpolation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -401,7 +402,7 @@ namespace psemek::gfx
|
||||||
else if (type == "spot")
|
else if (type == "spot")
|
||||||
target.type = gltf_asset::light::spot;
|
target.type = gltf_asset::light::spot;
|
||||||
else
|
else
|
||||||
throw std::runtime_error("unknown light type: " + type);
|
throw util::exception("Unknown light type: " + type);
|
||||||
|
|
||||||
if (light.HasMember("color"))
|
if (light.HasMember("color"))
|
||||||
{
|
{
|
||||||
|
|
@ -459,7 +460,7 @@ namespace psemek::gfx
|
||||||
case type_t::vec2: return 2;
|
case type_t::vec2: return 2;
|
||||||
case type_t::vec3: return 3;
|
case type_t::vec3: return 3;
|
||||||
case type_t::vec4: return 4;
|
case type_t::vec4: return 4;
|
||||||
default: throw std::runtime_error("unsupported attribute type");
|
default: throw util::exception("Unsupported attribute type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <psemek/gfx/init.hpp>
|
#include <psemek/gfx/init.hpp>
|
||||||
#include <psemek/gfx/gl.hpp>
|
#include <psemek/gfx/gl.hpp>
|
||||||
#include <psemek/log/log.hpp>
|
#include <psemek/log/log.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
namespace psemek::gfx
|
namespace psemek::gfx
|
||||||
{
|
{
|
||||||
|
|
@ -8,7 +9,7 @@ namespace psemek::gfx
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
if (!gl::sys::initialize())
|
if (!gl::sys::initialize())
|
||||||
throw std::runtime_error("Failed to load OpenGL functions");
|
throw util::exception("Failed to load OpenGL functions");
|
||||||
|
|
||||||
auto vendor = gl::GetString(gl::VENDOR);
|
auto vendor = gl::GetString(gl::VENDOR);
|
||||||
auto renderer = gl::GetString(gl::RENDERER);
|
auto renderer = gl::GetString(gl::RENDERER);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
#include <psemek/util/binary_stream.hpp>
|
#include <psemek/util/binary_stream.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
namespace psemek::gfx
|
namespace psemek::gfx
|
||||||
{
|
{
|
||||||
|
|
@ -127,7 +128,7 @@ namespace psemek::gfx
|
||||||
case gl::UNSIGNED_BYTE: return 1;
|
case gl::UNSIGNED_BYTE: return 1;
|
||||||
case gl::UNSIGNED_SHORT: return 2;
|
case gl::UNSIGNED_SHORT: return 2;
|
||||||
case gl::UNSIGNED_INT: return 4;
|
case gl::UNSIGNED_INT: return 4;
|
||||||
default: throw std::runtime_error("Unknown undex type");
|
default: throw util::exception("Unknown undex type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -291,7 +292,7 @@ namespace psemek::gfx
|
||||||
|
|
||||||
auto pose_count = s.read<std::uint32_t>();
|
auto pose_count = s.read<std::uint32_t>();
|
||||||
if (pose_count != result.bones.size())
|
if (pose_count != result.bones.size())
|
||||||
throw std::runtime_error("Number of transforms in a pose must be equal to the number of bones");
|
throw util::exception("Number of transforms in a pose must be equal to the number of bones");
|
||||||
auto pose_ptr = s.read_ptr<bone_transform<float>>(pose_count);
|
auto pose_ptr = s.read_ptr<bone_transform<float>>(pose_count);
|
||||||
|
|
||||||
std::string_view name(name_ptr, name_length);
|
std::string_view name(name_ptr, name_length);
|
||||||
|
|
@ -310,32 +311,32 @@ namespace psemek::gfx
|
||||||
{
|
{
|
||||||
case SECTION_MESH:
|
case SECTION_MESH:
|
||||||
if (had_section_mesh)
|
if (had_section_mesh)
|
||||||
throw std::runtime_error("Section 'mesh' must not repeat");
|
throw util::exception("Section 'mesh' must not repeat");
|
||||||
parse_section_mesh();
|
parse_section_mesh();
|
||||||
had_section_mesh = true;
|
had_section_mesh = true;
|
||||||
break;
|
break;
|
||||||
case SECTION_BONES:
|
case SECTION_BONES:
|
||||||
if (had_section_bones)
|
if (had_section_bones)
|
||||||
throw std::runtime_error("Section 'bones' must not repeat");
|
throw util::exception("Section 'bones' must not repeat");
|
||||||
if (!had_section_mesh)
|
if (!had_section_mesh)
|
||||||
throw std::runtime_error("Section 'bones' must come after section 'mesh'");
|
throw util::exception("Section 'bones' must come after section 'mesh'");
|
||||||
if ((vertex_format & WEIGHTS_MASK) == 0)
|
if ((vertex_format & WEIGHTS_MASK) == 0)
|
||||||
throw std::runtime_error("Section 'bones' requires weights in vertex format");
|
throw util::exception("Section 'bones' requires weights in vertex format");
|
||||||
parse_section_bones();
|
parse_section_bones();
|
||||||
had_section_bones = true;
|
had_section_bones = true;
|
||||||
break;
|
break;
|
||||||
case SECTION_POSE:
|
case SECTION_POSE:
|
||||||
if (!had_section_bones)
|
if (!had_section_bones)
|
||||||
throw std::runtime_error("Section 'pose' must come after section 'bones'");
|
throw util::exception("Section 'pose' must come after section 'bones'");
|
||||||
parse_section_pose();
|
parse_section_pose();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unknown section code " + util::to_string(section_type));
|
throw util::exception("Unknown section code " + util::to_string(section_type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!had_section_mesh)
|
if (!had_section_mesh)
|
||||||
throw std::runtime_error("Section 'mesh' must be present");
|
throw util::exception("Section 'mesh' must be present");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include <psemek/gfx/pixmap.hpp>
|
#include <psemek/gfx/pixmap.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
@ -11,7 +12,7 @@ namespace psemek::gfx
|
||||||
{
|
{
|
||||||
auto fail = [](std::string str)
|
auto fail = [](std::string str)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Error loading PBM image: " + str);
|
throw util::exception("Error loading PBM image: " + str);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
@ -73,7 +74,7 @@ namespace psemek::gfx
|
||||||
{
|
{
|
||||||
auto fail = [](std::string str)
|
auto fail = [](std::string str)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Error loading PGM image: " + str);
|
throw util::exception("Error loading PGM image: " + str);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
@ -134,7 +135,7 @@ namespace psemek::gfx
|
||||||
{
|
{
|
||||||
auto fail = [](std::string str)
|
auto fail = [](std::string str)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Error loading PPM image: " + str);
|
throw util::exception("Error loading PPM image: " + str);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include <psemek/gfx/obj_parser.hpp>
|
#include <psemek/gfx/obj_parser.hpp>
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
@ -20,7 +21,7 @@ namespace psemek::gfx
|
||||||
std::size_t line_count = 0;
|
std::size_t line_count = 0;
|
||||||
|
|
||||||
auto fail = [&](auto const & ... args){
|
auto fail = [&](auto const & ... args){
|
||||||
throw std::runtime_error(util::to_string("Error parsing OBJ data, line ", line_count, ": ", args...));
|
throw util::exception(util::to_string("Error parsing OBJ data, line ", line_count, ": ", args...));
|
||||||
};
|
};
|
||||||
|
|
||||||
while (std::getline(is >> std::ws, line))
|
while (std::getline(is >> std::ws, line))
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <psemek/gfx/resource/font_9x12_png.hpp>
|
#include <psemek/gfx/resource/font_9x12_png.hpp>
|
||||||
#include <psemek/geom/constants.hpp>
|
#include <psemek/geom/constants.hpp>
|
||||||
#include <psemek/io/memory_stream.hpp>
|
#include <psemek/io/memory_stream.hpp>
|
||||||
|
#include <psemek/util/enum.hpp>
|
||||||
|
|
||||||
static const char vertex_source[] =
|
static const char vertex_source[] =
|
||||||
R"(
|
R"(
|
||||||
|
|
@ -290,7 +291,7 @@ namespace psemek::gfx
|
||||||
s = {9.f, 12.f};
|
s = {9.f, 12.f};
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unknown font");
|
throw util::unknown_enum_value_exception(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
s[0] *= str.size() * scale;
|
s[0] *= str.size() * scale;
|
||||||
|
|
@ -485,7 +486,7 @@ namespace psemek::gfx
|
||||||
pen[0] -= size[0];
|
pen[0] -= size[0];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unknown x alignment");
|
throw util::unknown_enum_value_exception(opts.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (opts.y)
|
switch (opts.y)
|
||||||
|
|
@ -499,7 +500,7 @@ namespace psemek::gfx
|
||||||
pen[1] -= size[1];
|
pen[1] -= size[1];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unknown y alignment");
|
throw util::unknown_enum_value_exception(opts.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
geom::vector<float, 3> const sx = {9.f * opts.scale, 0.f, 0.f};
|
geom::vector<float, 3> const sx = {9.f * opts.scale, 0.f, 0.f};
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <psemek/log/log.hpp>
|
#include <psemek/log/log.hpp>
|
||||||
#include <psemek/util/at_scope_exit.hpp>
|
#include <psemek/util/at_scope_exit.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
|
|
||||||
|
|
@ -16,7 +17,7 @@ namespace psemek::gfx
|
||||||
{
|
{
|
||||||
png_error_ptr error = [](png_structp, png_const_charp str)
|
png_error_ptr error = [](png_structp, png_const_charp str)
|
||||||
{
|
{
|
||||||
throw std::runtime_error(str);
|
throw util::exception(str);
|
||||||
};
|
};
|
||||||
|
|
||||||
png_error_ptr warn = [](png_structp, png_const_charp str)
|
png_error_ptr warn = [](png_structp, png_const_charp str)
|
||||||
|
|
@ -25,7 +26,7 @@ namespace psemek::gfx
|
||||||
};
|
};
|
||||||
|
|
||||||
auto png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, error, warn);
|
auto png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, error, warn);
|
||||||
if (!png) throw std::runtime_error("png_create_read_struct returned null");
|
if (!png) throw util::exception("png_create_read_struct returned null");
|
||||||
|
|
||||||
png_set_error_fn(png, nullptr, error, warn);
|
png_set_error_fn(png, nullptr, error, warn);
|
||||||
|
|
||||||
|
|
@ -37,10 +38,10 @@ namespace psemek::gfx
|
||||||
});
|
});
|
||||||
|
|
||||||
info = png_create_info_struct(png);
|
info = png_create_info_struct(png);
|
||||||
if (!info) throw std::runtime_error("png_create_info_struct returned null");
|
if (!info) throw util::exception("png_create_info_struct returned null");
|
||||||
|
|
||||||
end_info = png_create_info_struct(png);
|
end_info = png_create_info_struct(png);
|
||||||
if (!end_info) throw std::runtime_error("png_create_info_struct returned null");
|
if (!end_info) throw util::exception("png_create_info_struct returned null");
|
||||||
|
|
||||||
png_rw_ptr read = [](png_structp png, png_bytep ptr, size_t count){
|
png_rw_ptr read = [](png_structp png, png_bytep ptr, size_t count){
|
||||||
reinterpret_cast<io::istream *>(png_get_io_ptr(png))->read(reinterpret_cast<char *>(ptr), count);
|
reinterpret_cast<io::istream *>(png_get_io_ptr(png))->read(reinterpret_cast<char *>(ptr), count);
|
||||||
|
|
@ -58,7 +59,7 @@ namespace psemek::gfx
|
||||||
png_set_strip_16(png);
|
png_set_strip_16(png);
|
||||||
|
|
||||||
if (monochrome && color_type != PNG_COLOR_TYPE_GRAY)
|
if (monochrome && color_type != PNG_COLOR_TYPE_GRAY)
|
||||||
throw std::runtime_error("invalid color type for monochrome PNG");
|
throw util::exception("Invalid color type for monochrome PNG");
|
||||||
|
|
||||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||||
png_set_palette_to_rgb(png);
|
png_set_palette_to_rgb(png);
|
||||||
|
|
@ -75,7 +76,7 @@ namespace psemek::gfx
|
||||||
|
|
||||||
auto const row_bytes = png_get_rowbytes(png, info);
|
auto const row_bytes = png_get_rowbytes(png, info);
|
||||||
if (row_bytes != width * sizeof(Pixel))
|
if (row_bytes != width * sizeof(Pixel))
|
||||||
throw std::runtime_error("PNG row bytes mismatch");
|
throw util::exception("PNG row bytes mismatch");
|
||||||
|
|
||||||
for (std::uint32_t i = 0; i < height; ++i)
|
for (std::uint32_t i = 0; i < height; ++i)
|
||||||
png_read_row(png, reinterpret_cast<png_bytep>(result.data() + i * width), nullptr);
|
png_read_row(png, reinterpret_cast<png_bytep>(result.data() + i * width), nullptr);
|
||||||
|
|
@ -87,7 +88,7 @@ namespace psemek::gfx
|
||||||
{
|
{
|
||||||
png_error_ptr error = [](png_structp, png_const_charp str)
|
png_error_ptr error = [](png_structp, png_const_charp str)
|
||||||
{
|
{
|
||||||
throw std::runtime_error(str);
|
throw util::exception(str);
|
||||||
};
|
};
|
||||||
|
|
||||||
png_error_ptr warn = [](png_structp, png_const_charp str)
|
png_error_ptr warn = [](png_structp, png_const_charp str)
|
||||||
|
|
@ -96,7 +97,7 @@ namespace psemek::gfx
|
||||||
};
|
};
|
||||||
|
|
||||||
auto png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, error, warn);
|
auto png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, error, warn);
|
||||||
if (!png) throw std::runtime_error("png_create_write_struct returned null");
|
if (!png) throw util::exception("png_create_write_struct returned null");
|
||||||
|
|
||||||
png_set_error_fn(png, nullptr, error, warn);
|
png_set_error_fn(png, nullptr, error, warn);
|
||||||
|
|
||||||
|
|
@ -107,7 +108,7 @@ namespace psemek::gfx
|
||||||
});
|
});
|
||||||
|
|
||||||
info = png_create_info_struct(png);
|
info = png_create_info_struct(png);
|
||||||
if (!info) throw std::runtime_error("png_create_info_struct returned null");
|
if (!info) throw util::exception("png_create_info_struct returned null");
|
||||||
|
|
||||||
png_rw_ptr write = [](png_structp png, png_bytep ptr, size_t count){
|
png_rw_ptr write = [](png_structp png, png_bytep ptr, size_t count){
|
||||||
reinterpret_cast<io::ostream *>(png_get_io_ptr(png))->write(reinterpret_cast<char const *>(ptr), count);
|
reinterpret_cast<io::ostream *>(png_get_io_ptr(png))->write(reinterpret_cast<char const *>(ptr), count);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
#include <psemek/util/at_scope_exit.hpp>
|
#include <psemek/util/at_scope_exit.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -256,7 +257,7 @@ namespace psemek::gfx
|
||||||
gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &log_len);
|
gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &log_len);
|
||||||
std::unique_ptr<char[]> log(new char [log_len]);
|
std::unique_ptr<char[]> log(new char [log_len]);
|
||||||
gl::GetShaderInfoLog(shader, log_len, nullptr, log.get());
|
gl::GetShaderInfoLog(shader, log_len, nullptr, log.get());
|
||||||
throw std::runtime_error(util::to_string("Shader compilation failed: ", log.get(), "\nShader source: \n", annotated_source(source)));
|
throw util::exception(util::to_string("Shader compilation failed: ", log.get(), "\nShader source: \n", annotated_source(source)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,7 +275,7 @@ namespace psemek::gfx
|
||||||
gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &log_len);
|
gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &log_len);
|
||||||
std::unique_ptr<char[]> log(new char [log_len]);
|
std::unique_ptr<char[]> log(new char [log_len]);
|
||||||
gl::GetProgramInfoLog(program, log_len, nullptr, log.get());
|
gl::GetProgramInfoLog(program, log_len, nullptr, log.get());
|
||||||
throw std::runtime_error(util::to_string("Program link failed: ", log.get()));
|
throw util::exception(util::to_string("Program link failed: ", log.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto s : shaders)
|
for (auto s : shaders)
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
#include <psemek/util/hash.hpp>
|
#include <psemek/util/hash.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
@ -1079,13 +1080,13 @@ void main(){}
|
||||||
assert(o.mesh);
|
assert(o.mesh);
|
||||||
|
|
||||||
if (o.mat->lit && o.mat->transparent)
|
if (o.mat->lit && o.mat->transparent)
|
||||||
throw std::runtime_error("Materials that are both lit & transparent are not supported");
|
throw util::exception("Materials that are both lit & transparent are not supported");
|
||||||
|
|
||||||
if (o.mat->lit && o.mat->blooming)
|
if (o.mat->lit && o.mat->blooming)
|
||||||
throw std::runtime_error("Materials that are both lit & blooming are not supported");
|
throw util::exception("Materials that are both lit & blooming are not supported");
|
||||||
|
|
||||||
if (o.mat->casts_shadow && o.mat->transparent)
|
if (o.mat->casts_shadow && o.mat->transparent)
|
||||||
throw std::runtime_error("Transparent objects cannot cast shadow");
|
throw util::exception("Transparent objects cannot cast shadow");
|
||||||
|
|
||||||
auto c = o.bbox.center() - all_bbox.corner(0, 0, 0);
|
auto c = o.bbox.center() - all_bbox.corner(0, 0, 0);
|
||||||
|
|
||||||
|
|
@ -1567,9 +1568,9 @@ void main(){}
|
||||||
if (l.shadowed)
|
if (l.shadowed)
|
||||||
{
|
{
|
||||||
if (l.cascades == 0)
|
if (l.cascades == 0)
|
||||||
throw std::runtime_error("The number of shadow map cascades should be positive");
|
throw util::exception("The number of shadow map cascades should be positive");
|
||||||
if (l.cascades > 8)
|
if (l.cascades > 8)
|
||||||
throw std::runtime_error("More than 8 shadow map cascades are not supported");
|
throw util::exception("More than 8 shadow map cascades are not supported");
|
||||||
|
|
||||||
light_transform.resize(l.cascades);
|
light_transform.resize(l.cascades);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,44 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <exception>
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
namespace psemek::io
|
namespace psemek::io
|
||||||
{
|
{
|
||||||
|
|
||||||
struct null_stream
|
struct null_stream
|
||||||
: std::exception
|
: util::exception
|
||||||
{};
|
{
|
||||||
|
using util::exception::exception;
|
||||||
|
};
|
||||||
|
|
||||||
struct null_istream
|
struct null_istream
|
||||||
: null_stream
|
: null_stream
|
||||||
{
|
{
|
||||||
char const * what() const noexcept override;
|
null_istream(boost::stacktrace::stacktrace stacktrace = {});
|
||||||
};
|
};
|
||||||
|
|
||||||
struct null_ostream
|
struct null_ostream
|
||||||
: null_stream
|
: null_stream
|
||||||
{
|
{
|
||||||
char const * what() const noexcept override;
|
null_ostream(boost::stacktrace::stacktrace stacktrace = {});
|
||||||
|
};
|
||||||
|
|
||||||
|
struct stream_end
|
||||||
|
: util::exception
|
||||||
|
{
|
||||||
|
using util::exception::exception;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct istream_end
|
struct istream_end
|
||||||
: std::exception
|
: stream_end
|
||||||
{
|
{
|
||||||
char const * what() const noexcept override;
|
istream_end(boost::stacktrace::stacktrace stacktrace = {});
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ostream_end
|
struct ostream_end
|
||||||
: std::exception
|
: stream_end
|
||||||
{
|
{
|
||||||
char const * what() const noexcept override;
|
ostream_end(boost::stacktrace::stacktrace stacktrace = {});
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,24 +3,20 @@
|
||||||
namespace psemek::io
|
namespace psemek::io
|
||||||
{
|
{
|
||||||
|
|
||||||
char const * null_istream::what() const noexcept
|
null_istream::null_istream(boost::stacktrace::stacktrace stacktrace)
|
||||||
{
|
: null_stream("Attempt to read from null input stream", std::move(stacktrace))
|
||||||
return "Attempt to read from null input stream";
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
char const * null_ostream::what() const noexcept
|
null_ostream::null_ostream(boost::stacktrace::stacktrace stacktrace)
|
||||||
{
|
: null_stream("Attempt to write to null output stream", std::move(stacktrace))
|
||||||
return "Attempt to write to null output stream";
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
char const * istream_end::what() const noexcept
|
istream_end::istream_end(boost::stacktrace::stacktrace stacktrace)
|
||||||
{
|
: stream_end("Unexpected input stream end", std::move(stacktrace))
|
||||||
return "Unexpected input stream end";
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
char const * ostream_end::what() const noexcept
|
ostream_end::ostream_end(boost::stacktrace::stacktrace stacktrace)
|
||||||
{
|
: stream_end("Unexpected output stream end", std::move(stacktrace))
|
||||||
return "Unexpected output stream end";
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include <psemek/io/file_stream.hpp>
|
#include <psemek/io/file_stream.hpp>
|
||||||
|
#include <psemek/util/system_error.hpp>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
|
|
@ -8,7 +9,7 @@ namespace psemek::io
|
||||||
|
|
||||||
static void throw_fopen [[noreturn]] (std::filesystem::path const & path)
|
static void throw_fopen [[noreturn]] (std::filesystem::path const & path)
|
||||||
{
|
{
|
||||||
throw std::system_error(std::error_code{errno, std::system_category()}, "Failed to open " + path.string());
|
throw util::system_error(std::error_code{errno, std::system_category()}, "Failed to open " + path.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
static FILE * safe_fopen(std::filesystem::path const & path, const char * mode)
|
static FILE * safe_fopen(std::filesystem::path const & path, const char * mode)
|
||||||
|
|
@ -42,7 +43,7 @@ namespace psemek::io
|
||||||
{
|
{
|
||||||
case 0: return "wb";
|
case 0: return "wb";
|
||||||
case file_ostream::append: return "ab";
|
case file_ostream::append: return "ab";
|
||||||
default: throw std::runtime_error("Unknown file_ostream open flags");
|
default: throw util::exception("Unknown file_ostream open flags");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include <psemek/log/log.hpp>
|
#include <psemek/log/log.hpp>
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
@ -153,7 +154,7 @@ namespace psemek::log
|
||||||
|
|
||||||
auto it = thread_names.find(id);
|
auto it = thread_names.find(id);
|
||||||
if (it != thread_names.end())
|
if (it != thread_names.end())
|
||||||
throw std::runtime_error("Thread \"" + name + "\" already registered!");
|
throw util::exception("Thread \"" + name + "\" already registered!");
|
||||||
|
|
||||||
thread_names[id] = name;
|
thread_names[id] = name;
|
||||||
}
|
}
|
||||||
|
|
@ -174,7 +175,7 @@ namespace psemek::log
|
||||||
{
|
{
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << "Thread " << id << " not found!";
|
os << "Thread " << id << " not found!";
|
||||||
throw std::runtime_error(os.str());
|
throw util::exception(os.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
name = std::move(it->second);
|
name = std::move(it->second);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/util/enum.hpp>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
@ -10,21 +12,12 @@ namespace psemek::ml
|
||||||
// All activation functions are chosen in a way so that the derivative
|
// All activation functions are chosen in a way so that the derivative
|
||||||
// can be expressed as a function of the activation function's value, i.e.
|
// can be expressed as a function of the activation function's value, i.e.
|
||||||
// f'(x) = G(f(x)) for some G: R -> R
|
// f'(x) = G(f(x)) for some G: R -> R
|
||||||
enum class activation_type
|
psemek_declare_enum(activation_type, std::uint8_t,
|
||||||
{
|
(id)
|
||||||
id,
|
(sigmoid)
|
||||||
sigmoid,
|
(tanh)
|
||||||
tanh,
|
(relu)
|
||||||
relu,
|
)
|
||||||
|
|
||||||
count,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct unknown_activation_type
|
|
||||||
: std::exception
|
|
||||||
{
|
|
||||||
char const * what() const noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T activation(T x, activation_type type)
|
T activation(T x, activation_type type)
|
||||||
|
|
@ -39,7 +32,7 @@ namespace psemek::ml
|
||||||
case activation_type::relu:
|
case activation_type::relu:
|
||||||
return std::max(T{0}, x);
|
return std::max(T{0}, x);
|
||||||
default:
|
default:
|
||||||
throw unknown_activation_type{};
|
throw util::unknown_enum_value_exception{type};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,7 +49,7 @@ namespace psemek::ml
|
||||||
case activation_type::relu:
|
case activation_type::relu:
|
||||||
return value == T{0} ? T{0} : T{1};
|
return value == T{0} ? T{0} : T{1};
|
||||||
default:
|
default:
|
||||||
throw unknown_activation_type{};
|
throw util::unknown_enum_value_exception{type};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,38 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <psemek/util/exception.hpp>
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
namespace psemek::ml
|
namespace psemek::ml
|
||||||
{
|
{
|
||||||
|
|
||||||
struct neural_net_error
|
struct neural_net_error
|
||||||
: std::runtime_error
|
: util::exception
|
||||||
{
|
{
|
||||||
using runtime_error::runtime_error;
|
using util::exception::exception;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct empty_neural_net_error
|
struct empty_neural_net_error
|
||||||
: neural_net_error
|
: neural_net_error
|
||||||
{
|
{
|
||||||
empty_neural_net_error();
|
empty_neural_net_error(boost::stacktrace::stacktrace stacktrace = {});
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wrong_activation_types_count_error
|
struct wrong_activation_types_count_error
|
||||||
: neural_net_error
|
: neural_net_error
|
||||||
{
|
{
|
||||||
wrong_activation_types_count_error(std::size_t expected, std::size_t actual);
|
wrong_activation_types_count_error(std::size_t expected, std::size_t actual, boost::stacktrace::stacktrace stacktrace = {});
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wrong_neural_net_input_size
|
struct wrong_neural_net_input_size
|
||||||
: neural_net_error
|
: neural_net_error
|
||||||
{
|
{
|
||||||
wrong_neural_net_input_size(std::size_t expected, std::size_t actual);
|
wrong_neural_net_input_size(std::size_t expected, std::size_t actual, boost::stacktrace::stacktrace stacktrace = {});
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wrong_neural_net_output_size
|
struct wrong_neural_net_output_size
|
||||||
: neural_net_error
|
: neural_net_error
|
||||||
{
|
{
|
||||||
wrong_neural_net_output_size(std::size_t expected, std::size_t actual);
|
wrong_neural_net_output_size(std::size_t expected, std::size_t actual, boost::stacktrace::stacktrace stacktrace = {});
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
#include <psemek/ml/neural_net/activation.hpp>
|
|
||||||
|
|
||||||
namespace psemek::ml
|
|
||||||
{
|
|
||||||
|
|
||||||
char const * unknown_activation_type::what() const noexcept
|
|
||||||
{
|
|
||||||
return "unknown activation type";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -5,20 +5,20 @@
|
||||||
namespace psemek::ml
|
namespace psemek::ml
|
||||||
{
|
{
|
||||||
|
|
||||||
empty_neural_net_error::empty_neural_net_error()
|
empty_neural_net_error::empty_neural_net_error(boost::stacktrace::stacktrace stacktrace)
|
||||||
: neural_net_error("neural net must have at least a single layer")
|
: neural_net_error("Neural net must have at least a single layer", std::move(stacktrace))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
wrong_activation_types_count_error::wrong_activation_types_count_error(std::size_t expected, std::size_t actual)
|
wrong_activation_types_count_error::wrong_activation_types_count_error(std::size_t expected, std::size_t actual, boost::stacktrace::stacktrace stacktrace)
|
||||||
: neural_net_error(util::to_string("wrong number of activation types: expected ", expected, ", got ", actual))
|
: neural_net_error(util::to_string("Wrong number of activation types: expected ", expected, ", got ", actual), std::move(stacktrace))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
wrong_neural_net_input_size::wrong_neural_net_input_size(std::size_t expected, std::size_t actual)
|
wrong_neural_net_input_size::wrong_neural_net_input_size(std::size_t expected, std::size_t actual, boost::stacktrace::stacktrace stacktrace)
|
||||||
: neural_net_error(util::to_string("wrong neural net input size: expected ", expected, ", got ", actual))
|
: neural_net_error(util::to_string("Wrong neural net input size: expected ", expected, ", got ", actual), std::move(stacktrace))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
wrong_neural_net_output_size::wrong_neural_net_output_size(std::size_t expected, std::size_t actual)
|
wrong_neural_net_output_size::wrong_neural_net_output_size(std::size_t expected, std::size_t actual, boost::stacktrace::stacktrace stacktrace)
|
||||||
: neural_net_error(util::to_string("wrong neural net output size: expected ", expected, ", got ", actual))
|
: neural_net_error(util::to_string("Wrong neural net output size: expected ", expected, ", got ", actual), std::move(stacktrace))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ test_case(ml_neural__net_gradient)
|
||||||
|
|
||||||
std::vector<activation_type> activations(sizes.size() - 1);
|
std::vector<activation_type> activations(sizes.size() - 1);
|
||||||
for (auto & a : activations)
|
for (auto & a : activations)
|
||||||
a = static_cast<activation_type>(uniform<std::size_t>(rng, 0, static_cast<std::size_t>(activation_type::count) - 1));
|
a = static_cast<activation_type>(uniform<std::size_t>(rng, 0, static_cast<std::size_t>(activation_type_values().size()) - 1));
|
||||||
|
|
||||||
neural_net<double> nn(std::move(sizes), std::move(activations));
|
neural_net<double> nn(std::move(sizes), std::move(activations));
|
||||||
randomize_normal(nn, rng);
|
randomize_normal(nn, rng);
|
||||||
|
|
@ -71,7 +71,7 @@ test_case(ml_neural__net_arg__gradient)
|
||||||
|
|
||||||
std::vector<activation_type> activations(sizes.size() - 1);
|
std::vector<activation_type> activations(sizes.size() - 1);
|
||||||
for (auto & a : activations)
|
for (auto & a : activations)
|
||||||
a = static_cast<activation_type>(uniform<std::size_t>(rng, 0, static_cast<std::size_t>(activation_type::count) - 1));
|
a = static_cast<activation_type>(uniform<std::size_t>(rng, 0, static_cast<std::size_t>(activation_type_values().size()) - 1));
|
||||||
|
|
||||||
neural_net<double> nn(std::move(sizes), std::move(activations));
|
neural_net<double> nn(std::move(sizes), std::move(activations));
|
||||||
randomize_normal(nn, rng);
|
randomize_normal(nn, rng);
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,7 @@ namespace psemek::parser
|
||||||
auto r = p.apply(buffer);
|
auto r = p.apply(buffer);
|
||||||
if (r.index() == 1) break;
|
if (r.index() == 1) break;
|
||||||
if (buffer.it == pos)
|
if (buffer.it == pos)
|
||||||
throw grammar_error("infinite loop");
|
throw grammar_error("Infinite loop");
|
||||||
res.push_back(std::move(std::get<0>(r)));
|
res.push_back(std::move(std::get<0>(r)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -265,7 +265,7 @@ namespace psemek::parser
|
||||||
if (res.index() == 1)
|
if (res.index() == 1)
|
||||||
return accum;
|
return accum;
|
||||||
if (pos == buffer.it)
|
if (pos == buffer.it)
|
||||||
throw grammar_error("infinite loop");
|
throw grammar_error("Infinite loop");
|
||||||
|
|
||||||
accum = f(accum, std::get<0>(res));
|
accum = f(accum, std::get<0>(res));
|
||||||
}
|
}
|
||||||
|
|
@ -289,7 +289,7 @@ namespace psemek::parser
|
||||||
if (res.index() == 1)
|
if (res.index() == 1)
|
||||||
return accum;
|
return accum;
|
||||||
if (pos == buffer.it)
|
if (pos == buffer.it)
|
||||||
throw grammar_error("infinite loop");
|
throw grammar_error("Infinite loop");
|
||||||
|
|
||||||
accum = f(std::move(accum), std::move(std::get<0>(res)));
|
accum = f(std::move(accum), std::move(std::get<0>(res)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,37 +8,35 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
namespace psemek::parser
|
namespace psemek::parser
|
||||||
{
|
{
|
||||||
|
|
||||||
struct parse_error
|
struct parse_error
|
||||||
: std::runtime_error
|
: util::exception
|
||||||
{
|
{
|
||||||
parse_error(std::string message, std::size_t line, std::size_t character)
|
parse_error(std::string message, std::size_t line, std::size_t character, boost::stacktrace::stacktrace stacktrace = {})
|
||||||
: std::runtime_error(std::move(message))
|
: util::exception(util::to_string(message, " at ", line, "#", character), std::move(stacktrace))
|
||||||
|
, message_{std::move(message)}
|
||||||
, line_{line}
|
, line_{line}
|
||||||
, character_{character}
|
, character_{character}
|
||||||
, what_{util::to_string(message, " at ", line, "#", character)}
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
std::string const & message() const { return message_; }
|
||||||
std::size_t line() const { return line_; }
|
std::size_t line() const { return line_; }
|
||||||
std::size_t character() const { return character_; }
|
std::size_t character() const { return character_; }
|
||||||
|
|
||||||
const char * what() const noexcept { return what_.data(); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::string message_;
|
||||||
std::size_t line_;
|
std::size_t line_;
|
||||||
std::size_t character_;
|
std::size_t character_;
|
||||||
std::string what_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct grammar_error
|
struct grammar_error
|
||||||
: std::runtime_error
|
: util::exception
|
||||||
{
|
{
|
||||||
grammar_error(std::string message)
|
using util::exception::exception;
|
||||||
: std::runtime_error(std::move(message))
|
|
||||||
{}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
#include <psemek/geom/constants.hpp>
|
#include <psemek/geom/constants.hpp>
|
||||||
#include <psemek/geom/box.hpp>
|
#include <psemek/geom/box.hpp>
|
||||||
|
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
@ -65,7 +67,7 @@ namespace psemek::random
|
||||||
using std::size;
|
using std::size;
|
||||||
using std::begin;
|
using std::begin;
|
||||||
if (size(container) == 0)
|
if (size(container) == 0)
|
||||||
throw std::runtime_error("cannot sample from empty container");
|
throw util::exception("Cannot sample from empty container");
|
||||||
return *std::next(begin(container), uniform<std::size_t>(rng, 0, size(container) - 1));
|
return *std::next(begin(container), uniform<std::size_t>(rng, 0, size(container) - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <psemek/rs/resource.hpp>
|
#include <psemek/rs/resource.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
@ -8,9 +9,9 @@ namespace psemek::rs
|
||||||
{
|
{
|
||||||
|
|
||||||
struct unknown_id_error
|
struct unknown_id_error
|
||||||
: std::runtime_error
|
: util::exception
|
||||||
{
|
{
|
||||||
unknown_id_error(rs::id id);
|
unknown_id_error(rs::id id, boost::stacktrace::stacktrace stacktrace = {});
|
||||||
|
|
||||||
rs::id id() const { return id_; }
|
rs::id id() const { return id_; }
|
||||||
|
|
||||||
|
|
@ -19,9 +20,9 @@ namespace psemek::rs
|
||||||
};
|
};
|
||||||
|
|
||||||
struct unknown_name_error
|
struct unknown_name_error
|
||||||
: std::runtime_error
|
: util::exception
|
||||||
{
|
{
|
||||||
unknown_name_error(std::string_view name);
|
unknown_name_error(std::string_view name, boost::stacktrace::stacktrace stacktrace = {});
|
||||||
|
|
||||||
std::string_view name() const { return name_; }
|
std::string_view name() const { return name_; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,13 @@ namespace psemek::rs
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unknown_id_error::unknown_id_error(rs::id id)
|
unknown_id_error::unknown_id_error(rs::id id, boost::stacktrace::stacktrace stacktrace)
|
||||||
: std::runtime_error(util::to_string("unknown resource id: ", id))
|
: util::exception(util::to_string("unknown resource id: ", id), std::move(stacktrace))
|
||||||
, id_(id)
|
, id_(id)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
unknown_name_error::unknown_name_error(std::string_view name)
|
unknown_name_error::unknown_name_error(std::string_view name, boost::stacktrace::stacktrace stacktrace)
|
||||||
: std::runtime_error(util::to_string("unknown resource name: ", name))
|
: util::exception(util::to_string("unknown resource name: ", name), std::move(stacktrace))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
resource const * find(id id)
|
resource const * find(id id)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include <psemek/sdl2/init.hpp>
|
#include <psemek/sdl2/init.hpp>
|
||||||
#include <psemek/log/log.hpp>
|
#include <psemek/log/log.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
|
@ -62,7 +63,7 @@ namespace psemek::sdl2
|
||||||
|
|
||||||
[[noreturn]] void fail(std::string const & message)
|
[[noreturn]] void fail(std::string const & message)
|
||||||
{
|
{
|
||||||
throw std::runtime_error(message + SDL_GetError());
|
throw util::exception(message + SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<void> init(std::uint32_t subsystems)
|
std::shared_ptr<void> init(std::uint32_t subsystems)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include <psemek/sir/trivial.hpp>
|
#include <psemek/sir/trivial.hpp>
|
||||||
#include <psemek/sir/container.hpp>
|
#include <psemek/sir/container.hpp>
|
||||||
#include <psemek/io/memory_stream.hpp>
|
#include <psemek/io/memory_stream.hpp>
|
||||||
|
#include <psemek/util/at.hpp>
|
||||||
|
|
||||||
namespace psemek::sir
|
namespace psemek::sir
|
||||||
{
|
{
|
||||||
|
|
@ -27,7 +28,6 @@ namespace psemek::sir
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string_view data_;
|
std::string_view data_;
|
||||||
std::size_t offset_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(is_istream_v<memory_istream>);
|
static_assert(is_istream_v<memory_istream>);
|
||||||
|
|
@ -93,7 +93,7 @@ namespace psemek::sir
|
||||||
T const & at(std::size_t i) const
|
T const & at(std::size_t i) const
|
||||||
{
|
{
|
||||||
if (i >= size())
|
if (i >= size())
|
||||||
throw std::out_of_range("psemek::sir::vector::at");
|
throw util::key_error(i);
|
||||||
return begin_[i];
|
return begin_[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -263,7 +263,7 @@ namespace psemek::sir
|
||||||
{
|
{
|
||||||
auto p = find(key);
|
auto p = find(key);
|
||||||
if (p == end_)
|
if (p == end_)
|
||||||
throw std::out_of_range("psemek::sir::map::at");
|
throw util::key_error(key);
|
||||||
return p->second;
|
return p->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
#include <psemek/util/type_name.hpp>
|
#include <psemek/util/type_name.hpp>
|
||||||
#include <psemek/util/function.hpp>
|
#include <psemek/util/function.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <typeindex>
|
#include <typeindex>
|
||||||
|
|
@ -16,21 +17,20 @@ namespace psemek::ui::impl
|
||||||
{
|
{
|
||||||
|
|
||||||
struct component_not_supported_exception
|
struct component_not_supported_exception
|
||||||
: std::exception
|
: util::exception
|
||||||
{
|
{
|
||||||
component_not_supported_exception(std::type_index type)
|
component_not_supported_exception(std::type_index type, boost::stacktrace::stacktrace stacktrace = {})
|
||||||
: type_(type)
|
: util::exception(util::to_string("UI component ", util::type_name(type_), " is not supported"), std::move(stacktrace))
|
||||||
, message_(util::to_string("UI component ", util::type_name(type_), " is not supported"))
|
, type_(type)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
const char * what() const noexcept override
|
std::type_index type() const
|
||||||
{
|
{
|
||||||
return message_.data();
|
return type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::type_index type_;
|
std::type_index type_;
|
||||||
std::string message_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct component_factory_base
|
struct component_factory_base
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
#undef assert
|
#undef assert
|
||||||
|
|
||||||
#ifdef PSEMEK_DEBUG
|
#ifdef PSEMEK_DEBUG
|
||||||
#define assert(x) ((void)(!(x) && ::psemek::util::assert_handler(#x, __FILE__, __LINE__)))
|
#define assert(x) ((void)(!(x) && ::psemek::util::assertion_handler("Assertion failed: " #x)))
|
||||||
#else
|
#else
|
||||||
#define assert(x) ((void)(x))
|
#define assert(x) ((void)(x))
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -11,6 +12,9 @@
|
||||||
namespace psemek::util
|
namespace psemek::util
|
||||||
{
|
{
|
||||||
|
|
||||||
[[noreturn]] bool assert_handler(char const * expression, char const * file, int line);
|
[[noreturn]] inline bool assertion_handler(char const * assertion, boost::stacktrace::stacktrace stacktrace = {})
|
||||||
|
{
|
||||||
|
throw ::psemek::util::exception(assertion, std::move(stacktrace));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string_view>
|
#include <psemek/util/exception.hpp>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace psemek::util
|
namespace psemek::util
|
||||||
|
|
@ -13,7 +13,7 @@ namespace psemek::util
|
||||||
|
|
||||||
inline void unexpected_end()
|
inline void unexpected_end()
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Unexpected binary stream end");
|
throw exception("Unexpected binary stream end");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <psemek/util/range.hpp>
|
#include <psemek/util/range.hpp>
|
||||||
#include <psemek/util/hash.hpp>
|
#include <psemek/util/hash.hpp>
|
||||||
#include <psemek/util/hstring.hpp>
|
#include <psemek/util/hstring.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <typeindex>
|
#include <typeindex>
|
||||||
|
|
@ -779,7 +780,7 @@ namespace psemek::util
|
||||||
{
|
{
|
||||||
auto p = species_[species.value]->get_species_component<Component>();
|
auto p = species_[species.value]->get_species_component<Component>();
|
||||||
if (!p)
|
if (!p)
|
||||||
throw std::runtime_error(util::to_string("Component ", type_name<Component>(), " is not present in species ", species_[species.value]->name()));
|
throw util::exception(util::to_string("Component ", type_name<Component>(), " is not present in species ", species_[species.value]->name()));
|
||||||
return *p;
|
return *p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -795,7 +796,7 @@ namespace psemek::util
|
||||||
auto u = ecs_detail::unpack(entity.value);
|
auto u = ecs_detail::unpack(entity.value);
|
||||||
auto p = species_[u.species]->get_entity_component<Component>();
|
auto p = species_[u.species]->get_entity_component<Component>();
|
||||||
if (!p)
|
if (!p)
|
||||||
throw std::runtime_error(util::to_string("Component ", type_name<Component>(), " is not present in species ", species_[u.species]->name()));
|
throw util::exception(util::to_string("Component ", type_name<Component>(), " is not present in species ", species_[u.species]->name()));
|
||||||
return p[u.entity];
|
return p[u.entity];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
#include <psemek/util/type_name.hpp>
|
#include <psemek/util/type_name.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
@ -16,17 +17,17 @@ namespace psemek::util
|
||||||
{
|
{
|
||||||
|
|
||||||
struct unknown_enum_value_exception_base
|
struct unknown_enum_value_exception_base
|
||||||
: std::runtime_error
|
: exception
|
||||||
{
|
{
|
||||||
using std::runtime_error::runtime_error;
|
using exception::exception;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Enum>
|
template <typename Enum>
|
||||||
struct unknown_enum_value_exception
|
struct unknown_enum_value_exception
|
||||||
: unknown_enum_value_exception_base
|
: unknown_enum_value_exception_base
|
||||||
{
|
{
|
||||||
unknown_enum_value_exception(Enum value)
|
unknown_enum_value_exception(Enum value, boost::stacktrace::stacktrace stacktrace = {})
|
||||||
: unknown_enum_value_exception_base(to_string("unknown ", type_name<Enum>(), " value: ", static_cast<std::underlying_type_t<Enum>>(value)))
|
: unknown_enum_value_exception_base(to_string("unknown ", type_name<Enum>(), " value: ", static_cast<std::underlying_type_t<Enum>>(value)), std::move(stacktrace))
|
||||||
, value_(value)
|
, value_(value)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
@ -7,6 +9,14 @@
|
||||||
namespace psemek::util
|
namespace psemek::util
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct empty_function_error
|
||||||
|
: exception
|
||||||
|
{
|
||||||
|
empty_function_error(boost::stacktrace::stacktrace stacktrace = {})
|
||||||
|
: exception("Trying to call an empty function", std::move(stacktrace))
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Signature>
|
template <typename Signature>
|
||||||
struct function;
|
struct function;
|
||||||
|
|
||||||
|
|
@ -149,7 +159,7 @@ namespace psemek::util
|
||||||
R function<R(Args...)>::operator()(Args1 && ... args) const
|
R function<R(Args...)>::operator()(Args1 && ... args) const
|
||||||
{
|
{
|
||||||
if (!vtable_)
|
if (!vtable_)
|
||||||
throw std::bad_function_call();
|
throw empty_function_error{};
|
||||||
|
|
||||||
return vtable_->call(const_cast<void *>(static_cast<void const *>(&storage_)), std::forward<Args1>(args)...);
|
return vtable_->call(const_cast<void *>(static_cast<void const *>(&storage_)), std::forward<Args1>(args)...);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <psemek/util/flat_list.hpp>
|
#include <psemek/util/flat_list.hpp>
|
||||||
|
#include <psemek/util/at.hpp>
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
@ -80,9 +81,10 @@ namespace psemek::util
|
||||||
template <typename F, typename T>
|
template <typename F, typename T>
|
||||||
struct tuple_apply_at_impl<F, T, std::index_sequence<>>
|
struct tuple_apply_at_impl<F, T, std::index_sequence<>>
|
||||||
{
|
{
|
||||||
static decltype(auto) apply(F && f, T & t, std::size_t)
|
static decltype(auto) apply(F && f, T & t, std::size_t i)
|
||||||
{
|
{
|
||||||
throw std::out_of_range("Bad tuple index");
|
throw key_error(i);
|
||||||
|
// For proper type deduction
|
||||||
return std::forward<F>(f)(std::get<0>(t));
|
return std::forward<F>(f)(std::get<0>(t));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -105,21 +107,13 @@ namespace psemek::util
|
||||||
decltype(auto) tuple_apply_at(F && f, T & t, std::size_t i)
|
decltype(auto) tuple_apply_at(F && f, T & t, std::size_t i)
|
||||||
{
|
{
|
||||||
if (i >= std::tuple_size_v<T>)
|
if (i >= std::tuple_size_v<T>)
|
||||||
throw std::out_of_range("Bad tuple index");
|
throw key_error(i);
|
||||||
|
|
||||||
return tuple_apply_at_impl<F, T, std::make_index_sequence<std::tuple_size_v<T>>>::apply(std::forward<F>(f), t, i);
|
return tuple_apply_at_impl<F, T, std::make_index_sequence<std::tuple_size_v<T>>>::apply(std::forward<F>(f), t, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bad_handle
|
|
||||||
: std::out_of_range
|
|
||||||
{
|
|
||||||
bad_handle()
|
|
||||||
: std::out_of_range("Bad handle")
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Handle, typename ... Types>
|
template <typename Handle, typename ... Types>
|
||||||
struct heterogeneous_container
|
struct heterogeneous_container
|
||||||
{
|
{
|
||||||
|
|
@ -230,7 +224,7 @@ namespace psemek::util
|
||||||
{
|
{
|
||||||
auto u = unpack_handle(h);
|
auto u = unpack_handle(h);
|
||||||
if (u.first >= types_count)
|
if (u.first >= types_count)
|
||||||
throw bad_handle{};
|
throw exception("Broken handle");
|
||||||
detail::tuple_apply_at([&u](auto & t) -> void {
|
detail::tuple_apply_at([&u](auto & t) -> void {
|
||||||
t.erase(u.second);
|
t.erase(u.second);
|
||||||
}, storage_, u.first);
|
}, storage_, u.first);
|
||||||
|
|
@ -275,12 +269,12 @@ namespace psemek::util
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(t[hh])>, T>)
|
if constexpr (std::is_same_v<std::decay_t<decltype(t[hh])>, T>)
|
||||||
{
|
{
|
||||||
if (i != j)
|
if (i != j)
|
||||||
throw std::bad_any_cast{};
|
throw exception("Error in heterogeneous_container");
|
||||||
res = &t[hh];
|
res = &t[hh];
|
||||||
}
|
}
|
||||||
}, storage_);
|
}, storage_);
|
||||||
if (!res)
|
if (!res)
|
||||||
throw std::bad_any_cast{};
|
throw exception("Error in heterogeneous_container");
|
||||||
|
|
||||||
return *res;
|
return *res;
|
||||||
}
|
}
|
||||||
|
|
@ -298,12 +292,12 @@ namespace psemek::util
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(t[hh])>, T>)
|
if constexpr (std::is_same_v<std::decay_t<decltype(t[hh])>, T>)
|
||||||
{
|
{
|
||||||
if (i != j)
|
if (i != j)
|
||||||
throw std::bad_any_cast{};
|
throw exception("Error in heterogeneous_container");
|
||||||
res = &t[hh];
|
res = &t[hh];
|
||||||
}
|
}
|
||||||
}, storage_);
|
}, storage_);
|
||||||
if (!res)
|
if (!res)
|
||||||
throw std::bad_any_cast{};
|
throw exception("Error in heterogeneous_container");
|
||||||
|
|
||||||
return *res;
|
return *res;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <exception>
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
namespace psemek::util
|
namespace psemek::util
|
||||||
{
|
{
|
||||||
|
|
||||||
struct not_implemented_error
|
struct not_implemented_error
|
||||||
: std::exception
|
: exception
|
||||||
{
|
{
|
||||||
char const * what() const noexcept override;
|
not_implemented_error(boost::stacktrace::stacktrace stacktrace = {});
|
||||||
};
|
};
|
||||||
|
|
||||||
[[noreturn]] void not_implemented();
|
[[noreturn]] void not_implemented();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <psemek/util/array.hpp>
|
#include <psemek/util/array.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
#include <psemek/util/to_string.hpp>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
@ -112,7 +114,7 @@ namespace psemek::util
|
||||||
for (std::size_t i = 0; i < N; ++i)
|
for (std::size_t i = 0; i < N; ++i)
|
||||||
{
|
{
|
||||||
if (ix[i] < origin_[i] || ix[i] >= origin_[i] + static_cast<Index>(size[i]))
|
if (ix[i] < origin_[i] || ix[i] >= origin_[i] + static_cast<Index>(size[i]))
|
||||||
throw std::runtime_error("element out of range");
|
throw exception(to_string("Spatial array index ", ix[i], "(#", i, ") is out of bounds [", origin_[i], origin_[i] + static_cast<Index>(size[i]), ")"));
|
||||||
ix[i] -= origin_[i];
|
ix[i] -= origin_[i];
|
||||||
}
|
}
|
||||||
return array_(ix);
|
return array_(ix);
|
||||||
|
|
|
||||||
25
libs/util/include/psemek/util/system_error.hpp
Normal file
25
libs/util/include/psemek/util/system_error.hpp
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
|
namespace psemek::util
|
||||||
|
{
|
||||||
|
|
||||||
|
struct system_error
|
||||||
|
: exception
|
||||||
|
{
|
||||||
|
system_error(std::error_code error_code, std::string message, boost::stacktrace::stacktrace stacktrace = {})
|
||||||
|
: exception(message + ": " + error_code.message(), std::move(stacktrace))
|
||||||
|
, error_code_(error_code)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::error_code error_code() const
|
||||||
|
{
|
||||||
|
return error_code_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::error_code error_code_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
@ -42,7 +44,7 @@ namespace psemek::util
|
||||||
T x;
|
T x;
|
||||||
iss >> x;
|
iss >> x;
|
||||||
if (!iss)
|
if (!iss)
|
||||||
throw std::invalid_argument("failed to parse from string");
|
throw exception("Failed to parse from string");
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <exception>
|
|
||||||
|
|
||||||
namespace psemek::util
|
namespace psemek::util
|
||||||
{
|
{
|
||||||
|
|
@ -70,14 +71,13 @@ namespace psemek::util
|
||||||
};
|
};
|
||||||
|
|
||||||
struct invalid_utf8
|
struct invalid_utf8
|
||||||
: std::exception
|
: exception
|
||||||
{
|
{
|
||||||
invalid_utf8(char const * data)
|
invalid_utf8(char const * data, boost::stacktrace::stacktrace stacktrace = {})
|
||||||
: data_{data}
|
: exception("Invalid UTF-8 string", std::move(stacktrace))
|
||||||
|
, data_{data}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
char const * what() const noexcept override;
|
|
||||||
|
|
||||||
char const * data() const { return data_; }
|
char const * data() const { return data_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
#include <psemek/util/assert.hpp>
|
|
||||||
#include <psemek/util/to_string.hpp>
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
namespace psemek::util
|
|
||||||
{
|
|
||||||
|
|
||||||
[[noreturn]] bool assert_handler(char const * expression, char const * file, int line)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(to_string(file, ":", line, " Assertion failed: ", expression));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include <psemek/util/executable_path.hpp>
|
#include <psemek/util/executable_path.hpp>
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <libloaderapi.h>
|
#include <libloaderapi.h>
|
||||||
|
|
@ -23,13 +24,13 @@ namespace psemek::util
|
||||||
else if (error == ERROR_INSUFFICIENT_BUFFER)
|
else if (error == ERROR_INSUFFICIENT_BUFFER)
|
||||||
result.resize(result.size() * 2);
|
result.resize(result.size() * 2);
|
||||||
else
|
else
|
||||||
throw std::runtime_error(util::to_string("failed to retrieve executable path: ", std::hex, error));
|
throw exception(util::to_string("failed to retrieve executable path: ", std::hex, error));
|
||||||
}
|
}
|
||||||
return std::filesystem::path(result);
|
return std::filesystem::path(result);
|
||||||
#elif defined __linux__
|
#elif defined __linux__
|
||||||
return std::filesystem::canonical("/proc/self/exe");
|
return std::filesystem::canonical("/proc/self/exe");
|
||||||
#else
|
#else
|
||||||
throw std::runtime_error("executable_path() is not implemented for this platform");
|
throw exception("executable_path() is not implemented for this platform");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
#include <psemek/util/function.hpp>
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
namespace psemek::util
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
|
|
||||||
void bad_function_call()
|
|
||||||
{
|
|
||||||
throw std::bad_function_call{};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -5,10 +5,9 @@
|
||||||
namespace psemek::util
|
namespace psemek::util
|
||||||
{
|
{
|
||||||
|
|
||||||
char const * not_implemented_error::what() const noexcept
|
not_implemented_error::not_implemented_error(boost::stacktrace::stacktrace stacktrace)
|
||||||
{
|
: exception("Not implemented", std::move(stacktrace))
|
||||||
return "not implemented";
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
void not_implemented()
|
void not_implemented()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -110,9 +110,4 @@ namespace psemek::util
|
||||||
throw invalid_utf8(ptr);
|
throw invalid_utf8(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
char const * invalid_utf8::what() const noexcept
|
|
||||||
{
|
|
||||||
return "Invalid UTF-8 string";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ using namespace psemek::util;
|
||||||
test_case(util_function_empty_call)
|
test_case(util_function_empty_call)
|
||||||
{
|
{
|
||||||
function<void()> f;
|
function<void()> f;
|
||||||
expect_throw(f(), std::bad_function_call);
|
expect_throw(f(), empty_function_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
using heavy = std::array<int, 256>;
|
using heavy = std::array<int, 256>;
|
||||||
|
|
|
||||||
|
|
@ -96,9 +96,9 @@ test_case(util_heterogeneous__container_get)
|
||||||
expect_equal_deref(std::get<2>(c.get(f0)), 3.14f);
|
expect_equal_deref(std::get<2>(c.get(f0)), 3.14f);
|
||||||
expect_equal_deref(std::get<float *>(c.get(f0)), 3.14f);
|
expect_equal_deref(std::get<float *>(c.get(f0)), 3.14f);
|
||||||
|
|
||||||
expect_throw(c.get<float>(c0), std::bad_any_cast);
|
expect_throw(c.get<float>(c0), std::exception);
|
||||||
expect_throw(c.get<float>(c1), std::bad_any_cast);
|
expect_throw(c.get<float>(c1), std::exception);
|
||||||
expect_throw(c.get<char>(f0), std::bad_any_cast);
|
expect_throw(c.get<char>(f0), std::exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
test_case(util_heterogeneous__container_visit)
|
test_case(util_heterogeneous__container_visit)
|
||||||
|
|
|
||||||
|
|
@ -13,64 +13,70 @@
|
||||||
|
|
||||||
// Have to put it before including to_string.hpp due to how unqualified lookup works,
|
// Have to put it before including to_string.hpp due to how unqualified lookup works,
|
||||||
// see e.g. https://alexanderlobov.net/posts/2019-07-08-function-lookup-in-templates
|
// see e.g. https://alexanderlobov.net/posts/2019-07-08-function-lookup-in-templates
|
||||||
template <typename T>
|
|
||||||
std::ostream & operator << (std::ostream & s, std::optional<T> const & o)
|
|
||||||
{
|
|
||||||
if (o)
|
|
||||||
s << *o;
|
|
||||||
else
|
|
||||||
s << "(empty)";
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
namespace std
|
||||||
std::ostream & operator << (std::ostream & s, std::pair<T1, T2> const & p)
|
|
||||||
{
|
{
|
||||||
s << '(' << p.first << ", " << p.second << ')';
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ... Ts>
|
template <typename T>
|
||||||
std::ostream & operator << (std::ostream & s, std::tuple<Ts...> const & t)
|
ostream & operator << (ostream & s, optional<T> const & o)
|
||||||
{
|
|
||||||
s << '(';
|
|
||||||
[&]<std::size_t ... Is>(std::index_sequence<Is...>){
|
|
||||||
((s << (Is == 0 ? "" : ", ") << std::get<Is>(t)), ...);
|
|
||||||
}(std::make_index_sequence<sizeof...(Ts)>{});
|
|
||||||
s << ')';
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
std::ostream & operator << (std::ostream & s, std::vector<T> const & v)
|
|
||||||
{
|
|
||||||
s << "[";
|
|
||||||
bool first = true;
|
|
||||||
for (auto const & x : v)
|
|
||||||
{
|
{
|
||||||
if (!first)
|
if (o)
|
||||||
s << ", ";
|
s << *o;
|
||||||
first = false;
|
else
|
||||||
s << x;
|
s << "(empty)";
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
s << "]";
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T1, typename T2>
|
||||||
std::ostream & operator << (std::ostream & s, std::set<T> const & v)
|
ostream & operator << (ostream & s, pair<T1, T2> const & p)
|
||||||
{
|
|
||||||
s << "{";
|
|
||||||
bool first = true;
|
|
||||||
for (auto const & x : v)
|
|
||||||
{
|
{
|
||||||
if (!first)
|
s << '(' << p.first << ", " << p.second << ')';
|
||||||
s << ", ";
|
return s;
|
||||||
first = false;
|
|
||||||
s << x;
|
|
||||||
}
|
}
|
||||||
s << "}";
|
|
||||||
return s;
|
template <typename ... Ts>
|
||||||
|
ostream & operator << (ostream & s, tuple<Ts...> const & t)
|
||||||
|
{
|
||||||
|
s << '(';
|
||||||
|
[&]<size_t ... Is>(index_sequence<Is...>){
|
||||||
|
((s << (Is == 0 ? "" : ", ") << get<Is>(t)), ...);
|
||||||
|
}(make_index_sequence<sizeof...(Ts)>{});
|
||||||
|
s << ')';
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
ostream & operator << (ostream & s, vector<T> const & v)
|
||||||
|
{
|
||||||
|
s << "[";
|
||||||
|
bool first = true;
|
||||||
|
for (auto const & x : v)
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
s << ", ";
|
||||||
|
first = false;
|
||||||
|
s << x;
|
||||||
|
}
|
||||||
|
s << "]";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
ostream & operator << (ostream & s, set<T> const & v)
|
||||||
|
{
|
||||||
|
s << "{";
|
||||||
|
bool first = true;
|
||||||
|
for (auto const & x : v)
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
s << ", ";
|
||||||
|
first = false;
|
||||||
|
s << x;
|
||||||
|
}
|
||||||
|
s << "}";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace psemek::util
|
namespace psemek::util
|
||||||
|
|
@ -81,16 +87,21 @@ namespace psemek::util
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::ostream & operator << (std::ostream & s, std::type_info const & type)
|
namespace std
|
||||||
{
|
{
|
||||||
s << psemek::util::type_name(type);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::ostream & operator << (std::ostream & s, std::type_index const & type)
|
inline ostream & operator << (ostream & s, type_info const & type)
|
||||||
{
|
{
|
||||||
s << psemek::util::type_name(type);
|
s << psemek::util::type_name(type);
|
||||||
return s;
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ostream & operator << (ostream & s, type_index const & type)
|
||||||
|
{
|
||||||
|
s << psemek::util::type_name(type);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <psemek/util/to_string.hpp>
|
#include <psemek/util/to_string.hpp>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue