Advertisement
ulfben

SDL wrappers for C++11

Oct 17th, 2016
351
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.80 KB | None | 0 0
  1. #pragma once
  2. #include <memory>
  3. #include <cerrno>
  4. #include <system_error>
  5. #include "SDL.h"
  6. /*
  7. A namespace for wrapping SDL in C++11 convenience, like:
  8.     1. unique and shared pointers for all SDL resource types
  9.             http://swarminglogic.com/jotting/2015_05_smartwrappers
  10.     2. templatized unique_ptr factory for arbitrary types: "make_resource"
  11.             https://eb2.co/blog/2014/04/c-plus-plus-14-and-sdl2-managing-resources/
  12.     3. exception classes that wraps the SDL_GetError-message
  13. */
  14. namespace sdl2 {
  15.     class SDLError : public std::exception {
  16.         std::string _msg;
  17.     public:
  18.         SDLError::SDLError() : exception(), _msg(SDL_GetError()) {}
  19.         SDLError::SDLError(const std::string& m) : exception(), _msg(m) {}
  20.         virtual ~SDLError() {};
  21.         virtual const char* what() const {
  22.             return _msg.c_str();
  23.         }
  24.     };
  25.     class InitError : public SDLError {    
  26.     public:
  27.         InitError::InitError() : SDLError() {};
  28.         InitError::InitError(const std::string& m) : SDLError(m){}         
  29.         virtual ~InitError() {};
  30.     };
  31.     struct SDL_Deleter {
  32.         void operator()(SDL_Surface*  ptr) { if (ptr) SDL_FreeSurface(ptr); }
  33.         void operator()(SDL_Texture*  ptr) { if (ptr) SDL_DestroyTexture(ptr); }
  34.         void operator()(SDL_Renderer* ptr) { if (ptr) SDL_DestroyRenderer(ptr); }
  35.         void operator()(SDL_Window*   ptr) { if (ptr) SDL_DestroyWindow(ptr); }
  36.         void operator()(SDL_RWops*    ptr) { if (ptr) SDL_RWclose(ptr); }
  37.         void operator()(char*         ptr) { if (ptr) SDL_free(ptr); } //for paths
  38.     }; 
  39.     //extending shared_ptr to support custom deletion
  40.     template<class T, class D = std::default_delete<T>>
  41.     struct shared_ptr_with_deleter : public std::shared_ptr<T>  {
  42.         explicit shared_ptr_with_deleter(T* t = nullptr) : std::shared_ptr<T>(t, D()) {}
  43.         void reset(T* t = nullptr) {
  44.             std::shared_ptr<T>::reset(t, D());
  45.         }
  46.     };
  47.     // unique pointers
  48.     using SurfacePtr    = std::unique_ptr<SDL_Surface,  SDL_Deleter>;
  49.     using TexturePtr    = std::unique_ptr<SDL_Texture,  SDL_Deleter>;
  50.     using RendererPtr   = std::unique_ptr<SDL_Renderer, SDL_Deleter>;
  51.     using WindowPtr     = std::unique_ptr<SDL_Window,   SDL_Deleter>;
  52.     using RWopsPtr      = std::unique_ptr<SDL_RWops,    SDL_Deleter>;
  53.     using CharPtr       = std::unique_ptr<char,         SDL_Deleter>;  
  54.     //shared pointers
  55.     using SurfaceShPtr  = shared_ptr_with_deleter<SDL_Surface,  SDL_Deleter>;
  56.     using TextureShPtr  = shared_ptr_with_deleter<SDL_Texture,  SDL_Deleter>;
  57.     using RendererShPtr = shared_ptr_with_deleter<SDL_Renderer, SDL_Deleter>;
  58.     using WindowShPtr   = shared_ptr_with_deleter<SDL_Window,   SDL_Deleter>;
  59.     using RWopsShPtr    = shared_ptr_with_deleter<SDL_RWops,    SDL_Deleter>;
  60.     using CharShPtr     = shared_ptr_with_deleter<char,         SDL_Deleter>;
  61.    
  62.     //templatized unique_ptr factory for arbitrary types
  63.         //unique_ptr<t> make_t(...);                       
  64.     template<typename Creator, typename Destructor, typename... Arguments>
  65.     auto make_resource(Creator c, Destructor d, Arguments&&... args) {
  66.         auto r = c(std::forward<Arguments>(args)...);
  67.         if (!r) {
  68.             throw std::system_error(errno, std::generic_category());
  69.         }
  70.         return std::unique_ptr<std::decay_t<decltype(*r)>, decltype(d)>(r, d);
  71.     }  
  72.     using window_ptr = std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)>;
  73.     using renderer_ptr = std::unique_ptr<SDL_Renderer, decltype(&SDL_DestroyRenderer)>;
  74.     using texture_ptr = std::unique_ptr<SDL_Texture, decltype(&SDL_DestroyTexture)>;
  75.     using surface_ptr = std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)>;
  76.  
  77.     inline window_ptr make_window(const char* title, int w, int h, Uint32 flags=SDL_WINDOW_OPENGL,
  78.                                     int x = SDL_WINDOWPOS_UNDEFINED, int y = SDL_WINDOWPOS_UNDEFINED) {
  79.         return make_resource(SDL_CreateWindow, SDL_DestroyWindow, title, x, y, w, h, flags);
  80.     }
  81.     inline renderer_ptr make_renderer(SDL_Window& w, Uint32 flags = SDL_RENDERER_ACCELERATED, int index = -1) {    
  82.         return make_resource(SDL_CreateRenderer, SDL_DestroyRenderer, &w, index, flags);
  83.     }      
  84.     inline texture_ptr make_texture(SDL_Renderer& r, Uint32 format /*SDL_PixelFormatEnum*/, int access /*SDL_TextureAccess*/,
  85.                                     int width, int height) {
  86.         return make_resource(SDL_CreateTexture, SDL_DestroyTexture, &r, format, access, width, height);
  87.     }
  88.     inline texture_ptr make_texture(SDL_Renderer& r, SDL_Surface* surface) {
  89.         return make_resource(SDL_CreateTextureFromSurface, SDL_DestroyTexture, &r, surface);
  90.     }
  91.     inline surface_ptr make_surface(Uint32 flags, int width, int height, int depth,
  92.                                     Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) {
  93.         return make_resource(SDL_CreateRGBSurface, SDL_FreeSurface, flags, width, height, depth, Rmask, Gmask, Bmask, Amask);
  94.     }
  95.     inline surface_ptr make_surface(void* pixels, int width, int height, int depth, int pitch,
  96.                                     Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) {
  97.         return make_resource(SDL_CreateRGBSurfaceFrom, SDL_FreeSurface, pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
  98.     }
  99. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement