shithub: dumb

Download patch

ref: 515d050b2df8654c957e3cc6aeb611d3a14be2df
parent: d9b1453cedbe0406701e152016bcf466c578d59d
author: Simon Naarmann <s.naarmann@gmail.com>
date: Sun Sep 24 10:51:36 EDT 2017

API, getnc returns dumb_ssize_t instead of size_t

This is necessary because getnc returns -1 on error. Spec updated with
the new function signatures.

Fixed resulting comparisons between signed and unsigned that gcc 7.2
shows when we compile with -Wall -Wextra -pedantic.

I have not compiled with -Wconversion to find implicit integer coercion
from assigning to narrower types, that would find far too many intended
coercions in the music rendering.

--- a/DUMBFILE_SYSTEM.md
+++ b/DUMBFILE_SYSTEM.md
@@ -1,6 +1,15 @@
 Specification of DUMBFILE_SYSTEM
 ================================
 
+DUMB is designed filesystem-agnostic, even though the C standard library
+already defines an abstraction over files on a disk. This is useful because
+Allegro 4 and 5 define their own abstractions.
+
+To register your own filesystem abstraction with DUMB, you must create an
+instance of struct `DUMBFILE_SYSTEM`, fill in your own function pointers
+according to the specification below, and call `register_dumbfile_system` on
+your instance.
+
 The header `dumb.h` defines `DUMBFILE_SYSTEM` as a struct of function pointers:
 
 ```
@@ -7,25 +16,21 @@
 typedef struct DUMBFILE_SYSTEM
 {
     void *(*open)(const char *filename);
-    int (*skip)(void *f, long n);
+    int (*skip)(void *f, dumb_off_t n);
     int (*getc)(void *f);
-    long (*getnc)(char *ptr, long n, void *f);
+    dumb_ssize_t (*getnc)(char *ptr, size_t n, void *f);
     void (*close)(void *f);
-    int (*seek)(void *f, long n);
-    long (*get_size)(void *f);
+    int (*seek)(void *f, dumb_off_t n);
+    dumb_off_t (*get_size)(void *f);
 }
 DUMBFILE_SYSTEM;
 ```
 
-DUMB is designed filesystem-agnostic, even though the C standard library
-already defines an abstraction over files on a disk. This is useful because
-Allegro 4 and 5 define their own abstractions.
+Here, `dumb_off_t` is a signed integer at least 64 bits wide, it is intended
+to measure file offsets. The return type `dumb_ssize_t` is a signed integer
+exactly as wide as `size_t`, it is intended to store either a `size_t` or a
+negative error code. Both `dumb_*_t` are defined in `dumb.h`.
 
-To register your own filesystem abstraction with DUMB, you must create an
-instance of struct `DUMBFILE_SYSTEM`, fill in your own function pointers
-according to the specification below, and call `register_dumbfile_system` on
-your instance.
-
 The function pointers `skip` and `getnc` are optional, i.e., you may set
 some of these to `NULL` in your struct instance. DUMB will then try to
 mimick the missing functions' behavior by calling your `getc` several times.
@@ -75,7 +80,7 @@
 ----
 
 ```
-int (*skip)(void *f, long n);
+int (*skip)(void *f, dumb_off_t n);
 ```
 
 Advance the position in the file.
@@ -84,8 +89,8 @@
 
 * `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
 
-* `long n`: Number of bytes to advance in the file. DUMB guarantees to
-    call this function only with `n >= 0`.
+* `dumb_off_t n`: Number of bytes to advance in the file. DUMB will only
+call this with `n >= 0`. For `n < 0`, the behavior of `skip` is undefined.
 
 Returns as `int`:
 
@@ -126,7 +131,7 @@
 -----
 
 ```
