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

« back to all changes in this revision

Viewing changes to misc/libfreetype/src/base/ftstream.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
/*  ftstream.c                                                             */
 
4
/*                                                                         */
 
5
/*    I/O stream support (body).                                           */
 
6
/*                                                                         */
 
7
/*  Copyright 2000-2002, 2004-2006, 2008-2011 by                           */
 
8
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 
9
/*                                                                         */
 
10
/*  This file is part of the FreeType project, and may only be used,       */
 
11
/*  modified, and distributed under the terms of the FreeType project      */
 
12
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
 
13
/*  this file you indicate that you have read the license and              */
 
14
/*  understand and accept it fully.                                        */
 
15
/*                                                                         */
 
16
/***************************************************************************/
 
17
 
 
18
 
 
19
#include <ft2build.h>
 
20
#include FT_INTERNAL_STREAM_H
 
21
#include FT_INTERNAL_DEBUG_H
 
22
 
 
23
 
 
24
  /*************************************************************************/
 
25
  /*                                                                       */
 
26
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
 
27
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
 
28
  /* messages during execution.                                            */
 
29
  /*                                                                       */
 
30
#undef  FT_COMPONENT
 
31
#define FT_COMPONENT  trace_stream
 
32
 
 
33
 
 
34
  FT_BASE_DEF( void )
 
35
  FT_Stream_OpenMemory( FT_Stream       stream,
 
36
                        const FT_Byte*  base,
 
37
                        FT_ULong        size )
 
38
  {
 
39
    stream->base   = (FT_Byte*) base;
 
40
    stream->size   = size;
 
41
    stream->pos    = 0;
 
42
    stream->cursor = 0;
 
43
    stream->read   = 0;
 
44
    stream->close  = 0;
 
45
  }
 
46
 
 
47
 
 
48
  FT_BASE_DEF( void )
 
49
  FT_Stream_Close( FT_Stream  stream )
 
50
  {
 
51
    if ( stream && stream->close )
 
52
      stream->close( stream );
 
53
  }
 
54
 
 
55
 
 
56
  FT_BASE_DEF( FT_Error )
 
57
  FT_Stream_Seek( FT_Stream  stream,
 
58
                  FT_ULong   pos )
 
59
  {
 
60
    FT_Error  error = FT_Err_Ok;
 
61
 
 
62
 
 
63
    if ( stream->read )
 
64
    {
 
65
      if ( stream->read( stream, pos, 0, 0 ) )
 
66
      {
 
67
        FT_ERROR(( "FT_Stream_Seek:"
 
68
                   " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
 
69
                   pos, stream->size ));
 
70
 
 
71
        error = FT_Err_Invalid_Stream_Operation;
 
72
      }
 
73
    }
 
74
    /* note that seeking to the first position after the file is valid */
 
75
    else if ( pos > stream->size )
 
76
    {
 
77
      FT_ERROR(( "FT_Stream_Seek:"
 
78
                 " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
 
79
                 pos, stream->size ));
 
80
 
 
81
      error = FT_Err_Invalid_Stream_Operation;
 
82
    }
 
83
 
 
84
    if ( !error )
 
85
      stream->pos = pos;
 
86
 
 
87
    return error;
 
88
  }
 
89
 
 
90
 
 
91
  FT_BASE_DEF( FT_Error )
 
92
  FT_Stream_Skip( FT_Stream  stream,
 
93
                  FT_Long    distance )
 
94
  {
 
95
    if ( distance < 0 )
 
96
      return FT_Err_Invalid_Stream_Operation;
 
97
 
 
98
    return FT_Stream_Seek( stream, (FT_ULong)( stream->pos + distance ) );
 
99
  }
 
100
 
 
101
 
 
102
  FT_BASE_DEF( FT_Long )
 
103
  FT_Stream_Pos( FT_Stream  stream )
 
104
  {
 
105
    return stream->pos;
 
106
  }
 
107
 
 
108
 
 
109
  FT_BASE_DEF( FT_Error )
 
110
  FT_Stream_Read( FT_Stream  stream,
 
111
                  FT_Byte*   buffer,
 
112
                  FT_ULong   count )
 
113
  {
 
114
    return FT_Stream_ReadAt( stream, stream->pos, buffer, count );
 
115
  }
 
116
 
 
117
 
 
118
  FT_BASE_DEF( FT_Error )
 
119
  FT_Stream_ReadAt( FT_Stream  stream,
 
120
                    FT_ULong   pos,
 
121
                    FT_Byte*   buffer,
 
122
                    FT_ULong   count )
 
123
  {
 
124
    FT_Error  error = FT_Err_Ok;
 
125
    FT_ULong  read_bytes;
 
126
 
 
127
 
 
128
    if ( pos >= stream->size )
 
129
    {
 
130
      FT_ERROR(( "FT_Stream_ReadAt:"
 
131
                 " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
 
132
                 pos, stream->size ));
 
133
 
 
134
      return FT_Err_Invalid_Stream_Operation;
 
135
    }
 
136
 
 
137
    if ( stream->read )
 
138
      read_bytes = stream->read( stream, pos, buffer, count );
 
139
    else
 
140
    {
 
141
      read_bytes = stream->size - pos;
 
142
      if ( read_bytes > count )
 
143
        read_bytes = count;
 
144
 
 
145
      FT_MEM_COPY( buffer, stream->base + pos, read_bytes );
 
146
    }
 
147
 
 
148
    stream->pos = pos + read_bytes;
 
149
 
 
150
    if ( read_bytes < count )
 
151
    {
 
152
      FT_ERROR(( "FT_Stream_ReadAt:"
 
153
                 " invalid read; expected %lu bytes, got %lu\n",
 
154
                 count, read_bytes ));
 
155
 
 
156
      error = FT_Err_Invalid_Stream_Operation;
 
157
    }
 
158
 
 
159
    return error;
 
160
  }
 
161
 
 
162
 
 
163
  FT_BASE_DEF( FT_ULong )
 
164
  FT_Stream_TryRead( FT_Stream  stream,
 
165
                     FT_Byte*   buffer,
 
166
                     FT_ULong   count )
 
167
  {
 
168
    FT_ULong  read_bytes = 0;
 
169
 
 
170
 
 
171
    if ( stream->pos >= stream->size )
 
172
      goto Exit;
 
173
 
 
174
    if ( stream->read )
 
175
      read_bytes = stream->read( stream, stream->pos, buffer, count );
 
176
    else
 
177
    {
 
178
      read_bytes = stream->size - stream->pos;
 
179
      if ( read_bytes > count )
 
180
        read_bytes = count;
 
181
 
 
182
      FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes );
 
183
    }
 
184
 
 
185
    stream->pos += read_bytes;
 
186
 
 
187
  Exit:
 
188
    return read_bytes;
 
189
  }
 
190
 
 
191
 
 
192
  FT_BASE_DEF( FT_Error )
 
193
  FT_Stream_ExtractFrame( FT_Stream  stream,
 
194
                          FT_ULong   count,
 
195
                          FT_Byte**  pbytes )
 
196
  {
 
197
    FT_Error  error;
 
198
 
 
199
 
 
200
    error = FT_Stream_EnterFrame( stream, count );
 
201
    if ( !error )
 
202
    {
 
203
      *pbytes = (FT_Byte*)stream->cursor;
 
204
 
 
205
      /* equivalent to FT_Stream_ExitFrame(), with no memory block release */
 
206
      stream->cursor = 0;
 
207
      stream->limit  = 0;
 
208
    }
 
209
 
 
210
    return error;
 
211
  }
 
212
 
 
213
 
 
214
  FT_BASE_DEF( void )
 
215
  FT_Stream_ReleaseFrame( FT_Stream  stream,
 
216
                          FT_Byte**  pbytes )
 
217
  {
 
218
    if ( stream && stream->read )
 
219
    {
 
220
      FT_Memory  memory = stream->memory;
 
221
 
 
222
#ifdef FT_DEBUG_MEMORY
 
223
      ft_mem_free( memory, *pbytes );
 
224
      *pbytes = NULL;
 
225
#else
 
226
      FT_FREE( *pbytes );
 
227
#endif
 
228
    }
 
229
    *pbytes = 0;
 
230
  }
 
231
 
 
232
 
 
233
  FT_BASE_DEF( FT_Error )
 
234
  FT_Stream_EnterFrame( FT_Stream  stream,
 
235
                        FT_ULong   count )
 
236
  {
 
237
    FT_Error  error = FT_Err_Ok;
 
238
    FT_ULong  read_bytes;
 
239
 
 
240
 
 
241
    /* check for nested frame access */
 
242
    FT_ASSERT( stream && stream->cursor == 0 );
 
243
 
 
244
    if ( stream->read )
 
245
    {
 
246
      /* allocate the frame in memory */
 
247
      FT_Memory  memory = stream->memory;
 
248
 
 
249
 
 
250
      /* simple sanity check */
 
251
      if ( count > stream->size )
 
252
      {
 
253
        FT_ERROR(( "FT_Stream_EnterFrame:"
 
254
                   " frame size (%lu) larger than stream size (%lu)\n",
 
255
                   count, stream->size ));
 
256
 
 
257
        error = FT_Err_Invalid_Stream_Operation;
 
258
        goto Exit;
 
259
      }
 
260
 
 
261
#ifdef FT_DEBUG_MEMORY
 
262
      /* assume _ft_debug_file and _ft_debug_lineno are already set */
 
263
      stream->base = (unsigned char*)ft_mem_qalloc( memory, count, &error );
 
264
      if ( error )
 
265
        goto Exit;
 
266
#else
 
267
      if ( FT_QALLOC( stream->base, count ) )
 
268
        goto Exit;
 
269
#endif
 
270
      /* read it */
 
271
      read_bytes = stream->read( stream, stream->pos,
 
272
                                 stream->base, count );
 
273
      if ( read_bytes < count )
 
274
      {
 
275
        FT_ERROR(( "FT_Stream_EnterFrame:"
 
276
                   " invalid read; expected %lu bytes, got %lu\n",
 
277
                   count, read_bytes ));
 
278
 
 
279
        FT_FREE( stream->base );
 
280
        error = FT_Err_Invalid_Stream_Operation;
 
281
      }
 
282
      stream->cursor = stream->base;
 
283
      stream->limit  = stream->cursor + count;
 
284
      stream->pos   += read_bytes;
 
285
    }
 
286
    else
 
287
    {
 
288
      /* check current and new position */
 
289
      if ( stream->pos >= stream->size        ||
 
290
           stream->size - stream->pos < count )
 
291
      {
 
292
        FT_ERROR(( "FT_Stream_EnterFrame:"
 
293
                   " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
 
294
                   stream->pos, count, stream->size ));
 
295
 
 
296
        error = FT_Err_Invalid_Stream_Operation;
 
297
        goto Exit;
 
298
      }
 
299
 
 
300
      /* set cursor */
 
301
      stream->cursor = stream->base + stream->pos;
 
302
      stream->limit  = stream->cursor + count;
 
303
      stream->pos   += count;
 
304
    }
 
305
 
 
306
  Exit:
 
307
    return error;
 
308
  }
 
309
 
 
310
 
 
311
  FT_BASE_DEF( void )
 
312
  FT_Stream_ExitFrame( FT_Stream  stream )
 
313
  {
 
314
    /* IMPORTANT: The assertion stream->cursor != 0 was removed, given    */
 
315
    /*            that it is possible to access a frame of length 0 in    */
 
316
    /*            some weird fonts (usually, when accessing an array of   */
 
317
    /*            0 records, like in some strange kern tables).           */
 
318
    /*                                                                    */
 
319
    /*  In this case, the loader code handles the 0-length table          */
 
320
    /*  gracefully; however, stream.cursor is really set to 0 by the      */
 
321
    /*  FT_Stream_EnterFrame() call, and this is not an error.            */
 
322
    /*                                                                    */
 
323
    FT_ASSERT( stream );
 
324
 
 
325
    if ( stream->read )
 
326
    {
 
327
      FT_Memory  memory = stream->memory;
 
328
 
 
329
#ifdef FT_DEBUG_MEMORY
 
330
      ft_mem_free( memory, stream->base );
 
331
      stream->base = NULL;
 
332
#else
 
333
      FT_FREE( stream->base );
 
334
#endif
 
335
    }
 
336
    stream->cursor = 0;
 
337
    stream->limit  = 0;
 
338
  }
 
339
 
 
340
 
 
341
  FT_BASE_DEF( FT_Char )
 
342
  FT_Stream_GetChar( FT_Stream  stream )
 
