ref: 657e36b7e60c9781ec4a8715e982955fd34e5305
dir: /src/core/dumbfile.c/
/* _______ ____ __ ___ ___ * \ _ \ \ / \ / \ \ / / ' ' ' * | | \ \ | | || | \/ | . . * | | | | | | || ||\ /| | * | | | | | | || || \/ | | ' ' ' * | | | | | | || || | | . . * | |_/ / \ \__// || | | * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque * / \ * / . \ * dumbfile.c - Hookable, strictly sequential / / \ \ * file input functions. | < / \_ * | \/ /\ / * By entheh. \_ / > / * | \ / / * | ' / * \__/ */ #include <stdlib.h> #include "dumb.h" #include "internal/dumb.h" static const DUMBFILE_SYSTEM *the_dfs = NULL; void register_dumbfile_system(const DUMBFILE_SYSTEM *dfs) { ASSERT(dfs); ASSERT(dfs->open); ASSERT(dfs->getc); ASSERT(dfs->close); ASSERT(dfs->seek); ASSERT(dfs->get_size); the_dfs = dfs; } #include "internal/dumbfile.h" DUMBFILE *dumbfile_open(const char *filename) { DUMBFILE *f; ASSERT(the_dfs); f = (DUMBFILE *)malloc(sizeof(*f)); if (!f) return NULL; f->dfs = the_dfs; f->file = (*the_dfs->open)(filename); if (!f->file) { free(f); return NULL; } f->pos = 0; return f; } DUMBFILE *dumbfile_open_ex(void *file, const DUMBFILE_SYSTEM *dfs) { DUMBFILE *f; ASSERT(dfs); ASSERT(dfs->getc); ASSERT(file); f = (DUMBFILE *)malloc(sizeof(*f)); if (!f) { if (dfs->close) (*dfs->close)(file); return NULL; } f->dfs = dfs; f->file = file; f->pos = 0; return f; } dumb_off_t dumbfile_pos(DUMBFILE *f) { ASSERT(f); return f->pos; } /* Move forward in the file from the current position by n bytes. */ int dumbfile_skip(DUMBFILE *f, dumb_off_t n) { int rv; ASSERT(f); ASSERT(n >= 0); if (f->pos < 0) return -1; f->pos += n; if (f->dfs->skip) { rv = (*f->dfs->skip)(f->file, n); if (rv) { f->pos = -1; return rv; } } else { while (n) { rv = (*f->dfs->getc)(f->file); if (rv < 0) { f->pos = -1; return rv; } n--; } } return 0; } int dumbfile_getc(DUMBFILE *f) { int rv; ASSERT(f); if (f->pos < 0) return -1; rv = (*f->dfs->getc)(f->file); if (rv < 0) { f->pos = -1; return rv; } f->pos++; return rv; } int dumbfile_igetw(DUMBFILE *f) { int l, h; ASSERT(f); if (f->pos < 0) return -1; l = (*f->dfs->getc)(f->file); if (l < 0) { f->pos = -1; return l; } h = (*f->dfs->getc)(f->file); if (h < 0) { f->pos = -1; return h; } f->pos += 2; return l | (h << 8); } int dumbfile_mgetw(DUMBFILE *f) { int l, h; ASSERT(f); if (f->pos < 0) return -1; h = (*f->dfs->getc)(f->file); if (h < 0) { f->pos = -1; return h; } l = (*f->dfs->getc)(f->file); if (l < 0) { f->pos = -1; return l; } f->pos += 2; return l | (h << 8); } long dumbfile_igetl(DUMBFILE *f) { unsigned long rv, b; ASSERT(f); if (f->pos < 0) return -1; rv = (*f->dfs->getc)(f->file); if ((signed long)rv < 0) { f->pos = -1; return rv; } b = (*f->dfs->getc)(f->file); if ((signed long)b < 0) { f->pos = -1; return b; } rv |= b << 8; b = (*f->dfs->getc)(f->file); if ((signed long)b < 0) { f->pos = -1; return b; } rv |= b << 16; b = (*f->dfs->getc)(f->file); if ((signed long)b < 0) { f->pos = -1; return b; } rv |= b << 24; f->pos += 4; return rv; } long dumbfile_mgetl(DUMBFILE *f) { unsigned long rv, b; ASSERT(f); if (f->pos < 0) return -1; rv = (*f->dfs->getc)(f->file); if ((signed long)rv < 0) { f->pos = -1; return rv; } rv <<= 24; b = (*f->dfs->getc)(f->file); if ((signed long)b < 0) { f->pos = -1; return b; } rv |= b << 16; b = (*f->dfs->getc)(f->file); if ((signed long)b < 0) { f->pos = -1; return b; } rv |= b << 8; b = (*f->dfs->getc)(f->file); if ((signed long)b < 0) { f->pos = -1; return b; } rv |= b; f->pos += 4; return rv; } unsigned long dumbfile_cgetul(DUMBFILE *f) { unsigned long rv = 0; int v; do { v = dumbfile_getc(f); if (v < 0) return v; rv <<= 7; rv |= v & 0x7F; } while (v & 0x80); return rv; } signed long dumbfile_cgetsl(DUMBFILE *f) { unsigned long rv = dumbfile_cgetul(f); if (f->pos < 0) return rv; return (rv >> 1) | (rv << 31); } dumb_ssize_t dumbfile_getnc(char *ptr, size_t n, DUMBFILE *f) { dumb_ssize_t rv; ASSERT(f); ASSERT(n >= 0); if (f->pos < 0) return -1; if (f->dfs->getnc) { rv = (*f->dfs->getnc)(ptr, n, f->file); if (rv < (dumb_ssize_t)n) { f->pos = -1; return MAX(rv, 0); } } else { for (rv = 0; rv < (dumb_ssize_t)n; rv++) { int c = (*f->dfs->getc)(f->file); if (c < 0) { f->pos = -1; return rv; } *ptr++ = c; } } f->pos += rv; return rv; } /* Move to an arbitrary position n in the file, specified relative to origin, * where origin shall be one of the DFS_SEEK_* constants. */ int dumbfile_seek(DUMBFILE *f, dumb_off_t n, int origin) { switch (origin) { case DFS_SEEK_CUR: n += f->pos; break; case DFS_SEEK_END: n += (*f->dfs->get_size)(f->file); break; default: break; /* keep n, seek position from beginning of file */ } f->pos = n; return (*f->dfs->seek)(f->file, n); } dumb_off_t dumbfile_get_size(DUMBFILE *f) { return (*f->dfs->get_size)(f->file); } int dumbfile_error(DUMBFILE *f) { ASSERT(f); return f->pos < 0; } int dumbfile_close(DUMBFILE *f) { int rv; ASSERT(f); rv = f->pos < 0; if (f->dfs->close) (*f->dfs->close)(f->file); free(f); return rv; }