Took out i18n from Documentor until we have our own gettext, too much of a hassle...
[sdk] / deps / freetype-2.3.5 / src / base / ftstream.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ftstream.c                                                             */
4 /*                                                                         */
5 /*    I/O stream support (body).                                           */
6 /*                                                                         */
7 /*  Copyright 2000-2001, 2002, 2004, 2005, 2006 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 #ifdef FT_DEBUG_MEMORY
216       ft_mem_free( memory, *pbytes );
217       *pbytes = NULL;
218 #else
219       FT_FREE( *pbytes );
220 #endif
221     }
222     *pbytes = 0;
223   }
224
225
226   FT_BASE_DEF( FT_Error )
227   FT_Stream_EnterFrame( FT_Stream  stream,
228                         FT_ULong   count )
229   {
230     FT_Error  error = FT_Err_Ok;
231     FT_ULong  read_bytes;
232
233
234     /* check for nested frame access */
235     FT_ASSERT( stream && stream->cursor == 0 );
236
237     if ( stream->read )
238     {
239       /* allocate the frame in memory */
240       FT_Memory  memory = stream->memory;
241
242 #ifdef FT_DEBUG_MEMORY
243       /* assume _ft_debug_file and _ft_debug_lineno are already set */
244       stream->base = (unsigned char*)ft_mem_qalloc( memory, count, &error );
245       if ( error )
246         goto Exit;
247 #else
248       if ( FT_QALLOC( stream->base, count ) )
249         goto Exit;
250 #endif
251       /* read it */
252       read_bytes = stream->read( stream, stream->pos,
253                                  stream->base, count );
254       if ( read_bytes < count )
255       {
256         FT_ERROR(( "FT_Stream_EnterFrame:" ));
257         FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n",
258                    count, read_bytes ));
259
260         FT_FREE( stream->base );
261         error = FT_Err_Invalid_Stream_Operation;
262       }
263       stream->cursor = stream->base;
264       stream->limit  = stream->cursor + count;
265       stream->pos   += read_bytes;
266     }
267     else
268     {
269       /* check current and new position */
270       if ( stream->pos >= stream->size        ||
271            stream->pos + count > stream->size )
272       {
273         FT_ERROR(( "FT_Stream_EnterFrame:" ));
274         FT_ERROR(( " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
275                    stream->pos, count, stream->size ));
276
277         error = FT_Err_Invalid_Stream_Operation;
278         goto Exit;
279       }
280
281       /* set cursor */
282       stream->cursor = stream->base + stream->pos;
283       stream->limit  = stream->cursor + count;
284       stream->pos   += count;
285     }
286
287   Exit:
288     return error;
289   }
290
291
292   FT_BASE_DEF( void )
293   FT_Stream_ExitFrame( FT_Stream  stream )
294   {
295     /* IMPORTANT: The assertion stream->cursor != 0 was removed, given    */
296     /*            that it is possible to access a frame of length 0 in    */
297     /*            some weird fonts (usually, when accessing an array of   */
298     /*            0 records, like in some strange kern tables).           */
299     /*                                                                    */
300     /*  In this case, the loader code handles the 0-length table          */
301     /*  gracefully; however, stream.cursor is really set to 0 by the      */
302     /*  FT_Stream_EnterFrame() call, and this is not an error.            */
303     /*                                                                    */
304     FT_ASSERT( stream );
305
306     if ( stream->read )
307     {
308       FT_Memory  memory = stream->memory;
309
310 #ifdef FT_DEBUG_MEMORY
311       ft_mem_free( memory, stream->base );
312       stream->base = NULL;
313 #else
314       FT_FREE( stream->base );
315 #endif
316     }
317     stream->cursor = 0;
318     stream->limit  = 0;
319   }
320
321
322   FT_BASE_DEF( FT_Char )
323   FT_Stream_GetChar( FT_Stream  stream )
324   {
325     FT_Char  result;
326
327
328     FT_ASSERT( stream && stream->cursor );
329
330     result = 0;
331     if ( stream->cursor < stream->limit )
332       result = *stream->cursor++;
333
334     return result;
335   }
336
337
338   FT_BASE_DEF( FT_Short )
339   FT_Stream_GetShort( FT_Stream  stream )
340   {
341     FT_Byte*  p;
342     FT_Short  result;
343
344
345     FT_ASSERT( stream && stream->cursor );
346
347     result         = 0;
348     p              = stream->cursor;
349     if ( p + 1 < stream->limit )
350       result       = FT_NEXT_SHORT( p );
351     stream->cursor = p;
352
353     return result;
354   }
355
356
357   FT_BASE_DEF( FT_Short )
358   FT_Stream_GetShortLE( 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_SHORT_LE( p );
370     stream->cursor = p;
371
372     return result;
373   }
374
375
376   FT_BASE_DEF( FT_Long )
377   FT_Stream_GetOffset( FT_Stream  stream )
378   {
379     FT_Byte*  p;
380     FT_Long   result;
381
382
383     FT_ASSERT( stream && stream->cursor );
384
385     result         = 0;
386     p              = stream->cursor;
387     if ( p + 2 < stream->limit )
388       result       = FT_NEXT_OFF3( p );
389     stream->cursor = p;
390     return result;
391   }
392
393
394   FT_BASE_DEF( FT_Long )
395   FT_Stream_GetLong( FT_Stream  stream )
396   {
397     FT_Byte*  p;
398     FT_Long   result;
399
400
401     FT_ASSERT( stream && stream->cursor );
402
403     result         = 0;
404     p              = stream->cursor;
405     if ( p + 3 < stream->limit )
406       result       = FT_NEXT_LONG( p );
407     stream->cursor = p;
408     return result;
409   }
410
411
412   FT_BASE_DEF( FT_Long )
413   FT_Stream_GetLongLE( FT_Stream  stream )
414   {
415     FT_Byte*  p;
416     FT_Long   result;
417
418
419     FT_ASSERT( stream && stream->cursor );
420
421     result         = 0;
422     p              = stream->cursor;
423     if ( p + 3 < stream->limit )
424       result       = FT_NEXT_LONG_LE( p );
425     stream->cursor = p;
426     return result;
427   }
428
429
430   FT_BASE_DEF( FT_Char )
431   FT_Stream_ReadChar( FT_Stream  stream,
432                       FT_Error*  error )
433   {
434     FT_Byte  result = 0;
435
436
437     FT_ASSERT( stream );
438
439     *error = FT_Err_Ok;
440
441     if ( stream->read )
442     {
443       if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
444         goto Fail;
445     }
446     else
447     {
448       if ( stream->pos < stream->size )
449         result = stream->base[stream->pos];
450       else
451         goto Fail;
452     }
453     stream->pos++;
454
455     return result;
456
457   Fail:
458     *error = FT_Err_Invalid_Stream_Operation;
459     FT_ERROR(( "FT_Stream_ReadChar: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
460                stream->pos, stream->size ));
461
462     return 0;
463   }
464
465
466   FT_BASE_DEF( FT_Short )
467   FT_Stream_ReadShort( FT_Stream  stream,
468                        FT_Error*  error )
469   {
470     FT_Byte   reads[2];
471     FT_Byte*  p = 0;
472     FT_Short  result = 0;
473
474
475     FT_ASSERT( stream );
476
477     *error = FT_Err_Ok;
478
479     if ( stream->pos + 1 < stream->size )
480     {
481       if ( stream->read )
482       {
483         if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
484           goto Fail;
485
486         p = reads;
487       }
488       else
489       {
490         p = stream->base + stream->pos;
491       }
492
493       if ( p )
494         result = FT_NEXT_SHORT( p );
495     }
496     else
497       goto Fail;
498
499     stream->pos += 2;
500
501     return result;
502
503   Fail:
504     *error = FT_Err_Invalid_Stream_Operation;
505     FT_ERROR(( "FT_Stream_ReadShort:" ));
506     FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
507                stream->pos, stream->size ));
508
509     return 0;
510   }
511
512
513   FT_BASE_DEF( FT_Short )
514   FT_Stream_ReadShortLE( FT_Stream  stream,
515                          FT_Error*  error )
516   {
517     FT_Byte   reads[2];
518     FT_Byte*  p = 0;
519     FT_Short  result = 0;
520
521
522     FT_ASSERT( stream );
523
524     *error = FT_Err_Ok;
525
526     if ( stream->pos + 1 < stream->size )
527     {
528       if ( stream->read )
529       {
530         if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
531           goto Fail;
532
533         p = reads;
534       }
535       else
536       {
537         p = stream->base + stream->pos;
538       }
539
540       if ( p )
541         result = FT_NEXT_SHORT_LE( p );
542     }
543     else
544       goto Fail;
545
546     stream->pos += 2;
547
548     return result;
549
550   Fail:
551     *error = FT_Err_Invalid_Stream_Operation;
552     FT_ERROR(( "FT_Stream_ReadShortLE:" ));
553     FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
554                stream->pos, stream->size ));
555
556     return 0;
557   }
558
559
560   FT_BASE_DEF( FT_Long )
561   FT_Stream_ReadOffset( FT_Stream  stream,
562                         FT_Error*  error )
563   {
564     FT_Byte   reads[3];
565     FT_Byte*  p = 0;
566     FT_Long   result = 0;
567
568
569     FT_ASSERT( stream );
570
571     *error = FT_Err_Ok;
572
573     if ( stream->pos + 2 < stream->size )
574     {
575       if ( stream->read )
576       {
577         if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
578           goto Fail;
579
580         p = reads;
581       }
582       else
583       {
584         p = stream->base + stream->pos;
585       }
586
587       if ( p )
588         result = FT_NEXT_OFF3( p );
589     }
590     else
591       goto Fail;
592
593     stream->pos += 3;
594
595     return result;
596
597   Fail:
598     *error = FT_Err_Invalid_Stream_Operation;
599     FT_ERROR(( "FT_Stream_ReadOffset:" ));
600     FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
601                stream->pos, stream->size ));
602
603     return 0;
604   }
605
606
607   FT_BASE_DEF( FT_Long )
608   FT_Stream_ReadLong( FT_Stream  stream,
609                       FT_Error*  error )
610   {
611     FT_Byte   reads[4];
612     FT_Byte*  p = 0;
613     FT_Long   result = 0;
614
615
616     FT_ASSERT( stream );
617
618     *error = FT_Err_Ok;
619
620     if ( stream->pos + 3 < stream->size )
621     {
622       if ( stream->read )
623       {
624         if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
625           goto Fail;
626
627         p = reads;
628       }
629       else
630       {
631         p = stream->base + stream->pos;
632       }
633
634       if ( p )
635         result = FT_NEXT_LONG( p );
636     }
637     else
638       goto Fail;
639
640     stream->pos += 4;
641
642     return result;
643
644   Fail:
645     FT_ERROR(( "FT_Stream_ReadLong: invalid i/o; pos = 0x%lx, size = 0x%lx\n",
646                stream->pos, stream->size ));
647     *error = FT_Err_Invalid_Stream_Operation;
648
649     return 0;
650   }
651
652
653   FT_BASE_DEF( FT_Long )
654   FT_Stream_ReadLongLE( FT_Stream  stream,
655                         FT_Error*  error )
656   {
657     FT_Byte   reads[4];
658     FT_Byte*  p = 0;
659     FT_Long   result = 0;
660
661
662     FT_ASSERT( stream );
663
664     *error = FT_Err_Ok;
665
666     if ( stream->pos + 3 < stream->size )
667     {
668       if ( stream->read )
669       {
670         if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
671           goto Fail;
672
673         p = reads;
674       }
675       else
676       {
677         p = stream->base + stream->pos;
678       }
679
680       if ( p )
681         result = FT_NEXT_LONG_LE( p );
682     }
683     else
684       goto Fail;
685
686     stream->pos += 4;
687
688     return result;
689
690   Fail:
691     FT_ERROR(( "FT_Stream_ReadLongLE:" ));
692     FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
693                stream->pos, stream->size ));
694     *error = FT_Err_Invalid_Stream_Operation;
695
696     return 0;
697   }
698
699
700   FT_BASE_DEF( FT_Error )
701   FT_Stream_ReadFields( FT_Stream              stream,
702                         const FT_Frame_Field*  fields,
703                         void*                  structure )
704   {
705     FT_Error  error;
706     FT_Bool   frame_accessed = 0;
707     FT_Byte*  cursor = stream->cursor;
708
709
710     if ( !fields || !stream )
711       return FT_Err_Invalid_Argument;
712
713     error = FT_Err_Ok;
714     do
715     {
716       FT_ULong  value;
717       FT_Int    sign_shift;
718       FT_Byte*  p;
719
720
721       switch ( fields->value )
722       {
723       case ft_frame_start:  /* access a new frame */
724         error = FT_Stream_EnterFrame( stream, fields->offset );
725         if ( error )
726           goto Exit;
727
728         frame_accessed = 1;
729         cursor         = stream->cursor;
730         fields++;
731         continue;  /* loop! */
732
733       case ft_frame_bytes:  /* read a byte sequence */
734       case ft_frame_skip:   /* skip some bytes      */
735         {
736           FT_UInt  len = fields->size;
737
738
739           if ( cursor + len > stream->limit )
740           {
741             error = FT_Err_Invalid_Stream_Operation;
742             goto Exit;
743           }
744
745           if ( fields->value == ft_frame_bytes )
746           {
747             p = (FT_Byte*)structure + fields->offset;
748             FT_MEM_COPY( p, cursor, len );
749           }
750           cursor += len;
751           fields++;
752           continue;
753         }
754
755       case ft_frame_byte:
756       case ft_frame_schar:  /* read a single byte */
757         value = FT_NEXT_BYTE(cursor);
758         sign_shift = 24;
759         break;
760
761       case ft_frame_short_be:
762       case ft_frame_ushort_be:  /* read a 2-byte big-endian short */
763         value = FT_NEXT_USHORT(cursor);
764         sign_shift = 16;
765         break;
766
767       case ft_frame_short_le:
768       case ft_frame_ushort_le:  /* read a 2-byte little-endian short */
769         value = FT_NEXT_USHORT_LE(cursor);
770         sign_shift = 16;
771         break;
772
773       case ft_frame_long_be:
774       case ft_frame_ulong_be:  /* read a 4-byte big-endian long */
775         value = FT_NEXT_ULONG(cursor);
776         sign_shift = 0;
777         break;
778
779       case ft_frame_long_le:
780       case ft_frame_ulong_le:  /* read a 4-byte little-endian long */
781         value = FT_NEXT_ULONG_LE(cursor);
782         sign_shift = 0;
783         break;
784
785       case ft_frame_off3_be:
786       case ft_frame_uoff3_be:  /* read a 3-byte big-endian long */
787         value = FT_NEXT_UOFF3(cursor);
788         sign_shift = 8;
789         break;
790
791       case ft_frame_off3_le:
792       case ft_frame_uoff3_le:  /* read a 3-byte little-endian long */
793         value = FT_NEXT_UOFF3_LE(cursor);
794         sign_shift = 8;
795         break;
796
797       default:
798         /* otherwise, exit the loop */
799         stream->cursor = cursor;
800         goto Exit;
801       }
802
803       /* now, compute the signed value is necessary */
804       if ( fields->value & FT_FRAME_OP_SIGNED )
805         value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
806
807       /* finally, store the value in the object */
808
809       p = (FT_Byte*)structure + fields->offset;
810       switch ( fields->size )
811       {
812       case (8 / FT_CHAR_BIT):
813         *(FT_Byte*)p = (FT_Byte)value;
814         break;
815
816       case (16 / FT_CHAR_BIT):
817         *(FT_UShort*)p = (FT_UShort)value;
818         break;
819
820       case (32 / FT_CHAR_BIT):
821         *(FT_UInt32*)p = (FT_UInt32)value;
822         break;
823
824       default:  /* for 64-bit systems */
825         *(FT_ULong*)p = (FT_ULong)value;
826       }
827
828       /* go to next field */
829       fields++;
830     }
831     while ( 1 );
832
833   Exit:
834     /* close the frame if it was opened by this read */
835     if ( frame_accessed )
836       FT_Stream_ExitFrame( stream );
837
838     return error;
839   }
840
841
842 /* END */