diff --git a/src/modules/loaders/loader_argb.c b/src/modules/loaders/loader_argb.c index 1519054..913ce83 100644 --- a/src/modules/loaders/loader_argb.c +++ b/src/modules/loaders/loader_argb.c @@ -1,13 +1,47 @@ #include "loader_common.h" +#include + +static struct { + const unsigned char *data, *dptr; + unsigned int size; +} mdata; + +static void +mm_init(void *src, unsigned int size) +{ + mdata.data = mdata.dptr = src; + mdata.size = size; +} + +static void +mm_seek(unsigned int offs) +{ + mdata.dptr = mdata.data + offs; +} + +static int +mm_read(void *dst, unsigned int len) +{ + if (mdata.dptr + len > mdata.data + mdata.size) + return 1; /* Out of data */ + + memcpy(dst, mdata.dptr, len); + mdata.dptr += len; + + return 0; +} + int load2(ImlibImage * im, int load_data) { int rc; + void *fdata; int alpha; DATA32 *ptr; int y; - char buf[256], buf2[256]; + const char *fptr, *row; + unsigned int size; #ifdef WORDS_BIGENDIAN int l; @@ -15,17 +49,23 @@ load2(ImlibImage * im, int load_data) rc = LOAD_FAIL; + fdata = mmap(NULL, im->fsize, PROT_READ, MAP_SHARED, fileno(im->fp), 0); + if (fdata == MAP_FAILED) + return rc; + + mm_init(fdata, im->fsize); + /* header */ - buf[0] = '\0'; - if (!fgets(buf, 255, im->fp)) + fptr = fdata; + size = im->fsize > 31 ? 31 : im->fsize; /* Look for \n in at most 31 byte */ + row = memchr(fptr, '\n', size); + if (!row) goto quit; + row += 1; /* After LF */ - buf2[0] = '\0'; im->w = im->h = alpha = 0; - sscanf(buf, "%s %i %i %i", buf2, &im->w, &im->h, &alpha); - if (strcmp(buf2, "ARGB")) - goto quit; + sscanf(fptr, "ARGB %i %i %i", &im->w, &im->h, &alpha); if (!IMAGE_DIMENSIONS_OK(im->w, im->h)) goto quit; @@ -47,9 +87,11 @@ load2(ImlibImage * im, int load_data) if (!ptr) goto quit; + mm_seek(row - fptr); + for (y = 0; y < im->h; y++) { - if (fread(ptr, im->w, 4, im->fp) != 4) + if (mm_read(ptr, 4 * im->w)) goto quit; #ifdef WORDS_BIGENDIAN @@ -70,6 +112,8 @@ load2(ImlibImage * im, int load_data) quit: if (rc <= 0) __imlib_FreeData(im); + if (fdata != MAP_FAILED) + munmap(fdata, im->fsize); return rc; }