Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <memory>
- #include <cerrno>
- #include <system_error>
- #include "SDL.h"
- /*
- A namespace for wrapping SDL in C++11 convenience, like:
- 1. unique and shared pointers for all SDL resource types
- http://swarminglogic.com/jotting/2015_05_smartwrappers
- 2. templatized unique_ptr factory for arbitrary types: "make_resource"
- https://eb2.co/blog/2014/04/c-plus-plus-14-and-sdl2-managing-resources/
- 3. exception classes that wraps the SDL_GetError-message
- */
- namespace sdl2 {
- class SDLError : public std::exception {
- std::string _msg;
- public:
- SDLError::SDLError() : exception(), _msg(SDL_GetError()) {}
- SDLError::SDLError(const std::string& m) : exception(), _msg(m) {}
- virtual ~SDLError() {};
- virtual const char* what() const {
- return _msg.c_str();
- }
- };
- class InitError : public SDLError {
- public:
- InitError::InitError() : SDLError() {};
- InitError::InitError(const std::string& m) : SDLError(m){}
- virtual ~InitError() {};
- };
- struct SDL_Deleter {
- void operator()(SDL_Surface* ptr) { if (ptr) SDL_FreeSurface(ptr); }
- void operator()(SDL_Texture* ptr) { if (ptr) SDL_DestroyTexture(ptr); }
- void operator()(SDL_Renderer* ptr) { if (ptr) SDL_DestroyRenderer(ptr); }
- void operator()(SDL_Window* ptr) { if (ptr) SDL_DestroyWindow(ptr); }
- void operator()(SDL_RWops* ptr) { if (ptr) SDL_RWclose(ptr); }
- void operator()(char* ptr) { if (ptr) SDL_free(ptr); } //for paths
- };
- //extending shared_ptr to support custom deletion
- template<class T, class D = std::default_delete<T>>
- struct shared_ptr_with_deleter : public std::shared_ptr<T> {
- explicit shared_ptr_with_deleter(T* t = nullptr) : std::shared_ptr<T>(t, D()) {}
- void reset(T* t = nullptr) {
- std::shared_ptr<T>::reset(t, D());
- }
- };
- // unique pointers
- using SurfacePtr = std::unique_ptr<SDL_Surface, SDL_Deleter>;
- using TexturePtr = std::unique_ptr<SDL_Texture, SDL_Deleter>;
- using RendererPtr = std::unique_ptr<SDL_Renderer, SDL_Deleter>;
- using WindowPtr = std::unique_ptr<SDL_Window, SDL_Deleter>;
- using RWopsPtr = std::unique_ptr<SDL_RWops, SDL_Deleter>;
- using CharPtr = std::unique_ptr<char, SDL_Deleter>;
- //shared pointers
- using SurfaceShPtr = shared_ptr_with_deleter<SDL_Surface, SDL_Deleter>;
- using TextureShPtr = shared_ptr_with_deleter<SDL_Texture, SDL_Deleter>;
- using RendererShPtr = shared_ptr_with_deleter<SDL_Renderer, SDL_Deleter>;
- using WindowShPtr = shared_ptr_with_deleter<SDL_Window, SDL_Deleter>;
- using RWopsShPtr = shared_ptr_with_deleter<SDL_RWops, SDL_Deleter>;
- using CharShPtr = shared_ptr_with_deleter<char, SDL_Deleter>;
- //templatized unique_ptr factory for arbitrary types
- //unique_ptr<t> make_t(...);
- template<typename Creator, typename Destructor, typename... Arguments>
- auto make_resource(Creator c, Destructor d, Arguments&&... args) {
- auto r = c(std::forward<Arguments>(args)...);
- if (!r) {
- throw std::system_error(errno, std::generic_category());
- }
- return std::unique_ptr<std::decay_t<decltype(*r)>, decltype(d)>(r, d);
- }
- using window_ptr = std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)>;
- using renderer_ptr = std::unique_ptr<SDL_Renderer, decltype(&SDL_DestroyRenderer)>;
- using texture_ptr = std::unique_ptr<SDL_Texture, decltype(&SDL_DestroyTexture)>;
- using surface_ptr = std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)>;
- inline window_ptr make_window(const char* title, int w, int h, Uint32 flags=SDL_WINDOW_OPENGL,
- int x = SDL_WINDOWPOS_UNDEFINED, int y = SDL_WINDOWPOS_UNDEFINED) {
- return make_resource(SDL_CreateWindow, SDL_DestroyWindow, title, x, y, w, h, flags);
- }
- inline renderer_ptr make_renderer(SDL_Window& w, Uint32 flags = SDL_RENDERER_ACCELERATED, int index = -1) {
- return make_resource(SDL_CreateRenderer, SDL_DestroyRenderer, &w, index, flags);
- }
- inline texture_ptr make_texture(SDL_Renderer& r, Uint32 format /*SDL_PixelFormatEnum*/, int access /*SDL_TextureAccess*/,
- int width, int height) {
- return make_resource(SDL_CreateTexture, SDL_DestroyTexture, &r, format, access, width, height);
- }
- inline texture_ptr make_texture(SDL_Renderer& r, SDL_Surface* surface) {
- return make_resource(SDL_CreateTextureFromSurface, SDL_DestroyTexture, &r, surface);
- }
- inline surface_ptr make_surface(Uint32 flags, int width, int height, int depth,
- Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) {
- return make_resource(SDL_CreateRGBSurface, SDL_FreeSurface, flags, width, height, depth, Rmask, Gmask, Bmask, Amask);
- }
- inline surface_ptr make_surface(void* pixels, int width, int height, int depth, int pitch,
- Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) {
- return make_resource(SDL_CreateRGBSurfaceFrom, SDL_FreeSurface, pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement