source: trunk/poppler/freetype-2.1.10/src/base/ftstream.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 15 years ago

First import

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