paysages3d/src/core/PackStream.cpp

138 lines
3.5 KiB
C++

#include "PackStream.h"
#include "Logs.h"
#include <cstring>
#include <fstream>
#include <sstream>
class PackStream::pimpl {
public:
fstream *file;
stringstream *buffer;
iostream* stream;
};
PackStream::PackStream() : pv(new pimpl) {
pv->file = new fstream();
pv->buffer = new stringstream();
pv->stream = pv->buffer;
}
PackStream::PackStream(const PackStream *other) : pv(new pimpl) {
pv->file = new fstream();
pv->buffer = new stringstream();
if (other->pv->file->is_open()) {
Logs::error("System") << "Try to read from a substream bound to a file: "
<< other->pv->file << endl;
} else {
other->pv->buffer->seekg(0);
other->pv->buffer->get(*pv->buffer->rdbuf());
}
pv->stream = pv->buffer;
}
PackStream::PackStream(const string &buffer_content) : pv(new pimpl) {
pv->file = new fstream();
pv->buffer = new stringstream(buffer_content);
pv->stream = pv->buffer;
}
PackStream::~PackStream() {
delete pv->file;
delete pv->buffer;
}
bool PackStream::bindToFile(const string &filepath, bool write) {
if (pv->file->is_open()) {
return false;
} else {
pv->file->open(filepath, write ? ios_base::out : ios_base::in);
if (pv->file->is_open()) {
pv->stream = pv->file;
return true;
} else {
return false;
}
}
}
void PackStream::write(const int *value) {
if (value) {
// TODO endianness and int size portability
pv->stream->write(reinterpret_cast<const char*>(value), sizeof(int));
}
}
void PackStream::write(const double *value) {
if (value) {
// TODO float format portability
pv->stream->write(reinterpret_cast<const char*>(value), sizeof(double));
}
}
void PackStream::write(const string &value) {
const int length = value.length();
write(&length);
pv->stream->write(value.c_str(), length);
}
void PackStream::writeFromBuffer(const PackStream &other, bool prepend_size) {
if (other.pv->file->is_open()) {
Logs::error("System") << "Try to write from a substream bound to a file: "
<< other.pv->file << endl;
} else {
int buffer_size = other.pv->buffer->rdbuf()->str().length();
if (prepend_size) {
write(&buffer_size);
}
pv->stream->write(other.pv->buffer->rdbuf()->str().c_str(), buffer_size);
}
}
string PackStream::getBuffer() {
if (pv->file->is_open()) {
Logs::error("System") << "Try to get buffer on a stream bound to a file: " << pv->file << endl;
return "";
} else {
return pv->buffer->rdbuf()->str();
}
}
void PackStream::read(int *value) {
if (value and not pv->stream->eof()) {
pv->stream->read(reinterpret_cast<char*>(value), sizeof(int));
}
}
void PackStream::read(double *value) {
if (value and not pv->stream->eof()) {
pv->stream->read(reinterpret_cast<char*>(value), sizeof(double));
}
}
string PackStream::readString() {
if (not pv->stream->eof()) {
int size;
read(&size);
if (size > 0) {
std::string str(size, '\0');
pv->stream->read(&str[0], size);
return str;
}
}
return "";
}
void PackStream::skip(const int &value, int count) {
skipBytes(sizeof(value) * count);
}
void PackStream::skip(const double &value, int count) {
skipBytes(sizeof(value) * count);
}
void PackStream::skipBytes(int bytes) {
pv->stream->seekg(bytes, ios_base::cur);
}