ReactOS 0.4.15-dev-8100-g1887773
ftbzip2.c
Go to the documentation of this file.
1/***************************************************************************/
2/* */
3/* ftbzip2.c */
4/* */
5/* FreeType support for .bz2 compressed files. */
6/* */
7/* This optional component relies on libbz2. It should mainly be used to */
8/* parse compressed PCF fonts, as found with many X11 server */
9/* distributions. */
10/* */
11/* Copyright 2010-2018 by */
12/* Joel Klinghed. */
13/* */
14/* based on `src/gzip/ftgzip.c' */
15/* */
16/* This file is part of the FreeType project, and may only be used, */
17/* modified, and distributed under the terms of the FreeType project */
18/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
19/* this file you indicate that you have read the license and */
20/* understand and accept it fully. */
21/* */
22/***************************************************************************/
23
24
25#include <ft2build.h>
26#include FT_INTERNAL_MEMORY_H
27#include FT_INTERNAL_STREAM_H
28#include FT_INTERNAL_DEBUG_H
29#include FT_BZIP2_H
30#include FT_CONFIG_STANDARD_LIBRARY_H
31
32
33#include FT_MODULE_ERRORS_H
34
35#undef FTERRORS_H_
36
37#undef FT_ERR_PREFIX
38#define FT_ERR_PREFIX Bzip2_Err_
39#define FT_ERR_BASE FT_Mod_Err_Bzip2
40
41#include FT_ERRORS_H
42
43
44#ifdef FT_CONFIG_OPTION_USE_BZIP2
45
46#ifdef FT_CONFIG_OPTION_PIC
47#error "bzip2 code does not support PIC yet"
48#endif
49
50#define BZ_NO_STDIO /* Do not need FILE */
51#include <bzlib.h>
52
53
54/***************************************************************************/
55/***************************************************************************/
56/***** *****/
57/***** B Z I P 2 M E M O R Y M A N A G E M E N T *****/
58/***** *****/
59/***************************************************************************/
60/***************************************************************************/
61
62 /* it is better to use FreeType memory routines instead of raw
63 'malloc/free' */
64
65 typedef void *(* alloc_func)(void*, int, int);
66 typedef void (* free_func)(void*, void*);
67
68 static void*
69 ft_bzip2_alloc( FT_Memory memory,
70 int items,
71 int size )
72 {
76
77
78 (void)FT_ALLOC( p, sz );
79 return p;
80 }
81
82
83 static void
84 ft_bzip2_free( FT_Memory memory,
85 void* address )
86 {
88 }
89
90
91/***************************************************************************/
92/***************************************************************************/
93/***** *****/
94/***** B Z I P 2 F I L E D E S C R I P T O R *****/
95/***** *****/
96/***************************************************************************/
97/***************************************************************************/
98
99#define FT_BZIP2_BUFFER_SIZE 4096
100
101 typedef struct FT_BZip2FileRec_
102 {
103 FT_Stream source; /* parent/source stream */
104 FT_Stream stream; /* embedding stream */
105 FT_Memory memory; /* memory allocator */
106 bz_stream bzstream; /* bzlib input stream */
107
108 FT_Byte input[FT_BZIP2_BUFFER_SIZE]; /* input read buffer */
109
110 FT_Byte buffer[FT_BZIP2_BUFFER_SIZE]; /* output buffer */
111 FT_ULong pos; /* position in output */
113 FT_Byte* limit;
114
115 } FT_BZip2FileRec, *FT_BZip2File;
116
117
118 /* check and skip .bz2 header - we don't support `transparent' compression */
119 static FT_Error
120 ft_bzip2_check_header( FT_Stream stream )
121 {
123 FT_Byte head[4];
124
125
126 if ( FT_STREAM_SEEK( 0 ) ||
127 FT_STREAM_READ( head, 4 ) )
128 goto Exit;
129
130 /* head[0] && head[1] are the magic numbers; */
131 /* head[2] is the version, and head[3] the blocksize */
132 if ( head[0] != 0x42 ||
133 head[1] != 0x5A ||
134 head[2] != 0x68 ) /* only support bzip2 (huffman) */
135 {
136 error = FT_THROW( Invalid_File_Format );
137 goto Exit;
138 }
139
140 Exit:
141 return error;
142 }
143
144
145 static FT_Error
146 ft_bzip2_file_init( FT_BZip2File zip,
149 {
150 bz_stream* bzstream = &zip->bzstream;
152
153
154 zip->stream = stream;
155 zip->source = source;
156 zip->memory = stream->memory;
157
158 zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
159 zip->cursor = zip->limit;
160 zip->pos = 0;
161
162 /* check .bz2 header */
163 {
164 stream = source;
165
166 error = ft_bzip2_check_header( stream );
167 if ( error )
168 goto Exit;
169
170 if ( FT_STREAM_SEEK( 0 ) )
171 goto Exit;
172 }
173
174 /* initialize bzlib */
175 bzstream->bzalloc = (alloc_func)ft_bzip2_alloc;
176 bzstream->bzfree = (free_func) ft_bzip2_free;
177 bzstream->opaque = zip->memory;
178
179 bzstream->avail_in = 0;
180 bzstream->next_in = (char*)zip->buffer;
181
182 if ( BZ2_bzDecompressInit( bzstream, 0, 0 ) != BZ_OK ||
183 !bzstream->next_in )
184 error = FT_THROW( Invalid_File_Format );
185
186 Exit:
187 return error;
188 }
189
190
191 static void
192 ft_bzip2_file_done( FT_BZip2File zip )
193 {
194 bz_stream* bzstream = &zip->bzstream;
195
196
197 BZ2_bzDecompressEnd( bzstream );
198
199 /* clear the rest */
200 bzstream->bzalloc = NULL;
201 bzstream->bzfree = NULL;
202 bzstream->opaque = NULL;
203 bzstream->next_in = NULL;
204 bzstream->next_out = NULL;
205 bzstream->avail_in = 0;
206 bzstream->avail_out = 0;
207
208 zip->memory = NULL;
209 zip->source = NULL;
210 zip->stream = NULL;
211 }
212
213
214 static FT_Error
215 ft_bzip2_file_reset( FT_BZip2File zip )
216 {
217 FT_Stream stream = zip->source;
219
220
221 if ( !FT_STREAM_SEEK( 0 ) )
222 {
223 bz_stream* bzstream = &zip->bzstream;
224
225
226 BZ2_bzDecompressEnd( bzstream );
227
228 bzstream->avail_in = 0;
229 bzstream->next_in = (char*)zip->input;
230 bzstream->avail_out = 0;
231 bzstream->next_out = (char*)zip->buffer;
232
233 zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
234 zip->cursor = zip->limit;
235 zip->pos = 0;
236
237 BZ2_bzDecompressInit( bzstream, 0, 0 );
238 }
239
240 return error;
241 }
242
243
244 static FT_Error
245 ft_bzip2_file_fill_input( FT_BZip2File zip )
246 {
247 bz_stream* bzstream = &zip->bzstream;
248 FT_Stream stream = zip->source;
250
251
252 if ( stream->read )
253 {
254 size = stream->read( stream, stream->pos, zip->input,
255 FT_BZIP2_BUFFER_SIZE );
256 if ( size == 0 )
257 {
258 zip->limit = zip->cursor;
259 return FT_THROW( Invalid_Stream_Operation );
260 }
261 }
262 else
263 {
264 size = stream->size - stream->pos;
265 if ( size > FT_BZIP2_BUFFER_SIZE )
266 size = FT_BZIP2_BUFFER_SIZE;
267
268 if ( size == 0 )
269 {
270 zip->limit = zip->cursor;
271 return FT_THROW( Invalid_Stream_Operation );
272 }
273
274 FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
275 }
276 stream->pos += size;
277
278 bzstream->next_in = (char*)zip->input;
279 bzstream->avail_in = size;
280
281 return FT_Err_Ok;
282 }
283
284
285 static FT_Error
286 ft_bzip2_file_fill_output( FT_BZip2File zip )
287 {
288 bz_stream* bzstream = &zip->bzstream;
290
291
292 zip->cursor = zip->buffer;
293 bzstream->next_out = (char*)zip->cursor;
294 bzstream->avail_out = FT_BZIP2_BUFFER_SIZE;
295
296 while ( bzstream->avail_out > 0 )
297 {
298 int err;
299
300
301 if ( bzstream->avail_in == 0 )
302 {
303 error = ft_bzip2_file_fill_input( zip );
304 if ( error )
305 break;
306 }
307
308 err = BZ2_bzDecompress( bzstream );
309
310 if ( err == BZ_STREAM_END )
311 {
312 zip->limit = (FT_Byte*)bzstream->next_out;
313 if ( zip->limit == zip->cursor )
314 error = FT_THROW( Invalid_Stream_Operation );
315 break;
316 }
317 else if ( err != BZ_OK )
318 {
319 zip->limit = zip->cursor;
320 error = FT_THROW( Invalid_Stream_Operation );
321 break;
322 }
323 }
324
325 return error;
326 }
327
328
329 /* fill output buffer; `count' must be <= FT_BZIP2_BUFFER_SIZE */
330 static FT_Error
331 ft_bzip2_file_skip_output( FT_BZip2File zip,
333 {
335 FT_ULong delta;
336
337
338 for (;;)
339 {
340 delta = (FT_ULong)( zip->limit - zip->cursor );
341 if ( delta >= count )
342 delta = count;
343
344 zip->cursor += delta;
345 zip->pos += delta;
346
347 count -= delta;
348 if ( count == 0 )
349 break;
350
351 error = ft_bzip2_file_fill_output( zip );
352 if ( error )
353 break;
354 }
355
356 return error;
357 }
358
359
360 static FT_ULong
361 ft_bzip2_file_io( FT_BZip2File zip,
365 {
366 FT_ULong result = 0;
368
369
370 /* Reset inflate stream if we're seeking backwards. */
371 /* Yes, that is not too efficient, but it saves memory :-) */
372 if ( pos < zip->pos )
373 {
374 error = ft_bzip2_file_reset( zip );
375 if ( error )
376 goto Exit;
377 }
378
379 /* skip unwanted bytes */
380 if ( pos > zip->pos )
381 {
382 error = ft_bzip2_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
383 if ( error )
384 goto Exit;
385 }
386
387 if ( count == 0 )
388 goto Exit;
389
390 /* now read the data */
391 for (;;)
392 {
393 FT_ULong delta;
394
395
396 delta = (FT_ULong)( zip->limit - zip->cursor );
397 if ( delta >= count )
398 delta = count;
399
400 FT_MEM_COPY( buffer, zip->cursor, delta );
401 buffer += delta;
402 result += delta;
403 zip->cursor += delta;
404 zip->pos += delta;
405
406 count -= delta;
407 if ( count == 0 )
408 break;
409
410 error = ft_bzip2_file_fill_output( zip );
411 if ( error )
412 break;
413 }
414
415 Exit:
416 return result;
417 }
418
419
420/***************************************************************************/
421/***************************************************************************/
422/***** *****/
423/***** B Z E M B E D D I N G S T R E A M *****/
424/***** *****/
425/***************************************************************************/
426/***************************************************************************/
427
428 static void
429 ft_bzip2_stream_close( FT_Stream stream )
430 {
431 FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
432 FT_Memory memory = stream->memory;
433
434
435 if ( zip )
436 {
437 /* finalize bzip file descriptor */
438 ft_bzip2_file_done( zip );
439
440 FT_FREE( zip );
441
442 stream->descriptor.pointer = NULL;
443 }
444 }
445
446
447 static unsigned long
448 ft_bzip2_stream_io( FT_Stream stream,
449 unsigned long offset,
450 unsigned char* buffer,
451 unsigned long count )
452 {
453 FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
454
455
456 return ft_bzip2_file_io( zip, offset, buffer, count );
457 }
458
459
463 {
466 FT_BZip2File zip = NULL;
467
468
469 if ( !stream || !source )
470 {
471 error = FT_THROW( Invalid_Stream_Handle );
472 goto Exit;
473 }
474
475 memory = source->memory;
476
477 /*
478 * check the header right now; this prevents allocating unnecessary
479 * objects when we don't need them
480 */
481 error = ft_bzip2_check_header( source );
482 if ( error )
483 goto Exit;
484
485 FT_ZERO( stream );
486 stream->memory = memory;
487
488 if ( !FT_QNEW( zip ) )
489 {
490 error = ft_bzip2_file_init( zip, stream, source );
491 if ( error )
492 {
493 FT_FREE( zip );
494 goto Exit;
495 }
496
497 stream->descriptor.pointer = zip;
498 }
499
500 stream->size = 0x7FFFFFFFL; /* don't know the real size! */
501 stream->pos = 0;
502 stream->base = 0;
503 stream->read = ft_bzip2_stream_io;
504 stream->close = ft_bzip2_stream_close;
505
506 Exit:
507 return error;
508 }
509
510#else /* !FT_CONFIG_OPTION_USE_BZIP2 */
511
515 {
516 FT_UNUSED( stream );
517 FT_UNUSED( source );
518
519 return FT_THROW( Unimplemented_Feature );
520 }
521
522#endif /* !FT_CONFIG_OPTION_USE_BZIP2 */
523
524
525/* END */
struct outqueuenode * head
Definition: adnsresfilter.c:66
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
#define NULL
Definition: types.h:112
void(* free_func)(voidpf opaque, voidpf address)
Definition: zlib.h:54
voidpf(* alloc_func)(voidpf opaque, uInt items, uInt size)
Definition: zlib.h:53
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
return FT_Err_Ok
Definition: ftbbox.c:511
FT_Stream_OpenBzip2(FT_Stream stream, FT_Stream source)
Definition: ftbzip2.c:513
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
#define FT_EXPORT_DEF(x)
Definition: ftconfig.h:483
#define FT_THROW(e)
Definition: ftdebug.h:213
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:303
#define FT_FREE(ptr)
Definition: ftmemory.h:329
#define FT_MEM_FREE(ptr)
Definition: ftmemory.h:156
#define FT_ZERO(p)
Definition: ftmemory.h:237
#define FT_MEM_COPY(dest, source, count)
Definition: ftmemory.h:228
#define FT_QNEW(ptr)
Definition: ftmemory.h:339
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:489
#define FT_STREAM_READ(buffer, count)
Definition: ftstream.h:497
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
unsigned long FT_ULong
Definition: fttypes.h:253
unsigned char FT_Byte
Definition: fttypes.h:154
int FT_Error
Definition: fttypes.h:300
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLuint address
Definition: glext.h:9393
GLuint buffer
Definition: glext.h:5915
GLint limit
Definition: glext.h:10326
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLenum GLenum input
Definition: glext.h:9031
GLuint64EXT * result
Definition: glext.h:11304
GLintptr offset
Definition: glext.h:5920
const char cursor[]
Definition: icontest.c:13
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
static char memory[1024 *256]
Definition: process.c:116
static TCHAR * items[]
Definition: page1.c:45
#define err(...)
static void Exit(void)
Definition: sock.c:1330
Definition: parse.h:23
ULARGE_INTEGER pos
Definition: request.c:4380
unsigned int size
Definition: parse.h:27