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