Simplify exceptions

This commit is contained in:
Andrea Blankenstijn 2021-08-13 22:00:42 +02:00
parent e52b55f460
commit f0e89f837b
10 changed files with 96 additions and 144 deletions

View File

@ -9,6 +9,7 @@
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include <basic_widgets/core/error_helper.hpp>
#include <basic_widgets/core/font.hpp>
#include <basic_widgets/core/renderer.hpp>
#include <basic_widgets/w/aligned_layout.hpp>
@ -31,21 +32,17 @@ void run_example(
{
std::atexit(lib_exit);
try {
bwidgets::SDLError::success_or_throw(SDL_Init(SDL_INIT_VIDEO), __FILE__,
__FUNCTION__, __LINE__);
bwidgets::SDLError::success_or_throw(TTF_Init(), __FILE__, __FUNCTION__,
__LINE__);
bwidgets::success_or_throw<bwidgets::SDLError>(SDL_Init(SDL_INIT_VIDEO));
bwidgets::success_or_throw<bwidgets::SDLError>(TTF_Init());
const bwidgets::Size size_init {854, 480};
auto font =
std::make_shared<bwidgets::Font>(bwidgets::Font::find("Monospace"),
16); // NOLINT(readability-magic-numbers)
auto win = bwidgets::OpaqueStruct<SDL_Window>(
bwidgets::ptr_or_throw<bwidgets::SDLError>(
SDL_CreateWindow("basic_widgets example", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, size_init.w, size_init.h,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
| SDL_WINDOW_UTILITY),
__FILE__, __FUNCTION__, __LINE__),
bwidgets::ptr_or_throw<bwidgets::SDLError>(SDL_CreateWindow(
"basic_widgets example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
size_init.w, size_init.h,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_UTILITY)),
[](auto ptr) noexcept { SDL_DestroyWindow(ptr); });
auto renderer =
std::make_shared<bwidgets::Renderer>(win(), -1, SDL_RENDERER_ACCELERATED);
@ -93,8 +90,7 @@ void run_example(
renderer->present();
}
} catch (const bwidgets::SDLError& e) {
std::cerr << "Error: " << e.file << ":" << e.func << ":" << e.line << ": "
<< e.what << std::endl;
std::cerr << "Error: " << e.what << std::endl;
}
}

View File

@ -0,0 +1,35 @@
#ifndef BWIDGETS_ERROR_HELPER
#define BWIDGETS_ERROR_HELPER
#include <basic_widgets/core/type/exception.hpp>
#include <basic_widgets/core/type/sdl_error.hpp>
namespace bwidgets
{
template<Exception E, typename T>
static inline auto ptr_or_throw(T* ptr, const std::string& w = "") -> T*
{
std::string what;
if constexpr (std::is_same_v<E, SDLError>) what = w.empty() ? SDL_GetError() : w;
else what = w;
if (ptr == nullptr) throw E(what);
return ptr;
}
template<Exception E, typename T>
static inline auto success_or_throw(
T code, const std::string& w = "",
std::function<bool(T)> success = [](T code) { return code == 0; }) -> T
{
std::string what {w.empty() ? SDL_GetError() : w};
if constexpr (std::is_same_v<E, SDLError>) {
if (code <= 0) throw E(what);
}
else if (!success(code)) throw E(what);
return code;
}
}
#endif

View File

@ -7,6 +7,7 @@
#include <SDL2/SDL_render.h>
#include <basic_widgets/core/error_helper.hpp>
#include <basic_widgets/core/type/color.hpp>
#include <basic_widgets/core/type/opaque_struct.hpp>
#include <basic_widgets/core/type/sdl_error.hpp>
@ -23,8 +24,7 @@ namespace bwidgets
static inline auto _info(SDL_Renderer* r) -> SDL_RendererInfo
{
SDL_RendererInfo info;
SDLError::success_or_throw(SDL_GetRendererInfo(r, &info), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_GetRendererInfo(r, &info));
return info;
}

View File

@ -7,6 +7,7 @@
#include <SDL2/SDL_pixels.h>
#include <SDL2/SDL_render.h>
#include <basic_widgets/core/error_helper.hpp>
#include <basic_widgets/core/type/color.hpp>
#include <basic_widgets/core/type/opaque_struct.hpp>
#include <basic_widgets/core/type/sdl_error.hpp>
@ -64,13 +65,11 @@ namespace bwidgets
[[nodiscard]] static inline auto attributes(SDL_Texture* t)
{
Attr attr {};
SDLError::success_or_throw(
success_or_throw<SDLError>(
SDL_QueryTexture(t, &attr.format_raw,
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
(int*)&attr.access, &attr.w, &attr.h),
__FILE__, __FUNCTION__, __LINE__);
attr.format = SDLError::ptr_or_throw(SDL_AllocFormat(attr.format_raw),
__FILE__, __FUNCTION__, __LINE__);
(int*)&attr.access, &attr.w, &attr.h));
attr.format = ptr_or_throw<SDLError>(SDL_AllocFormat(attr.format_raw));
return attr;
}

View File

@ -12,36 +12,13 @@ namespace bwidgets
{
struct BaseException : std::exception
{
const char* file;
const char* func;
const int line;
const char* what;
std::string what;
BaseException(const char* file, const char* func, int l, const char* w) noexcept
: file(file), func(func), line(l), what(w)
{}
BaseException(std::string w) noexcept : what(std::move(w)) {}
};
template<typename T>
concept Exception = std::derived_from<T, BaseException>;
template<Exception E, typename T>
static inline auto ptr_or_throw(T* ptr, const char* file, const char* func, int l,
const char* w = nullptr) -> T*
{
if (ptr == nullptr) throw E(file, func, l, w);
return ptr;
}
template<Exception E, typename T>
static inline auto success_or_throw(
T code, const char* file, const char* func, int l, const char* w = nullptr,
std::function<bool(const T&)> success = [](const T& code) { return code == 0; })
-> T
{
if (!success(code)) throw E(file, func, l, w);
return code;
}
}
#endif

View File

@ -7,9 +7,7 @@ namespace bwidgets
{
struct FCError final : BaseException
{
FCError(const char* file, const char* func, int l, const char* w = nullptr)
: BaseException(file, func, l, w)
{}
using BaseException::BaseException;
};
}

View File

@ -11,32 +11,7 @@ namespace bwidgets
{
struct SDLError final : BaseException
{
SDLError(const char* file, const char* func, const int l,
const char* w = nullptr) noexcept
: BaseException(file, func, l, w)
{}
template<typename T>
[[nodiscard]] static inline auto ptr_or_throw(T* ptr, const char* file,
const char* func, int l,
const char* w = nullptr) -> T*
{
if (!ptr) {
if (!w) w = SDL_GetError();
throw SDLError(file, func, l, w);
}
return ptr;
}
static inline auto success_or_throw(int code, const char* file, const char* func,
int l, const char* w = nullptr) -> int
{
if (code < 0) {
if (w == nullptr) w = SDL_GetError();
throw SDLError(file, func, l, w);
}
return code;
}
using BaseException::BaseException;
};
}

View File

@ -3,6 +3,7 @@
#include <fontconfig/fontconfig.h>
#include <basic_widgets/core/error_helper.hpp>
#include <basic_widgets/core/font.hpp>
#include <basic_widgets/core/type/fc_error.hpp>
#include <basic_widgets/core/type/sdl_error.hpp>
@ -13,8 +14,7 @@ const Color Font::default_color_bg {255, 255, 255, SDL_ALPHA_OPAQUE};
const Color Font::default_color_fg {0, 0, 0, SDL_ALPHA_OPAQUE};
Font::Font(TTF_Font* f)
: Wrapper(ptr_or_throw<SDLError>(f, __FILE__, __FUNCTION__, __LINE__),
[f](TTF_Font*) noexcept { TTF_CloseFont(f); }),
: Wrapper(ptr_or_throw<SDLError>(f), [f](TTF_Font*) noexcept { TTF_CloseFont(f); }),
ascent(TTF_FontAscent(f)),
descent(TTF_FontDescent(f)),
faces(TTF_FontFaces(f)),
@ -84,7 +84,7 @@ auto Font::render(const RenderMode m, const std::string& str, const Color& fg,
break;
}
return ptr_or_throw<SDLError>(renderer(), __FILE__, __FUNCTION__, __LINE__);
return ptr_or_throw<SDLError>(renderer());
}
auto Font::style() const noexcept -> uint8_t
@ -109,20 +109,18 @@ auto Font::find(const std::string& pat) -> std::string
{
std::stack<std::function<void()>> cleaners;
FcConfig* conf = ptr_or_throw<FCError>(FcInitLoadConfigAndFonts(), __FILE__,
__FUNCTION__, __LINE__, "init failed");
FcConfig* conf = ptr_or_throw<FCError>(FcInitLoadConfigAndFonts(), "init failed");
cleaners.emplace([conf]() { FcConfigDestroy(conf); });
FcPattern* pattern = nullptr;
try {
pattern =
ptr_or_throw<FCError>(FcNameParse((FcChar8*)pat.c_str()), __FILE__,
__FUNCTION__, __LINE__, "pattern parsing failed");
pattern = ptr_or_throw<FCError>(FcNameParse((FcChar8*)pat.c_str()),
"pattern parsing failed");
cleaners.emplace([pattern]() { FcPatternDestroy(pattern); });
if (FcConfigSubstitute(conf, pattern, FcMatchPattern) == FcFalse)
throw FCError {__FILE__, __FUNCTION__, __LINE__,
"FcConfigSubstitute failed"};
success_or_throw<FCError, FcBool>(
FcConfigSubstitute(conf, pattern, FcMatchPattern), "FcConfigSubstitue failed",
[](FcBool code) { return code != FcFalse; });
} catch (const std::exception& e) {
while (!cleaners.empty()) {
cleaners.top()();
@ -149,8 +147,7 @@ auto Font::find(const std::string& pat) -> std::string
cleaners.pop();
}
if (file_path.empty())
throw FCError {__FILE__, __FUNCTION__, __LINE__, "no font found"};
if (file_path.empty()) throw FCError {"no font found"};
return file_path;
}

View File

@ -4,37 +4,33 @@
using namespace bwidgets;
Renderer::Renderer(SDL_Renderer* r)
: Wrapper(ptr_or_throw<SDLError>(r, __FILE__, __FUNCTION__, __LINE__),
: Wrapper(ptr_or_throw<SDLError>(r),
[r](SDL_Renderer*) noexcept { SDL_DestroyRenderer(r); }),
info(_info(r))
{}
Renderer::Renderer(SDL_Window* w, const int index, const uint32_t flags = 0)
: Renderer(ptr_or_throw<SDLError>(SDL_CreateRenderer(w, index, flags), __FILE__,
__FUNCTION__, __LINE__))
: Renderer(ptr_or_throw<SDLError>(SDL_CreateRenderer(w, index, flags)))
{}
auto Renderer::blend_mode() -> SDL_BlendMode
{
SDL_BlendMode mode {};
SDLError::success_or_throw(SDL_GetRenderDrawBlendMode(_data(), &mode), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_GetRenderDrawBlendMode(_data(), &mode));
return mode;
}
auto Renderer::blend_mode(const SDL_BlendMode mode) -> Renderer*
{
SDLError::success_or_throw(SDL_SetRenderDrawBlendMode(_data(), mode), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_SetRenderDrawBlendMode(_data(), mode));
return this;
}
auto Renderer::clear() -> Renderer*
{
SDLError::success_or_throw(SDL_RenderClear(_data()), __FILE__, __FUNCTION__,
__LINE__);
success_or_throw<SDLError>(SDL_RenderClear(_data()));
return this;
}
@ -42,8 +38,7 @@ auto Renderer::clear() -> Renderer*
auto Renderer::copy(const Texture* t, const SDL_Rect* src, const SDL_Rect* dst)
-> Renderer*
{
SDLError::success_or_throw(SDL_RenderCopy(_data(), t->_data(), src, dst), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_RenderCopy(_data(), t->_data(), src, dst));
return this;
}
@ -51,51 +46,46 @@ auto Renderer::copy(const Texture* t, const SDL_Rect* src, const SDL_Rect* dst)
auto Renderer::draw_color() -> Color
{
Color c;
SDLError::success_or_throw(
SDL_GetRenderDrawColor(_data(), &c().r, &c().g, &c().b, &c().a), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(
SDL_GetRenderDrawColor(_data(), &c().r, &c().g, &c().b, &c().a));
return c;
}
auto Renderer::draw_color(const Color& c) -> Renderer*
{
SDLError::success_or_throw(
SDL_SetRenderDrawColor(_data(), c().r, c().g, c().b, c().a), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(
SDL_SetRenderDrawColor(_data(), c().r, c().g, c().b, c().a));
return this;
}
auto Renderer::draw_line(const SDL_Point& a, const SDL_Point& b) -> Renderer*
{
SDLError::success_or_throw(SDL_RenderDrawLine(_data(), a.x, a.y, b.x, b.y), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_RenderDrawLine(_data(), a.x, a.y, b.x, b.y));
return this;
}
auto Renderer::draw_lines(const std::vector<SDL_Point>& pts) -> Renderer*
{
SDLError::success_or_throw(SDL_RenderDrawLines(_data(), pts.data(), (int)pts.size()),
__FILE__, __FUNCTION__, __LINE__);
success_or_throw<SDLError>(
SDL_RenderDrawLines(_data(), pts.data(), (int)pts.size()));
return this;
}
auto Renderer::draw_point(const SDL_Point& p) -> Renderer*
{
SDLError::success_or_throw(SDL_RenderDrawPoint(_data(), p.x, p.y), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_RenderDrawPoint(_data(), p.x, p.y));
return this;
}
auto Renderer::draw_points(const std::vector<SDL_Point>& pts) -> Renderer*
{
SDLError::success_or_throw(
SDL_RenderDrawPoints(_data(), pts.data(), (int)pts.size()), __FILE__, __FUNCTION__,
__LINE__);
success_or_throw<SDLError>(
SDL_RenderDrawPoints(_data(), pts.data(), (int)pts.size()));
return this;
}
@ -108,8 +98,7 @@ auto Renderer::draw_rect(const SDL_Rect* r) -> Renderer*
// The second corner is missing a pixel.
if (r != nullptr)
viewport({vp.x + r->x, vp.y + r->y, r->w - 1, r->h - 1}); // crop extra pixel
SDLError::success_or_throw(SDL_RenderDrawRect(_data(), nullptr), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_RenderDrawRect(_data(), nullptr));
// add missing pixel. works sometimes…
if (r != nullptr) draw_point({r->w - 1, r->h - 1});
else draw_point({vp.w - 1, vp.h - 1});
@ -121,24 +110,21 @@ auto Renderer::draw_rect(const SDL_Rect* r) -> Renderer*
auto Renderer::draw_rects(const std::vector<SDL_Rect>& rs) -> Renderer*
{
SDLError::success_or_throw(SDL_RenderDrawRects(_data(), rs.data(), (int)rs.size()),
__FILE__, __FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_RenderDrawRects(_data(), rs.data(), (int)rs.size()));
return this;
}
auto Renderer::fill_rect(const SDL_Rect* r) -> Renderer*
{
SDLError::success_or_throw(SDL_RenderFillRect(_data(), r), __FILE__, __FUNCTION__,
__LINE__);
success_or_throw<SDLError>(SDL_RenderFillRect(_data(), r));
return this;
}
auto Renderer::fill_rects(const std::vector<SDL_Rect>& rs) -> Renderer*
{
SDLError::success_or_throw(SDL_RenderFillRects(_data(), rs.data(), (int)rs.size()),
__FILE__, __FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_RenderFillRects(_data(), rs.data(), (int)rs.size()));
return this;
}
@ -146,8 +132,7 @@ auto Renderer::fill_rects(const std::vector<SDL_Rect>& rs) -> Renderer*
auto Renderer::output_size() -> Size
{
Size s {};
SDLError::success_or_throw(SDL_GetRendererOutputSize(_data(), &s.w, &s.h), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_GetRendererOutputSize(_data(), &s.w, &s.h));
return s;
}
@ -167,8 +152,7 @@ auto Renderer::viewport() noexcept -> SDL_Rect
auto Renderer::viewport(const SDL_Rect* vp) -> Renderer*
{
SDLError::success_or_throw(SDL_RenderSetViewport(_data(), vp), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_RenderSetViewport(_data(), vp));
return this;
}

View File

@ -4,7 +4,7 @@
using namespace bwidgets;
Texture::Texture(SDL_Texture* t)
: Wrapper(ptr_or_throw<SDLError>(t, __FILE__, __FUNCTION__, __LINE__),
: Wrapper(ptr_or_throw<SDLError>(t),
[t](SDL_Texture*) noexcept { SDL_DestroyTexture(t); })
{
_attributes = attributes(t);
@ -30,16 +30,14 @@ Texture::~Texture() noexcept
auto Texture::alpha_mode() -> uint8_t
{
uint8_t mode = 0;
SDLError::success_or_throw(SDL_GetTextureAlphaMod(_data(), &mode), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_GetTextureAlphaMod(_data(), &mode));
return mode;
}
auto Texture::alpha_mode(const uint8_t m) -> Texture*
{
SDLError::success_or_throw(SDL_SetTextureAlphaMod(_data(), m), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_SetTextureAlphaMod(_data(), m));
return this;
}
@ -47,16 +45,14 @@ auto Texture::alpha_mode(const uint8_t m) -> Texture*
auto Texture::blend_mode() -> SDL_BlendMode
{
SDL_BlendMode mode {};
SDLError::success_or_throw(SDL_GetTextureBlendMode(_data(), &mode), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_GetTextureBlendMode(_data(), &mode));
return mode;
}
auto Texture::blend_mode(const SDL_BlendMode m) -> Texture*
{
SDLError::success_or_throw(SDL_SetTextureBlendMode(_data(), m), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_SetTextureBlendMode(_data(), m));
return this;
}
@ -64,17 +60,15 @@ auto Texture::blend_mode(const SDL_BlendMode m) -> Texture*
auto Texture::color_mode() -> Color
{
Color mode;
SDLError::success_or_throw(
SDL_GetTextureColorMod(_data(), &mode().r, &mode().g, &mode().b), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(
SDL_GetTextureColorMod(_data(), &mode().r, &mode().g, &mode().b));
return mode;
}
auto Texture::color_mode(const Color& m) -> Texture*
{
SDLError::success_or_throw(SDL_SetTextureColorMod(_data(), m().r, m().g, m().b),
__FILE__, __FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_SetTextureColorMod(_data(), m().r, m().g, m().b));
return this;
}
@ -82,24 +76,21 @@ auto Texture::color_mode(const Color& m) -> Texture*
auto Texture::scale_mode() -> SDL_ScaleMode
{
SDL_ScaleMode mode {};
SDLError::success_or_throw(SDL_GetTextureScaleMode(_data(), &mode), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_GetTextureScaleMode(_data(), &mode));
return mode;
}
auto Texture::scale_mode(const SDL_ScaleMode m) -> Texture*
{
SDLError::success_or_throw(SDL_SetTextureScaleMode(_data(), m), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_SetTextureScaleMode(_data(), m));
return this;
}
auto Texture::update(SDL_Rect* r, const void* pixels, const int pitch) -> Texture*
{
SDLError::success_or_throw(SDL_UpdateTexture(_data(), r, pixels, pitch), __FILE__,
__FUNCTION__, __LINE__);
success_or_throw<SDLError>(SDL_UpdateTexture(_data(), r, pixels, pitch));
return this;
}