shithub: npe

Download patch

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);
+}