X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fphysfs%2Fphysfs_stream.cpp;h=48bc10c28d620c71e084f28e14a7776ca702db1e;hb=84abfaeb33c5bf8dac0cfd9499d9d4c3e7d39881;hp=0a41a545cf8dd2fb3bb27f5066bb9ad8fdd2a40a;hpb=36266bca23c8ef1a4b036572b7c5fa07df7a1afd;p=supertux.git diff --git a/src/physfs/physfs_stream.cpp b/src/physfs/physfs_stream.cpp index 0a41a545c..48bc10c28 100644 --- a/src/physfs/physfs_stream.cpp +++ b/src/physfs/physfs_stream.cpp @@ -1,127 +1,179 @@ -/* -Copyright (C) 2005 Matthias Braun - -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 2 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, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include +// SuperTux +// Copyright (C) 2006 Matthias Braun +// +// 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 . + +#include "physfs/physfs_stream.hpp" -#include "physfs_stream.h" +#include -#include -#include +#include #include +#include -IFileStreambuf::IFileStreambuf(const std::string& filename) +IFileStreambuf::IFileStreambuf(const std::string& filename) : + file() { - file = PHYSFS_openRead(filename.c_str()); - if(file == 0) { - std::stringstream msg; - msg << "Couldn't open file '" << filename << "': " - << PHYSFS_getLastError(); - throw std::runtime_error(msg.str()); - } + // check this as PHYSFS seems to be buggy and still returns a + // valid pointer in this case + if(filename == "") { + throw std::runtime_error("Couldn't open file: empty filename"); + } + file = PHYSFS_openRead(filename.c_str()); + if(file == 0) { + std::stringstream msg; + msg << "Couldn't open file '" << filename << "': " + << PHYSFS_getLastError(); + throw std::runtime_error(msg.str()); + } } IFileStreambuf::~IFileStreambuf() { - PHYSFS_close(file); + PHYSFS_close(file); } int IFileStreambuf::underflow() { - if(PHYSFS_eof(file)) - return traits_type::eof(); - - size_t bytesread = (size_t) PHYSFS_read(file, buf, 1, sizeof(buf)); - if(bytesread == 0) - return traits_type::eof(); - setg(buf, buf, buf + bytesread); - - return buf[0]; + if(PHYSFS_eof(file)) { + return traits_type::eof(); + } + + PHYSFS_sint64 bytesread = PHYSFS_read(file, buf, 1, sizeof(buf)); + if(bytesread <= 0) { + return traits_type::eof(); + } + setg(buf, buf, buf + bytesread); + + return buf[0]; +} + +IFileStreambuf::pos_type +IFileStreambuf::seekpos(pos_type pos, std::ios_base::openmode) +{ + if(PHYSFS_seek(file, static_cast (pos)) == 0) { + return pos_type(off_type(-1)); + } + + // the seek invalidated the buffer + setg(buf, buf, buf); + return pos; +} + +IFileStreambuf::pos_type +IFileStreambuf::seekoff(off_type off, std::ios_base::seekdir dir, + std::ios_base::openmode mode) +{ + off_type pos = off; + PHYSFS_sint64 ptell = PHYSFS_tell(file); + + switch(dir) { + case std::ios_base::beg: + break; + case std::ios_base::cur: + if(off == 0) + return static_cast (ptell) - static_cast (egptr() - gptr()); + pos += static_cast (ptell) - static_cast (egptr() - gptr()); + break; + case std::ios_base::end: + pos += static_cast (PHYSFS_fileLength(file)); + break; + default: +#ifdef DEBUG + assert(false); +#else + return pos_type(off_type(-1)); +#endif + } + + return seekpos(static_cast (pos), mode); } //--------------------------------------------------------------------------- -OFileStreambuf::OFileStreambuf(const std::string& filename) +OFileStreambuf::OFileStreambuf(const std::string& filename) : + file() { - file = PHYSFS_openWrite(filename.c_str()); - if(file == 0) { - std::stringstream msg; - msg << "Couldn't open file '" << filename << "': " - << PHYSFS_getLastError(); - throw std::runtime_error(msg.str()); - } - - setp(buf, buf+sizeof(buf)); + file = PHYSFS_openWrite(filename.c_str()); + if(file == 0) { + std::stringstream msg; + msg << "Couldn't open file '" << filename << "': " + << PHYSFS_getLastError(); + throw std::runtime_error(msg.str()); + } + + setp(buf, buf+sizeof(buf)); } OFileStreambuf::~OFileStreambuf() { - sync(); - PHYSFS_close(file); + sync(); + PHYSFS_close(file); } int OFileStreambuf::overflow(int c) { - if(pbase() == pptr()) - return 0; + char c2 = (char)c; - size_t size = pptr() - pbase(); - PHYSFS_sint64 res = PHYSFS_write(file, pbase(), 1, size); - if(res <= 0) - return traits_type::eof(); - - if(c != traits_type::eof()) { - PHYSFS_sint64 res = PHYSFS_write(file, &c, 1, 1); - if(res <= 0) - return traits_type::eof(); - } - - setp(buf, buf + res); + if(pbase() == pptr()) return 0; + + size_t size = pptr() - pbase(); + PHYSFS_sint64 res = PHYSFS_write(file, pbase(), 1, size); + if(res <= 0) + return traits_type::eof(); + + if(c != traits_type::eof()) { + PHYSFS_sint64 res = PHYSFS_write(file, &c2, 1, 1); + if(res <= 0) + return traits_type::eof(); + } + + setp(buf, buf + res); + return 0; } int OFileStreambuf::sync() { - return overflow(traits_type::eof()); + return overflow(traits_type::eof()); } //--------------------------------------------------------------------------- IFileStream::IFileStream(const std::string& filename) - : std::istream(new IFileStreambuf(filename)) + : std::istream(new IFileStreambuf(filename)) { } IFileStream::~IFileStream() { - delete rdbuf(); + delete rdbuf(); } //--------------------------------------------------------------------------- OFileStream::OFileStream(const std::string& filename) - : std::ostream(new OFileStreambuf(filename)) + : std::ostream(new OFileStreambuf(filename)) { } OFileStream::~OFileStream() { - delete rdbuf(); + delete rdbuf(); } +/* EOF */