source: libcaca/trunk/cucul/file.c @ 2299

Last change on this file since 2299 was 2299, checked in by Sam Hocevar, 12 years ago
  • Remove #include <stdint.h> etc. from "common.h". Instead, make sure that <cucul.h> will provide the C99 types, even if libcaca has been installed.
  • Rename what's left of "common.h" to "stubs.h".
  • Remove all references to erroneous <inttypes.h> from source files.
File size: 4.6 KB
Line 
1/*
2 *  libcucul      Canvas for ultrafast compositing of Unicode letters
3 *  Copyright (c) 2006-2007 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id$
7 *
8 *  This library is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 *  This file contains functions for compressed file I/O.
17 */
18
19#include "config.h"
20
21#if !defined __KERNEL__
22#   include <stdio.h>
23#   include <stdlib.h>
24#   include <string.h>
25#   if defined HAVE_ZLIB_H
26#       include <zlib.h>
27#       define READSIZE  128 /* Read buffer size */
28#       define WRITESIZE 128 /* Inflate buffer size */
29#   endif
30#endif
31
32#include "cucul.h"
33#include "cucul_internals.h"
34
35#if !defined __KERNEL__ && defined HAVE_ZLIB_H
36static int zipread(cucul_file_t *, void *, unsigned int);
37#endif
38
39#if !defined __KERNEL__
40struct cucul_file
41{
42#   if defined HAVE_ZLIB_H
43    unsigned char read_buffer[READSIZE];
44    z_stream stream;
45    gzFile gz;
46    int eof, zip;
47#   endif
48    FILE *f;
49};
50#endif
51
52cucul_file_t *_cucul_file_open(char const *path, const char *mode)
53{
54#if defined __KERNEL__
55    return NULL;
56#else
57    cucul_file_t *fp = malloc(sizeof(*fp));
58
59#   if defined HAVE_ZLIB_H
60    uint8_t buf[4];
61    unsigned int skip_size = 0;
62
63    fp->gz = gzopen(path, "rb");
64    if(!fp->gz)
65    {
66        free(fp);
67        return NULL;
68    }
69
70    fp->eof = 0;
71    fp->zip = 0;
72
73    /* Parse ZIP file and go to start of first file */
74    gzread(fp->gz, buf, 4);
75    if(memcmp(buf, "PK\3\4", 4))
76    {
77        gzseek(fp->gz, 0, SEEK_SET);
78        return fp;
79    }
80
81    fp->zip = 1;
82
83    gzseek(fp->gz, 22, SEEK_CUR);
84
85    gzread(fp->gz, buf, 2); /* Filename size */
86    skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
87    gzread(fp->gz, buf, 2); /* Extra field size */
88    skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
89
90    gzseek(fp->gz, skip_size, SEEK_CUR);
91
92    /* Initialise inflate stream */
93    fp->stream.total_out = 0;
94    fp->stream.zalloc = NULL;
95    fp->stream.zfree = NULL;
96    fp->stream.opaque = NULL;
97    fp->stream.next_in = NULL;
98    fp->stream.avail_in = 0;
99
100    if(inflateInit2(&fp->stream, -MAX_WBITS))
101    {
102        free(fp);
103        gzclose(fp->gz);
104        return NULL;
105    }
106#   else
107    fp->f = fopen(path, mode);
108
109    if(!fp->f)
110    {
111        free(fp);
112        return NULL;
113    }
114#   endif
115
116    return fp;
117#endif
118}
119
120int _cucul_file_close(cucul_file_t *fp)
121{
122#if defined __KERNEL__
123    return 0;
124#elif defined HAVE_ZLIB_H
125    gzFile gz = fp->gz;
126    if(fp->zip)
127        inflateEnd(&fp->stream);
128    free(fp);
129    return gzclose(gz);
130#else
131    FILE *f = fp->f;
132    free(fp);
133    return fclose(f);
134#endif
135}
136
137int _cucul_file_eof(cucul_file_t *fp)
138{
139#if defined __KERNEL__
140    return 1;
141#elif defined HAVE_ZLIB_H
142    return fp->zip ? fp->eof : gzeof(fp->gz);
143#else
144    return feof(fp->f);
145#endif
146}
147
148char *_cucul_file_gets(char *s, int size, cucul_file_t *fp)
149{
150#if defined __KERNEL__
151    return NULL;
152#elif defined HAVE_ZLIB_H
153    if(fp->zip)
154    {
155        int i;
156
157        for(i = 0; i < size; i++)
158        {
159            int ret = zipread(fp, s + i, 1);
160
161            if(ret < 0)
162                return NULL;
163
164            if(ret == 0 || s[i] == '\n')
165            {
166                if(i + 1 < size)
167                    s[i + 1] = '\0';
168                return s;
169            }
170        }
171
172        return s;
173    }
174
175    return gzgets(fp->gz, s, size);
176#else
177    return fgets(s, size, fp->f);
178#endif
179}
180
181#if !defined __KERNEL__ && defined HAVE_ZLIB_H
182static int zipread(cucul_file_t *fp, void *buf, unsigned int len)
183{
184    unsigned int total_read = 0;
185
186    if(len == 0)
187        return 0;
188
189    fp->stream.next_out = buf;
190    fp->stream.avail_out = len;
191
192    while(fp->stream.avail_out > 0)
193    {
194        unsigned int tmp;
195        int ret = 0;
196
197        if(fp->stream.avail_in == 0 && !gzeof(fp->gz))
198        {
199            int bytes_read;
200
201            bytes_read = gzread(fp->gz, fp->read_buffer, READSIZE);
202            if(bytes_read < 0)
203                return -1;
204
205            fp->stream.next_in = fp->read_buffer;
206            fp->stream.avail_in = bytes_read;
207        }
208
209        tmp = fp->stream.total_out;
210        ret = inflate(&fp->stream, Z_SYNC_FLUSH);
211        total_read += fp->stream.total_out - tmp;
212
213        if(ret == Z_STREAM_END)
214        {
215            fp->eof = 1;
216            return total_read;
217        }
218
219        if(ret != Z_OK)
220            return ret;
221    }
222
223    return total_read;
224}
225#endif
226
Note: See TracBrowser for help on using the repository browser.