1
/***************************************************************************/
5
/* I/O stream support (body). */
7
/* Copyright 2000-2002, 2004-2006, 2008-2011 by */
8
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16
/***************************************************************************/
20
#include FT_INTERNAL_STREAM_H
21
#include FT_INTERNAL_DEBUG_H
24
/*************************************************************************/
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. */
31
#define FT_COMPONENT trace_stream
35
FT_Stream_OpenMemory( FT_Stream stream,
39
stream->base = (FT_Byte*) base;
49
FT_Stream_Close( FT_Stream stream )
51
if ( stream && stream->close )
52
stream->close( stream );
56
FT_BASE_DEF( FT_Error )
57
FT_Stream_Seek( FT_Stream stream,
60
FT_Error error = FT_Err_Ok;
65
if ( stream->read( stream, pos, 0, 0 ) )
67
FT_ERROR(( "FT_Stream_Seek:"
68
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
71
error = FT_Err_Invalid_Stream_Operation;
74
/* note that seeking to the first position after the file is valid */
75
else if ( pos > stream->size )
77
FT_ERROR(( "FT_Stream_Seek:"
78
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
81
error = FT_Err_Invalid_Stream_Operation;
91
FT_BASE_DEF( FT_Error )
92
FT_Stream_Skip( FT_Stream stream,
96
return FT_Err_Invalid_Stream_Operation;
98
return FT_Stream_Seek( stream, (FT_ULong)( stream->pos + distance ) );
102
FT_BASE_DEF( FT_Long )
103
FT_Stream_Pos( FT_Stream stream )
109
FT_BASE_DEF( FT_Error )
110
FT_Stream_Read( FT_Stream stream,
114
return FT_Stream_ReadAt( stream, stream->pos, buffer, count );
118
FT_BASE_DEF( FT_Error )
119
FT_Stream_ReadAt( FT_Stream stream,
124
FT_Error error = FT_Err_Ok;
128
if ( pos >= stream->size )
130
FT_ERROR(( "FT_Stream_ReadAt:"
131
" invalid i/o; pos = 0x%lx, size = 0x%lx\n",
132
pos, stream->size ));
134
return FT_Err_Invalid_Stream_Operation;
138
read_bytes = stream->read( stream, pos, buffer, count );
141
read_bytes = stream->size - pos;
142
if ( read_bytes > count )
145
FT_MEM_COPY( buffer, stream->base + pos, read_bytes );
148
stream->pos = pos + read_bytes;
150
if ( read_bytes < count )
152
FT_ERROR(( "FT_Stream_ReadAt:"
153
" invalid read; expected %lu bytes, got %lu\n",
154
count, read_bytes ));
156
error = FT_Err_Invalid_Stream_Operation;
163
FT_BASE_DEF( FT_ULong )
164
FT_Stream_TryRead( FT_Stream stream,
168
FT_ULong read_bytes = 0;
171
if ( stream->pos >= stream->size )
175
read_bytes = stream->read( stream, stream->pos, buffer, count );
178
read_bytes = stream->size - stream->pos;
179
if ( read_bytes > count )
182
FT_MEM_COPY( buffer, stream->base + stream->pos, read_bytes );
185
stream->pos += read_bytes;
192
FT_BASE_DEF( FT_Error )
193
FT_Stream_ExtractFrame( FT_Stream stream,
200
error = FT_Stream_EnterFrame( stream, count );
203
*pbytes = (FT_Byte*)stream->cursor;
205
/* equivalent to FT_Stream_ExitFrame(), with no memory block release */
215
FT_Stream_ReleaseFrame( FT_Stream stream,
218
if ( stream && stream->read )
220
FT_Memory memory = stream->memory;
222
#ifdef FT_DEBUG_MEMORY
223
ft_mem_free( memory, *pbytes );
233
FT_BASE_DEF( FT_Error )
234
FT_Stream_EnterFrame( FT_Stream stream,
237
FT_Error error = FT_Err_Ok;
241
/* check for nested frame access */
242
FT_ASSERT( stream && stream->cursor == 0 );
246
/* allocate the frame in memory */
247
FT_Memory memory = stream->memory;
250
/* simple sanity check */
251
if ( count > stream->size )
253
FT_ERROR(( "FT_Stream_EnterFrame:"
254
" frame size (%lu) larger than stream size (%lu)\n",
255
count, stream->size ));
257
error = FT_Err_Invalid_Stream_Operation;
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 );
267
if ( FT_QALLOC( stream->base, count ) )
271
read_bytes = stream->read( stream, stream->pos,
272
stream->base, count );
273
if ( read_bytes < count )
275
FT_ERROR(( "FT_Stream_EnterFrame:"
276
" invalid read; expected %lu bytes, got %lu\n",
277
count, read_bytes ));
279
FT_FREE( stream->base );
280
error = FT_Err_Invalid_Stream_Operation;
282
stream->cursor = stream->base;
283
stream->limit = stream->cursor + count;
284
stream->pos += read_bytes;
288
/* check current and new position */
289
if ( stream->pos >= stream->size ||
290
stream->size - stream->pos < count )
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 ));
296
error = FT_Err_Invalid_Stream_Operation;
301
stream->cursor = stream->base + stream->pos;
302
stream->limit = stream->cursor + count;
303
stream->pos += count;
312
FT_Stream_ExitFrame( FT_Stream stream )
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). */
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. */
327
FT_Memory memory = stream->memory;
329
#ifdef FT_DEBUG_MEMORY
330
ft_mem_free( memory, stream->base );
333
FT_FREE( stream->base );
341
FT_BASE_DEF( FT_Char )
342
FT_Stream_GetChar( FT_Stream stream )
347
FT_ASSERT( stream && stream->cursor );
350
if ( stream->cursor < stream->limit )
351
result = *stream->cursor++;
357
FT_BASE_DEF( FT_UShort )
358
FT_Stream_GetUShort( FT_Stream stream )
364
FT_ASSERT( stream && stream->cursor );
368
if ( p + 1 < stream->limit )
369
result = FT_NEXT_USHORT( p );
376
FT_BASE_DEF( FT_UShort )
377
FT_Stream_GetUShortLE( FT_Stream stream )
383
FT_ASSERT( stream && stream->cursor );
387
if ( p + 1 < stream->limit )
388
result = FT_NEXT_USHORT_LE( p );
395
FT_BASE_DEF( FT_ULong )
396
FT_Stream_GetUOffset( FT_Stream stream )
402
FT_ASSERT( stream && stream->cursor );
406
if ( p + 2 < stream->limit )
407
result = FT_NEXT_UOFF3( p );
413
FT_BASE_DEF( FT_ULong )
414
FT_Stream_GetULong( FT_Stream stream )
420
FT_ASSERT( stream && stream->cursor );
424
if ( p + 3 < stream->limit )
425
result = FT_NEXT_ULONG( p );
431
FT_BASE_DEF( FT_ULong )
432
FT_Stream_GetULongLE( FT_Stream stream )
438
FT_ASSERT( stream && stream->cursor );
442
if ( p + 3 < stream->limit )
443
result = FT_NEXT_ULONG_LE( p );
449
FT_BASE_DEF( FT_Char )
450
FT_Stream_ReadChar( FT_Stream stream,
462
if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
467
if ( stream->pos < stream->size )
468
result = stream->base[stream->pos];
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 ));
486
FT_BASE_DEF( FT_UShort )
487
FT_Stream_ReadUShort( FT_Stream stream,
499
if ( stream->pos + 1 < stream->size )
503
if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
510
p = stream->base + stream->pos;
514
result = FT_NEXT_USHORT( p );
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 ));
533
FT_BASE_DEF( FT_UShort )
534
FT_Stream_ReadUShortLE( FT_Stream stream,
546
if ( stream->pos + 1 < stream->size )
550
if ( stream->read( stream, stream->pos, reads, 2L ) != 2L )
557
p = stream->base + stream->pos;
561
result = FT_NEXT_USHORT_LE( p );
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 ));
580
FT_BASE_DEF( FT_ULong )
581
FT_Stream_ReadUOffset( FT_Stream stream,
593
if ( stream->pos + 2 < stream->size )
597
if (stream->read( stream, stream->pos, reads, 3L ) != 3L )
604
p = stream->base + stream->pos;
608
result = FT_NEXT_UOFF3( p );
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 ));
627
FT_BASE_DEF( FT_ULong )
628
FT_Stream_ReadULong( FT_Stream stream,
640
if ( stream->pos + 3 < stream->size )
644
if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
651
p = stream->base + stream->pos;
655
result = FT_NEXT_ULONG( p );
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 ));
674
FT_BASE_DEF( FT_ULong )
675
FT_Stream_ReadULongLE( FT_Stream stream,
687
if ( stream->pos + 3 < stream->size )
691
if ( stream->read( stream, stream->pos, reads, 4L ) != 4L )
698
p = stream->base + stream->pos;
702
result = FT_NEXT_ULONG_LE( p );
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 ));
721
FT_BASE_DEF( FT_Error )
722
FT_Stream_ReadFields( FT_Stream stream,
723
const FT_Frame_Field* fields,
727
FT_Bool frame_accessed = 0;
730
if ( !fields || !stream )
731
return FT_Err_Invalid_Argument;
733
cursor = stream->cursor;
743
switch ( fields->value )
745
case ft_frame_start: /* access a new frame */
746
error = FT_Stream_EnterFrame( stream, fields->offset );
751
cursor = stream->cursor;
753
continue; /* loop! */
755
case ft_frame_bytes: /* read a byte sequence */
756
case ft_frame_skip: /* skip some bytes */
758
FT_UInt len = fields->size;
761
if ( cursor + len > stream->limit )
763
error = FT_Err_Invalid_Stream_Operation;
767
if ( fields->value == ft_frame_bytes )
769
p = (FT_Byte*)structure + fields->offset;
770
FT_MEM_COPY( p, cursor, len );
778
case ft_frame_schar: /* read a single byte */
779
value = FT_NEXT_BYTE(cursor);
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);
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);
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);
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);
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);
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);
820
/* otherwise, exit the loop */
821
stream->cursor = cursor;
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 );
829
/* finally, store the value in the object */
831
p = (FT_Byte*)structure + fields->offset;
832
switch ( fields->size )
834
case (8 / FT_CHAR_BIT):
835
*(FT_Byte*)p = (FT_Byte)value;
838
case (16 / FT_CHAR_BIT):
839
*(FT_UShort*)p = (FT_UShort)value;
842
case (32 / FT_CHAR_BIT):
843
*(FT_UInt32*)p = (FT_UInt32)value;
846
default: /* for 64-bit systems */
847
*(FT_ULong*)p = (FT_ULong)value;
850
/* go to next field */
856
/* close the frame if it was opened by this read */
857
if ( frame_accessed )
858
FT_Stream_ExitFrame( stream );