-long (*getnc)(char *ptr, long n, void *f);
+dumb_ssize_t (*getnc)(char *ptr, size_t n, void *f);
 ```
 
 Read up to the given number of bytes from the file into a given buffer.
@@ -133,14 +138,14 @@
 
 * `char *ptr`: The start of a buffer provided by DUMB.
 
-* `long n`: The length of the number of bytes to be read. DUMB guarantees
-    to call this function only with `n >= 0`.
+* `size_t n`: The length of the number of bytes to be read.
 
 * `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
 
-Returns as `long`:
+Returns as `dumb_ssize_t`:
 
-* the number of bytes successfully read.
+* the number of bytes successfully read, if it was possible to read at least
+one byte.
 
 * `-1` on error.
 
@@ -178,7 +183,7 @@
 ----
 
 ```
-int (*seek)(void *f, long n);
+int (*seek)(void *f, dumb_off_t n);
 ```
 
 Jump to an arbitrary position in the file.
@@ -187,7 +192,7 @@
 
 * `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
 
-* `long n`: The position in the file, relative to the beginning.
+* `dumb_off_t n`: The position in the file, relative to the beginning.
     There is no guarantee whether `n >= 0`.
 
 Returns as `int`:
@@ -207,7 +212,7 @@
 --------
 
 ```
