More work on streams

dev-mp
Krzysztof Dermont 2014-06-23 23:19:55 +02:00
parent 3aca1de731
commit 68d41d3b21
10 changed files with 321 additions and 189 deletions

View File

@ -75,7 +75,8 @@ common/profile.cpp
common/restext.cpp
common/stringutils.cpp
common/resources/resourcemanager.cpp
common/resources/resourcestreambuffer.cpp
common/resources/inputstreambuffer.cpp
common/resources/outputstreambuffer.cpp
common/resources/inputstream.cpp
common/resources/outputstream.cpp
common/resources/sndfile.cpp

View File

@ -15,10 +15,10 @@
// * along with this program. If not, see http://www.gnu.org/licenses/.
#include "common/resources/inputstream.h"
#include "common/resources/resourcestreambuffer.h"
#include "common/resources/inputstreambuffer.h"
CInputStream::CInputStream() : std::istream(new CResourceStreamBuffer())
CInputStream::CInputStream() : std::istream(new CInputStreamBuffer())
{
}
@ -31,23 +31,23 @@ CInputStream::~CInputStream()
void CInputStream::open(const std::string& filename)
{
static_cast<CResourceStreamBuffer *>(rdbuf())->open(filename);
static_cast<CInputStreamBuffer *>(rdbuf())->open(filename);
}
void CInputStream::close()
{
static_cast<CResourceStreamBuffer *>(rdbuf())->close();
static_cast<CInputStreamBuffer *>(rdbuf())->close();
}
bool CInputStream::is_open()
{
return static_cast<CResourceStreamBuffer *>(rdbuf())->is_open();
return static_cast<CInputStreamBuffer *>(rdbuf())->is_open();
}
size_t CInputStream::size()
{
return static_cast<CResourceStreamBuffer *>(rdbuf())->size();
return static_cast<CInputStreamBuffer *>(rdbuf())->size();
}

View File

@ -0,0 +1,129 @@
// * 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/inputstreambuffer.h"
#include <stdexcept>
#include <sstream>
CInputStreamBuffer::CInputStreamBuffer(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];
m_file = nullptr;
}
CInputStreamBuffer::~CInputStreamBuffer()
{
close();
delete m_buffer;
}
void CInputStreamBuffer::open(const std::string &filename)
{
if (PHYSFS_isInit())
m_file = PHYSFS_openRead(filename.c_str());
}
void CInputStreamBuffer::close()
{
if (is_open())
PHYSFS_close(m_file);
}
bool CInputStreamBuffer::is_open()
{
return m_file;
}
size_t CInputStreamBuffer::size()
{
return PHYSFS_fileLength(m_file);
}
std::streambuf::int_type CInputStreamBuffer::underflow()
{
if (gptr() < egptr())
return traits_type::to_int_type(*gptr());
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 CInputStreamBuffer::seekpos(std::streampos sp, std::ios_base::openmode which)
{
return seekoff(off_type(sp), std::ios_base::beg, which);
}
std::streampos CInputStreamBuffer::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 */
std::streamoff new_position;
switch (way)
{
case std::ios_base::beg:
new_position = off;
break;
case std::ios_base::cur:
// tell will give cursor at begining of block so we have to add where in block we currently are
new_position = off + static_cast<off_type>(PHYSFS_tell(m_file)) - static_cast<off_type> (egptr() - gptr());
break;
case std::ios_base::end:
new_position = off + static_cast<off_type>(PHYSFS_fileLength(m_file));
break;
default:
break;
}
if (PHYSFS_seek(m_file, new_position))
{
setg(m_buffer, m_buffer, m_buffer); // reset buffer
return pos_type(new_position);
}
return pos_type(off_type(-1));
}

View File

@ -0,0 +1,48 @@
// * 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 CInputStreamBuffer : public std::streambuf
{
public:
CInputStreamBuffer(size_t buffer_size = 512);
virtual ~CInputStreamBuffer();
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
CInputStreamBuffer(const CInputStreamBuffer &);
CInputStreamBuffer &operator= (const CInputStreamBuffer &);
PHYSFS_File *m_file;
char *m_buffer;
size_t m_buffer_size;
};

View File

@ -15,10 +15,10 @@
// * along with this program. If not, see http://www.gnu.org/licenses/.
#include "common/resources/outputstream.h"
#include "common/resources/resourcestreambuffer.h"
#include "common/resources/outputstreambuffer.h"
COutputStream::COutputStream() : std::ostream(new CResourceStreamBuffer())
COutputStream::COutputStream() : std::ostream(new COutputStreamBuffer())
{
}
@ -31,23 +31,17 @@ COutputStream::~COutputStream()
void COutputStream::open(const std::string& filename)
{
static_cast<CResourceStreamBuffer *>(rdbuf())->open(filename);
static_cast<COutputStreamBuffer *>(rdbuf())->open(filename);
}
void COutputStream::close()
{
static_cast<CResourceStreamBuffer *>(rdbuf())->close();
static_cast<COutputStreamBuffer *>(rdbuf())->close();
}
bool COutputStream::is_open()
{
return static_cast<CResourceStreamBuffer *>(rdbuf())->is_open();
}
size_t COutputStream::size()
{
return static_cast<CResourceStreamBuffer *>(rdbuf())->size();
return static_cast<COutputStreamBuffer *>(rdbuf())->is_open();
}

View File

@ -28,6 +28,5 @@ public:
void open(const std::string &filename);
void close();
bool is_open();
size_t size();
bool is_open();
};

View File

@ -0,0 +1,85 @@
// * 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/outputstreambuffer.h"
#include <stdexcept>
#include <sstream>
COutputStreamBuffer::COutputStreamBuffer(size_t buffer_size) : m_buffer_size(buffer_size)
{
m_file = nullptr;
m_buffer = new char[buffer_size];
setp(m_buffer, m_buffer + buffer_size);
}
COutputStreamBuffer::~COutputStreamBuffer()
{
close();
delete m_buffer;
}
void COutputStreamBuffer::open(const std::string &filename)
{
if (PHYSFS_isInit())
m_file = PHYSFS_openWrite(filename.c_str());
}
void COutputStreamBuffer::close()
{
if (is_open())
PHYSFS_close(m_file);
}
bool COutputStreamBuffer::is_open()
{
return m_file;
}
std::streambuf::int_type COutputStreamBuffer::overflow(std::streambuf::int_type ch)
{
/* This function should be called when pptr() == epptr(). We use it also in sync()
so we also have to write data if buffer is not full. */
if (pbase() == pptr()) // no data to write, sync() called with empty buffer
return 0;
// save buffer
PHYSFS_sint64 bytes_written = PHYSFS_write(m_file, pbase(), 1, pptr() - pbase());
if (bytes_written <= 0)
return traits_type::eof();
pbump(-bytes_written);
// write final char
if (ch != traits_type::eof()) {
bytes_written = PHYSFS_write(m_file, &ch, 1, 1);
if (bytes_written <= 0)
return traits_type::eof();
}
return ch;
}
int COutputStreamBuffer::sync()
{
return overflow(traits_type::eof());
}

View File

@ -0,0 +1,45 @@
// * 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 COutputStreamBuffer : public std::streambuf
{
public:
COutputStreamBuffer(size_t buffer_size = 512);
virtual ~COutputStreamBuffer();
void open(const std::string &filename);
void close();
bool is_open();
private:
int_type overflow(int_type ch);
int sync();
// copy ctor and assignment not implemented;
// copying not allowed
COutputStreamBuffer(const COutputStreamBuffer &);
COutputStreamBuffer &operator= (const COutputStreamBuffer &);
PHYSFS_File *m_file;
char *m_buffer;
size_t m_buffer_size;
};

View File

@ -1,122 +0,0 @@
// * 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];
m_file = nullptr;
}
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));
}

View File

@ -1,47 +0,0 @@
// * 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;
};