home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: SysTools / SysTools.zip / ft-beta.zip / freetype / lib / ttfile.c < prev    next >
C/C++ Source or Header  |  1997-10-06  |  26KB  |  903 lines

  1. /*******************************************************************
  2.  *
  3.  *  ttfile.c                                                     1.3
  4.  *
  5.  *    File I/O Component (body).
  6.  *
  7.  *  Copyright 1996, 1997 by
  8.  *  David Turner, Robert Wilhelm, and Werner Lemberg
  9.  *
  10.  *  This file is part of the FreeType project, and may only be used
  11.  *  modified and distributed under the terms of the FreeType project
  12.  *  license, LICENSE.TXT. By continuing to use, modify or distribute
  13.  *  this file you indicate that you have read the license and
  14.  *  understand and accept it fully.
  15.  *
  16.  *  NOTES :
  17.  *
  18.  *   This implementation relies on the ANSI libc. You may wish to
  19.  *   modify it to get rid of the libc and go straight to the your
  20.  *   platform's stream routines.
  21.  *
  22.  *   The same source code can be used for thread-safe and re-entrant
  23.  *   builds of the library.
  24.  *
  25.  *  Changes between 1.3 and 1.2 :
  26.  *
  27.  *  - all functions report error values now
  28.  *
  29.  *  - the stream semantics have also changed
  30.  *
  31.  ******************************************************************/
  32.  
  33. const char  _ttfile_to_satisfy_ANSI_C_[] = "";
  34. /* ANSI C prevents the compilation of empty units. We thus introduce */
  35. /* a dummy external to get rid of compiler warnings/errors.          */
  36. /* Note that gcc's -ansi -pedantic do not report any error here..    */
  37. /* Watcom, VC++ or Borland C++ do however..                          */
  38.  
  39. #include "ttconfig.h"
  40.  
  41. #ifndef HAVE_MMAP
  42.  
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46.  
  47. #ifdef HAVE_UNISTD_H
  48. #include <unistd.h>
  49. #endif
  50.  
  51. #include "freetype.h"
  52. #include "tttypes.h"
  53. #include "tterror.h"
  54. #include "ttengine.h"
  55. #include "ttmutex.h"
  56. #include "ttmemory.h"
  57. #include "ttfile.h"     /* our prototypes */
  58.  
  59. const TFileFrame  Null_FileFrame = { NULL, 0, 0 };
  60. /* This definition is mandatory for each file component !! */
  61.  
  62. /* It has proven useful to do some bounds checks during
  63.    development phase.
  64.    The should propably be undefined for speed reasons
  65.    in a later release. */
  66.  
  67. #define CHECK_FRAME(frame, n)                         \
  68.   do {                                                \
  69.     if (frame.cursor+n > frame.address+frame.size)    \
  70.       Panic("Frame boundary error!\n");               \
  71.   } while (0)
  72.   
  73.  
  74.   #define FRAME_CACHE_SIZE  2048
  75.   /* in non-rentrant builds, we allocate a single block where we'll  */
  76.   /* place all the frames smaller than FRAME_CACHE_SIZE, rather than */
  77.   /* allocating a new block on each access. Bigger frames will be    */
  78.   /* malloced normally in the heap..                                 */
  79.   /*                                                                 */
  80.   /* See TT_Access_Frame and TT_Forget_Frame for details..           */
  81.   /*                                                                 */
  82.  
  83.   #define MAX_FONT_PATHNAME 128
  84.  
  85.   typedef struct _TStream_Rec
  86.   {
  87.     FILE*      file;    /* file handle */
  88.     Long       base;    /* stream base in file */
  89.     Long       size;    /* stream size in file */
  90.  
  91. #ifdef TT_CONFIG_REENTRANT
  92.     char    path[ MAX_FONT_PATHNAME ];  /* current pathname */
  93. #endif
  94.  
  95.   } TStream_Rec;
  96.   /* we support embedded TrueType files by allowing them to be   */
  97.   /* inside any file, at any location, hence the 'base' argument */
  98.  
  99.   /* note however that the current implementation does not allow you */
  100.   /* to specify a 'base' index when opening a file.                  */
  101.   /* (will come later)                                               */
  102.  
  103.   /* I still don't know if this will turn out useful ??   - DavidT */
  104.  
  105.   /* note also that the only reason to keep the stream's pathname is   */
  106.   /* the fact that the ANSI libc seems to lack a function to duplicate */
  107.   /* FILE structures. We need several streams to access the same font  */
  108.   /* file in a re-entrant build, and we're obliged to re-open the same */
  109.   /* font file to get a new valid FILE* !! Ugly but portable..         */
  110.  
  111.   typedef TStream_Rec*  PStream_Rec;
  112.  
  113. #define STREAM2REC(x)  ((TStream_Rec*)( (x).z ))
  114.  
  115.   /* The TFile_Component structure holds all the data that was */
  116.   /* previously declared static or global in this component    */
  117.   /*                                                           */
  118.   /* It is accessible through the 'engine.file_component'      */
  119.   /* variable in re-entrant builds, or directly through the    */
  120.   /* static 'files' variable in other builds                   */
  121.   /*                                                           */
  122.  
  123.   struct _TFile_Component
  124.   {
  125.  
  126.     TT_Error        dummy_error;
  127.  
  128. #ifndef TT_CONFIG_REENTRANT
  129.  
  130.     TMutex          lock;        /* used by the thread-safe build only */
  131.  
  132.     unsigned char*  frame_cache; /* frame cache     */
  133.     PStream_Rec     stream;      /* current stream  */
  134.     TFileFrame      frame;       /* current frame   */
  135.  
  136. #endif /* reentrant */
  137.   };
  138.  
  139.   typedef struct _TFile_Component  TFile_Component;
  140.  
  141.  
  142. #ifdef TT_CONFIG_REENTRANT
  143.  
  144.   #define files (*((TFile_Component*)engine.file_component))
  145.   /* a simple macro to access the file component's data */
  146.  
  147.   #define CUR_Stream   STREAM2REC(stream)      /* re-entrant macros */
  148.   #define CUR_Frame    (*frame)
  149.  
  150.   #define STREAM_VARS  stream,
  151.   #define STREAM_VAR   stream
  152.  
  153. #else
  154.  
  155.   #define CUR_Stream   files.stream            /* thread-safe macros */
  156.   #define CUR_Frame    files.frame
  157.  
  158.   #define STREAM_VARS  /* void */
  159.   #define STREAM_VAR   /* void */
  160.   
  161.   static TFile_Component  files;
  162.   /* the 'files' variable is only defined in non-reentrant builds */
  163.  
  164. #endif /* REENTRANT */
  165.  
  166.   /* The macro CUR_Stream denotes the current input stream             */
  167.   /* Note that for the re-entrant version, the 'stream' name has been  */
  168.   /* chosen according to the macro STREAM_ARGS                           */
  169.  
  170.   /* The macro CUR_Frame denotes the current file frame               */
  171.   /* Note that for the re-entrant version, the 'frame' name has been  */
  172.   /* chosen according to the macro FRAME_ARGS                         */
  173.  
  174.   /* The macro STREAM_VAR is used when calling public functions */
  175.   /* that need an 'optional' stream argument                    */
  176.  
  177. /*******************************************************************
  178.  *
  179.  *  Function    :  TTFile_Init
  180.  *
  181.  *  Description :  Init the File component
  182.  *
  183.  ******************************************************************/
  184.  
  185.  TT_Error TTFile_Init()
  186.  {
  187.    TT_Error  error;
  188.  
  189. #ifdef TT_CONFIG_REENTRANT
  190.  
  191.    /* in re-entrant builds, we  need  to allocate the file component */
  192.    /* data on the fly before anything else..                         */
  193.    if ( ALLOC( engine.file_component, sizeof(TFile_Component) ))
  194.      return error;
  195.  
  196. #else  /* non re-entrant builds */
  197.  
  198.    engine.file_component = (void*)&files;
  199.  
  200.    MUTEX_Create( files.lock );
  201.  
  202.    files.stream = NULL;
  203.    ZERO_Frame( files.frame );
  204.  
  205.    if ( ALLOC( files.frame_cache, FRAME_CACHE_SIZE ) )
  206.      return error;
  207.  
  208. #endif
  209.  
  210.    files.dummy_error = TT_Err_Ok;
  211.  
  212.    return TT_Err_Ok;
  213.  }
  214.  
  215. /*******************************************************************
  216.  *
  217.  *  Function    :  TTFile_Done
  218.  *
  219.  *  Description :  Finalize the File component
  220.  *
  221.  ******************************************************************/
  222.  
  223.  TT_Error  TTFile_Done()
  224.  {
  225.  
  226. #ifndef TT_CONFIG_REENTRANT
  227.  
  228.    FREE( files.frame_cache );
  229.    MUTEX_Destroy( files.lock );
  230.  
  231.    engine.file_component = NULL;
  232.  
  233. #else
  234.  
  235.    FREE( engine.file_component );
  236.  
  237. #endif
  238.  
  239.    return TT_Err_Ok;
  240.  }
  241.  
  242.  
  243. /*******************************************************************
  244.  *
  245.  *  Function    :  TT_Open_Stream
  246.  *
  247.  *  Description :  opens the font file and saves the total file size.
  248.  *
  249.  *  Input  :  error          address of stream's error variable
  250.  *                           ( re-entrant build only ).
  251.  *
  252.  *            filepathname   pathname of the file to open
  253.  *            stream         address of target TT_Stream structure
  254.  *
  255.  *
  256.  *  Output :  SUCCESS on sucess, FAILURE on error.
  257.  *            The target stream is set to -1 in case of failure.
  258.  *
  259.  *
  260.  ******************************************************************/
  261.  
  262.   TT_Error  TT_Open_Stream( const char*  filepathname, 
  263.                             TT_Stream*   stream )
  264.   {
  265.     TT_Error     error;
  266.     FILE*        font_file;
  267.     PStream_Rec  stream_rec;
  268.  
  269.     if ( ALLOC( *stream, sizeof(TStream_Rec) ) )
  270.       return error;
  271.  
  272.     stream_rec = STREAM2REC(*stream);
  273.  
  274.     if ( !( font_file = fopen( filepathname, "rb" ) ) )
  275.     {
  276.       FREE( stream_rec );
  277.       return TT_Err_Could_Not_Open_File;
  278.     }
  279.  
  280.     stream_rec->base = 0;
  281.     stream_rec->file = font_file;
  282.  
  283.     fseek( font_file, 0, SEEK_END );
  284.     stream_rec->size = ftell( font_file );
  285.     fseek( font_file, 0, SEEK_SET );
  286.  
  287. #ifdef TT_CONFIG_REENTRANT
  288.     /* duplicate the font path name, as there is no 100% standard & */
  289.     /* portable way to re-open a FILE other than by re-opening it   */
  290.     strncpy( stream_rec->path, filepathname, MAX_FONT_PATHNAME-1 );
  291.     stream_rec->path[ MAX_FONT_PATHNAME ] = '\0';
  292. #else
  293.     CUR_Stream = stream_rec;
  294. #endif
  295.  
  296.     return TT_Err_Ok;
  297.   }
  298.  
  299.  
  300.  
  301. #ifdef TT_CONFIG_REENTRANT
  302.  
  303. /*******************************************************************
  304.  *
  305.  *  Function    :  TT_Duplicate_Stream
  306.  *
  307.  *  Description :  Duplicate a stream for a new instance record
  308.  *
  309.  *  Input  :  input_stream   source stream to duplicate
  310.  *            copy           address of target duplicate stream
  311.  *            error          error of duplicate's error variable
  312.  *
  313.  *  Output :  SUCCESS on sucess, FAILURE on error.
  314.  *            The target stream is set to -1 in case of failure.
  315.  *
  316.  *  Note : This function is only available to re-entrant builds of
  317.  *         the engine. Note that we kept a font pathname in the
  318.  *         stream structure because we like an ANSI function to
  319.  *         duplicate FILE structures conveniently.
  320.  *
  321.  ******************************************************************/
  322.  
  323.   TT_Error  TT_Duplicate_Stream( TT_Stream   input_stream,
  324.                                  TT_Stream*  copy )
  325.   {
  326.     TT_Error     error;
  327.     FILE*        font_file;
  328.     PStream_Rec  stream_rec;
  329.     PStream_Rec  copy_rec;
  330.  
  331.     stream_rec = STREAM2REC(input_stream);
  332.  
  333.     if ( ALLOC( copy_rec, sizeof(TStream_Rec) ) )
  334.       return error;
  335.  
  336.     HANDLE_Set( *copy, copy_rec );
  337.  
  338.     if ( !( font_file = fopen( stream_rec->path, "rb" ) ) )
  339.     {
  340.       FREE( copy_rec );
  341.       return TT_Err_Could_Not_Open_File;
  342.     }
  343.  
  344.     copy_rec->base  = stream_rec->base;
  345.     copy_rec->size  = stream_rec->size;
  346.     copy_rec->file  = font_file;
  347.  
  348.     strncpy( copy_rec->path, stream_rec->path, MAX_FONT_PATHNAME-1 );
  349.     stream_rec->path[ MAX_FONT_PATHNAME ] = '\0';
  350.  
  351.     return TT_Err_Ok;
  352.   }
  353.  
  354. #endif /* REENTRANT */
  355.  
  356.  
  357. /*******************************************************************
  358.  *
  359.  *  Function    : TT_Close_Stream
  360.  *
  361.  *  Description : Closes a stream.
  362.  *
  363.  *  Input  :  
  364.  *
  365.  *  Output :  SUCCESS (always)
  366.  *
  367.  ******************************************************************/
  368.  
  369.   TT_Error  TT_Close_Stream( TT_Stream*  stream )
  370.   {
  371.     PStream_Rec  rec = STREAM2REC(*stream);
  372.  
  373.     fclose( rec->file );
  374.     FREE( rec );
  375.  
  376.     HANDLE_Set( *stream, NULL );
  377.     return TT_Err_Ok;
  378.   }
  379.  
  380. /*******************************************************************
  381.  *
  382.  *  Function    : TT_Use_Stream
  383.  *
  384.  *  Description : copy or duplicate a given stream
  385.  *
  386.  *  Input  :  org_stream   original stream
  387.  *            stream       target stream ( copy or duplicate )
  388.  *            error        target error
  389.  *
  390.  *  Output :  
  391.  *
  392.  ******************************************************************/
  393.  
  394.   TT_Error  TT_Use_Stream( TT_Stream   org_stream,
  395.                            TT_Stream*  stream )
  396.   {
  397. #ifndef TT_CONFIG_REENTRANT
  398.  
  399.      MUTEX_Lock( files.lock );
  400.      /* lock file mutex */
  401.  
  402.      *stream = org_stream;
  403.      /* copy the stream */
  404.  
  405.      return TT_Err_Ok;
  406.  
  407. #else
  408.      return TT_Duplicate_Stream( org_stream, stream );
  409. #endif
  410.   }
  411.  
  412. /*******************************************************************
  413.  *
  414.  *  Function    : TT_Done_Stream
  415.  *
  416.  *  Description : copy or duplicate a given stream
  417.  *
  418.  *  Input  :  org_stream   original stream
  419.  *            stream       target stream ( copy or duplicate )
  420.  *            error        target error
  421.  *
  422.  *  Output :  
  423.  *
  424.  ******************************************************************/
  425.  
  426.  TT_Error  TT_Done_Stream( TT_Stream*  stream )
  427.  {
  428.  
  429. #ifndef TT_CONFIG_REENTRANT
  430.  
  431.     HANDLE_Set( *stream, NULL );
  432.     MUTEX_Release( files.lock );
  433.  
  434.     return TT_Err_Ok;
  435. #else
  436.  
  437.     return TT_Close_Stream(stream);
  438.  
  439. #endif
  440.  }
  441.  
  442. /*******************************************************************
  443.  *
  444.  *  Function    : TT_Seek_File
  445.  *
  446.  *  Description : Seeks the file cursor to a different position.
  447.  *
  448.  *  Input  :  position     new position in file
  449.  *
  450.  *  Output :  SUCCESS on success. FAILURE if out of range.
  451.  *
  452.  ******************************************************************/
  453.  
  454.   TT_Error  TT_Seek_File( STREAM_ARGS long position )
  455.   {
  456.     position += CUR_Stream->base;
  457.  
  458.     if ( fseek( CUR_Stream->file, position, SEEK_SET ) )
  459.       return TT_Err_Invalid_File_Offset;
  460.  
  461.     return TT_Err_Ok;
  462.   }
  463.  
  464. /*******************************************************************
  465.  *
  466.  *  Function    : TT_Skip_File
  467.  *
  468.  *  Description : Skips forward the file cursor.
  469.  *
  470.  *  Input  :  distance    number of bytes to skip
  471.  *
  472.  *  Output :  see TT_Seek_File
  473.  *
  474.  ******************************************************************/
  475.  
  476.   TT_Error  TT_Skip_File( STREAM_ARGS long distance )
  477.   {
  478.     return TT_Seek_File( STREAM_VARS ftell( CUR_Stream->file ) -
  479.                                      CUR_Stream->base + distance );
  480.   }
  481.  
  482. /*******************************************************************
  483.  *
  484.  *  Function    : TT_Read_File
  485.  *
  486.  *  Description : Reads a chunk of the file and copies it to memory.
  487.  *
  488.  *  Input  :  buffer    target buffer
  489.  *            count     length in bytes to read
  490.  *
  491.  *  Output :  SUCCESS on success. FAILURE if out of range.
  492.  *
  493.  ******************************************************************/
  494.  
  495.   TT_Error  TT_Read_File( STREAM_ARGS void* buffer, long count )
  496.   {
  497.     if ( fread( buffer, 1, count, CUR_Stream->file ) != (unsigned long)count )
  498.       return TT_Err_Invalid_File_Read;
  499.  
  500.     return TT_Err_Ok;
  501.   }
  502.  
  503. /*******************************************************************
  504.  *
  505.  *  Function    : TT_Read_At_File
  506.  *
  507.  *  Description : Reads file at a specified position.
  508.  *
  509.  *  Input  :  position  position to seek to before read
  510.  *            buffer    target buffer
  511.  *            count     number of bytes to read
  512.  *
  513.  *  Output :  SUCCESS on success. FAILURE if error.
  514.  *
  515.  ******************************************************************/
  516.  
  517.   TT_Error  TT_Read_At_File( STREAM_ARGS long   position, 
  518.                                          void*  buffer, 
  519.                                          long   count )
  520.   {
  521.     TT_Error  error;
  522.     if ( (error = TT_Seek_File( STREAM_VARS position ))      || 
  523.          (error = TT_Read_File( STREAM_VARS buffer, count )) )
  524.       return error;
  525.  
  526.     return TT_Err_Ok;
  527.   }
  528.  
  529. /*******************************************************************
  530.  *
  531.  *  Function    :  TT_File_Pos
  532.  *
  533.  *  Description :  Returns current file seek pointer.
  534.  *
  535.  *  Input  :  none
  536.  *
  537.  *  Output :  current file position
  538.  *
  539.  ******************************************************************/
  540.  
  541.   Long  TT_File_Pos( STREAM_ARG )
  542.   {
  543.     return (ftell( CUR_Stream->file ) - CUR_Stream->base);
  544.   }
  545.  
  546. /*******************************************************************
  547.  *
  548.  *  Function    :  TT_Access_Frame
  549.  *
  550.  *  Description :  Notifies the component that we're going to read
  551.  *                 'size' bytes from the current file position.
  552.  *                 This function should load/cache/map these bytes
  553.  *                 so that they will be addressed by the GET_xxx
  554.  *                 functions easily.
  555.  *
  556.  *  Input  :  size   number of bytes to access.
  557.  *
  558.  *  Output :  SUCCESS on success. FAILURE on error.
  559.  *
  560.  *  Notes:    The function fails if the byte range is not within the
  561.  *            the file, or if there is not enough memory to cache
  562.  *            the bytes properly (which usually means that aSize is
  563.  *            too big in both cases).
  564.  *
  565.  ******************************************************************/
  566.  
  567.   TT_Error  TT_Access_Frame( STREAM_ARGS FRAME_ARGS int size )
  568.   {
  569.     TT_Error  error;
  570.  
  571.     if ( CUR_Frame.address != NULL )
  572.       return TT_Err_Nested_Frame_Access;
  573.  
  574. #ifndef TT_CONFIG_REENTRANT
  575.  
  576.     if ( size <= FRAME_CACHE_SIZE )
  577.     {
  578.       /* use the cache */
  579.  
  580.       CUR_Frame.address = files.frame_cache;
  581.       CUR_Frame.size    = FRAME_CACHE_SIZE;
  582.     }
  583.     else
  584. #endif
  585.  
  586.     {
  587.       if ( ALLOC( CUR_Frame.address, size ) )
  588.         return error;
  589.  
  590.       CUR_Frame.size    = size;
  591.     }
  592.  
  593.     if ((error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size )))
  594.     {
  595.  
  596. #ifndef TT_CONFIG_REENTRANT
  597.       if ( size > FRAME_CACHE_SIZE )
  598. #endif
  599.         FREE( CUR_Frame.address );
  600.  
  601.       CUR_Frame.address = NULL;
  602.       CUR_Frame.size    = 0;
  603.     }
  604.  
  605.     CUR_Frame.cursor = CUR_Frame.address;
  606.  
  607.     return error;
  608.   }
  609.  
  610.  
  611. /*******************************************************************
  612.  *
  613.  *  Function    :  TT_Check_And_Access_Frame
  614.  *
  615.  *  Description :  Notifies the component that we're going to read
  616.  *                 aSize bytes from the current file position.
  617.  *                 This function should load/cache/map these bytes
  618.  *                 so that they will be addressed by the GET_xxx
  619.  *                 functions easily.
  620.  *
  621.  *  Input  :  size   number of bytes to access.
  622.  *
  623.  *  Output :  SUCCESS on success. FAILURE on error.
  624.  *
  625.  *  Notes:    The function truncates aSize if the byte range is not 
  626.  *            within the file.
  627.  *
  628.  *            It will fail if there is not enough memory to cache
  629.  *            the bytes properly (which usually means that aSize is
  630.  *            too big).
  631.  *
  632.  *            It will fail if you make two consecutive calls
  633.  *            to TT_Access_Frame(), without a TT_Forget_Frame() between
  634.  *            them.
  635.  *
  636.  *            The only difference with TT_Access_Frame() is that we
  637.  *            check that the frame is within the current file.  We
  638.  *            otherwise truncate it.
  639.  *
  640.  ******************************************************************/
  641.  
  642.   TT_Error  TT_Check_And_Access_Frame( STREAM_ARGS FRAME_ARGS int size )
  643.   {
  644.     TT_Error  error;
  645.     Long      readBytes;
  646.  
  647.     if ( CUR_Frame.address != NULL )
  648.       return TT_Err_Nested_Frame_Access;
  649.  
  650. #ifndef TT_CONFIG_REENTRANT
  651.  
  652.     if ( size <= FRAME_CACHE_SIZE )
  653.     {
  654.       /* use the cache */
  655.  
  656.       CUR_Frame.address = files.frame_cache;
  657.       CUR_Frame.size    = FRAME_CACHE_SIZE;
  658.     }
  659.     else
  660. #endif
  661.  
  662.     {
  663.       if ( ALLOC( CUR_Frame.address, size ) )
  664.         return error;
  665.  
  666.       CUR_Frame.size    = size;
  667.     }
  668.  
  669.     readBytes = CUR_Stream->size - TT_File_Pos( STREAM_VAR );
  670.     if ( size > readBytes ) size = readBytes;
  671.  
  672.     if ((error = TT_Read_File( STREAM_VARS (void*)CUR_Frame.address, size )))
  673.     {
  674.  
  675. #ifndef TT_CONFIG_REENTRANT
  676.       if ( size > FRAME_CACHE_SIZE )
  677. #endif
  678.         FREE( CUR_Frame.address );
  679.  
  680.       CUR_Frame.address = NULL;
  681.       CUR_Frame.size    = 0;
  682.     }
  683.  
  684.     CUR_Frame.cursor = CUR_Frame.address;
  685.  
  686.     return error;
  687.   }
  688.  
  689. /*******************************************************************
  690.  *
  691.  *  Function    :  TT_Forget_Frame
  692.  *
  693.  *  Description :  Releases a cached frame after reading.
  694.  *
  695.  *  Input  :  None
  696.  *
  697.  *  Output :  SUCCESS on success. FAILURE on error.
  698.  *
  699.  ******************************************************************/
  700.  
  701.   TT_Error  TT_Forget_Frame( FRAME_ARG )
  702.   {
  703.     if ( CUR_Frame.address == NULL )
  704.       return TT_Err_Nested_Frame_Access;
  705.  
  706. #ifndef TT_CONFIG_REENTRANT
  707.     if ( CUR_Frame.size > FRAME_CACHE_SIZE )
  708. #endif
  709.       FREE( CUR_Frame.address );
  710.  
  711.     CUR_Frame.address = NULL;
  712.     CUR_Frame.cursor  = NULL;
  713.     CUR_Frame.size    = 0;
  714.  
  715.     return TT_Err_Ok;
  716.   }
  717.  
  718.  
  719. /*******************************************************************
  720.  *
  721.  *  Function    :  GET_Byte
  722.  *
  723.  *  Description :  Extracts a byte from the current file frame.
  724.  *
  725.  *  Input  :  None or current frame
  726.  *
  727.  *  Output :  Extracted Byte
  728.  *
  729.  *  NOTES : We consider that the programmer is intelligent enough
  730.  *          not to try to get a byte that is out of the frame. Hence,
  731.  *          we provide no bounds check here. (A misbehaving client
  732.  *          could easily page fault using this call.)
  733.  *
  734.  ******************************************************************/
  735.  
  736.   unsigned char Get_Byte( FRAME_ARG )
  737.   {
  738.     CHECK_FRAME(CUR_Frame, 1);
  739.  
  740.     return (unsigned char)(*CUR_Frame.cursor++);
  741.   }
  742.  
  743.  
  744. /*******************************************************************
  745.  *
  746.  *  Function    :  GET_Char
  747.  *
  748.  *  Description :  Extracts a signed byte from the current file frame.
  749.  *
  750.  *  Input  :  None or current frame
  751.  *
  752.  *  Output :  Extracted char
  753.  *
  754.  *  NOTES : We consider that the programmer is intelligent enough
  755.  *          not to try to get a byte that is out of the frame. Hence,
  756.  *          we provide no bounds check here. (A misbehaving client
  757.  *          could easily page fault using this call.)
  758.  *
  759.  ******************************************************************/
  760.  
  761.   char Get_Char( FRAME_ARG )
  762.   {
  763.     CHECK_FRAME(CUR_Frame, 1);
  764.  
  765.     return (char)(*CUR_Frame.cursor++);
  766.   }
  767.  
  768. /*******************************************************************
  769.  *
  770.  *  Function    :  GET_Short
  771.  *
  772.  *  Description :  Extracts a short from the current file frame.
  773.  *
  774.  *  Input  :  None or current frame
  775.  *
  776.  *  Output :  Extracted short
  777.  *
  778.  *  NOTES : We consider that the programmer is intelligent enough
  779.  *          not to try to get a byte that is out of the frame. Hence,
  780.  *          we provide no bounds check here. (A misbehaving client
  781.  *          could easily page fault using this call.)
  782.  *
  783.  ******************************************************************/
  784.  
  785.   short  Get_Short( FRAME_ARG )
  786.   {
  787.     short  getshort;
  788.  
  789.     CHECK_FRAME(CUR_Frame, 2);
  790.  
  791.     getshort = ((short)CUR_Frame.cursor[0] << 8) |
  792.                 (short)CUR_Frame.cursor[1];
  793.  
  794.     CUR_Frame.cursor += 2;
  795.  
  796.     return getshort;
  797.   }
  798.  
  799.  
  800. /*******************************************************************
  801.  *
  802.  *  Function    :  GET_UShort
  803.  *
  804.  *  Description :  Extracts an unsigned short from the frame.
  805.  *
  806.  *  Input  :  None or current frame
  807.  *
  808.  *  Output :  Extracted ushort
  809.  *
  810.  *  NOTES : We consider that the programmer is intelligent enough
  811.  *          not to try to get a byte that is out of the frame. Hence,
  812.  *          we provide no bounds check here. (A misbehaving client
  813.  *          could easily page fault using this call.)
  814.  *
  815.  ******************************************************************/
  816.  
  817.   unsigned short  Get_UShort( FRAME_ARG )
  818.   {
  819.     unsigned short  getshort;
  820.  
  821.     CHECK_FRAME(CUR_Frame, 2);
  822.  
  823.     getshort = ((unsigned short)CUR_Frame.cursor[0] << 8) |
  824.                 (unsigned short)CUR_Frame.cursor[1];
  825.  
  826.     CUR_Frame.cursor += 2;
  827.  
  828.     return getshort;
  829.   }
  830.  
  831.  
  832. /*******************************************************************
  833.  *
  834.  *  Function    :  GET_Long
  835.  *
  836.  *  Description :  Extracts a long from the frame.
  837.  *
  838.  *  Input  :  None or current frame
  839.  *
  840.  *  Output :  Extracted long
  841.  *
  842.  *  NOTES : We consider that the programmer is intelligent enough
  843.  *          not to try to get a byte that is out of the frame. Hence,
  844.  *          we provide no bounds check here. (A misbehaving client
  845.  *          could easily page fault using this call.)
  846.  *
  847.  ******************************************************************/
  848.  
  849.   long Get_Long( FRAME_ARG )
  850.   {
  851.     long  getlong;
  852.  
  853.     CHECK_FRAME(CUR_Frame, 4);
  854.  
  855.     getlong = ((long)CUR_Frame.cursor[0] << 24) |
  856.               ((long)CUR_Frame.cursor[1] << 16) |
  857.               ((long)CUR_Frame.cursor[2] << 8 ) |
  858.                (long)CUR_Frame.cursor[3];
  859.  
  860.     CUR_Frame.cursor += 4;
  861.  
  862.     return getlong;
  863.   }
  864.  
  865.  
  866. /*******************************************************************
  867.  *
  868.  *  Function    :  GET_ULong
  869.  *
  870.  *  Description :  Extracts an unsigned long from the frame.
  871.  *
  872.  *  Input  :  None
  873.  *
  874.  *  Output :  Extracted ulong
  875.  *
  876.  *  NOTES : We consider that the programmer is intelligent enough
  877.  *          not to try to get a byte that is out of the frame. Hence,
  878.  *          we provide no bounds check here. (A misbehaving client
  879.  *          could easily page fault using this call.)
  880.  *
  881.  ******************************************************************/
  882.  
  883.   unsigned long Get_ULong( FRAME_ARG )
  884.   {
  885.     unsigned long  getlong;
  886.  
  887.     CHECK_FRAME(CUR_Frame, 4);
  888.  
  889.     getlong = ( ((unsigned long)CUR_Frame.cursor[0] << 24) |
  890.                 ((unsigned long)CUR_Frame.cursor[1] << 16) |
  891.                 ((unsigned long)CUR_Frame.cursor[2] << 8 ) |
  892.                  (unsigned long)CUR_Frame.cursor[3] );
  893.  
  894.     CUR_Frame.cursor += 4;
  895.  
  896.     return getlong;
  897.   }
  898.  
  899. #endif /* HAVE_MMAP */
  900.  
  901.  
  902. /* End */
  903.