343
  {
 
344
    FT_Char  result;
 
345
 
 
346
 
 
347
    FT_ASSERT( stream && stream->cursor );
 
348
 
 
349
    result = 0;
 
350
    if ( stream->cursor < stream->limit )
 
351
      result = *stream->cursor++;
 
352
 
 
353
    return result;
 
354
  }
 
355
 
 
356
 
 
357
  FT_BASE_DEF( FT_UShort )
 
358
  FT_Stream_GetUShort( FT_Stream  stream )
 
359
  {
 
360
    FT_Byte*  p;
 
361
    FT_Short  result;
 
362
 
 
363
 
 
364
    FT_ASSERT( stream && stream->cursor );
 
365
 
 
366
    result         = 0;
 
367
    p              = stream->cursor;
 
368
    if ( p + 1 < stream->limit )
 
369
      result       = FT_NEXT_USHORT( p );
 
370
    stream->cursor = p;
 
371
 
 
372
    return result;
 
373
  }
 
374
 
 
375
 
 
376
  FT_BASE_DEF( FT_UShort )
 
377
  FT_Stream_GetUShortLE( FT_Stream  stream )
 
378
  {
 
379
    FT_Byte*  p;
 
380
    FT_Short  result;
 
381
 
 
382
 
 
383
    FT_ASSERT( stream && stream->cursor );
 
384
 
 
385
    result         = 0;
 
386
    p              = stream->cursor;
 
387
    if ( p + 1 < stream->limit )
 
388
      result       = FT_NEXT_USHORT_LE( p );
 
389
    stream->cursor = p;
 
390
 
 
391
    return result;
 
392
  }
 
393
 
 
394
 
 
395
  FT_BASE_DEF( FT_ULong )
 
396
  FT_Stream_GetUOffset( FT_Stream  stream )
 
397
  {
 
398
    FT_Byte*  p;
 
399
    FT_Long   result;
 
400
 
 
401
 
 
402
    FT_ASSERT( stream && stream->cursor );
 
403
 
 
404
    result         = 0;
 
405
    p              = stream->cursor;
 
406
    if ( p + 2 < stream->limit )
 
407
      result       = FT_NEXT_UOFF3( p );
 
408
    stream->cursor = p;
 
409
    return result;
 
410
  }
 
411
 
 
412
 
 
413
  FT_BASE_DEF( FT_ULong )
 
414
  FT_Stream_GetULong( FT_Stream  stream )
 
415
  {
 
416
    FT_Byte*  p;
 
417
    FT_Long   result;
 
418
 
 
419
 
 
420
    FT_ASSERT( stream && stream->cursor );
 
421
 
 
422
    result         = 0;
 
423
    p              = stream->cursor;
 
424
    if ( p + 3 < stream->limit )
 
425
      result       = FT_NEXT_ULONG( p );
 
426
    stream->cursor = p;
 
427
    return result;
 
428
  }
 
429
 
 
430
 
 
431
  FT_BASE_DEF( FT_ULong )
 
432
  FT_Stream_GetULongLE( FT_Stream  stream )
 
433
  {
 
434
    FT_Byte*  p;
 
435
    FT_Long   result;
 
436
 
 
437
 
 
438
    FT_ASSERT( stream && stream->cursor );
 
439
 
 
440
    result         = 0;
 
441
    p              = stream->cursor;
 
442
    if ( p + 3 < stream->limit )
 
443
      result       = FT_NEXT_ULONG_LE( p );
 
444
    stream->cursor = p;
 
445
    return result;
 
446
  }
 
447
 
 
448
 
 
449
  FT_BASE_DEF( FT_Char )
 
450
  FT_Stream_ReadChar( FT_Stream  stream,
 
451
                      FT_Error*  error )
 
452
  {
 
453
    FT_Byte  result = 0;
 
454
 
 
455
 
 
456
    FT_ASSERT( stream );
 
457
 
 
458
    *error = FT_Err_Ok;
 
459
 
 
460
    if ( stream->read )
 
461
    {
 
462
      if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
 
463
        goto Fail;
 
464
    }
 
465
    else
 
466
    {
 
467
      if ( stream->pos < stream->size )
 
468
        result = stream->base[stream->pos];
 
469
      else
 
470
        goto Fail;
 
471
    }
 
472
    stream->pos++;
 
473
 
 
474
    return result;
 
475
 
 
476
  Fail:
 
477
    *error = FT_Err_Invalid_Stream_Operation;
 
478
    FT_ERROR(( "FT_Stream_ReadChar:"
 
479
               " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
 
480
               stream->pos, stream->size ));
 
481
 
 
482
    return 0;
 
483
  }
 
