WResFileOffset res_seek( WResFileID fid, WResFileOffset amount, int where ) { if( fid == hInstance.fid ) { if( where == SEEK_SET ) { return( lseek( WRES_FID2PH( fid ), amount + WResFileShift, where ) - WResFileShift ); } else { return( lseek( WRES_FID2PH( fid ), amount, where ) ); } } DbgAssert( where != SEEK_END ); DbgAssert( !(where == SEEK_CUR && amount < 0) ); if( WRES_FID2PH( fid ) == Root->outfile->handle ) { if( where == SEEK_CUR ) { unsigned long old_pos; unsigned long new_pos; old_pos = PosLoad(); new_pos = old_pos + amount; if( new_pos > old_pos ) { PadLoad( (size_t)amount ); } else { SeekLoad( new_pos ); } return( new_pos ); } else { SeekLoad( amount ); return( amount ); } } else { return( QLSeek( WRES_FID2PH( fid ), amount, where, "resource file" ) ); } }
WResFileOffset res_tell( WResFileID fid ) { if( fid == hInstance.fid ) { return( tell( WRES_FID2PH( fid ) ) ); } DbgAssert( WRES_FID2PH( fid ) == Root->outfile->handle ); fid = fid; return( PosLoad() ); }
WResFileSSize res_read( WResFileID fid, void * in_buff, WResFileSize size ) /*************************************************************************/ { RcBuffer *buff; size_t copy_bytes; size_t total_read; int i; WResFileSSize bytes_added; /* return value of FillRcBuffer */ if( hInstance.fid == fid ) { return( posix_read( WRES_FID2PH( fid ), in_buff, size ) ); } i = RcFindIndex( fid ); if( i >= RC_MAX_FILES ) { return( posix_read( WRES_FID2PH( fid ), in_buff, size ) ); } buff = RcFileList[i].Buffer; if( buff->IsDirty ) { if( FlushRcBuffer( fid, buff ) ) { return( -1 ); } } total_read = 0; while( size > 0 ) { if( buff->Count == 0 ) { bytes_added = FillRcBuffer( fid, buff ); if( bytes_added == -1 ) { return( bytes_added ); } else if( bytes_added == 0 ) { return( total_read ); } } copy_bytes = size; if( copy_bytes > buff->Count ) copy_bytes = buff->Count; memcpy( in_buff, buff->NextChar, copy_bytes ); buff->NextChar += copy_bytes; buff->Count -= copy_bytes; in_buff = (char *)in_buff + copy_bytes; size -= copy_bytes; total_read += copy_bytes; } return( total_read ); } /* RcRead */
WResFileOffset res_tell( WResFileID fid ) /***************************************/ { RcBuffer * buff; int i; if( hInstance.fid == fid ) { return( tell( WRES_FID2PH( fid ) ) ); } i = RcFindIndex( fid ); if( i >= RC_MAX_FILES ) { return( tell( WRES_FID2PH( fid ) ) ); } buff = RcFileList[i].Buffer; if( buff->IsDirty ) { return( tell( WRES_FID2PH( fid ) ) + (WResFileOffset)buff->Count ); } else { return( tell( WRES_FID2PH( fid ) ) - (WResFileOffset)buff->Count ); } } /* RcTell */
static WResFileSSize FillRcBuffer( WResFileID fid, RcBuffer * buff ) /******************************************************************/ { buff->Count = posix_read( WRES_FID2PH( fid ), buff->Buffer, RC_BUFFER_SIZE ); if( buff->Count == -1 ) { buff->Count = 0; buff->BytesRead = 0; return( -1 ); } buff->BytesRead = buff->Count; buff->NextChar = buff->Buffer; return( buff->Count ); } /* FillRcBuffer */
WResFileSSize res_write( WResFileID fid, const void *out_buff, WResFileSize size ) /********************************************************************************/ { RcBuffer *buff; size_t copy_bytes; size_t total_wrote; int i; i = RcFindIndex( fid ); if( i >= RC_MAX_FILES ) { return( posix_write( WRES_FID2PH( fid ), out_buff, size ) ); } buff = RcFileList[i].Buffer; /* this is in case we have just read from the file */ if( !buff->IsDirty ) { if( FlushRcBuffer( fid, buff ) ) { return( -1 ); } } total_wrote = 0; while( size > 0 ) { copy_bytes = RC_BUFFER_SIZE - buff->Count; if( copy_bytes > size ) copy_bytes = size; memcpy( buff->NextChar, out_buff, copy_bytes ); buff->IsDirty = true; buff->NextChar += copy_bytes; buff->Count += copy_bytes; out_buff = (char *)out_buff + copy_bytes; size -= copy_bytes; total_wrote += copy_bytes; if( buff->Count == RC_BUFFER_SIZE ) { if( FlushRcBuffer( fid, buff ) ) { return( -1 ); } } } return( total_wrote ); } /* RcWrite */
static bool FlushRcBuffer( WResFileID fid, RcBuffer *buff ) /*********************************************************/ { bool error; error = false; if( buff->IsDirty ) { error = ( (size_t)posix_write( WRES_FID2PH( fid ), buff->Buffer, buff->Count ) != buff->Count ); memset( buff->Buffer, 0, RC_BUFFER_SIZE ); } buff->IsDirty = false; buff->Count = 0; buff->BytesRead = 0; buff->NextChar = buff->Buffer; return( error ); } /* FlushRcBuffer */
int res_close( WResFileID fid ) /*****************************/ { RcBuffer *buff; int i; i = RcFindIndex( fid ); if( i < RC_MAX_FILES ) { buff = RcFileList[i].Buffer; if( buff->IsDirty ) { if( FlushRcBuffer( fid, buff ) ) { return( -1 ); } } RcMemFree( buff ); RcFileList[i].HasRcBuffer = false; RcFileList[i].fid = WRES_NIL_HANDLE; RcFileList[i].Buffer = NULL; } UnRegisterOpenFile( fid ); return( close( WRES_FID2PH( fid ) ) ); } /* RcClose */
WResFileOffset res_tell( WResFileID fid ) { return( tell( WRES_FID2PH( fid ) ) ); }
WResFileOffset res_seek( WResFileID fid, WResFileOffset pos, int where ) { return( lseek( WRES_FID2PH( fid ), pos, where ) ); }
WResFileSSize res_write( WResFileID fid, const void *buf, WResFileSize size ) { return( posix_write( WRES_FID2PH( fid ), buf, size ) ); }
WResFileSSize res_read( WResFileID fid, void *buf, WResFileSize size ) { return( posix_read( WRES_FID2PH( fid ), buf, size ) ); }
int res_close( WResFileID fid ) { return( close( WRES_FID2PH( fid ) ) ); }
WResFileOffset res_seek( WResFileID fid, WResFileOffset amount, int where ) /*************************************************************************/ /* Note: Don't seek backwards in a buffer that has been writen to without */ /* flushing the buffer and doing an lseek since moving the NextChar pointer */ /* back will make it look like less data has been writen */ { RcBuffer *buff; WResFileOffset currpos; int diff; int i; if( hInstance.fid == fid ) { if( where == SEEK_SET ) { return( lseek( WRES_FID2PH( fid ), amount + WResFileShift, where ) - WResFileShift ); } else { return( lseek( WRES_FID2PH( fid ), amount, where ) ); } } i = RcFindIndex( fid ); if( i >= RC_MAX_FILES ) { return( lseek( WRES_FID2PH( fid ), amount, where ) ); } buff = RcFileList[i].Buffer; currpos = res_tell( fid ); if( buff->IsDirty ) { switch( where ) { case SEEK_CUR: amount += currpos; where = SEEK_SET; /* FALL THROUGH */ case SEEK_SET: /* if we are seeking backwards any amount or forwards past the */ /* end of the buffer */ if( amount < currpos || amount >= currpos + ( RC_BUFFER_SIZE - buff->Count ) ) { if( FlushRcBuffer( fid, buff ) ) return( -1 ); if( lseek( WRES_FID2PH( fid ), amount, SEEK_SET ) == -1 ) { return( -1 ); } } else { diff = amount - currpos; /* add here because Count is chars to left of NextChar */ /* for writing */ buff->NextChar += diff; buff->Count += diff; } break; case SEEK_END: if( FlushRcBuffer( fid, buff ) ) return( -1 ); if( lseek( WRES_FID2PH( fid ), amount, where ) == -1 ) return( -1 ); break; default: return( -1 ); break; } } else { switch( where ) { case SEEK_CUR: amount += currpos; where = SEEK_SET; /* FALL THROUGH */ case SEEK_SET: /* if the new pos is outside the buffer */ if( amount < currpos + buff->Count - buff->BytesRead || amount >= currpos + buff->Count ) { if( FlushRcBuffer( fid, buff ) ) return( -1 ); if( lseek( WRES_FID2PH( fid ), amount, SEEK_SET ) == -1 ) { return( -1 ); } } else { diff = amount - currpos; /* subtract here because Count is chars to right of NextChar */ /* for reading */ buff->Count -= diff; buff->NextChar += diff; } break; case SEEK_END: if( FlushRcBuffer( fid, buff ) ) return( -1 ); if( lseek( WRES_FID2PH( fid ), amount, SEEK_END ) == -1 ) return( -1 ); break; default: return( -1 ); break; } } return( currpos ); } /* RcSeek */