fixes in streams

master
Daniel Kolesa 2017-04-04 01:06:55 +02:00
parent 4a7baa40a0
commit 9f35909660
4 changed files with 73 additions and 33 deletions

View File

@ -12,19 +12,18 @@
#include <SDL2/SDL.h>
#endif
#include "ostd/types.hh"
#include "ostd/stream.hh"
namespace ostd {
namespace sdl {
#ifdef OSTD_EXT_SDL_USE_SDL1
using SDLRWopsOffset = int;
using sdl_rwops_off_t = int;
#else
using SDLRWopsOffset = int64_t;
using sdl_rwops_off_t = int64_t;
#endif
inline SDL_RWops *stream_to_rwops(Stream &s) {
inline SDL_RWops *stream_to_rwops(stream &s) {
SDL_RWops *rwr = SDL_AllocRW();
if (!rwr) {
return nullptr;
@ -32,32 +31,52 @@ inline SDL_RWops *stream_to_rwops(Stream &s) {
rwr->hidden.unknown.data1 = &s;
rwr->size = [](SDL_RWops *rw) -> SDLRWopsOffset {
Stream *is = static_cast<Stream *>(rw->hidden.unknown.data1);
return static_cast<SDLRWopsOffset>(is->size());
rwr->size = [](SDL_RWops *rw) -> sdl_rwops_off_t {
auto &is = *static_cast<stream *>(rw->hidden.unknown.data1);
try {
return static_cast<sdl_rwops_off_t>(is.size());
} catch (stream_error const &) {
return -1;
}
};
rwr->seek = [](SDL_RWops *rw, SDLRWopsOffset pos, int whence) ->
SDLRWopsOffset
rwr->seek = [](SDL_RWops *rw, sdl_rwops_off_t pos, int whence) ->
sdl_rwops_off_t
{
Stream *is = static_cast<Stream *>(rw->hidden.unknown.data1);
if (!pos && whence == SEEK_CUR) {
return static_cast<SDLRWopsOffset>(is->tell());
}
if (is->seek(((StreamOffset)pos, (StreamSeek)whence)) {
return static_cast<SDLRWopsOffset>(is->tell());
auto &is = *static_cast<stream *>(rw->hidden.unknown.data1);
try {
if (!pos && whence == SEEK_CUR) {
return static_cast<sdl_rwops_off_t(is.tell());
}
if (is->seek((stream_off_t(pos), stream_seek(whence)))) {
return static_cast<sdl_rwops_off_t>(is.tell());
}
} catch (stream_error const &) {
return -1;
}
return -1;
};
rwr->read = [](SDL_RWops *rw, void *buf, size_t size, size_t nb) -> size_t {
Stream *is = static_cast<Stream *>(rw->hidden.unknown.data1);
return is->read_bytes(buf, size * nb) / size;
rwr->read = [](SDL_RWops *rw, void *buf, size_t size, size_t nb) ->
size_t
{
auto &is = *static_cast<stream *>(rw->hidden.unknown.data1);
try {
return is.read_bytes(buf, size * nb) / size;
} catch (stream_error const &) {
return 0;
}
};
rwr->write = [](SDL_RWops *rw, const void *buf, size_t size, size_t nb) -> size_t {
Stream *is = static_cast<Stream *>(rw->hidden.unknown.data1);
return is->write_bytes(buf, size * nb) / size;
rwr->write = [](SDL_RWops *rw, void const *buf, size_t size, size_t nb) ->
size_t
{
stream &is = *static_cast<stream *>(rw->hidden.unknown.data1);
try {
return is->write_bytes(buf, size * nb) / size;
} catch (stream_error const &) {
return 0;
}
};
rwr->close = [](SDL_RWops *) -> int {

View File

@ -61,7 +61,7 @@ struct OSTD_EXPORT file_stream: stream {
void flush();
void read_bytes(void *buf, size_t count);
size_t read_bytes(void *buf, size_t count);
void write_bytes(void const *buf, size_t count);
int get_char();

View File

@ -6,6 +6,7 @@
#ifndef OSTD_STREAM_HH
#define OSTD_STREAM_HH
#include <cerrno>
#include <cstdlib>
#include <type_traits>
#include <locale>
@ -66,18 +67,30 @@ struct stream {
return e;
}
virtual void seek(offset_type, stream_seek = stream_seek::SET) {}
virtual void seek(offset_type, stream_seek = stream_seek::SET) {
throw stream_error{EINVAL, std::generic_category()};
}
virtual offset_type tell() const { return -1; }
virtual offset_type tell() const {
throw stream_error{EINVAL, std::generic_category()};
}
virtual void flush() {}
virtual void flush() {
throw stream_error{EINVAL, std::generic_category()};
}
virtual void read_bytes(void *, size_t) {}
virtual void write_bytes(void const *, size_t) {}
virtual size_t read_bytes(void *, size_t) {
throw stream_error{EINVAL, std::generic_category()};
}
virtual void write_bytes(void const *, size_t) {
throw stream_error{EINVAL, std::generic_category()};
}
virtual int get_char() {
unsigned char c;
read_bytes(&c, 1);
if (!read_bytes(&c, 1)) {
throw stream_error{EIO, std::generic_category()};
}
return c;
}
@ -150,13 +163,16 @@ struct stream {
}
template<typename T>
void get(T *v, size_t count) {
read_bytes(v, count * sizeof(T));
size_t get(T *v, size_t count) {
/* if eof was reached, at least return how many values succeeded */
return read_bytes(v, count * sizeof(T)) / sizeof(T);
}
template<typename T>
void get(T &v) {
read_bytes(&v, sizeof(T));
if (read_bytes(&v, sizeof(T)) != sizeof(T)) {
throw stream_error{EIO, std::generic_category()};
}
}
template<typename T>

View File

@ -84,10 +84,15 @@ void file_stream::flush() {
}
}
void file_stream::read_bytes(void *buf, size_t count) {
if (std::fread(buf, 1, count, p_f) != count) {
size_t file_stream::read_bytes(void *buf, size_t count) {
size_t readn = std::fread(buf, 1, count, p_f);
if (readn != count) {
if (std::feof(p_f) != 0) {
return readn;
}
throw stream_error{EIO, std::generic_category()};
}
return readn;
}
void file_stream::write_bytes(void const *buf, size_t count) {