~ubuntu-branches/ubuntu/wily/hedgewars/wily

« back to all changes in this revision

Viewing changes to misc/libfreetype/src/bzip2/ftbzip2.c

  • Committer: Package Import Robot
  • Author(s): Dmitry E. Oboukhov
  • Date: 2011-09-23 10:16:55 UTC
  • mfrom: (1.2.11 upstream)
  • Revision ID: package-import@ubuntu.com-20110923101655-3977th2gc5n0a3pv
Tags: 0.9.16-1
* New upstream version.
 + Downloadable content! Simply click to install any content.
   New voices, hats, maps, themes, translations, music, scripts...
   Hedgewars is now more customisable than ever before! As time goes
   by we will be soliciting community content to feature on this page,
   so remember to check it from time to time. If you decide you want
   to go back to standard Hedgewars, just remove the Data directory
   from your Hedgewars config directory.
 + 3-D rendering! Diorama-like rendering of the game in a variety
   of 3D modes. Let us know which ones work best for you, we didn't
   really have the equipment to test them all.
 + Resizable game window.
 + New utilities! The Time Box will remove one of your hedgehogs
   from the game for a while, protecting from attack until it returns,
   somewhere else on the map. Land spray will allow you to build bridges,
   seal up holes, or just make life unpleasant for your enemies.
 + New single player: Bamboo Thicket, That Sinking Feeling, Newton and
   the Tree and multi-player: The Specialists, Space Invaders,
   Racer - scripts! And a ton more script hooks for scripters
 + New twists on old weapons. Drill strike, seduction and fire have
   been adjusted. Defective mines have been added, rope can attach to
   hogs/crates/barrels again, grenades now have variable bounce (use
   precise key + 1-5). Portal gun is now more usable in flight and
   all game actions are a lot faster.
 + New theme - Golf, dozens of new community hats and a new
   localised Default voice, Ukranian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 by                                                      */
 
12
/*  Joel Klinghed.                                                         */
 
13
/*                                                                         */
 
14
/*  Based on src/gzip/ftgzip.c, Copyright 2002 - 2010 by                   */
 
15
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 
16
/*                                                                         */
 
17
/*  This file is part of the FreeType project, and may only be used,       */
 
18
/*  modified, and distributed under the terms of the FreeType project      */
 
19
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
 
20
/*  this file you indicate that you have read the license and              */
 
21
/*  understand and accept it fully.                                        */
 
22
/*                                                                         */
 
23
/***************************************************************************/
 
24
 
 
25
 
 
26
#include <ft2build.h>
 
27
#include FT_INTERNAL_MEMORY_H
 
28
#include FT_INTERNAL_STREAM_H
 
29
#include FT_INTERNAL_DEBUG_H
 
30
#include FT_BZIP2_H
 
31
#include FT_CONFIG_STANDARD_LIBRARY_H
 
32
 
 
33
 
 
34
#include FT_MODULE_ERRORS_H
 
35
 
 
36
#undef __FTERRORS_H__
 
37
 
 
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
  {
 
73
    FT_ULong    sz = (FT_ULong)size * items;
 
74
    FT_Error    error;
 
75
    FT_Pointer  p  = NULL;
 
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
  {
 
87
    FT_MEM_FREE( address );
 
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 */
 
112
    FT_Byte*   cursor;
 
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
  {
 
122
    FT_Error  error = Bzip2_Err_Ok;
 
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 = Bzip2_Err_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,
 
147
                      FT_Stream     stream,
 
148
                      FT_Stream     source )
 
149
  {
 
150
    bz_stream*  bzstream = &zip->bzstream;
 
151
    FT_Error    error    = Bzip2_Err_Ok;
 
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 == NULL                       )
 
184
      error = Bzip2_Err_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;
 
218
    FT_Error   error;
 
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;
 
249
    FT_ULong    size;
 
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
        return Bzip2_Err_Invalid_Stream_Operation;
 
258
    }
 
259
    else
 
260
    {
 
261
      size = stream->size - stream->pos;
 
262
      if ( size > FT_BZIP2_BUFFER_SIZE )
 
263
        size = FT_BZIP2_BUFFER_SIZE;
 
264
 
 
265
      if ( size == 0 )
 
266
        return Bzip2_Err_Invalid_Stream_Operation;
 
267
 
 
268
      FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
 
269
    }
 
270
    stream->pos += size;
 
271
 
 
272
    bzstream->next_in  = (char*)zip->input;
 
273
    bzstream->avail_in = size;
 
274
 
 
275
    return Bzip2_Err_Ok;
 
276
  }
 
