ReactOS 0.4.16-dev-1093-g93e9710
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 (C) 2010-2019 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#define BZ_NO_STDIO /* Do not need FILE */
47#include <bzlib.h>
48
49
50/***************************************************************************/
51/***************************************************************************/
52/***** *****/
53/***** B Z I P 2 M E M O R Y M A N A G E M E N T *****/
54/***** *****/
55/***************************************************************************/
56/***************************************************************************/
57
58 /* it is better to use FreeType memory routines instead of raw
59 'malloc/free' */
60
61 typedef void *(* alloc_func)(void*, int, int);
62 typedef void (* free_func)(void*, void*);
63
64 static void*
65 ft_bzip2_alloc( FT_Memory memory,
66 int items,
67 int size )
68 {
72
73
74 (void)FT_ALLOC( p, sz );
75 return p;
76 }
77
78
79 static void
80 ft_bzip2_free( FT_Memory memory,
81 void* address )
82 {
84 }
85
86
87/***************************************************************************/
88/***************************************************************************/
89/***** *****/
90/***** B Z I P 2 F I L E D E S C R I P T O R *****/
91/***** *****/
92/***************************************************************************/
93/***************************************************************************/
94
95#define FT_BZIP2_BUFFER_SIZE 4096
96
97 typedef struct FT_BZip2FileRec_
98 {
99 FT_Stream source; /* parent/source stream */
100 FT_Stream stream; /* embedding stream */
101 FT_Memory memory; /* memory allocator */
102 bz_stream bzstream; /* bzlib input stream */
103
104 FT_Byte input[FT_BZIP2_BUFFER_SIZE]; /* input read buffer */
105
106 FT_Byte buffer[FT_BZIP2_BUFFER_SIZE]; /* output buffer */
107 FT_ULong pos; /* position in output */
109 FT_Byte* limit;
110
111 } FT_BZip2FileRec, *FT_BZip2File;
112
113
114 /* check and skip .bz2 header - we don't support `transparent' compression */
115 static FT_Error
116 ft_bzip2_check_header( FT_Stream stream )
117 {
119 FT_Byte head[4];
120
121
122 if ( FT_STREAM_SEEK( 0 ) ||
123 FT_STREAM_READ( head, 4 ) )
124 goto Exit;
125
126 /* head[0] && head[1] are the magic numbers; */
127 /* head[2] is the version, and head[3] the blocksize */
128 if ( head[0] != 0x42 ||
129 head[1] != 0x5A ||
130 head[2] != 0x68 ) /* only support bzip2 (huffman) */
131 {
132 error = FT_THROW( Invalid_File_Format );
133 goto Exit;
134 }
135
136 Exit:
137 return error;
138 }
139
140
141 static FT_Error
142 ft_bzip2_file_init( FT_BZip2File zip,
145 {
146 bz_stream* bzstream = &zip->bzstream;
148
149
150 zip->stream = stream;
151 zip->source = source;
152 zip->memory = stream->memory;
153
154 zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
155 zip->cursor = zip->limit;
156 zip->pos = 0;
157
158 /* check .bz2 header */
159 {
160 stream = source;
161
162 error = ft_bzip2_check_header( stream );
163 if ( error )
164 goto Exit;
165
166 if ( FT_STREAM_SEEK( 0 ) )
167 goto Exit;
168 }
169
170 /* initialize bzlib */
171 bzstream->bzalloc = (alloc_func)ft_bzip2_alloc;
172 bzstream->bzfree = (free_func) ft_bzip2_free;
173 bzstream->opaque = zip->memory;
174
175 bzstream->avail_in = 0;
176 bzstream->next_in = (char*)zip->buffer;
177
178 if ( BZ2_bzDecompressInit( bzstream, 0, 0 ) != BZ_OK ||
179 !bzstream->next_in )
180 error = FT_THROW( Invalid_File_Format );
181
182 Exit:
183 return error;
184 }
185
186
187 static void
188 ft_bzip2_file_done( FT_BZip2File zip )
189 {
190 bz_stream* bzstream = &zip->bzstream;
191
192
193 BZ2_bzDecompressEnd( bzstream );
194
195 /* clear the rest */
196 bzstream->bzalloc = NULL;
197 bzstream->bzfree = NULL;
198 bzstream->opaque = NULL;
199 bzstream->next_in = NULL;
200 bzstream->next_out = NULL;
201 bzstream->avail_in = 0;
202 bzstream->avail_out = 0;
203
204 zip->memory = NULL;
205 zip->source = NULL;
206 zip->stream = NULL;
207 }
208
209
210 static FT_Error
211 ft_bzip2_file_reset( FT_BZip2File zip )
212 {
213 FT_Stream stream = zip->source;
215
216
217 if ( !FT_STREAM_SEEK( 0 ) )
218 {
219 bz_stream* bzstream = &zip->bzstream;
220
221
222 BZ2_bzDecompressEnd( bzstream );
223
224 bzstream->avail_in = 0;
225 bzstream->next_in = (char*)zip->input;
226 bzstream->avail_out = 0;
227 bzstream->next_out = (char*)zip->buffer;
228
229 zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
230 zip->cursor = zip->limit;
231 zip->pos = 0;
232
233 BZ2_bzDecompressInit( bzstream, 0, 0 );
234 }
235
236 return error;
237 }
238
239
240 static FT_Error
241 ft_bzip2_file_fill_input( FT_BZip2File zip )
242 {
243 bz_stream* bzstream = &zip->bzstream;
244 FT_Stream stream = zip->source;
246
247
248 if ( stream->read )
249 {
250 size = stream->read( stream, stream->pos, zip->input,
251 FT_BZIP2_BUFFER_SIZE );
252 if ( size == 0 )
253 {
254 zip->limit = zip->cursor;
255 return FT_THROW( Invalid_Stream_Operation );
256 }
257 }
258 else
259 {
260 size = stream->size - stream->pos;
261 if ( size > FT_BZIP2_BUFFER_SIZE )
262 size = FT_BZIP2_BUFFER_SIZE;
263
264 if ( size == 0 )
265 {
266 zip->limit = zip->cursor;
267 return FT_THROW( Invalid_Stream_Operation );
268 }
269
270 FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
271 }
272 stream->pos += size;
273
274 bzstream->next_in = (char*)zip->input;
275 bzstream->avail_in = size;
276
277 return FT_Err_Ok;
278 }
279
280
281 static FT_Error
282 ft_bzip2_file_fill_output( FT_BZip2File zip )
283 {
284 bz_stream* bzstream = &zip->bzstream;
286
287
288 zip->cursor = zip->buffer;
289 bzstream->next_out = (char*)zip->cursor;
290 bzstream->avail_out = FT_BZIP2_BUFFER_SIZE;
291
292 while ( bzstream->avail_out > 0 )
293 {
294 int err;
295
296
297 if ( bzstream->avail_in == 0 )
298 {
299 error = ft_bzip2_file_fill_input( zip );
300 if ( error )
301 break;
302 }
303
304 err = BZ2_bzDecompress( bzstream );
305
306 if ( err == BZ_STREAM_END )
307 {
308 zip->limit = (FT_Byte*)bzstream->next_out;
309 if ( zip->limit == zip->cursor )
310 error = FT_THROW( Invalid_Stream_Operation );
311 break;
312 }
313 else if ( err != BZ_OK )
314 {
315 zip->limit = zip->cursor;
316 error = FT_THROW( Invalid_Stream_Operation );
317 break;
318 }
319 }
320
321 return error;
322 }
323
324
325 /* fill output buffer; `count' must be <= FT_BZIP2_BUFFER_SIZE */
326 static FT_Error
327 ft_bzip2_file_skip_output( FT_BZip2File zip,
329 {
331 FT_ULong delta;
332
333
334 for (;;)
335 {
336 delta = (FT_ULong)( zip->limit - zip->cursor );
337 if ( delta >= count )
338 delta = count;
339
340 zip->cursor += delta;
341 zip->pos += delta;
342
343 count -= delta;
344 if ( count == 0 )
345 break;
346
347 error = ft_bzip2_file_fill_output( zip );
348 if ( error )
349 break;
350 }
351
352 return error;
353 }
354
355
356 static FT_ULong
357 ft_bzip2_file_io( FT_BZip2File zip,
361 {
362 FT_ULong result = 0;
364
365
366 /* Reset inflate stream if we're seeking backwards. */
367 /* Yes, that is not too efficient, but it saves memory :-) */
368 if ( pos < zip->pos )
369 {
370 error = ft_bzip2_file_reset( zip );
371 if ( error )
372 goto Exit;
373 }
374
375 /* skip unwanted bytes */
376 if ( pos > zip->pos )
377 {
378 error = ft_bzip2_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
379 if ( error )
380 goto Exit;
381 }
382
383 if ( count == 0 )
384 goto Exit;
385
386 /* now read the data */
387 for (;;)
388 {
389 FT_ULong delta;
390
391
392 delta = (FT_ULong)( zip->limit - zip->cursor );
393 if ( delta >= count )
394 delta = count;
395
396 FT_MEM_COPY( buffer, zip->cursor, delta );
397 buffer += delta;
398 result += delta;
399 zip->cursor += delta;
400 zip->pos += delta;
401
402 count -= delta;
403 if ( count == 0 )
404 break;
405
406 error = ft_bzip2_file_fill_output( zip );
407 if ( error )
408 break;
409 }
410
411 Exit:
412 return result;
413 }
414
415
416/***************************************************************************/
417/***************************************************************************/
418/***** *****/
419/***** B Z E M B E D D I N G S T R E A M *****/
420/***** *****/
421/***************************************************************************/
422/***************************************************************************/
423
424 static void
425 ft_bzip2_stream_close( FT_Stream stream )
426 {
427 FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
428 FT_Memory memory = stream->memory;
429
430
431 if ( zip )
432 {
433 /* finalize bzip file descriptor */
434 ft_bzip2_file_done( zip );
435
436 FT_FREE( zip );
437
438 stream->descriptor.pointer = NULL;
439 }
440 }
441
442
443 static unsigned long
444 ft_bzip2_stream_io( FT_Stream stream,
445 unsigned long offset,
446 unsigned char* buffer,
447 unsigned long count )
448 {
449 FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
450
451
452 return ft_bzip2_file_io( zip, offset, buffer, count );
453 }
454
455
459 {
462 FT_BZip2File zip = NULL;
463
464
465 if ( !stream || !source )
466 {
467 error = FT_THROW( Invalid_Stream_Handle );
468 goto Exit;
469 }
470
471 memory = source->memory;
472
473 /*
474 * check the header right now; this prevents allocating unnecessary
475 * objects when we don't need them
476 */
477 error = ft_bzip2_check_header( source );
478 if ( error )
479 goto Exit;
480
481 FT_ZERO( stream );
482 stream->memory = memory;
483
484 if ( !FT_QNEW( zip ) )
485 {
486 error = ft_bzip2_file_init( zip, stream, source );
487 if ( error )
488 {
489 FT_FREE( zip );
490 goto Exit;
491 }
492
493 stream->descriptor.pointer = zip;
494 }
495
496 stream->size = 0x7FFFFFFFL; /* don't know the real size! */
497 stream->pos = 0;
498 stream->base = 0;
499 stream->read = ft_bzip2_stream_io;
500 stream->close = ft_bzip2_stream_close;
501
502 Exit:
503 return error;
504 }
505
506#else /* !FT_CONFIG_OPTION_USE_BZIP2 */
507
511 {
512 FT_UNUSED( stream );
513 FT_UNUSED( source );
514
515 return FT_THROW( Unimplemented_Feature );
516 }
517
518#endif /* !FT_CONFIG_OPTION_USE_BZIP2 */
519
520
521/* 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:527
FT_Stream_OpenBzip2(FT_Stream stream, FT_Stream source)
Definition: ftbzip2.c:509
#define FT_UNUSED(arg)
Definition: ftconfig.h:100
#define FT_EXPORT_DEF(x)
Definition: ftconfig.h:494
#define FT_THROW(e)
Definition: ftdebug.h:241
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:302
#define FT_FREE(ptr)
Definition: ftmemory.h:328
#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:338
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:514
#define FT_STREAM_READ(buffer, count)
Definition: ftstream.h:522
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:65
unsigned long FT_ULong
Definition: fttypes.h:253
unsigned char FT_Byte
Definition: fttypes.h:154
int FT_Error
Definition: fttypes.h:299
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint address
Definition: glext.h:9393
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLint limit
Definition: glext.h:10326
GLuint64EXT * result
Definition: glext.h:11304
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLenum GLenum input
Definition: glext.h:9031
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