* Implement cucul_file_read() and cucul_file_write().tags/v0.99.beta14
| @@ -278,6 +278,19 @@ __extern int cucul_canvas_set_figfont(cucul_canvas_t *, char const *); | |||||
| __extern int cucul_put_figchar(cucul_canvas_t *, uint32_t); | __extern int cucul_put_figchar(cucul_canvas_t *, uint32_t); | ||||
| /* @} */ | /* @} */ | ||||
| /** \defgroup cucul_file libcucul file IO | |||||
| * | |||||
| * These functions allow to read and write files in a platform-independent | |||||
| * way. | |||||
| * @{ */ | |||||
| __extern cucul_file_t *cucul_file_open(char const *, const char *); | |||||
| __extern int cucul_file_close(cucul_file_t *); | |||||
| __extern size_t cucul_file_read(cucul_file_t *, void *, size_t); | |||||
| __extern size_t cucul_file_write(cucul_file_t *, const void *, size_t); | |||||
| __extern char * cucul_file_gets(cucul_file_t *, char *, int); | |||||
| __extern int cucul_file_eof(cucul_file_t *); | |||||
| /* @} */ | |||||
| /** \defgroup cucul_importexport libcucul importers/exporters from/to various | /** \defgroup cucul_importexport libcucul importers/exporters from/to various | ||||
| * formats | * formats | ||||
| * | * | ||||
| @@ -77,10 +77,4 @@ extern uint32_t _cucul_attr_to_rgb24bg(uint32_t); | |||||
| extern void _cucul_save_frame_info(cucul_canvas_t *); | extern void _cucul_save_frame_info(cucul_canvas_t *); | ||||
| extern void _cucul_load_frame_info(cucul_canvas_t *); | extern void _cucul_load_frame_info(cucul_canvas_t *); | ||||
| /* File functions */ | |||||
| extern cucul_file_t *_cucul_file_open(const char *, const char *); | |||||
| extern int _cucul_file_close(cucul_file_t *); | |||||
| extern int _cucul_file_eof(cucul_file_t *); | |||||
| extern char *_cucul_file_gets(char *, int, cucul_file_t *); | |||||
| #endif /* __CUCUL_INTERNALS_H__ */ | #endif /* __CUCUL_INTERNALS_H__ */ | ||||
| @@ -301,7 +301,7 @@ cucul_figfont_t * open_figfont(char const *path) | |||||
| } | } | ||||
| /* Open font: if not found, try .tlf, then .flf */ | /* Open font: if not found, try .tlf, then .flf */ | ||||
| f = _cucul_file_open(path, "r"); | |||||
| f = cucul_file_open(path, "r"); | |||||
| #if !defined __KERNEL__ && defined HAVE_SNPRINTF | #if !defined __KERNEL__ && defined HAVE_SNPRINTF | ||||
| #if (! defined(snprintf)) && ( defined(_WIN32) || defined(WIN32) ) && (! defined(__CYGWIN__)) | #if (! defined(snprintf)) && ( defined(_WIN32) || defined(WIN32) ) && (! defined(__CYGWIN__)) | ||||
| @@ -312,13 +312,13 @@ cucul_figfont_t * open_figfont(char const *path) | |||||
| { | { | ||||
| snprintf(altpath, 2047, "%s.tlf", path); | snprintf(altpath, 2047, "%s.tlf", path); | ||||
| altpath[2047] = '\0'; | altpath[2047] = '\0'; | ||||
| f = _cucul_file_open(altpath, "r"); | |||||
| f = cucul_file_open(altpath, "r"); | |||||
| } | } | ||||
| if(!f) | if(!f) | ||||
| { | { | ||||
| snprintf(altpath, 2047, "%s.flf", path); | snprintf(altpath, 2047, "%s.flf", path); | ||||
| altpath[2047] = '\0'; | altpath[2047] = '\0'; | ||||
| f = _cucul_file_open(altpath, "r"); | |||||
| f = cucul_file_open(altpath, "r"); | |||||
| } | } | ||||
| #endif | #endif | ||||
| if(!f) | if(!f) | ||||
| @@ -332,14 +332,14 @@ cucul_figfont_t * open_figfont(char const *path) | |||||
| ff->print_direction = 0; | ff->print_direction = 0; | ||||
| ff->full_layout = 0; | ff->full_layout = 0; | ||||
| ff->codetag_count = 0; | ff->codetag_count = 0; | ||||
| _cucul_file_gets(buf, 2048, f); | |||||
| cucul_file_gets(f, buf, 2048); | |||||
| if(sscanf(buf, "%*[ft]lf2a%6s %u %u %u %i %u %u %u %u\n", hardblank, | if(sscanf(buf, "%*[ft]lf2a%6s %u %u %u %i %u %u %u %u\n", hardblank, | ||||
| &ff->height, &ff->baseline, &ff->max_length, | &ff->height, &ff->baseline, &ff->max_length, | ||||
| &ff->old_layout, &comment_lines, &ff->print_direction, | &ff->old_layout, &comment_lines, &ff->print_direction, | ||||
| &ff->full_layout, &ff->codetag_count) < 6) | &ff->full_layout, &ff->codetag_count) < 6) | ||||
| { | { | ||||
| debug("figfont error: `%s' has invalid header: %s", path, buf); | debug("figfont error: `%s' has invalid header: %s", path, buf); | ||||
| _cucul_file_close(f); | |||||
| cucul_file_close(f); | |||||
| free(ff); | free(ff); | ||||
| seterrno(EINVAL); | seterrno(EINVAL); | ||||
| return NULL; | return NULL; | ||||
| @@ -351,7 +351,7 @@ cucul_figfont_t * open_figfont(char const *path) | |||||
| { | { | ||||
| debug("figfont error: `%s' has invalid layout %i/%u", | debug("figfont error: `%s' has invalid layout %i/%u", | ||||
| path, ff->old_layout, ff->full_layout); | path, ff->old_layout, ff->full_layout); | ||||
| _cucul_file_close(f); | |||||
| cucul_file_close(f); | |||||
| free(ff); | free(ff); | ||||
| seterrno(EINVAL); | seterrno(EINVAL); | ||||
| return NULL; | return NULL; | ||||
| @@ -361,14 +361,14 @@ cucul_figfont_t * open_figfont(char const *path) | |||||
| /* Skip comment lines */ | /* Skip comment lines */ | ||||
| for(i = 0; i < comment_lines; i++) | for(i = 0; i < comment_lines; i++) | ||||
| _cucul_file_gets(buf, 2048, f); | |||||
| cucul_file_gets(f, buf, 2048); | |||||
| /* Read mandatory characters (32-127, 196, 214, 220, 228, 246, 252, 223) | /* Read mandatory characters (32-127, 196, 214, 220, 228, 246, 252, 223) | ||||
| * then read additional characters. */ | * then read additional characters. */ | ||||
| ff->glyphs = 0; | ff->glyphs = 0; | ||||
| ff->lookup = NULL; | ff->lookup = NULL; | ||||
| for(i = 0, size = 0; !_cucul_file_eof(f); ff->glyphs++) | |||||
| for(i = 0, size = 0; !cucul_file_eof(f); ff->glyphs++) | |||||
| { | { | ||||
| if((ff->glyphs % 2048) == 0) | if((ff->glyphs % 2048) == 0) | ||||
| ff->lookup = realloc(ff->lookup, | ff->lookup = realloc(ff->lookup, | ||||
| @@ -385,7 +385,7 @@ cucul_figfont_t * open_figfont(char const *path) | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| if(_cucul_file_gets(buf, 2048, f) == NULL) | |||||
| if(cucul_file_gets(f, buf, 2048) == NULL) | |||||
| break; | break; | ||||
| /* Ignore blank lines, as in jacky.flf */ | /* Ignore blank lines, as in jacky.flf */ | ||||
| @@ -396,7 +396,7 @@ cucul_figfont_t * open_figfont(char const *path) | |||||
| if(buf[0] == '-') | if(buf[0] == '-') | ||||
| { | { | ||||
| for(j = 0; j < ff->height; j++) | for(j = 0; j < ff->height; j++) | ||||
| _cucul_file_gets(buf, 2048, f); | |||||
| cucul_file_gets(f, buf, 2048); | |||||
| continue; | continue; | ||||
| } | } | ||||
| @@ -423,12 +423,12 @@ cucul_figfont_t * open_figfont(char const *path) | |||||
| if(i + 2048 >= size) | if(i + 2048 >= size) | ||||
| data = realloc(data, size += 2048); | data = realloc(data, size += 2048); | ||||
| _cucul_file_gets(data + i, 2048, f); | |||||
| cucul_file_gets(f, data + i, 2048); | |||||
| i = (uintptr_t)strchr(data + i, 0) - (uintptr_t)data; | i = (uintptr_t)strchr(data + i, 0) - (uintptr_t)data; | ||||
| } | } | ||||
| } | } | ||||
| _cucul_file_close(f); | |||||
| cucul_file_close(f); | |||||
| if(ff->glyphs < EXT_GLYPHS) | if(ff->glyphs < EXT_GLYPHS) | ||||
| { | { | ||||
| @@ -46,21 +46,24 @@ struct cucul_file | |||||
| int eof, zip; | int eof, zip; | ||||
| # endif | # endif | ||||
| FILE *f; | FILE *f; | ||||
| int readonly; | |||||
| }; | }; | ||||
| #endif | #endif | ||||
| cucul_file_t *_cucul_file_open(char const *path, const char *mode) | |||||
| cucul_file_t *cucul_file_open(char const *path, const char *mode) | |||||
| { | { | ||||
| #if defined __KERNEL__ | #if defined __KERNEL__ | ||||
| return NULL; | return NULL; | ||||
| #else | #else | ||||
| cucul_file_t *fp = malloc(sizeof(*fp)); | cucul_file_t *fp = malloc(sizeof(*fp)); | ||||
| fp->readonly = !strchr(mode, 'r'); | |||||
| # if defined HAVE_ZLIB_H | # if defined HAVE_ZLIB_H | ||||
| uint8_t buf[4]; | uint8_t buf[4]; | ||||
| unsigned int skip_size = 0; | unsigned int skip_size = 0; | ||||
| fp->gz = gzopen(path, "rb"); | |||||
| fp->gz = gzopen(path, fp->readonly ? "rb" : "wb"); | |||||
| if(!fp->gz) | if(!fp->gz) | ||||
| { | { | ||||
| free(fp); | free(fp); | ||||
| @@ -70,41 +73,44 @@ cucul_file_t *_cucul_file_open(char const *path, const char *mode) | |||||
| fp->eof = 0; | fp->eof = 0; | ||||
| fp->zip = 0; | fp->zip = 0; | ||||
| /* Parse ZIP file and go to start of first file */ | |||||
| gzread(fp->gz, buf, 4); | |||||
| if(memcmp(buf, "PK\3\4", 4)) | |||||
| if(fp->readonly) | |||||
| { | { | ||||
| gzseek(fp->gz, 0, SEEK_SET); | |||||
| return fp; | |||||
| } | |||||
| /* Parse ZIP file and go to start of first file */ | |||||
| gzread(fp->gz, buf, 4); | |||||
| if(memcmp(buf, "PK\3\4", 4)) | |||||
| { | |||||
| gzseek(fp->gz, 0, SEEK_SET); | |||||
| return fp; | |||||
| } | |||||
| fp->zip = 1; | |||||
| fp->zip = 1; | |||||
| gzseek(fp->gz, 22, SEEK_CUR); | |||||
| gzseek(fp->gz, 22, SEEK_CUR); | |||||
| gzread(fp->gz, buf, 2); /* Filename size */ | |||||
| skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8); | |||||
| gzread(fp->gz, buf, 2); /* Extra field size */ | |||||
| skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8); | |||||
| gzread(fp->gz, buf, 2); /* Filename size */ | |||||
| skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8); | |||||
| gzread(fp->gz, buf, 2); /* Extra field size */ | |||||
| skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8); | |||||
| gzseek(fp->gz, skip_size, SEEK_CUR); | |||||
| gzseek(fp->gz, skip_size, SEEK_CUR); | |||||
| /* Initialise inflate stream */ | |||||
| fp->stream.total_out = 0; | |||||
| fp->stream.zalloc = NULL; | |||||
| fp->stream.zfree = NULL; | |||||
| fp->stream.opaque = NULL; | |||||
| fp->stream.next_in = NULL; | |||||
| fp->stream.avail_in = 0; | |||||
| /* Initialise inflate stream */ | |||||
| fp->stream.total_out = 0; | |||||
| fp->stream.zalloc = NULL; | |||||
| fp->stream.zfree = NULL; | |||||
| fp->stream.opaque = NULL; | |||||
| fp->stream.next_in = NULL; | |||||
| fp->stream.avail_in = 0; | |||||
| if(inflateInit2(&fp->stream, -MAX_WBITS)) | |||||
| { | |||||
| free(fp); | |||||
| gzclose(fp->gz); | |||||
| return NULL; | |||||
| if(inflateInit2(&fp->stream, -MAX_WBITS)) | |||||
| { | |||||
| free(fp); | |||||
| gzclose(fp->gz); | |||||
| return NULL; | |||||
| } | |||||
| } | } | ||||
| # else | # else | ||||
| fp->f = fopen(path, mode); | |||||
| fp->f = fopen(path, fmode); | |||||
| if(!fp->f) | if(!fp->f) | ||||
| { | { | ||||
| @@ -117,7 +123,7 @@ cucul_file_t *_cucul_file_open(char const *path, const char *mode) | |||||
| #endif | #endif | ||||
| } | } | ||||
| int _cucul_file_close(cucul_file_t *fp) | |||||
| int cucul_file_close(cucul_file_t *fp) | |||||
| { | { | ||||
| #if defined __KERNEL__ | #if defined __KERNEL__ | ||||
| return 0; | return 0; | ||||
| @@ -134,18 +140,34 @@ int _cucul_file_close(cucul_file_t *fp) | |||||
| #endif | #endif | ||||
| } | } | ||||
| int _cucul_file_eof(cucul_file_t *fp) | |||||
| size_t cucul_file_read(cucul_file_t *fp, void *ptr, size_t size) | |||||
| { | { | ||||
| #if defined __KERNEL__ | #if defined __KERNEL__ | ||||
| return 1; | |||||
| return 0; | |||||
| #elif defined HAVE_ZLIB_H | #elif defined HAVE_ZLIB_H | ||||
| return fp->zip ? fp->eof : gzeof(fp->gz); | |||||
| if(fp->zip) | |||||
| return zipread(fp, ptr, size); | |||||
| return gzread(fp->gz, ptr, size); | |||||
| #else | #else | ||||
| return feof(fp->f); | |||||
| return fread(ptr, 1, size, fp->f); | |||||
| #endif | |||||
| } | |||||
| size_t cucul_file_write(cucul_file_t *fp, const void *ptr, size_t size) | |||||
| { | |||||
| if(fp->readonly) | |||||
| return 0; | |||||
| #if defined __KERNEL__ | |||||
| return 0; | |||||
| #elif defined HAVE_ZLIB_H | |||||
| return gzwrite(fp->gz, ptr, size); | |||||
| #else | |||||
| return fwrite(ptr, 1, size, fp->f); | |||||
| #endif | #endif | ||||
| } | } | ||||
| char *_cucul_file_gets(char *s, int size, cucul_file_t *fp) | |||||
| char *cucul_file_gets(cucul_file_t *fp, char *s, int size) | |||||
| { | { | ||||
| #if defined __KERNEL__ | #if defined __KERNEL__ | ||||
| return NULL; | return NULL; | ||||
| @@ -178,6 +200,17 @@ char *_cucul_file_gets(char *s, int size, cucul_file_t *fp) | |||||
| #endif | #endif | ||||
| } | } | ||||
| int cucul_file_eof(cucul_file_t *fp) | |||||
| { | |||||
| #if defined __KERNEL__ | |||||
| return 1; | |||||
| #elif defined HAVE_ZLIB_H | |||||
| return fp->zip ? fp->eof : gzeof(fp->gz); | |||||
| #else | |||||
| return feof(fp->f); | |||||
| #endif | |||||
| } | |||||
| #if !defined __KERNEL__ && defined HAVE_ZLIB_H | #if !defined __KERNEL__ && defined HAVE_ZLIB_H | ||||
| static int zipread(cucul_file_t *fp, void *buf, unsigned int len) | static int zipread(cucul_file_t *fp, void *buf, unsigned int len) | ||||
| { | { | ||||