ref: fde88f040b42fef86ce3e7362ca0bf5faa14a48b
dir: /libnpe_sdl2/rwops.c/
#include "_sdl.h"
#include <bio.h>
struct npe_sdl_rwops {
Biobuf;
};
static vlong bsize(struct SDL_RWops *);
static vlong bseek(struct SDL_RWops *, vlong, int);
static size_t bread(struct SDL_RWops *, void *, size_t, size_t);
static size_t bwrite(struct SDL_RWops *, const void *, size_t, size_t);
static int bclose(struct SDL_RWops *);
SDL_RWops *
SDL_RWFromFile(const char *file, const char *m)
{
SDL_RWops *o;
int f, mode;
o = nil;
mode = -1;
for(; m != nil && *m; m++){
if(*m == 'r'){
if(mode == OWRITE){
badmode:
werrstr("either read or write supported only");
return nil;
}
mode = OREAD;
}else if(*m == 'w'){
if(mode == OREAD)
goto badmode;
mode = OWRITE;
}
}
if(mode < 0)
goto badmode;
if((f = open(file, mode|OCEXEC)) >= 0 &&
(o = calloc(1, sizeof(*o)+sizeof(npe_sdl_rwops))) != nil &&
Binit((o->p = (void*)(o+1)), f, mode) == 0){
o->size = bsize;
o->seek = bseek;
o->read = bread;
o->write = bwrite;
o->close = bclose;
return o;
}
if(f >= 0)
close(f);
free(o);
return nil;
}
size_t
SDL_RWread(SDL_RWops *o, void *b, size_t sz, size_t n)
{
return o->read ? o->read(o, b, sz, n) : 0;
}
size_t
SDL_RWwrite(SDL_RWops *o, const void *b, size_t sz, size_t n)
{
return o->write ? o->write(o, b, sz, n) : 0;
}
vlong
SDL_RWseek(SDL_RWops *o, vlong off, int whence)
{
return o->seek ? o->seek(o, off, whence) : -1;
}
vlong
SDL_RWtell(SDL_RWops *o)
{
return o->seek ? o->seek(o, 0, 1) : -1;
}
vlong
SDL_RWsize(SDL_RWops *o)
{
return o->size ? o->size(o) : -1;
}
int
SDL_RWclose(SDL_RWops *o)
{
int r;
r = o->close ? o->close(o) : 0;
if(r == 0)
free(o);
return r;
}
static vlong
bseek(struct SDL_RWops *o, vlong off, int whence)
{
return Bseek(o->p, off, whence);
}
static size_t
bread(struct SDL_RWops *o, void *b, size_t sz, size_t n)
{
uchar *p;
size_t i;
vlong x;
for(i = 0, p = b; i < n; i++, p += sz){
if((x = Bread(o->p, p, sz)) != sz){
if(x > 0)
Bseek(o->p, -x, 1);
break;
}
}
return i;
}
static size_t
bwrite(struct SDL_RWops *o, const void *b, size_t sz, size_t n)
{
const uchar *p;
size_t i;
for(i = 0, p = b; i < n; i++, p += sz){
if(Bwrite(o->p, p, sz) != sz) /* FIXME dunno what to do with partial writes */
break;
}
return i;
}
static vlong
bsize(struct SDL_RWops *o)
{
Dir *s;
vlong sz;
sz = -1;
if((s = dirfstat(Bfildes(o->p))) != nil){
sz = s->length;
free(s);
}
return sz;
}
static int
bclose(struct SDL_RWops *o)
{
return Bterm(o->p);
}