home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / fastfile / fastfile.c next >
C/C++ Source or Header  |  1997-07-14  |  8KB  |  361 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1997 Microsoft Corporation.  All Rights Reserved.
  4.  *
  5.  *  File:       fastfile.c
  6.  *  Content:    Fast file I/O for large numbers of files.
  7.  *        Uses a single file built using FFCREATE.EXE; this file
  8.  *        contains a directory + all the files.
  9.  *
  10.  * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  11.  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  12.  * WARRANTIES OF MERCHANTBILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
  13.  *
  14.  ***************************************************************************/
  15. #include <windows.h>
  16. #include <io.h>
  17. #include <fcntl.h>
  18. #include <search.h>
  19. #include <stdio.h>
  20. #include "fastfile.h"
  21. #include "ffent.h"
  22.  
  23. #ifdef DEBUG
  24. #define ODS( a ) OutputDebugString( a )
  25. #else
  26. #define ODS( a )
  27. #endif
  28.  
  29. #ifdef __WATCOMC__
  30. #define _stricmp stricmp
  31. #endif
  32.  
  33. typedef struct {
  34.     BOOL    inuse;
  35.     LONG    pos;
  36.     LONG    size;
  37.     LPFILEENTRY    pfe;
  38. } FILEHANDLE, FAR *LPFILEHANDLE;
  39.  
  40. static int              LockCount;
  41. static HANDLE           hFile;
  42. static HANDLE        hFileMapping;
  43. static LPFILEENTRY    pFE;
  44. static LPBYTE           pBase;
  45. static DWORD        dwFECnt;
  46. static LPFILEHANDLE    lpFH;
  47. static DWORD        dwFHCnt;
  48. static long        lFileEnd;
  49.  
  50. /*
  51.  * Compare 
  52.  *
  53.  * bsearch comparison routine
  54.  */
  55. int Compare( LPFILEENTRY p1, LPFILEENTRY p2 )
  56. {
  57.     return( _stricmp( (p1)->name,(p2)->name ) );
  58.  
  59. } /* Compare */
  60.  
  61. /*
  62.  * FastFileInit
  63.  *
  64.  * Initialize for fast file access. The master file and maximum number
  65.  * of open "files" are specified.
  66.  */
  67. BOOL FastFileInit( LPSTR fname, int max_handles )
  68. {
  69.     HRSRC  h;
  70.  
  71.     LockCount = 0;
  72.     FastFileFini();
  73.  
  74.     /*
  75.      * get a file handle array
  76.      */
  77.     lpFH = LocalAlloc( LPTR, max_handles * sizeof( FILEHANDLE ) );
  78.     if( lpFH == NULL ) {
  79.     return FALSE;
  80.     }
  81.     dwFHCnt = max_handles;
  82.  
  83.     /*
  84.      * try our resourse file first
  85.      */
  86.     if (h = FindResource(NULL, fname, RT_RCDATA))
  87.     {
  88.         pBase = LockResource(LoadResource(NULL, h));
  89.  
  90.         if (pBase == NULL)
  91.         {
  92.             ODS( "FastFileInit: unable to lock resource\r\n" );
  93.             FastFileFini();
  94.             return FALSE;
  95.         }
  96.  
  97.         ODS( "FastFileInit: opened resource: "); ODS(fname); ODS("\r\n");
  98.     }
  99.     else   
  100.     {
  101.  
  102.         /*
  103.          * create a memory mapped file for the master file
  104.          */
  105.         hFile = CreateFile( fname, GENERIC_READ, FILE_SHARE_READ, NULL,
  106.                 OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0 );
  107.  
  108.         if( hFile == NULL || hFile == (HANDLE)HFILE_ERROR )
  109.     {
  110.             ODS( "FastFileInit: CreateFile(" ); ODS( fname ); ODS( ")\r\n" );
  111.             hFile = NULL;
  112.             FastFileFini();
  113.             return FALSE;
  114.         }
  115.         hFileMapping = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
  116.         if( hFileMapping == NULL ) {
  117.             ODS( "FastFileInit: CreateFileMapping Failed\r\n" );
  118.             FastFileFini();
  119.             return FALSE;
  120.         }
  121.         pBase = MapViewOfFile( hFileMapping, FILE_MAP_READ, 0, 0, 0 );
  122.         if( pBase == NULL ) {
  123.             ODS( "FastFileInit: MapViewOfFile Failed\r\n" );
  124.             FastFileFini();
  125.             return FALSE;
  126.         }
  127.     }
  128.  
  129.     /*
  130.      * get initial data from the memory mapped file
  131.      */
  132.     dwFECnt = *((DWORD *) pBase);
  133.     pFE = (LPFILEENTRY) (pBase + 4);
  134.     lFileEnd = pFE[dwFECnt-1].offset;
  135.  
  136.     return TRUE;
  137.  
  138. } /* FastFileInit */
  139.  
  140. /*
  141.  * FastFileFini
  142.  *
  143.  * Clean up resources
  144.  */
  145. void FastFileFini( void )
  146. {
  147.     //
  148.     //  dont unmap things if we have locks out standing
  149.     //
  150.     if (LockCount != 0)
  151.         return;
  152.  
  153.     if( hFileMapping != NULL && pBase ) {
  154.         UnmapViewOfFile( pBase );
  155.     }
  156.     if( hFileMapping != NULL ) {
  157.     CloseHandle( hFileMapping );
  158.     hFileMapping = NULL;
  159.     }
  160.     if( hFile != NULL ) {
  161.     CloseHandle( hFile );
  162.     hFile = NULL;
  163.     }
  164.     if( lpFH != NULL ) {
  165.     LocalFree( lpFH );
  166.     lpFH = NULL;
  167.     }
  168.     dwFHCnt = 0;
  169.     pBase = NULL;
  170.     dwFECnt = 0;
  171.     pFE = NULL;
  172.  
  173. } /* FastFileFini */
  174.  
  175. /*
  176.  * FastFileOpen
  177.  *
  178.  * Search the directory for the file, and return a file handle if found.
  179.  */
  180. HFASTFILE FastFileOpen( LPSTR name )
  181. {
  182.     FILEENTRY    fe;
  183.     LPFILEENTRY    pfe;
  184.  
  185.     if( pFE == NULL ) {
  186.     ODS( "FastFileOpen: not initialized\r\n" );
  187.     return NULL;
  188.     }
  189.     if( name == NULL || name[0] == 0 ) {
  190.     ODS( "FastFileOpen: invalid name\r\n" );
  191.     return NULL;
  192.     }
  193.  
  194.     strcpy( fe.name, name );
  195.     pfe = bsearch( &fe, pFE, dwFECnt, sizeof( FILEENTRY ), (LPVOID) Compare );
  196.     if( pfe != NULL ) {
  197.     DWORD    i;
  198.     for( i=0;i<dwFHCnt;i++ ) {
  199.         if( !lpFH[i].inuse ) {
  200.         lpFH[i].inuse = TRUE;
  201.         lpFH[i].pos = pfe->offset;
  202.         lpFH[i].size = (pfe+1)->offset - pfe->offset;
  203.         lpFH[i].pfe = pfe;
  204.         return &lpFH[i];
  205.         }
  206.     }
  207.     ODS( "FastFileOpen: Out of file handles\r\n" );
  208.     } else {
  209.     ODS( "FastFileOpen: File \"" ); ODS( name ); ODS( "\" not found\r\n" );
  210.     }
  211.  
  212.     return NULL;
  213.  
  214. } /* FastFileOpen */
  215.  
  216. /*
  217.  * FastFileClose
  218.  *
  219.  * Mark a fast file handle as closed
  220.  */
  221. BOOL FastFileClose( LPFILEHANDLE pfh )
  222. {
  223.     if( pfh == NULL || pfh->inuse != TRUE ) {
  224.     ODS( "FastFileClose: invalid handle\r\n" );
  225.     return FALSE;
  226.     }
  227.     pfh->inuse = FALSE;
  228.     return TRUE;
  229.  
  230. } /* FastFileClose */
  231.  
  232. /*
  233.  * FastFileLock
  234.  *
  235.  * return a memory pointer into a fast file
  236.  */
  237. LPVOID FastFileLock( LPFILEHANDLE pfh, int pos, int size )
  238. {
  239.     if( pfh == NULL || pfh->inuse != TRUE ) {
  240.         ODS( "FastFileLock: invalid handle\r\n" );
  241.         return NULL;
  242.     }
  243.     if( size < 0 ) {
  244.         ODS( "FastFileLock: invalid size\r\n" );
  245.         return NULL;
  246.     }
  247.     if( (pos + size) > ((pfh->pfe)+1)->offset ) {
  248.         ODS( "FastFileLock: read past end of file\r\n" );
  249.         return NULL;
  250.     }
  251.     LockCount++;
  252.     return pBase + pfh->pos + pos;
  253.  
  254. } /* FastFileLock */
  255.  
  256. /*
  257.  * FastFileUnlock
  258.  *
  259.  */
  260. BOOL FastFileUnlock( LPFILEHANDLE pfh, int pos, int size )
  261. {
  262.     if( pfh == NULL || pfh->inuse != TRUE ) {
  263.         ODS( "FastFileUnlock: invalid handle\r\n" );
  264.         return FALSE;
  265.     }
  266.     if( size < 0 ) {
  267.         ODS( "FastFileUnlock: invalid size\r\n" );
  268.         return FALSE;
  269.     }
  270.     if( (pos + size) > ((pfh->pfe)+1)->offset ) {
  271.         ODS( "FastFileUnlock: read past end of file\r\n" );
  272.         return FALSE;
  273.     }
  274.  
  275.     LockCount--;
  276.     return TRUE;
  277.  
  278. } /* FastFileUnlock */
  279.  
  280. /*
  281.  * FastFileRead
  282.  *
  283.  * read from a fast file (memcpy!)
  284.  */
  285. BOOL FastFileRead( LPFILEHANDLE pfh, LPVOID ptr, int size )
  286. {
  287.     if( pfh == NULL || pfh->inuse != TRUE ) {
  288.     ODS( "FastFileRead: invalid handle\r\n" );
  289.     return FALSE;
  290.     }
  291.     if( size < 0 ) {
  292.     ODS( "FastFileRead: invalid size\r\n" );
  293.     return FALSE;
  294.     }
  295.     if( (pfh->pos + size) > ((pfh->pfe)+1)->offset ) {
  296.     ODS( "FastFileRead: read past end of file\r\n" );
  297.     return FALSE;
  298.     }
  299.     memcpy( ptr, pBase + pfh->pos, size );
  300.     pfh->pos += size;
  301.     return TRUE;
  302.  
  303. } /* FastFileRead */
  304.  
  305. /*
  306.  * FastFileSeek
  307.  *
  308.  * Set to a new position in a fast file.  Uses standard SEEK_SET, SEEK_CUR,
  309.  * SEEK_END definitions.
  310.  */
  311. BOOL FastFileSeek( LPFILEHANDLE pfh, int off, int how )
  312. {
  313.     LPFILEENTRY    pfe;
  314.  
  315.     if( pfh == NULL || pfh->inuse != TRUE ) {
  316.     ODS( "FastFileSeek: invalid handle\r\n" );
  317.     return FALSE;
  318.     }
  319.     pfe = pfh->pfe;
  320.     if( how == SEEK_SET ) {
  321.     if( off < 0 || off >= pfh->size ) {
  322.         ODS( "FastFileSeek: Invalid offset\r\n" );
  323.         return FALSE;
  324.     }
  325.     off += pfe->offset;
  326.     } else if( how == SEEK_END ) {
  327.     if( off < 0 || off >= pfh->size ) {
  328.         ODS( "FastFileSeek: Invalid offset\r\n" );
  329.         return FALSE;
  330.     }
  331.     off = (pfe+1)->offset - off;
  332.     } else if( how == SEEK_CUR ) {
  333.     off = pfh->pos + off;
  334.     if( off < pfe->offset || off >= (pfe+1)->offset ) {
  335.         ODS( "FastFileSeek: Invalid offset\r\n" );
  336.         return FALSE;
  337.     }
  338.     } else {
  339.     ODS( "FastFileSeek: Invalid 'how' field\r\n" );
  340.     return FALSE;
  341.     }
  342.     pfh->pos = off;
  343.     return TRUE;
  344.  
  345. } /* FastFileSeek */
  346.  
  347. /*
  348.  * FastFileTell
  349.  *
  350.  * Get the current position in a fast file
  351.  */
  352. long FastFileTell( LPFILEHANDLE pfh )
  353. {
  354.     if( pfh == NULL || pfh->inuse != TRUE ) {
  355.     ODS( "FastFileTell: invalid handle\r\n" );
  356.     return -1;
  357.     }
  358.     return pfh->pos - pfh->pfe->offset;
  359.  
  360. } /* FastFileTell */
  361.