diff options
Diffstat (limited to 'src/common/resources')
-rw-r--r-- | src/common/resources/inputstream.cpp | 53 | ||||
-rw-r--r-- | src/common/resources/inputstream.h | 33 | ||||
-rw-r--r-- | src/common/resources/resourcemanager.cpp | 200 | ||||
-rw-r--r-- | src/common/resources/resourcemanager.h | 40 | ||||
-rw-r--r-- | src/common/resources/resourcestreambuffer.cpp | 121 | ||||
-rw-r--r-- | src/common/resources/resourcestreambuffer.h | 47 |
6 files changed, 494 insertions, 0 deletions
diff --git a/src/common/resources/inputstream.cpp b/src/common/resources/inputstream.cpp new file mode 100644 index 0000000..e121971 --- /dev/null +++ b/src/common/resources/inputstream.cpp @@ -0,0 +1,53 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +#include "common/resources/inputstream.h" +#include "common/resources/resourcestreambuffer.h" + + +CInputStream::CInputStream() : std::istream(new CResourceStreamBuffer()) +{ +} + + +CInputStream::~CInputStream() +{ + delete rdbuf(); +} + + +void CInputStream::open(const std::string& filename) +{ + static_cast<CResourceStreamBuffer *>(rdbuf())->open(filename); +} + + +void CInputStream::close() +{ + static_cast<CResourceStreamBuffer *>(rdbuf())->close(); +} + + +bool CInputStream::is_open() +{ + return static_cast<CResourceStreamBuffer *>(rdbuf())->is_open(); +} + + +size_t CInputStream::size() +{ + return static_cast<CResourceStreamBuffer *>(rdbuf())->size(); +} diff --git a/src/common/resources/inputstream.h b/src/common/resources/inputstream.h new file mode 100644 index 0000000..9d1c578 --- /dev/null +++ b/src/common/resources/inputstream.h @@ -0,0 +1,33 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +#pragma once + +#include <istream> +#include <string> + + +class CInputStream : public std::istream +{ +public: + CInputStream(); + virtual ~CInputStream(); + + void open(const std::string &filename); + void close(); + bool is_open(); + size_t size(); +}; diff --git a/src/common/resources/resourcemanager.cpp b/src/common/resources/resourcemanager.cpp new file mode 100644 index 0000000..ccef2a3 --- /dev/null +++ b/src/common/resources/resourcemanager.cpp @@ -0,0 +1,200 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + + +#include "common/resources/resourcemanager.h" + +#include "common/config.h" + +#include <physfs.h> + + +CResourceManager::CResourceManager(const char *argv0) +{ + if (PHYSFS_init(argv0)) + { + // TODO error + } +} + + +CResourceManager::~CResourceManager() +{ + if (PHYSFS_isInit()) + { + if (PHYSFS_deinit()) + { + // TODO error + } + } +} + + +bool CResourceManager::AddLocation(const std::string &location, bool prepend) +{ + if (PHYSFS_isInit()) + { + if (PHYSFS_mount(location.c_str(), nullptr, prepend ? 0 : 1)) + { + // TODO error + } + } + + return false; +} + + +bool CResourceManager::RemoveLocation(const std::string &location) +{ + if (PHYSFS_isInit()) + { + if (PHYSFS_removeFromSearchPath(location.c_str())) + { + // TODO error + } + } + + return false; +} + + +bool CResourceManager::SetSaveLocation(const std::string &location) +{ + if (PHYSFS_isInit()) + { + if (PHYSFS_setWriteDir(location.c_str())) + { + // TODO error + } + } + + return false; +} + + +std::string CResourceManager::GetLanguageLocation() +{ + return COLOBOT_I18N_DIR; +} + + +SDL_RWops* CResourceManager::GetSDLFileHandler(const std::string &filename) +{ + SDL_RWops *handler = SDL_AllocRW(); + if (!handler) + { + // TODO error + return nullptr; + } + + if (!PHYSFS_isInit()) + { + SDL_FreeRW(handler); + return nullptr; + } + + PHYSFS_File *file = PHYSFS_openRead(filename.c_str()); + if (!file) + { + SDL_FreeRW(handler); + return nullptr; + } + + handler->seek = SDLSeek; + handler->read = SDLRead; + handler->write = SDLWrite; + handler->close = SDLClose; + handler->type = 0xc010b04f; + handler->hidden.unknown.data1 = file; + + return handler; +} + + +int CResourceManager::SDLClose(SDL_RWops* context) +{ + if (CheckSDLContext(context)) + { + PHYSFS_close(static_cast<PHYSFS_File *>(context->hidden.unknown.data1)); + SDL_FreeRW(context); + + return 0; + } + + return 1; +} + + +int CResourceManager::SDLRead(SDL_RWops* context, void* ptr, int size, int maxnum) +{ + if (CheckSDLContext(context)) + { + PHYSFS_File *file = static_cast<PHYSFS_File *>(context->hidden.unknown.data1); + SDL_memset(ptr, 0, size * maxnum); + + return PHYSFS_read(file, ptr, size, maxnum); + } + + return 0; +} + + +int CResourceManager::SDLWrite(SDL_RWops* context, const void* ptr, int size, int num) +{ + return 0; +} + + +int CResourceManager::SDLSeek(SDL_RWops* context, int offset, int whence) +{ + if (CheckSDLContext(context)) + { + PHYSFS_File *file = static_cast<PHYSFS_File *>(context->hidden.unknown.data1); + int position, result; + + switch (whence) + { + default: + case RW_SEEK_SET: + result = PHYSFS_seek(file, offset); + return result > 0 ? offset : -1; + + case RW_SEEK_CUR: + position = offset + PHYSFS_tell(file); + result = PHYSFS_seek(file, position); + return result > 0 ? position : -1; + + case RW_SEEK_END: + position = PHYSFS_fileLength(file) - offset; + result = PHYSFS_seek(file, position); + return result > 0 ? position : -1; + } + } + + return -1; +} + + +bool CResourceManager::CheckSDLContext(SDL_RWops* context) +{ + if (context->type != 0xc010b04f) + { + SDL_SetError("Wrong kind of RWops"); + return false; + } + + return true; +} diff --git a/src/common/resources/resourcemanager.h b/src/common/resources/resourcemanager.h new file mode 100644 index 0000000..ba11d73 --- /dev/null +++ b/src/common/resources/resourcemanager.h @@ -0,0 +1,40 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +#pragma once + +#include <string> +#include <SDL.h> + +class CResourceManager +{ +public: + CResourceManager(const char *argv0); + ~CResourceManager(); + + static bool AddLocation(const std::string &location, bool prepend = true); + static bool RemoveLocation(const std::string &location); + static bool SetSaveLocation(const std::string &location); + static std::string GetLanguageLocation(); + static SDL_RWops* GetSDLFileHandler(const std::string &filename); + +private: + static int SDLSeek(SDL_RWops *context, int offset, int whence); + static int SDLRead(SDL_RWops *context, void *ptr, int size, int maxnum); + static int SDLWrite(SDL_RWops *context, const void *ptr, int size, int num); + static int SDLClose(SDL_RWops *context); + static bool CheckSDLContext(SDL_RWops *context); +}; diff --git a/src/common/resources/resourcestreambuffer.cpp b/src/common/resources/resourcestreambuffer.cpp new file mode 100644 index 0000000..e7be51d --- /dev/null +++ b/src/common/resources/resourcestreambuffer.cpp @@ -0,0 +1,121 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +#include "common/resources/resourcestreambuffer.h" + +#include <stdexcept> +#include <sstream> + +CResourceStreamBuffer::CResourceStreamBuffer(size_t buffer_size) : m_buffer_size(buffer_size) +{ + if (buffer_size <= 0) + { + throw std::runtime_error("File buffer must be larger then 0 bytes"); + } + + m_buffer = new char[buffer_size]; +} + + +CResourceStreamBuffer::~CResourceStreamBuffer() +{ + close(); + delete m_buffer; +} + + +void CResourceStreamBuffer::open(const std::string &filename) +{ + if (PHYSFS_isInit()) + { + m_file = PHYSFS_openRead(filename.c_str()); + } +} + + +void CResourceStreamBuffer::close() +{ + if (is_open()) + { + PHYSFS_close(m_file); + } +} + + +bool CResourceStreamBuffer::is_open() +{ + return m_file; +} + + +size_t CResourceStreamBuffer::size() +{ + return PHYSFS_fileLength(m_file); +} + + +std::streambuf::int_type CResourceStreamBuffer::underflow() +{ + if (PHYSFS_eof(m_file)) + { + return traits_type::eof(); + } + + PHYSFS_sint64 read_count = PHYSFS_read(m_file, m_buffer, sizeof(char), m_buffer_size); + if (read_count <= 0) + { + return traits_type::eof(); + } + + setg(m_buffer, m_buffer, m_buffer + read_count); + + return traits_type::to_int_type(*gptr()); +} + + +std::streampos CResourceStreamBuffer::seekpos(std::streampos sp, std::ios_base::openmode which) +{ + return seekoff(off_type(sp), std::ios_base::beg, which); +} + + +std::streampos CResourceStreamBuffer::seekoff(std::streamoff off, std::ios_base::seekdir way, std::ios_base::openmode which) +{ + /* A bit of explanation: + We are reading file by m_buffer_size parts so our 3 internal pointers will be + * eback (not used here) - start of block + * gptr - position of read cursor in block + * egtpr - end of block + off argument is relative to way */ + + switch (way) + { + case std::ios_base::beg: + return pos_type(off_type(off)); + + case std::ios_base::cur: + // tell will give cursor at begining of block so we have to add where in block we currently are + return off + static_cast<off_type>(PHYSFS_tell(m_file)) - static_cast<off_type> (egptr() - gptr()); + + case std::ios_base::end: + return off + static_cast<off_type>(PHYSFS_fileLength(m_file)); + + default: + break; + } + + return pos_type(off_type(-1)); +} diff --git a/src/common/resources/resourcestreambuffer.h b/src/common/resources/resourcestreambuffer.h new file mode 100644 index 0000000..a9ec0db --- /dev/null +++ b/src/common/resources/resourcestreambuffer.h @@ -0,0 +1,47 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2014 Polish Portal of Colobot (PPC) +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +#pragma once + +#include <streambuf> +#include <string> +#include <physfs.h> + +class CResourceStreamBuffer : public std::streambuf +{ +public: + CResourceStreamBuffer(size_t buffer_size = 512); + virtual ~CResourceStreamBuffer(); + + void open(const std::string &filename); + void close(); + bool is_open(); + size_t size(); + +private: + int_type underflow(); + std::streampos seekpos(std::streampos sp, std::ios_base::openmode which); + std::streampos seekoff(std::streamoff off, std::ios_base::seekdir way, std::ios_base::openmode which); + + // copy ctor and assignment not implemented; + // copying not allowed + CResourceStreamBuffer(const CResourceStreamBuffer &); + CResourceStreamBuffer &operator= (const CResourceStreamBuffer &); + + PHYSFS_File *m_file; + char *m_buffer; + size_t m_buffer_size; +}; |