home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mksmvp10.zip / MKFFILE.PAS < prev    next >
Pascal/Delphi Source File  |  1997-09-23  |  9KB  |  312 lines

  1. Unit MKFFile; {Buffered File Object Unit}
  2.  
  3. {
  4.      MKFFile - Copyright 1993 by Mark May - MK Software
  5.      You are free to use this code in your programs, however
  6.      it may not be included in Source/TPU function libraries
  7.      without my permission.
  8.  
  9.      Mythical Kingom Tech BBS (513)237-7737 HST/v32
  10.      FidoNet: 1:110/290
  11.      Rime: ->MYTHKING
  12.      You may also reach me at maym@dmapub.dma.org
  13. }
  14.  
  15. {
  16.      MKFFile is a buffered file unit.  You set the buffer size when
  17.      calling the init method.  The MKFFile methods (seekfile, blkread,
  18.      blkwrite) take advantage of the buffer to minimize actual DOS calls
  19.      to access your data.  This can significantly speed up your program.
  20.      MKFFile does handle blkread/blkwrites that are larger than the
  21.      buffer size, and is intended to be truely transparant to your
  22.      application.
  23.  
  24. }
  25.  
  26. {$I MKB.Def}
  27.  
  28. Interface Uses Use32;
  29.  
  30. Type FBufType = Array[0..$fff0] of Byte;
  31.  
  32. Type FFileObj = Object
  33.   BufFile: File;             {File to be buffered}
  34.   Buf: ^FBufType;            {Pointer to the buffer-actual size given by init}
  35.   BufStart: LongInt;         {File position of buffer start}
  36.   BufSize: LongInt;          {Size of the buffer}
  37.   BufChars: Word;            {Number of valid characters in the buffer}
  38.   CurrSize: LongInt;         {Current file size}
  39.   NeedWritten: Boolean;      {Buffer dirty/needs written flag}
  40.   IsOpen: Boolean;           {File is currently open flag}
  41.   CurrPos: LongInt;          {Current position in file/buffer}
  42.   Constructor Init(BSize: Word);
  43.     {Initialize object and set buffer size/allocate memory}
  44.   Destructor Done; Virtual;  {Done}
  45.   Function  OpenFile(FName: String; FMode: Word): Boolean;  Virtual;
  46.                              {Open a file FNAME in the filemode FMode}
  47.   Function  CloseFile: Boolean; Virtual; {Close the currently open file}
  48.   Function  BlkRead(Var V; Num: Word; Var NumRead: Word): Boolean; Virtual;
  49.     {Equivalent to BlockRead but makes use of buffer to reduce real reads}
  50.   Function  BlkWrite(Var V; Num: Word): Boolean; Virtual;
  51.     {Equivalent to BlockWrite but uses buffer to reduce real writes}
  52.   Function  SeekFile(FP: LongInt): Boolean; Virtual;
  53.     {Equivalent to seek but uses buffer to reduce real seeks}
  54.   Function  WriteBuffer: Boolean; Virtual;
  55.     {Internal use normally - flushes buffer if needed}
  56.   Function  ReadBuffer: Boolean; Virtual;
  57.     {Internal use normally - refills buffer}
  58.   Function  RawSize: LongInt; Virtual;
  59.     {Pass through to filesize function}
  60.   Function  FilePos: LongInt; Virtual;
  61.   End;
  62.  
  63.  
  64. Implementation
  65.  
  66. Uses MKFile,
  67. {$IFDEF WINDOWS}
  68.   WinDos;
  69. {$ELSE}
  70.   Dos,
  71.   {$IFDEF OPRO}
  72.   OpCrt;
  73.   {$ELSE}
  74.   Crt;
  75.   {$ENDIF}
  76. {$ENDIF}
  77.  
  78.  
  79.  
  80. Constructor FFileObj.Init(BSize: Word);
  81.   Begin
  82.   Buf := Nil;
  83.   BufSize := BSize;
  84.   BufStart := 0;           {Invalidate buffer}
  85.   BufChars := 0;
  86.   IsOpen := False;           {Initialize values}
  87.   NeedWritten := False;
  88.   CurrPos := 0;
  89.   GetMem(Buf, BufSize);      {Allocate memory for buffer}
  90.   If Buf = Nil Then
  91.     Fail;
  92.   End;
  93.  
  94.  
  95. Destructor FFileObj.Done;
  96.   Begin
  97.   If IsOpen Then             {If file is open then close it}
  98.     If CloseFile Then;
  99.   If Buf <> Nil Then         {Free up memory}
  100.     FreeMem(Buf, BufSize);
  101.   End;
  102.  
  103.  
  104.  
  105. Function FFileObj.OpenFile(FName: String; FMode: Word): Boolean;
  106.   Var
  107.     DoneOk: Boolean;
  108.  
  109.   Begin
  110.   If IoResult <> 0 Then;     {protect against unchecked errors in calling proc}
  111.   DoneOk := True;
  112.   If IsOpen Then             {If file is open then close it first}
  113.     DoneOk := CloseFile;
  114.   If DoneOk Then
  115.     Begin                    {Create file if needed}
  116.     If Not FileExist(FName) Then
  117.       DoneOk := SaveFile(FName, DoneOk, 0) = 0;
  118.     End;
  119.   If DoneOk Then
  120.     Begin                    {open file}
  121.     Assign(BufFile, FName);
  122.     FileMode := FMode;
  123.     If DoneOk Then
  124.       DoneOk := shReset(BufFile, 1);
  125.     IsOpen := DoneOk;
  126.     CurrPos := 0;            {Initialize file position}
  127.     BufStart := 0;           {Invalidate buffer}
  128.     BufChars := 0;
  129.     NeedWritten := False;
  130.     CurrSize := RawSize;
  131.     End;
  132.   OpenFile := DoneOk;
  133.   End;
  134.  
  135.  
  136. Function FFileObj.CloseFile: Boolean;
  137.   Var
  138.     DoneOk: Boolean;
  139.  
  140.   Begin
  141.   If IoResult <> 0 Then;     {protect against calling proc problems}
  142.   DoneOk := True;
  143.   If NeedWritten Then        {If buffer needs written then write it first}
  144.     DoneOk := WriteBuffer;
  145.   If DoneOk Then
  146.     Begin
  147.     Close(BufFile);         {Close file}
  148.     DoneOk := (IoResult = 0);
  149.     End;
  150.   If DoneOk Then
  151.     IsOpen := False;
  152.   CloseFile := DoneOk;
  153.   End;
  154.  
  155.  
  156. Function FFileObj.BlkRead(Var V; Num: Word; Var NumRead: Word): Boolean;
  157.   Var
  158.     Tmp: LongInt;                      {Number of chars to write}
  159.     DoneOk: Boolean;
  160.  
  161.   Begin
  162.   If IoResult <> 0 Then;
  163.   DoneOk := IsOpen;
  164.   NumRead := 0;                        {Initialize number read to zero}
  165.   DoneOk := SeekFile(CurrPos);          {Make currpos valid}
  166.   While ((NumRead < Num) and (DoneOk)) Do
  167.     Begin
  168.     If BufChars = 0 Then
  169.       DoneOk := ReadBuffer;
  170.     Tmp := Num - NumRead;
  171.     If Tmp > (BufChars - (CurrPos - BufStart)) Then
  172.       Tmp := (BufChars - (CurrPos - BufStart));
  173.     Move(Buf^[CurrPos - BufStart], FBufType(V)[NumRead] , Tmp);
  174.     Inc(NumRead, Tmp);
  175.     DoneOk := SeekFile(CurrPos + Tmp);
  176.     If CurrPos >= CurrSize Then
  177.       Num := NumRead;
  178.     End;
  179.   BlkRead := DoneOk;
  180.   End;
  181.  
  182.  
  183. Function FFileObj.BlkWrite(Var V; Num: Word): Boolean;
  184.   Var
  185.     Tmp: LongInt;                      {Number of chars to write}
  186.     NumWritten: LongInt;               {Number of chars written}
  187.     DoneOk: Boolean;
  188.  
  189.   Begin
  190.   NumWritten := 0;
  191.   DoneOk := IsOpen;
  192.   While ((NumWritten < Num) and (DoneOk)) Do
  193.     Begin
  194.     Tmp := Num - NumWritten;  {num left to write}
  195.     If (CurrPos >= CurrSize) Then
  196.       Begin
  197.       If CurrPos - BufStart + Tmp > BufChars Then
  198.         BufChars := CurrPos - BufStart + Tmp;
  199.       If BufChars > BufSize Then
  200.         BufChars := BufSize;
  201.       End;
  202.     If Tmp > (BufChars - (CurrPos - BufStart)) Then
  203.       Tmp := (BufChars - (CurrPos - BufStart));
  204.     If ((Tmp > 0) and (DoneOk)) Then
  205.       Begin
  206.       Move(FBufType(V)[NumWritten], Buf^[CurrPos - BufStart] , Tmp);
  207.       Inc(NumWritten, Tmp);
  208.       NeedWritten := True;
  209.       End;
  210.     DoneOk := SeekFile(CurrPos + Tmp);
  211.     If DoneOk Then
  212.       Begin
  213.       If BufChars = 0 Then
  214.         Begin
  215.         If Num - NumWritten < BufSize Then
  216.           DoneOk := ReadBuffer
  217.         Else
  218.           BufChars := BufSize;
  219.         End;
  220.       End;
  221.     End;
  222.   BlkWrite := DoneOk;
  223.   End;
  224.  
  225.  
  226. Function FFileObj. SeekFile(FP: LongInt): Boolean;
  227.   Var
  228.     DoneOk: Boolean;
  229.  
  230.   Begin
  231.   DoneOk := IsOpen;
  232.   If (FP < BufStart) or (FP > (BufStart + BufChars - 1)) Then
  233.     Begin {not in buffer}
  234.     If (FP >= BufStart) and (FP < (BufStart + BufSize - 1)) and
  235.     (FP >= CurrSize) Then
  236.       Begin {Out of orig buffer but beyond eof and within bufsize}
  237.       CurrPos := FP;
  238.       If (CurrPos - BufStart) > BufChars Then
  239.         BufChars := CurrPos - BufStart;
  240.       End
  241.     Else
  242.       Begin {write buffer if needed and reposition}
  243.       If (NeedWritten and (BufChars > 0)) Then  {Write old buffer first if needed}
  244.         DoneOk := WriteBuffer;
  245.       BufStart := FP;
  246.       CurrPos := FP;
  247.       BufChars := 0;
  248.       End;
  249.     End
  250.   Else
  251.     Begin  {was within buffer}
  252.     CurrPos := FP;
  253.     End;
  254.   SeekFile := DoneOk;
  255.   End;
  256.  
  257.  
  258.  
  259. Function FFileObj.WriteBuffer: Boolean;
  260.   Var
  261.     DoneOK: Boolean;
  262.  
  263.   Begin
  264.   If IoResult <> 0 Then;
  265.   DoneOk := shSeekFile(BufFile, BufStart);
  266.   If DoneOk Then
  267.     DoneOk := shWrite(BufFile, Buf^, BufChars); {Write buffer}
  268.   If (BufStart + BufChars - 1) > CurrSize Then
  269.     CurrSize := BufStart + BufChars - 1;
  270.   If DoneOk Then
  271.     NeedWritten := False;              {Turn off needs-written flag}
  272.   WriteBuffer := DoneOk;               {Return result}
  273.   End;
  274.  
  275.  
  276. Function FFileObj.ReadBuffer: Boolean;
  277.   Var
  278.     DoneOK: Boolean;
  279.  
  280.   Begin
  281.   If IoResult <> 0 Then;
  282.   If NeedWritten Then
  283.     DoneOk := WriteBuffer;
  284.   Seek(BufFile, BufStart);
  285.   DoneOk := (ioResult = 0);            {Seek to buffer start first}
  286.   If DoneOk Then
  287.     Begin
  288.     If BufStart >= RawSize Then
  289.       BufChars := 0
  290.     Else
  291.       DoneOk := shRead(BufFile, Buf^, BufSize, BufChars); {Read buffer}
  292.     End;
  293.   ReadBuffer := DoneOk;               {Return result}
  294.   End;
  295.  
  296.  
  297. Function FFileObj.RawSize: LongInt;
  298.   Begin
  299.   If IoResult <> 0 Then;
  300.   RawSize := FileSize(BufFile);
  301.   If IoResult <> 0 Then;
  302.   End;
  303.  
  304.  
  305. Function FFileObj.FilePos: LongInt;
  306.   Begin
  307.   FilePos := CurrPos;
  308.   End;
  309.  
  310.  
  311. End.
  312.