#ifndef SDLUTIL_H #define SDLUTIL_H #include #include #include #include #include struct AtomicFlag { AtomicFlag() { clear(); } void set() { SDL_AtomicSet(&atom, 1); } void clear() { SDL_AtomicSet(&atom, 0); } operator bool() const { return SDL_AtomicGet(&atom); } private: mutable SDL_atomic_t atom; }; template int __sdlThreadFun(void *obj) { (static_cast(obj)->*func)(); return 0; } template SDL_Thread *createSDLThread(C *obj, const std::string &name = std::string()) { return SDL_CreateThread(__sdlThreadFun, name.c_str(), obj); } inline bool readFileSDL(const char *path, std::string &out) { SDL_RWops *f = SDL_RWFromFile(path, "rb"); if (!f) return false; long size = SDL_RWsize(f); size_t back = out.size(); out.resize(back+size); size_t read = SDL_RWread(f, &out[back], 1, size); SDL_RWclose(f); if (read != (size_t) size) out.resize(back+read); return true; } template class SDLRWBuf : public std::streambuf { public: SDLRWBuf(SDL_RWops *ops) : ops(ops) { char *end = buf + bufSize + pbSize; setg(end, end, end); } private: int_type underflow() { if (!ops) return traits_type::eof(); if (gptr() < egptr()) return traits_type::to_int_type(*gptr()); char *base = buf; char *start = base; if (eback() == base) { memmove(base, egptr() - pbSize, pbSize); start += pbSize; } size_t n = SDL_RWread(ops, start, 1, bufSize - (start - base)); if (n == 0) return traits_type::eof(); setg(base, start, start + n); return underflow(); } SDL_RWops *ops; char buf[bufSize+pbSize]; }; class SDLRWStream { public: SDLRWStream(const char *filename, const char *mode) : ops(SDL_RWFromFile(filename, mode)), buf(ops), s(&buf) {} ~SDLRWStream() { if (ops) SDL_RWclose(ops); } operator bool() const { return ops != 0; } std::istream &stream() { return s; } private: SDL_RWops *ops; SDLRWBuf<> buf; std::istream s; }; #endif // SDLUTIL_H