484
 
 
485
 
 
486
  FT_BASE_DEF( FT_UShort )
 
487
  FT_Stream_ReadUShort( FT_Stream  stream,
 
488
                       FT_Error*  error )
 
489
  {
 
490
    FT_Byte   reads[2];
 
491
    FT_Byte*  p = 0;
 
492
    FT_Short  result = 0;
 
493
 
 
494
 
 
495
    FT_ASSERT( stream );
 
496
 
 
497
    *error = FT_Err_Ok;
 
498
 
 
499
    if ( stream->pos + 1 < stream->size )
 
500
    {
 
501
      if ( stream->read )
 
502
      {
 
503
        if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
 
504
          goto Fail;
 
505
 
 
506
        p = reads;
 
507
      }
 
508
      else
 
509
      {
 
510
        p = stream->base + stream->pos;
 
511
      }
 
512
 
 
513
      if ( p )
 
514
        result = FT_NEXT_USHORT( p );
 
515
    }
 
516
    else
 
517
      goto Fail;
 
518
 
 
519
    stream->pos += 2;
 
520
 
 
521
    return result;
 
522
 
 
523
  Fail:
 
524
    *error = FT_Err_Invalid_Stream_Operation;
 
525
    FT_ERROR(( "FT_Stream_ReadUShort:"
 
526
               " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
 
527
               stream->pos, stream->size ));
 
528
 
 
529
    return 0;
 
530
  }
 
531
 
 
532
 
 
533
  FT_BASE_DEF( FT_UShort )
 
534
  FT_Stream_ReadUShortLE( FT_Stream  stream,
 
535
                         FT_Error*  error )
 
536
  {
 
537
    FT_Byte   reads[2];
 
538
    FT_Byte*  p = 0;
 
539
    FT_Short  result = 0;
 
540
 
 
541
 
 
542
    FT_ASSERT( stream );
 
543
 
 
544
    *error = FT_Err_Ok;
 
545
 
 
546
    if ( stream->pos + 1 < stream->size )
 
547
    {
 
548
      if ( stream->read )
 
549
      {
 
550
        if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
 
551
          goto Fail;
 
552
 
 
553
        p = reads;
 
554
      }
 
555
      else
 
556
      {
 
557
        p = stream->base + stream->pos;
 
558
      }
 
559
 
 
560
      if ( p )
 
561
        result = FT_NEXT_USHORT_LE( p );
 
562
    }
 
563
    else
 
564
      goto Fail;
 
565
 
 
566
    stream->pos += 2;
 
567
 
 
568
    return result;
 
569
 
 
570
  Fail:
 
571
    *error = FT_Err_Invalid_Stream_Operation;
 
572
    FT_ERROR(( "FT_Stream_ReadUShortLE:"
 
573
               " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
 
574
               stream->pos, stream->size ));
 
575
 
 
576
    return 0;
 
577
  }
 
578
 
 
579
 
 
580
  FT_BASE_DEF( FT_ULong )
 
581
  FT_Stream_ReadUOffset( FT_Stream  stream,
 
582
                        FT_Error*  error )
 
583
  {
 
584
    FT_Byte   reads[3];
 
585
    FT_Byte*  p = 0;
 
586
    FT_Long   result = 0;
 
587
 
 
588
 
 
589
    FT_ASSERT( stream );
 
590
 
 
591
    *error = FT_Err_Ok;
 
592
 
 
593
    if ( stream->pos + 2 < stream->size )
 
594
    {
 
595
      if ( stream->read )
 
596
      {
 
597
        if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
 
598
          goto Fail;
 
599
 
 
600
        p = reads;
 
601
      }
 
602
      else
 
603
      {
 
604
        p = stream->base + stream->pos;
 
605
      }
 
606
 
 
607
      if ( p )
 
608
        result = FT_NEXT_UOFF3( p );
 
609
    }
 
610
    else
 
611
      goto Fail;
 
612
 
 
613
    stream->pos += 3;
 
614
 
 
615
    return result;
 
616
 
 
617
  Fail:
 
618
    *error = FT_Err_Invalid_Stream_Operation;
 
619
    FT_ERROR(( "FT_Stream_ReadUOffset:"
 
620
               " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
 
621
               stream->pos, stream->size ));
 
622
 
 
623
    return 0;
 
624
  }
 