277
 
 
278
 
 
279
  static FT_Error
 
280
  ft_bzip2_file_fill_output( FT_BZip2File  zip )
 
281
  {
 
282
    bz_stream*  bzstream = &zip->bzstream;
 
283
    FT_Error    error    = Bzip2_Err_Ok;
 
284
 
 
285
 
 
286
    zip->cursor         = zip->buffer;
 
287
    bzstream->next_out  = (char*)zip->cursor;
 
288
    bzstream->avail_out = FT_BZIP2_BUFFER_SIZE;
 
289
 
 
290
    while ( bzstream->avail_out > 0 )
 
291
    {
 
292
      int  err;
 
293
 
 
294
 
 
295
      if ( bzstream->avail_in == 0 )
 
296
      {
 
297
        error = ft_bzip2_file_fill_input( zip );
 
298
        if ( error )
 
299
          break;
 
300
      }
 
301
 
 
302
      err = BZ2_bzDecompress( bzstream );
 
303
 
 
304
      if ( err == BZ_STREAM_END )
 
305
      {
 
306
        zip->limit = (FT_Byte*)bzstream->next_out;
 
307
        if ( zip->limit == zip->cursor )
 
308
          error = Bzip2_Err_Invalid_Stream_Operation;
 
309
        break;
 
310
      }
 
311
      else if ( err != BZ_OK )
 
312
      {
 
313
        error = Bzip2_Err_Invalid_Stream_Operation;
 
314
        break;
 
315
      }
 
316
    }
 
317
 
 
318
    return error;
 
319
  }
 
320
 
 
321
 
 
322
  /* fill output buffer; `count' must be <= FT_BZIP2_BUFFER_SIZE */
 
323
  static FT_Error
 
324
  ft_bzip2_file_skip_output( FT_BZip2File  zip,
 
325
                             FT_ULong      count )
 
326
  {
 
327
    FT_Error  error = Bzip2_Err_Ok;
 
328
    FT_ULong  delta;
 
329
 
 
330
 
 
331
    for (;;)
 
332
    {
 
333
      delta = (FT_ULong)( zip->limit - zip->cursor );
 
334
      if ( delta >= count )
 
335
        delta = count;
 
336
 
 
337
      zip->cursor += delta;
 
338
      zip->pos    += delta;
 
339
 
 
340
      count -= delta;
 
341
      if ( count == 0 )
 
342
        break;
 
343
 
 
344
      error = ft_bzip2_file_fill_output( zip );
 
345
      if ( error )
 
346
        break;
 
347
    }
 
348
 
 
349
    return error;
 
350
  }
 
351
 
 
352
 
 
353
  static FT_ULong
 
354
  ft_bzip2_file_io( FT_BZip2File  zip,
 
355
                    FT_ULong      pos,
 
356
                    FT_Byte*      buffer,
 
357
                    FT_ULong      count )
 
358
  {
 
359
    FT_ULong  result = 0;
 
360
    FT_Error  error;
 
361
 
 
362
 
 
363
    /* Reset inflate stream if we're seeking backwards.        */
 
364
    /* Yes, that is not too efficient, but it saves memory :-) */
 
365
    if ( pos < zip->pos )
 
366
    {
 
367
      error = ft_bzip2_file_reset( zip );
 
368
      if ( error )
 
369
        goto Exit;
 
370
    }
 
371
 
 
372
    /* skip unwanted bytes */
 
373
    if ( pos > zip->pos )
 
374
    {
 
375
      error = ft_bzip2_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
 
376
      if ( error )
 
377
        goto Exit;
 
378
    }
 
379
 
 
380
    if ( count == 0 )
 
381
      goto Exit;
 
382
 
 
383
    /* now read the data */
 
384
    for (;;)
 
385
    {
 
386
      FT_ULong  delta;
 
387
 
 
388
 
 
389
      delta = (FT_ULong)( zip->limit - zip->cursor );
 
390
      if ( delta >= count )
 
391
        delta = count;
 
392
 
 
393
      FT_MEM_COPY( buffer, zip->cursor, delta );
 
394
      buffer      += delta;
 
395
      result      += delta;
 
396
      zip->cursor += delta;
 
397
      zip->pos    += delta;
 
398
 
 
399
      count -= delta;
 
400
      if ( count == 0 )
 
401
        break;
 
402
 
 
403
      error = ft_bzip2_file_fill_output( zip );
 
404
      if ( error )
 
405
        break;
 
406
    }
 
407
 
 
408
  Exit:
 
409
    return result;
 
410
  }
 
