diff --git a/binding-mri/binding-mri.cpp b/binding-mri/binding-mri.cpp index 39f3a63..5cb518e 100644 --- a/binding-mri/binding-mri.cpp +++ b/binding-mri/binding-mri.cpp @@ -25,6 +25,7 @@ #include "eventthread.h" #include "filesystem.h" #include "util.h" +#include "sdl-util.h" #include "debugwriter.h" #include "graphics.h" #include "audio.h" @@ -339,7 +340,7 @@ static void runCustomScript(const std::string &filename) { std::string scriptData; - if (!readFile(filename.c_str(), scriptData)) + if (!readFileSDL(filename.c_str(), scriptData)) { showMsg(std::string("Unable to open '") + filename + "'"); return; diff --git a/src/config.cpp b/src/config.cpp index f4fbb34..8ff09cf 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -32,6 +32,7 @@ #include "debugwriter.h" #include "util.h" +#include "sdl-util.h" #ifdef INI_ENCODING extern "C" { @@ -223,22 +224,19 @@ void Config::read(int argc, char *argv[]) } /* Parse configuration file */ - std::ifstream confFile; - confFile.open(CONF_FILE); + SDLRWStream confFile(CONF_FILE, "r"); if (confFile) { try { - po::store(po::parse_config_file(confFile, podesc, true), vm); + po::store(po::parse_config_file(confFile.stream(), podesc, true), vm); po::notify(vm); } catch (po::error &error) { Debug() << CONF_FILE":" << error.what(); } - - confFile.close(); } #undef PO_DESC @@ -306,16 +304,25 @@ void Config::readGameINI() ("Game.Scripts", po::value()) ; - std::string iniPath = gameFolder + "/Game.ini"; - - std::ifstream iniFile; - iniFile.open((iniPath).c_str()); - po::variables_map vm; - po::store(po::parse_config_file(iniFile, podesc, true), vm); - po::notify(vm); + SDLRWStream iniFile("Game.ini", "r"); - iniFile.close(); + if (iniFile) + { + try + { + po::store(po::parse_config_file(iniFile.stream(), podesc, true), vm); + po::notify(vm); + } + catch (po::error &error) + { + Debug() << "Game.ini:" << error.what(); + } + } + else + { + Debug() << "FAILED to open Game.ini"; + } GUARD_ALL( game.title = vm["Game.Title"].as(); ); GUARD_ALL( game.scripts = vm["Game.Scripts"].as(); ); diff --git a/src/sdl-util.h b/src/sdl-util.h index ba02046..103b195 100644 --- a/src/sdl-util.h +++ b/src/sdl-util.h @@ -3,8 +3,10 @@ #include #include +#include #include +#include struct AtomicFlag { @@ -45,4 +47,99 @@ 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