625
 
 
626
 
 
627
  FT_BASE_DEF( FT_ULong )
 
628
  FT_Stream_ReadULong( FT_Stream  stream,
 
629
                      FT_Error*  error )
 
630
  {
 
631
    FT_Byte   reads[4];
 
632
    FT_Byte*  p = 0;
 
633
    FT_Long   result = 0;
 
634
 
 
635
 
 
636
    FT_ASSERT( stream );
 
637
 
 
638
    *error = FT_Err_Ok;
 
639
 
 
640
    if ( stream->pos + 3 < stream->size )
 
641
    {
 
642
      if ( stream->read )
 
643
      {
 
644
        if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
 
645
          goto Fail;
 
646
 
 
647
        p = reads;
 
648
      }
 
649
      else
 
650
      {
 
651
        p = stream->base + stream->pos;
 
652
      }
 
653
 
 
654
      if ( p )
 
655
        result = FT_NEXT_ULONG( p );
 
656
    }
 
657
    else
 
658
      goto Fail;
 
659
 
 
660
    stream->pos += 4;
 
661
 
 
662
    return result;
 
663
 
 
664
  Fail:
 
665
    *error = FT_Err_Invalid_Stream_Operation;
 
666
    FT_ERROR(( "FT_Stream_ReadULong:"
 
667
               " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
 
668
               stream->pos, stream->size ));
 
669
 
 
670
    return 0;
 
671
  }
 
672
 
 
673
 
 
674
  FT_BASE_DEF( FT_ULong )
 
675
  FT_Stream_ReadULongLE( FT_Stream  stream,
 
676
                        FT_Error*  error )
 
677
  {
 
678
    FT_Byte   reads[4];
 
679
    FT_Byte*  p = 0;
 
680
    FT_Long   result = 0;
 
681
 
 
682
 
 
683
    FT_ASSERT( stream );
 
684
 
 
685
    *error = FT_Err_Ok;
 
686
 
 
687
    if ( stream->pos + 3 < stream->size )
 
688
    {
 
689
      if ( stream->read )
 
690
      {
 
691
        if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
 
692
          goto Fail;
 
693
 
 
694
        p = reads;
 
695
      }
 
696
      else
 
697
      {
 
698
        p = stream->base + stream->pos;
 
699
      }
 
700
 
 
701
      if ( p )
 
702
        result = FT_NEXT_ULONG_LE( p );
 
703
    }
 
704
    else
 
705
      goto Fail;
 
706
 
 
707
    stream->pos += 4;
 
708
 
 
709
    return result;
 
710
 
 
711
  Fail:
 
712
    *error = FT_Err_Invalid_Stream_Operation;
 
713
    FT_ERROR(( "FT_Stream_ReadULongLE:"
 
714
               " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
 
715
               stream->pos, stream->size ));
 
716
 
 
717
    return 0;
 
718
  }
 
719
 
 
720
 
 
721
  FT_BASE_DEF( FT_Error )
 
722
  FT_Stream_ReadFields( FT_Stream              stream,
 
723
                        const FT_Frame_Field*  fields,
 
724
                        void*                  structure )
 
