fixes in streams

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

View file

@ -61,7 +61,7 @@ struct OSTD_EXPORT file_stream: stream {
void flush(); 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); void write_bytes(void const *buf, size_t count);
int get_char(); int get_char();

View file

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

View file

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