411
 
 
412
 
 
413
/***************************************************************************/
 
414
/***************************************************************************/
 
415
/*****                                                                 *****/
 
416
/*****               B Z   E M B E D D I N G   S T R E A M             *****/
 
417
/*****                                                                 *****/
 
418
/***************************************************************************/
 
419
/***************************************************************************/
 
420
 
 
421
  static void
 
422
  ft_bzip2_stream_close( FT_Stream  stream )
 
423
  {
 
424
    FT_BZip2File  zip    = (FT_BZip2File)stream->descriptor.pointer;
 
425
    FT_Memory     memory = stream->memory;
 
426
 
 
427
 
 
428
    if ( zip )
 
429
    {
 
430
      /* finalize bzip file descriptor */
 
431
      ft_bzip2_file_done( zip );
 
432
 
 
433
      FT_FREE( zip );
 
434
 
 
435
      stream->descriptor.pointer = NULL;
 
436
    }
 
437
  }
 
438
 
 
439
 
 
440
  static FT_ULong
 
441
  ft_bzip2_stream_io( FT_Stream  stream,
 
442
                      FT_ULong   pos,
 
443
                      FT_Byte*   buffer,
 
444
                      FT_ULong   count )
 
445
  {
 
446
    FT_BZip2File  zip = (FT_BZip2File)stream->descriptor.pointer;
 
447
 
 
448
 
 
449
    return ft_bzip2_file_io( zip, pos, buffer, count );
 
450
  }
 
451
 
 
452
 
 
453
  FT_EXPORT_DEF( FT_Error )
 
454
  FT_Stream_OpenBzip2( FT_Stream  stream,
 
455
                       FT_Stream  source )
 
456
  {
 
457
    FT_Error      error;
 
458
    FT_Memory     memory = source->memory;
 
459
    FT_BZip2File  zip;
 
460
 
 
461
 
 
462
    /*
 
463
     *  check the header right now; this prevents allocating unnecessary
 
464
     *  objects when we don't need them
 
465
     */
 
466
    error = ft_bzip2_check_header( source );
 
467
    if ( error )
 
468
      goto Exit;
 
469
 
 
470
    FT_ZERO( stream );
 
471
    stream->memory = memory;
 
472
 
 
473
    if ( !FT_QNEW( zip ) )
 
474
    {
 
475
      error = ft_bzip2_file_init( zip, stream, source );
 
476
      if ( error )
 
477
      {
 
478
        FT_FREE( zip );
 
479
        goto Exit;
 
480
      }
 
481
 
 
482
      stream->descriptor.pointer = zip;
 
483
    }
 
484
 
 
485
    stream->size  = 0x7FFFFFFFL;  /* don't know the real size! */
 
486
    stream->pos   = 0;
 
487
    stream->base  = 0;
 
488
    stream->read  = ft_bzip2_stream_io;
 
489
    stream->close = ft_bzip2_stream_close;
 
490
 
 
491
  Exit:
 
492
    return error;
 
493
  }
 
494
 
 
495
#else  /* !FT_CONFIG_OPTION_USE_BZIP2 */
 
496
 
 
497
  FT_EXPORT_DEF( FT_Error )
 
498
  FT_Stream_OpenBzip2( FT_Stream  stream,
 
499
                       FT_Stream  source )
 
500
  {
 
501
    FT_UNUSED( stream );
 
502
    FT_UNUSED( source );
 
503
 
 
504
    return Bzip2_Err_Unimplemented_Feature;
 
505
  }
 
506
 
 
507
#endif /* !FT_CONFIG_OPTION_USE_BZIP2 */
 
508
 
 
509
 
 
510
/* END */