You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

227 lines
4.6 KiB

  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. * This file contains functions for compressed file I/O.
  16. */
  17. #include "config.h"
  18. #if !defined __KERNEL__
  19. # include <stdio.h>
  20. # include <stdlib.h>
  21. # include <string.h>
  22. # if defined HAVE_ZLIB_H
  23. # include <zlib.h>
  24. # define READSIZE 128 /* Read buffer size */
  25. # define WRITESIZE 128 /* Inflate buffer size */
  26. # endif
  27. #endif
  28. #include "cucul.h"
  29. #include "cucul_internals.h"
  30. #if !defined __KERNEL__ && defined HAVE_ZLIB_H
  31. static int zipread(cucul_file_t *, void *, unsigned int);
  32. #endif
  33. #if !defined __KERNEL__
  34. struct cucul_file
  35. {
  36. # if defined HAVE_ZLIB_H
  37. uint8_t read_buffer[READSIZE];
  38. z_stream stream;
  39. gzFile gz;
  40. int eof, zip;
  41. # endif
  42. FILE *f;
  43. };
  44. #endif
  45. cucul_file_t *_cucul_file_open(char const *path, const char *mode)
  46. {
  47. #if defined __KERNEL__
  48. return NULL;
  49. #else
  50. cucul_file_t *fp = malloc(sizeof(*fp));
  51. # if defined HAVE_ZLIB_H
  52. uint8_t buf[4];
  53. unsigned int skip_size = 0;
  54. fp->gz = gzopen(path, "rb");
  55. if(!fp->gz)
  56. {
  57. free(fp);
  58. return NULL;
  59. }
  60. fp->eof = 0;
  61. fp->zip = 0;
  62. /* Parse ZIP file and go to start of first file */
  63. gzread(fp->gz, buf, 4);
  64. if(memcmp(buf, "PK\3\4", 4))
  65. {
  66. gzseek(fp->gz, 0, SEEK_SET);
  67. return fp;
  68. }
  69. fp->zip = 1;
  70. gzseek(fp->gz, 22, SEEK_CUR);
  71. gzread(fp->gz, buf, 2); /* Filename size */
  72. skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
  73. gzread(fp->gz, buf, 2); /* Extra field size */
  74. skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
  75. gzseek(fp->gz, skip_size, SEEK_CUR);
  76. /* Initialise inflate stream */
  77. fp->stream.total_out = 0;
  78. fp->stream.zalloc = NULL;
  79. fp->stream.zfree = NULL;
  80. fp->stream.opaque = NULL;
  81. fp->stream.next_in = NULL;
  82. fp->stream.avail_in = 0;
  83. if(inflateInit2(&fp->stream, -MAX_WBITS))
  84. {
  85. free(fp);
  86. gzclose(fp->gz);
  87. return NULL;
  88. }
  89. # else
  90. fp->f = fopen(path, mode);
  91. if(!fp->f)
  92. {
  93. free(fp);
  94. return NULL;
  95. }
  96. # endif
  97. return fp;
  98. #endif
  99. }
  100. int _cucul_file_close(cucul_file_t *fp)
  101. {
  102. #if defined __KERNEL__
  103. return 0;
  104. #elif defined HAVE_ZLIB_H
  105. gzFile gz = fp->gz;
  106. if(fp->zip)
  107. inflateEnd(&fp->stream);
  108. free(fp);
  109. return gzclose(gz);
  110. #else
  111. FILE *f = fp->f;
  112. free(fp);
  113. return fclose(f);
  114. #endif
  115. }
  116. int _cucul_file_eof(cucul_file_t *fp)
  117. {
  118. #if defined __KERNEL__
  119. return 1;
  120. #elif defined HAVE_ZLIB_H
  121. return fp->zip ? fp->eof : gzeof(fp->gz);
  122. #else
  123. return feof(fp->f);
  124. #endif
  125. }
  126. char *_cucul_file_gets(char *s, int size, cucul_file_t *fp)
  127. {
  128. #if defined __KERNEL__
  129. return NULL;
  130. #elif defined HAVE_ZLIB_H
  131. if(fp->zip)
  132. {
  133. int i;
  134. for(i = 0; i < size; i++)
  135. {
  136. int ret = zipread(fp, s + i, 1);
  137. if(ret < 0)
  138. return NULL;
  139. if(ret == 0 || s[i] == '\n')
  140. {
  141. if(i + 1 < size)
  142. s[i + 1] = '\0';
  143. return s;
  144. }
  145. }
  146. return s;
  147. }
  148. return gzgets(fp->gz, s, size);
  149. #else
  150. return fgets(s, size, fp->f);
  151. #endif
  152. }
  153. #if !defined __KERNEL__ && defined HAVE_ZLIB_H
  154. static int zipread(cucul_file_t *fp, void *buf, unsigned int len)
  155. {
  156. unsigned int total_read = 0;
  157. if(len == 0)
  158. return 0;
  159. fp->stream.next_out = buf;
  160. fp->stream.avail_out = len;
  161. while(fp->stream.avail_out > 0)
  162. {
  163. unsigned int tmp;
  164. int ret = 0;
  165. if(fp->stream.avail_in == 0 && !gzeof(fp->gz))
  166. {
  167. int bytes_read;
  168. bytes_read = gzread(fp->gz, fp->read_buffer, READSIZE);
  169. if(bytes_read < 0)
  170. return -1;
  171. fp->stream.next_in = fp->read_buffer;
  172. fp->stream.avail_in = bytes_read;
  173. }
  174. tmp = fp->stream.total_out;
  175. ret = inflate(&fp->stream, Z_SYNC_FLUSH);
  176. total_read += fp->stream.total_out - tmp;
  177. if(ret == Z_STREAM_END)
  178. {
  179. fp->eof = 1;
  180. return total_read;
  181. }
  182. if(ret != Z_OK)
  183. return ret;
  184. }
  185. return total_read;
  186. }
  187. #endif