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