ref: 2d42c484b86d9551a6e586b6bf446956602490eb
parent: aae3169cd7a839619bf1c43a152ebbf7489202d1
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Fri Mar 19 11:48:46 EDT 2021
sdl2: add SDL_RWops (not tested yet)
--- a/include/npe/SDL2/SDL.h
+++ b/include/npe/SDL2/SDL.h
@@ -19,6 +19,7 @@
#include <SDL2/SDL_audio.h>
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_thread.h>
+#include <SDL2/SDL_rwops.h>
typedef struct SDL_Window SDL_Window;
typedef struct SDL_Renderer SDL_Renderer;
--- /dev/null
+++ b/include/npe/SDL2/SDL_rwops.h
@@ -1,0 +1,31 @@
+#ifndef _npe_SDL_rwops_h_
+#define _npe_SDL_rwops_h_
+
+typedef struct SDL_RWops SDL_RWops;
+typedef struct npe_sdl_rwops npe_sdl_rwops;
+#pragma incomplete npe_sdl_rwops
+
+enum {
+ RW_SEEK_SET,
+ RW_SEEK_CUR,
+ RW_SEEK_END,
+};
+
+struct SDL_RWops {
+ vlong (*size)(struct SDL_RWops *);
+ vlong (*seek)(struct SDL_RWops *, vlong, int);
+ size_t (*read)(struct SDL_RWops *, void *, size_t, size_t);
+ size_t (*write)(struct SDL_RWops *, const void *, size_t, size_t);
+ int (*close)(struct SDL_RWops *);
+ npe_sdl_rwops *p;
+};
+
+SDL_RWops *SDL_RWFromFile(const char *, const char *);
+size_t SDL_RWread(SDL_RWops *, void *, size_t, size_t);
+size_t SDL_RWwrite(SDL_RWops *, const void *, size_t, size_t);
+vlong SDL_RWseek(SDL_RWops *, vlong, int);
+vlong SDL_RWtell(SDL_RWops *);
+vlong SDL_RWsize(SDL_RWops *);
+int SDL_RWclose(SDL_RWops *);
+
+#endif
--- a/libnpe_sdl2/mkfile
+++ b/libnpe_sdl2/mkfile
@@ -8,6 +8,7 @@
OFILES=\
audio.$O\
events.$O\
+ rwops.$O\
sdl2.$O\
threads.$O\
--- /dev/null
+++ b/libnpe_sdl2/rwops.c
@@ -1,0 +1,151 @@
+#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){
+ 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);
+}