725
  {
 
726
    FT_Error  error;
 
727
    FT_Bool   frame_accessed = 0;
 
728
    FT_Byte*  cursor;
 
729
 
 
730
    if ( !fields || !stream )
 
731
      return FT_Err_Invalid_Argument;
 
732
 
 
733
    cursor = stream->cursor;
 
734
 
 
735
    error = FT_Err_Ok;
 
736
    do
 
737
    {
 
738
      FT_ULong  value;
 
739
      FT_Int    sign_shift;
 
740
      FT_Byte*  p;
 
741
 
 
742
 
 
743
      switch ( fields->value )
 
744
      {
 
745
      case ft_frame_start:  /* access a new frame */
 
746
        error = FT_Stream_EnterFrame( stream, fields->offset );
 
747
        if ( error )
 
748
          goto Exit;
 
749
 
 
750
        frame_accessed = 1;
 
751
        cursor         = stream->cursor;
 
752
        fields++;
 
753
        continue;  /* loop! */
 
754
 
 
755
      case ft_frame_bytes:  /* read a byte sequence */
 
756
      case ft_frame_skip:   /* skip some bytes      */
 
757
        {
 
758
          FT_UInt  len = fields->size;
 
759
 
 
760
 
 
761
          if ( cursor + len > stream->limit )
 
762
          {
 
763
            error = FT_Err_Invalid_Stream_Operation;
 
764
            goto Exit;
 
765
          }
 
766
 
 
767
          if ( fields->value == ft_frame_bytes )
 
768
          {
 
769
            p = (FT_Byte*)structure + fields->offset;
 
770
            FT_MEM_COPY( p, cursor, len );
 
771
          }
 
772
          cursor += len;
 
773
          fields++;
 
774
          continue;
 
775
        }
 
776
 
 
777
      case ft_frame_byte:
 
778
      case ft_frame_schar:  /* read a single byte */
 
779
        value = FT_NEXT_BYTE(cursor);
 
780
        sign_shift = 24;
 
781
        break;
 
782
 
 
783
      case ft_frame_short_be:
 
784
      case ft_frame_ushort_be:  /* read a 2-byte big-endian short */
 
785
        value = FT_NEXT_USHORT(cursor);
 
786
        sign_shift = 16;
 
787
        break;
 
788
 
 
789
      case ft_frame_short_le:
 
790
      case ft_frame_ushort_le:  /* read a 2-byte little-endian short */
 
791
        value = FT_NEXT_USHORT_LE(cursor);
 
792
        sign_shift = 16;
 
793
        break;
 
794
 
 
795
      case ft_frame_long_be:
 
796
      case ft_frame_ulong_be:  /* read a 4-byte big-endian long */
 
797
        value = FT_NEXT_ULONG(cursor);
 
798
        sign_shift = 0;
 
799
        break;
 
800
 
 
801
      case ft_frame_long_le:
 
802
      case ft_frame_ulong_le:  /* read a 4-byte little-endian long */
 
803
        value = FT_NEXT_ULONG_LE(cursor);
 
804
        sign_shift = 0;
 
805
        break;
 
806
 
 
807
      case ft_frame_off3_be:
 
808
      case ft_frame_uoff3_be:  /* read a 3-byte big-endian long */
 
809
        value = FT_NEXT_UOFF3(cursor);
 
810
        sign_shift = 8;
 
811
        break;
 
812
 
 
813
      case ft_frame_off3_le:
 
814
      case ft_frame_uoff3_le:  /* read a 3-byte little-endian long */
 
815
        value = FT_NEXT_UOFF3_LE(cursor);
 
816
        sign_shift = 8;
 
817
        break;
 
818
 
 
819
      default:
 
820
        /* otherwise, exit the loop */
 
821
        stream->cursor = cursor;
 
822
        goto Exit;
 
823
      }
 
824
 
 
825
      /* now, compute the signed value is necessary */
 
826
      if ( fields->value & FT_FRAME_OP_SIGNED )
 
827
        value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
 
828
 
 
829
      /* finally, store the value in the object */
 
830
 
 
831
      p = (FT_Byte*)structure + fields->offset;
 
832
      switch ( fields->size )
 
833
      {
 
834
      case (8 / FT_CHAR_BIT):
 
835
        *(FT_Byte*)p = (FT_Byte)value;
 
836
        break;
 
837
 
 
838
      case (16 / FT_CHAR_BIT):
 
839
        *(FT_UShort*)p = (FT_UShort)value;
 
840
        break;
 
841
 
 
842
      case (32 / FT_CHAR_BIT):
 
843
        *(FT_UInt32*)p = (FT_UInt32)value;
 
844
        break;
 
845
 
 
846
      default:  /* for 64-bit systems */
 
847
        *(FT_ULong*)p = (FT_ULong)value;
 
848
      }
 
849
 
 
850
      /* go to next field */
 
851
      fields++;
 
852
    }
 
853
    while ( 1 );
 
854
 
 
855
  Exit:
 
856
    /* close the frame if it was opened by this read */
 
857
    if ( frame_accessed )
 
858
      FT_Stream_ExitFrame( stream );
 
859
 
 
860
    return error;
 
861
  }
 
862
 
 
863
 
 
864
/* END */