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