-long (*get_size)(void *f);
+dumb_off_t (*get_size)(void *f);
 ```
 
 Get the length in bytes, i.e., the position after the final byte, of a file.
@@ -216,6 +221,6 @@
 
 * `void *f`: A file handle that `open` returned. Guaranteed non-`NULL`.
 
-Returns as `long`:
+Returns as `dumb_off_t`:
 
 * the length of the file in bytes.
--- a/include/dumb.h
+++ b/include/dumb.h
@@ -129,13 +129,30 @@
 	};
 #endif
 
+/*
+ * ssize_t is defined in POSIX to hold either a size_t or an error.
+ * We will use dumb_ssize_t on all platforms for (either size_t or error) in
+ * all getnc-type functions. See DUMBFILE_SYSTEM.md for that function's spec.
+ */
+#if defined(_MSC_VER)
+#include <BaseTsd.h>
+typedef SSIZE_T dumb_ssize_t;
+#else
+#include <sys/types.h>
+typedef ssize_t dumb_ssize_t;
+#endif
 
+/*
+ * Register your own file-handling functions as callbacks via this struct.
+ * See DUMBFILE_SYSTEM.md in the project root directory for the spec.
+ * DUMB 2.0 doesn't use long anymore. The 64-bit dumb_*_t are defined above.
+ */
 typedef struct DUMBFILE_SYSTEM
 {
 	void *(*open)(const char *filename);
 	int (*skip)(void *f, dumb_off_t n);
 	int (*getc)(void *f);
-	size_t (*getnc)(char *ptr, size_t n, void *f);
+	dumb_ssize_t (*getnc)(char *ptr, size_t n, void *f);
 	void (*close)(void *f);
     int (*seek)(void *f, dumb_off_t offset);
     dumb_off_t (*get_size)(void *f);
@@ -171,7 +188,7 @@
 unsigned long dumbfile_cgetul(DUMBFILE *f);
 signed long dumbfile_cgetsl(DUMBFILE *f);
 
-size_t dumbfile_getnc(char *ptr, size_t n, DUMBFILE *f);
+dumb_ssize_t dumbfile_getnc(char *ptr, size_t n, DUMBFILE *f);
 
 int dumbfile_error(DUMBFILE *f);
 int dumbfile_close(DUMBFILE *f);
--- a/include/internal/it.h
+++ b/include/internal/it.h
@@ -385,7 +385,7 @@
 struct IT_PATTERN
 {
 	int n_rows;
-	size_t n_entries;
+	int n_entries;
 	IT_ENTRY *entry;
 };
 
@@ -724,7 +724,7 @@
 	void * played;
 
 	/*
-	   Loop indicator for internal processes, may also be useful for external processes 
+	   Loop indicator for internal processes, may also be useful for external processes
 	   0 - Not looped
 	   1 - Looped
 	  -1 - Continued past loop
@@ -743,7 +743,7 @@
 	int gvz_sub_time;
 
     int ramp_style;
-    
+
 	//int max_output;
 };
 
--- a/src/core/dumbfile.c
+++ b/src/core/dumbfile.c
@@ -340,9 +340,9 @@
 
 
 
-size_t dumbfile_getnc(char *ptr, size_t n, DUMBFILE *f)
+dumb_ssize_t dumbfile_getnc(char *ptr, size_t n, DUMBFILE *f)
 {
-	long rv;
+	dumb_ssize_t rv;
 
 	ASSERT(f);
 	ASSERT(n >= 0);
@@ -352,12 +352,12 @@
 
 	if (f->dfs->getnc) {
 		rv = (*f->dfs->getnc)(ptr, n, f->file);
-		if (rv < n) {
+		if (rv < (dumb_ssize_t) n) {
 			f->pos = -1;
 			return MAX(rv, 0);
 		}
 	} else {
-		for (rv = 0; rv < n; rv++) {
+		for (rv = 0; rv < (dumb_ssize_t) n; rv++) {
 			int c = (*f->dfs->getc)(f->file);
 			if (c < 0) {
 				f->pos = -1;
--- a/src/helpers/memfile.c
+++ b/src/helpers/memfile.c
@@ -37,7 +37,7 @@
 static int dumb_memfile_skip(void *f, dumb_off_t n)
 {
 	MEMFILE *m = f;
-	if (n > m->left) return -1;
+	if (n > (dumb_off_t)m->left) return -1;
 	m->ptr += n;
 	m->left -= n;
 	return 0;
@@ -55,7 +55,7 @@
 
 
 
-static size_t dumb_memfile_getnc(char *ptr, size_t n, void *f)
+static dumb_ssize_t dumb_memfile_getnc(char *ptr, size_t n, void *f)
 {
 	MEMFILE *m = f;
 	if (n > m->left) n = m->left;
--- a/src/helpers/stdfile.c
+++ b/src/helpers/stdfile.c
@@ -70,7 +70,7 @@
 
 
 
-static size_t dumb_stdfile_getnc(char *ptr, size_t n, void *f)
+static dumb_ssize_t dumb_stdfile_getnc(char *ptr, size_t n, void *f)
 {
     dumb_stdfile * file = ( dumb_stdfile * ) f;
     return fread(ptr, 1, n, file->file);
--- a/src/it/readam.c
+++ b/src/it/readam.c
@@ -267,7 +267,7 @@
 	DUMB_IT_SIGDATA *sigdata;
 
     int n, found;
-    size_t o, p;
+    int o, p;
 
 	if ( ! stream ) goto error;
 
@@ -301,7 +301,7 @@
         case DUMB_ID( 'P', 'A', 'T', 'T' ):
             if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_sd;
             o = dumbfile_getc( f );
-            if ( o >= sigdata->n_patterns ) sigdata->n_patterns = (int)(o + 1);
+            if ( o >= sigdata->n_patterns ) sigdata->n_patterns = (o + 1);
             o = dumbfile_igetl( f );
             if ( (unsigned)o + 5 > c->size ) goto error_sd;
 			break;
@@ -468,7 +468,7 @@
 	DUMB_IT_SIGDATA *sigdata;
 
 	int n, found;
-    size_t o, p;
+    int o, p;
 
     if ( ! f || ! stream ) goto error;
 
--- a/src/it/readpsm.c
+++ b/src/it/readpsm.c
@@ -59,7 +59,7 @@
 static int it_psm_process_sample(IT_SAMPLE * sample, const unsigned char * data, size_t len, int id, int version) {
 	int flags;
 	int insno;
-	int length;
+	size_t length;
 	int loopstart;
 	int loopend;
 	int panpos;
@@ -100,7 +100,7 @@
 		sample->flags &= ~IT_SAMPLE_EXISTS;
 		return 0;
 	}
-	
+
 	if ((length > len - 0x60) || ((flags & 0x7F) != 0)) return -1;
 
 	sample->flags = IT_SAMPLE_EXISTS;
@@ -143,7 +143,8 @@
 }
 
 static int it_psm_process_pattern(IT_PATTERN * pattern, const unsigned char * data, size_t len, int speed, int bpm, const unsigned char * pan, const int * vol, int version) {
-	int length, nrows, row, rowlen, pos;
+	size_t length, pos, rowlen;
+	int nrows, row;
 	unsigned flags, chan;
 	IT_ENTRY * entry;
 
@@ -474,7 +475,7 @@
 
 	unsigned char * ptr;
 
-	size_t n, length;
+	int n, length;
     int o;
 
 	int found;
@@ -519,7 +520,7 @@
 	}
 
 	if (!n_chunks) goto error_fc;
-				
+
 	sigdata = malloc(sizeof(*sigdata));
 	if (!sigdata) goto error_fc;
 
@@ -814,7 +815,7 @@
 							if (it_psm_process_pattern(&sigdata->pattern[n_patterns], ptr, length, speed, bpm, pan, vol, found)) goto error_ev;
 							if (first_pattern_line < 0) {
 								first_pattern_line = n;
-								first_pattern = (int)o;
+								first_pattern = o;
 							}
 							e->data[0] = n_patterns;
 							e->data[1] = n_patterns >> 8;
@@ -827,7 +828,7 @@
 							if (it_psm_process_pattern(&sigdata->pattern[n_patterns], ptr, length, speed, bpm, pan, vol, found)) goto error_ev;
 							if (first_pattern_line < 0) {
 								first_pattern_line = n;
-								first_pattern = (int)o;
+								first_pattern = o;
 							}
 							e->data[0] = n_patterns;
 							e->data[1] = n_patterns >> 8;
@@ -1078,7 +1079,7 @@
 
 	if (p1 == p2) return 1;
 	if (p1->n_entries != p2->n_entries) return 0;
-	
+
 	e1 = p1->entry; end = e1 + p1->n_entries;
 	e2 = p2->entry;
 
@@ -1196,7 +1197,7 @@
 	size_t length;
     int subsongs;
 	long l;
-	
+
 	if (dumbfile_mgetl(f) != DUMB_ID('P','S','M',' ')) return 0;
 
 	length = dumbfile_igetl(f);
@@ -1222,8 +1223,8 @@
 /* Eww */
 int pattcmp( const unsigned char * a, const unsigned char * b, size_t l )
 {
-    int i;
-    unsigned long j, na, nb;
+    size_t i, j;
+    unsigned long na, nb;
 	char * p;
 
 	na = nb = 0;
@@ -1261,7 +1262,7 @@
 	i = memcmp( a, b, j );
 	if ( i ) return i;
 
-	return (int)(na - nb);
+	return (int)((long)na) - ((long)nb);
 }
 
 
--- a/src/it/readptm.c
+++ b/src/it/readptm.c
@@ -216,7 +216,7 @@
 		/* Great. We ran out of data, but there should be data for more rows.
 		 * Fill the rest with null data...
 		 */
-		if (buflen >= length && pattern->n_rows < 64)
+		if (buflen >= (dumb_ssize_t) length && pattern->n_rows < 64)
 		{
 			while (pattern->n_rows < 64)
 			{
--- a/src/it/readxm.c
+++ b/src/it/readxm.c
@@ -419,12 +419,12 @@
 
 
 
-static size_t limit_xm_getnc(char *ptr, size_t n, void *f)
+static dumb_ssize_t limit_xm_getnc(char *ptr, size_t n, void *f)
 {
 	LIMITED_XM *lx = f;
-	long left;
+	dumb_ssize_t left;
 	left = lx->allocated - lx->ptr;
-	if (n > left) {
+	if ((dumb_ssize_t) n > left) {
 		if (left > 0) {
 			memcpy( ptr, lx->buffered + lx->ptr, left );
 			memset( ptr + left, 0, n - left );