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

Last change on this file since 2109 was 2109, checked in by Sam Hocevar, 13 years ago
  • Import io.c from TOIlet directly into libcucul. Can you see where this is going?
File size: 4.3 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#include "common.h"
21
22#if !defined(__KERNEL__)
23#   include <stdio.h>
24#   include <stdlib.h>
25#   include <string.h>
26#   if defined HAVE_ZLIB_H
27#       include <zlib.h>
28#       define READSIZE  128 /* Read buffer size */
29#       define WRITESIZE 128 /* Inflate buffer size */
30#   endif
31#endif
32
33#include "cucul.h"
34#include "cucul_internals.h"
35
36#if defined HAVE_ZLIB_H
37static int zipread(cucul_file_t *, void *, unsigned int);
38#endif
39
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
51cucul_file_t *_cucul_file_open(char const *path, const char *mode)
52{
53    cucul_file_t *fp = malloc(sizeof(*fp));
54
55#if defined HAVE_ZLIB_H
56    uint8_t buf[4];
57    unsigned int skip_size = 0;
58
59    fp->gz = gzopen(path, "rb");
60    if(!fp->gz)
61    {
62        free(fp);
63        return NULL;
64    }
65
66    fp->eof = 0;
67    fp->zip = 0;
68
69    /* Parse ZIP file and go to start of first file */
70    gzread(fp->gz, buf, 4);
71    if(memcmp(buf, "PK\3\4", 4))
72    {
73        gzseek(fp->gz, 0, SEEK_SET);
74        return fp;
75    }
76
77    fp->zip = 1;
78
79    gzseek(fp->gz, 22, SEEK_CUR);
80
81    gzread(fp->gz, buf, 2); /* Filename size */
82    skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
83    gzread(fp->gz, buf, 2); /* Extra field size */
84    skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
85
86    gzseek(fp->gz, skip_size, SEEK_CUR);
87
88    /* Initialise inflate stream */
89    fp->stream.total_out = 0;
90    fp->stream.zalloc = NULL;
91    fp->stream.zfree = NULL;
92    fp->stream.opaque = NULL;
93    fp->stream.next_in = NULL;
94    fp->stream.avail_in = 0;
95
96    if(inflateInit2(&fp->stream, -MAX_WBITS))
97    {
98        free(fp);
99        gzclose(fp->gz);
100        return NULL;
101    }
102#else
103    fp->f = fopen(path, mode);
104
105    if(!fp->f)
106    {
107        free(fp);
108        return NULL;
109    }
110#endif
111
112    return fp;
113}
114
115int _cucul_file_close(cucul_file_t *fp)
116{
117#if defined HAVE_ZLIB_H
118    gzFile gz = fp->gz;
119    if(fp->zip)
120        inflateEnd(&fp->stream);
121    free(fp);
122    return gzclose(gz);
123#else
124    FILE *f = fp->f;
125    free(fp);
126    return fclose(f);
127#endif
128}
129
130int _cucul_file_eof(cucul_file_t *fp)
131{
132#if defined HAVE_ZLIB_H
133    return fp->zip ? fp->eof : gzeof(fp->gz);
134#else
135    return feof(fp->f);
136#endif
137}
138
139char *_cucul_file_gets(char *s, int size, cucul_file_t *fp)
140{
141#if defined HAVE_ZLIB_H
142    if(fp->zip)
143    {
144        int i;
145
146        for(i = 0; i < size; i++)
147        {
148            int ret = zipread(fp, s + i, 1);
149
150            if(ret < 0)
151                return NULL;
152
153            if(ret == 0 || s[i] == '\n')
154            {
155                if(i + 1 < size)
156                    s[i + 1] = '\0';
157                return s;
158            }
159        }
160
161        return s;
162    }
163
164    return gzgets(fp->gz, s, size);
165#else
166    return fgets(s, size, fp->f);
167#endif
168}
169
170#if defined HAVE_ZLIB_H
171static int zipread(cucul_file_t *fp, void *buf, unsigned int len)
172{
173    unsigned int total_read = 0;
174
175    if(len == 0)
176        return 0;
177
178    fp->stream.next_out = buf;
179    fp->stream.avail_out = len;
180
181    while(fp->stream.avail_out > 0)
182    {
183        unsigned int tmp;
184        int ret = 0;
185
186        if(fp->stream.avail_in == 0 && !gzeof(fp->gz))
187        {
188            int bytes_read;
189
190            bytes_read = gzread(fp->gz, fp->read_buffer, READSIZE);
191            if(bytes_read < 0)
192                return -1;
193
194            fp->stream.next_in = fp->read_buffer;
195            fp->stream.avail_in = bytes_read;
196        }
197
198        tmp = fp->stream.total_out;
199        ret = inflate(&fp->stream, Z_SYNC_FLUSH);
200        total_read += fp->stream.total_out - tmp;
201
202        if(ret == Z_STREAM_END)
203        {
204            fp->eof = 1;
205            return total_read;
206        }
207
208        if(ret != Z_OK)
209            return ret;
210    }
211
212    return total_read;
213}
214#endif
215
Note: See TracBrowser for help on using the repository browser.