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

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