libcaca  0.99.beta19
About: libcaca is a graphics library that outputs text instead of pixels, so that it can work on older video cards or text terminals (something like an advanced AAlib library).
  Fossies Dox: libcaca-0.99.beta19.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

file.c
Go to the documentation of this file.
1 /*
2  * libcaca Colour ASCII-Art library
3  * Copyright (c) 2006-2012 Sam Hocevar <sam@hocevar.net>
4  * All Rights Reserved
5  *
6  * This library is free software. It comes without any warranty, to
7  * the extent permitted by applicable law. You can redistribute it
8  * and/or modify it under the terms of the Do What the Fuck You Want
9  * to Public License, Version 2, as published by Sam Hocevar. See
10  * http://www.wtfpl.net/ for more details.
11  */
12 
13 /*
14  * This file contains functions for compressed file I/O.
15  */
16 
17 #include "config.h"
18 
19 #if !defined __KERNEL__
20 # include <stdio.h>
21 # include <stdlib.h>
22 # include <string.h>
23 # if defined HAVE_ZLIB_H
24 # include <zlib.h>
25 # define READSIZE 128 /* Read buffer size */
26 # define WRITESIZE 128 /* Inflate buffer size */
27 # endif
28 #endif
29 
30 #include "caca.h"
31 #include "caca_internals.h"
32 
33 #if !defined __KERNEL__ && defined HAVE_ZLIB_H
34 static int zipread(caca_file_t *, void *, unsigned int);
35 #endif
36 
37 #if !defined __KERNEL__
38 struct caca_file
39 {
40 # if defined HAVE_ZLIB_H
41  uint8_t read_buffer[READSIZE];
42  z_stream stream;
43  gzFile gz;
44  int eof, zip, total;
45 # endif
46  FILE *f;
47  int readonly;
48 };
49 #endif
50 
64 caca_file_t *caca_file_open(char const *path, const char *mode)
65 {
66 #if defined __KERNEL__
67  seterrno(ENOSYS);
68  return NULL;
69 #else
70  caca_file_t *fp = malloc(sizeof(*fp));
71 
72  fp->readonly = !!strchr(mode, 'r');
73 
74 # if defined HAVE_ZLIB_H
75  uint8_t buf[4];
76  unsigned int skip_size = 0;
77 
78  fp->gz = gzopen(path, fp->readonly ? "rb" : "wb");
79  if(!fp->gz)
80  {
81  free(fp);
82  seterrno(EINVAL);
83  return NULL;
84  }
85 
86  fp->eof = 0;
87  fp->zip = 0;
88  fp->total = 0;
89 
90  if(fp->readonly)
91  {
92  /* Parse ZIP file and go to start of first file */
93  gzread(fp->gz, buf, 4);
94  if(memcmp(buf, "PK\3\4", 4))
95  {
96  gzseek(fp->gz, 0, SEEK_SET);
97  return fp;
98  }
99 
100  fp->zip = 1;
101 
102  gzseek(fp->gz, 22, SEEK_CUR);
103 
104  gzread(fp->gz, buf, 2); /* Filename size */
105  skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
106  gzread(fp->gz, buf, 2); /* Extra field size */
107  skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
108 
109  gzseek(fp->gz, skip_size, SEEK_CUR);
110 
111  /* Initialise inflate stream */
112  fp->stream.total_out = 0;
113  fp->stream.zalloc = NULL;
114  fp->stream.zfree = NULL;
115  fp->stream.opaque = NULL;
116  fp->stream.next_in = NULL;
117  fp->stream.avail_in = 0;
118 
119  if(inflateInit2(&fp->stream, -MAX_WBITS))
120  {
121  gzclose(fp->gz);
122  free(fp);
123  seterrno(EINVAL);
124  return NULL;
125  }
126  }
127 # else
128  fp->f = fopen(path, mode);
129 
130  if(!fp->f)
131  {
132  free(fp);
133  seterrno(EINVAL);
134  return NULL;
135  }
136 # endif
137 
138  return fp;
139 #endif
140 }
141 
152 {
153 #if defined __KERNEL__
154  seterrno(ENOSYS);
155  return 0;
156 #elif defined HAVE_ZLIB_H
157  gzFile gz = fp->gz;
158  if(fp->zip)
159  inflateEnd(&fp->stream);
160  free(fp);
161  return gzclose(gz);
162 #else
163  FILE *f = fp->f;
164  free(fp);
165  return fclose(f);
166 #endif
167 }
168 
177 {
178 #if defined __KERNEL__
179  seterrno(ENOSYS);
180  return 0;
181 #elif defined HAVE_ZLIB_H
182  if(fp->zip)
183  return fp->total;
184  return gztell(fp->gz);
185 #else
186  return ftell(fp->f);
187 #endif
188 }
189 
199 size_t caca_file_read(caca_file_t *fp, void *ptr, size_t size)
200 {
201 #if defined __KERNEL__
202  seterrno(ENOSYS);
203  return 0;
204 #elif defined HAVE_ZLIB_H
205  if(fp->zip)
206  return zipread(fp, ptr, size);
207  return gzread(fp->gz, ptr, size);
208 #else
209  return fread(ptr, 1, size, fp->f);
210 #endif
211 }
212 
222 size_t caca_file_write(caca_file_t *fp, const void *ptr, size_t size)
223 {
224 #if defined __KERNEL__
225  seterrno(ENOSYS);
226  return 0;
227 #else
228  if(fp->readonly)
229  return 0;
230 
231 # if defined HAVE_ZLIB_H
232  if(fp->zip)
233  {
234  /* FIXME: zip files are not supported */
235  seterrno(ENOSYS);
236  return 0;
237  }
238  return gzwrite(fp->gz, ptr, size);
239 # else
240  return fwrite(ptr, 1, size, fp->f);
241 # endif
242 #endif
243 }
244 
255 char *caca_file_gets(caca_file_t *fp, char *s, int size)
256 {
257 #if defined __KERNEL__
258  seterrno(ENOSYS);
259  return NULL;
260 #elif defined HAVE_ZLIB_H
261  if(fp->zip)
262  {
263  int i;
264 
265  for(i = 0; i < size; i++)
266  {
267  int ret = zipread(fp, s + i, 1);
268 
269  if(ret < 0)
270  return NULL;
271 
272  if(ret == 0 || s[i] == '\n')
273  {
274  if(i + 1 < size)
275  s[i + 1] = '\0';
276  return s;
277  }
278  }
279 
280  return s;
281  }
282 
283  return gzgets(fp->gz, s, size);
284 #else
285  return fgets(s, size, fp->f);
286 #endif
287 }
288 
299 {
300 #if defined __KERNEL__
301  return 1;
302 #elif defined HAVE_ZLIB_H
303  return fp->zip ? fp->eof : gzeof(fp->gz);
304 #else
305  return feof(fp->f);
306 #endif
307 }
308 
309 #if !defined __KERNEL__ && defined HAVE_ZLIB_H
310 static int zipread(caca_file_t *fp, void *buf, unsigned int len)
311 {
312  unsigned int total_read = 0;
313 
314  if(len == 0)
315  return 0;
316 
317  fp->stream.next_out = buf;
318  fp->stream.avail_out = len;
319 
320  while(fp->stream.avail_out > 0)
321  {
322  unsigned int tmp;
323  int ret = 0;
324 
325  if(fp->stream.avail_in == 0 && !gzeof(fp->gz))
326  {
327  int bytes_read;
328 
329  bytes_read = gzread(fp->gz, fp->read_buffer, READSIZE);
330  if(bytes_read < 0)
331  return -1;
332 
333  fp->stream.next_in = fp->read_buffer;
334  fp->stream.avail_in = bytes_read;
335  }
336 
337  tmp = fp->stream.total_out;
338  ret = inflate(&fp->stream, Z_SYNC_FLUSH);
339  total_read += fp->stream.total_out - tmp;
340 
341  if(ret == Z_STREAM_END)
342  {
343  fp->eof = 1;
344  fp->total += total_read;
345  return total_read;
346  }
347 
348  if(ret != Z_OK)
349  return ret;
350  }
351 
352  fp->total += total_read;
353  return total_read;
354 }
355 #endif
356 
357 /*
358  * XXX: The following functions are aliases.
359  */
360 
361 cucul_file_t *cucul_file_open(char const *, const char *)
365 size_t cucul_file_read(cucul_file_t *, void *, size_t)
367 size_t cucul_file_write(cucul_file_t *, const void *, size_t)
369 char * cucul_file_gets(cucul_file_t *, char *, int)
372 
cucul_file_t
#define cucul_file_t
Definition: caca.h:766
caca_file
Definition: file.c:38
CACA_ALIAS
#define CACA_ALIAS(x)
Definition: caca.h:689
cucul_file_eof
#define cucul_file_eof
Definition: caca.h:876
cucul_file_close
#define cucul_file_close
Definition: caca.h:871
caca_file_write
size_t caca_file_write(caca_file_t *fp, const void *ptr, size_t size)
Write data to a file handle.
Definition: file.c:222
cucul_file_gets
#define cucul_file_gets
Definition: caca.h:875
caca_file_eof
int caca_file_eof(caca_file_t *fp)
Tell whether a file handle reached end of file.
Definition: file.c:298
cucul_file_read
#define cucul_file_read
Definition: caca.h:873
total
int total[0x7f][2][3]
Definition: sortchars.c:32
cucul_file_tell
#define cucul_file_tell
Definition: caca.h:872
cucul_file_write
#define cucul_file_write
Definition: caca.h:874
caca_file::f
FILE * f
Definition: file.c:46
seterrno
#define seterrno(x)
Definition: caca_stubs.h:27
mode
int mode
Definition: cacaview.c:60
caca_file_tell
uint64_t caca_file_tell(caca_file_t *fp)
Return the position in a file handle.
Definition: file.c:176
caca_file_close
int caca_file_close(caca_file_t *fp)
Close a file handle.
Definition: file.c:151
cucul_file_open
#define cucul_file_open
Definition: caca.h:870
caca_file::readonly
int readonly
Definition: file.c:47
caca_internals.h
caca_file_open
caca_file_t * caca_file_open(char const *path, const char *mode)
Open a file for reading or writing.
Definition: file.c:64
caca.h
The libcaca public header.
config.h
caca_file_read
size_t caca_file_read(caca_file_t *fp, void *ptr, size_t size)
Read data from a file handle.
Definition: file.c:199
caca_file_gets
char * caca_file_gets(caca_file_t *fp, char *s, int size)
Read a line from a file handle.
Definition: file.c:255