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.
 
 
 
 
 
 

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