{ File - Buffers                                 }
{ V. 0.003                                       }
{ Martijn Dijksterhuis                           }

{ Deze versie bevat slechts een read-ahead cache }
{ RvdW: gelukkig... }

{ History:

RvdW 27-02-93 FBufferClose aangepast, deze gaf het geheugen niet goed terug
              omdat eerst Size=0 gedaan werd en Size daarna werd gebruikt
              voor de lengte van het vrij te geven blok geheugen.
     27-02-93 FBReadLn bloedsnel gemaakt door vooruit te laten kijken en
              dan in een keer de hele string over te nemen. Volgende de
              profiler is een acties als "Regel:=Regel+Teken" heel erg
              traag. En als je naar de disassembly kijkt dan krijg je daar
              heel wat code voor... Dus voorkomen we dit vanaf nu!
     27-02-93 FBReadLn uitgebreid met een Return value -1 bij EOF. Anders
              liepen de UseNet routines in de soep.
MD   14-09-93 Toevoegen van FBSeek om random access mogenlijk te maken
     12-03-94 FBReadLn helemaal omgebouwd, de routine had problemen met
              het inlezen en correct afhandelen van de afbreek routines
              overlappende buffers etc.etc.
     16-04-94 De readln routine geeft nu het aantal werkelijk verwerkte
              tekens terug, dit omdat <CR><LF> combinaties als 1 teken
              werden gezien, wat problemen gaf bij JAM bases

RWI  05-11-94 FBBlockReadWhatsLeft toegevoegd voor exporteren JAM berichten.
     06-11-94 Hierbovengenoemde weer verwijderd. FBReadLnKeepEOL is de
              nieuwe routine om een regel uit een gecachete file te lezen
              en daarbij de CR's en LF's te behouden.
}

UNIT FBuffer;

{$i platform.inc}


INTERFACE

TYPE FBMemBlockPtr = ^FBMemBlock;
     FBMemBlock    = ARRAY[0..65528] OF CHAR;

     FBufferType = RECORD
                         Bestand  : FILE;                           { file }
                         Filename : STRING;
                         Buffer   : ^FBMemBlock;         { geheugen buffer }
                         RegelBuf : ARRAY[1..255] OF BYTE;
                         RegelLen : BYTE;
                         Curpos   : INTEGER;           { positie in buffer }
                         EndPos   : INTEGER;    { einde buffer in geheugen }
                         Size     : WORD;     { grootte buffer in geheugen }
                         Eof      : BOOLEAN;         { einde file bereikt? }
                   END;

FUNCTION  FBByteRead (VAR Invoer : FBufferType) : BYTE;
FUNCTION  FBReadNull (VAR Invoer : FBufferType) : STRING;
FUNCTION  FBReadLnCR (VAR Invoer : FBufferType; VAR Regel : STRING) : BOOLEAN;
FUNCTION  FBReadLnCRTell (VAR Invoer : FBufferType; VAR Regel : STRING; VAR TrashCount : WORD) : BOOLEAN;
FUNCTION  FBReadLnLF (VAR Invoer : FBufferType; VAR Regel : STRING) : BOOLEAN;
PROCEDURE FBReadSquishHdrLn (VAR Invoer : FBufferType; VAR Regel : STRING);
FUNCTION  FBBlockRead (VAR Invoer : FBufferType; VAR Opslag; Bytes : WORD) : BOOLEAN;
FUNCTION  FBBlockPeek (VAR Invoer : FBufferType; VAR Opslag; Bytes : WORD) : BOOLEAN;
FUNCTION  FBufferOpen (VAR Invoer : FBufferType; Naam : STRING; Size,FirstRead : WORD) : BOOLEAN;
PROCEDURE FBufferClose (VAR Invoer : FBufferType);
FUNCTION  FBSeek (VAR Invoer : FBufferType; Positie : LONGINT) : BOOLEAN;
PROCEDURE FBufferFreeCache (VAR Invoer : FBufferType); { RWI 960225 }
FUNCTION  FBSeekWrite (VAR FB : FBufferType; VAR Pos : LONGINT; VAR Data; Length : WORD) : BOOLEAN;
FUNCTION  FBSkipReadNul (VAR FB : FBufferType) : BOOLEAN;
FUNCTION  FBGetFilename (VAR FB : FBufferType) : STRING;

VAR LastFBufferError : BYTE;    { alleen na FBufferOpen op dit moment }


IMPLEMENTATION

USES Logs,
     Ramon,
     Dos,
     Globals,
     Strings;

{--------------------------------------------------------------------------}
{ FBufferFreeCache                                                         }
{                                                                          }
{ Deze routine kan gebruikt worden om het cache geheugen weer vrij te      }
{ geven. Er kan dan niets meer gelezen worden uit de file, maar deze       }
{ blijft nog wel open voor eventuele directe writes.                       }
{                                                                          }
PROCEDURE FBufferFreeCache (VAR Invoer : FBufferType);
BEGIN
     IF (Invoer.Buffer = NIL) THEN
        Exit; { already gone }

     FreeMem (Invoer.Buffer,Invoer.Size);
     Invoer.Buffer:=NIL;
END;


{--------------------------------------------------------------------------}
{ FBufferFill                                                              }
{                                                                          }
{ Deze routine haalt voor 1 buffer grootte aan gegevens uit de file. Als   }
{ er niet uit de file gelezen kan worden dan wordt een foutmelding geLogt  }
{ en de file gesloten. De velden van Invoer worden gezet aan de hand van   }
{ het aantal ingelezen bytes en het mogelijk bereikte einde van de file.   }
{                                                                          }
FUNCTION FBufferFill (VAR Invoer : FBufferType) : BOOLEAN;

VAR Inlees : WordLong;
    IORes  : BYTE;

BEGIN
     IF (Invoer.Buffer = NIL) THEN
     BEGIN
          FBufferFill:=FALSE;
          LogMessage (liReport,'[FBufferFill] Cache has been disabled; cannot read.');
          Exit;
     END;

     {$I-} BlockRead (Invoer.Bestand,Invoer.Buffer^,Invoer.Size,Inlees); {$I+}
     IORes:=IOResult;

     IF (IORes <> 0) THEN
     BEGIN
          LogDiskIOError (IORes,'[FBufferFill] Unable to read from file');
          FBufferFill:=FALSE;
          {$IFDEF LogFileIO}PreCloseF (Invoer.Bestand);{$ENDIF}
          Close (Invoer.Bestand);
          Exit;
     END;

     { Einde van de file bereikt, en dus misschien minder ingelezen ? }
     WITH Invoer DO
          IF (Inlees < Size) THEN
          BEGIN
               EndPos:=Inlees;
               Eof:=TRUE;
          END ELSE
              EndPos:=Size;

     { Buffer pointer naar begin }
     Invoer.CurPos:=0;
     FBufferFill:=TRUE;
END;


{-------------------------------------------------------------------------}
{ FBByteRead                                                              }
{                                                                         }
{ Deze routine leest een enkel teken uit de buffer.                       }
{                                                                         }
FUNCTION FBByteRead (VAR Invoer : FBufferType) : BYTE;
BEGIN
     WITH Invoer DO
     BEGIN
          IF (CurPos < EndPos) THEN
          BEGIN
               FBByteRead:=Byte (Buffer^[CurPos]);
               Inc (CurPos);
          END ELSE
          BEGIN
               IF (NOT Eof) THEN
                  IF (NOT FBufferFill (Invoer)) THEN
                  BEGIN
                       LogMessage (liDebug,'[FBByteRead] Read error on byte read');
                       FBByteRead:=0;
                  END ELSE
                  BEGIN
                       FBByteRead:=Byte (Buffer^[CurPos]);
                       Inc (CurPos);
                  END ELSE
                      FBByteRead := 0;
          END;
     END; { with }
END;


{--------------------------------------------------------------------------}
{ FBReadNull                                                               }
{                                                                          }
{ Deze routine leest een aantal tekens uit de file tot en met een 0 of het }
{ opgegeven aantal tekens. De uitgelezen tekens (behalve de 0) worden als  }
{ String terug gegeven.                                                    }
{                                                                          }
FUNCTION FBReadNull (VAR Invoer : FBufferType) : STRING;

VAR Teken  : BYTE;
    Count  : BYTE;
    OrgPos : WORD;
    Regel  : STRING;

BEGIN
     { De oude routine ging op zijn bek toen er een bericht doorkwam }
     { met een rotte header, dit is nu een aangepaste versie van     }
     { readln , die alleen controleer of de regel op een NULL        }
     { eindigd.                                                      }

     { stukje ingevoegde code om sneller door het buffer heen te rossen }
     WITH Invoer DO
     BEGIN
          Count:=0;
          OrgPos:=CurPos;

          WHILE (CurPos < EndPos) AND
                (NOT (Buffer^[CurPos] = #0)) AND
                (Count < 255) DO
          BEGIN
               Inc (Count);
               Inc (CurPos);
          END; { while }

          IF (Count > 0) THEN
             Move (Buffer^[OrgPos],Regel[1],Count);

          Regel[0]:=Char (Count);
          FBReadNull := Regel;

          IF (CurPos <> EndPos) THEN
          BEGIN
               Inc (CurPos);
               Exit;
          END;
     END; { with }

     REPEAT
           Teken:=FBByteRead (Invoer);
           IF (Teken <> 0) THEN
              Regel:=Regel+Chr (Teken);
     UNTIL (Teken = 0);
END;


{--------------------------------------------------------------------------}
{ FBReadLnCR                                                               }
{                                                                          }
{ Deze routine leest een regel uit een file. Hierbij wordt de CR als einde }
{ van de regel gezien en verder alle LF's eruit gehaald. Als er binnen 255 }
{ tekens geen CR of LF gevonden wordt, dan wordt gewoon de hele regel      }
{ terug gegeven zonder een CR erin.                                        }
{ Als er een NULL in voorkomt, dan wordt die apart teruggegeven.           }
{ Het resultaat van de functie is FALSE als het fysieke einde van de file  }
{ bereikt is, anders TRUE.                                                 }
{                                                                          }
FUNCTION FBReadLnCRTell (VAR Invoer : FBufferType; VAR Regel : STRING; VAR TrashCount : WORD) : BOOLEAN;

VAR FoundEnd : BOOLEAN;
    Teken    : CHAR;

BEGIN
     {# hele routine versnellen met assembly }

     TrashCount:=0;
     WITH Invoer DO
     BEGIN
          { vul het buffer aan zodat er altijd minimaal 255 tekens in }
          { zitten, tenzij we aan het einde van de file zitten.       }
          IF ((EndPos-CurPos) < 260) AND (NOT Eof) THEN
          BEGIN
               { terug naar de byte in de file die nu ook vooraan in het }
               { buffer staat.                                           }
               Seek (Bestand,FilePos (Bestand)-(EndPos-CurPos));
               FBufferFill (Invoer);
          END;

          IF Eof AND (EndPos = CurPos) THEN
          BEGIN
               Regel:='';
               FBReadLnCRTell:=FALSE; { einde van de file bereikt }
               Exit;
          END;

          FBReadLnCRTell:=TRUE; { nog niet het einde van de file bereikt }

          { kijk of we een #0 tegen zijn gekomen, die wordt namelijk apart }
          { terug gegeven voor de liefhebber.                              }
          IF (Buffer^[CurPos] = #0) THEN
          BEGIN
               Regel:=#0;
               Inc (CurPos);
               Exit;
          END;

          Regel:='';
          FoundEnd:=FALSE;
          REPEAT
                Teken:=Buffer^[CurPos];

                IF (Teken IN [#0,#13]) THEN
                   FoundEnd:=TRUE;

                IF (NOT (Teken IN [#0,#10])) THEN
                   Regel:=Regel+Teken
                ELSE
                    Inc (TrashCount);

                IF (Teken <> #0) THEN
                   Inc (CurPos);

          UNTIL FoundEnd OR (CurPos = EndPos) OR (Length (Regel) = 255);
     END; { with }
END;

FUNCTION FBReadLnCR (VAR Invoer : FBufferType; VAR Regel : STRING) : BOOLEAN;

VAR Dummy : WORD;

BEGIN
     FBReadLnCR:=FBReadLnCRTell (Invoer,Regel,Dummy);
END;


{--------------------------------------------------------------------------}
{ FBReadLnLF                                                               }
{                                                                          }
{ Zelfde als FBReadLnCR, maar de CR is dan een LF. Het afsluitteken dat    }
{ toegevoegd wordt is wel een CR!!                                         }
{                                                                          }
FUNCTION FBReadLnLF (VAR Invoer : FBufferType; VAR Regel : STRING) : BOOLEAN;

VAR FoundEnd : BOOLEAN;
    Teken    : CHAR;

BEGIN
     {## hele routine versnellen met assembly }
     WITH Invoer DO
     BEGIN
          { vul het buffer aan zodat er altijd minimaal 255 tekens in }
          { zitten, tenzij we aan het einde van de file zitten.       }
          IF ((EndPos-CurPos) < 260) AND (NOT Eof) THEN
          BEGIN
               { terug naar de byte in de file die nu ook vooraan in het }
               { buffer staat.                                           }
               Seek (Bestand,FilePos (Bestand)-(EndPos-CurPos));
               FBufferFill (Invoer);
          END;

          IF Eof AND (EndPos = CurPos) THEN
          BEGIN
               Regel:='';
               FBReadLnLF:=FALSE; { einde van de file bereikt }
               Exit;
          END;

          FBReadLnLF:=TRUE; { nog niet het einde van de file bereikt }

          Regel:='';
          FoundEnd:=FALSE;
          REPEAT
                Teken:=Buffer^[CurPos];

                IF (Teken IN [#10,#0]) THEN
                   FoundEnd:=TRUE;

                IF (Teken <> #13) THEN
                BEGIN
                     IF (Teken = #10) THEN
                        Teken:=#13;

                     Regel:=Regel+Teken;
                END;

                Inc (CurPos);

          UNTIL FoundEnd OR (CurPos = EndPos) OR (Length (Regel) = 255);
     END; { with }
END;


{--------------------------------------------------------------------------}
{ FBReadSquishHdrLn                                                        }
{                                                                          }
{ Deze routine is speciaal voor squish header regels met kludges. Als een  }
{ regel met #1 begint, dan geeft de volgende #1 het begin van de volgende  }
{ regel aan. Een #0 is het einde van de header en wordt apart terug        }
{ gegeven.                                                                 }
{                                                                          }
PROCEDURE FBReadSquishHdrLn (VAR Invoer : FBufferType; VAR Regel : STRING);

VAR FoundEnd : BOOLEAN;
    Teken    : CHAR;

BEGIN
     WITH Invoer DO
     BEGIN
          { vul het buffer aan zodat er altijd minimaal 255 tekens in }
          { zitten, tenzij we aan het einde van de file zitten.       }
          IF ((EndPos-CurPos) < 260) AND (NOT Eof) THEN
          BEGIN
               { terug naar de byte in de file die nu ook vooraan in het }
               { buffer staat.                                           }
               Seek (Bestand,FilePos (Bestand)-(EndPos-CurPos));
               FBufferFill (Invoer);
          END;

          IF Eof AND (EndPos = CurPos) THEN
          BEGIN
               Regel:=#0;
               Exit;
          END;

          IF (Buffer^[CurPos] = #0) THEN
          BEGIN
               Regel:=#0;
               Inc (CurPos);
               Exit;
          END;

          Regel:='';
          FoundEnd:=FALSE;
          REPEAT
                Teken:=Buffer^[CurPos];

                IF (Teken IN [#0,#13]) THEN
                   FoundEnd:=TRUE;

                IF (Regel <> '') AND (Teken = #1) THEN
                BEGIN
                     { begin van volgende header }
                     FoundEnd:=TRUE;
                     Break;
                END;

                IF (NOT (Teken IN [#0,#10])) THEN
                   Regel:=Regel+Teken;

                IF (Teken <> #0) THEN
                   Inc (CurPos);

          UNTIL FoundEnd OR (CurPos = EndPos) OR (Length (Regel) = 255);

     END; { with }
END;


{--------------------------------------------------------------------------}
{ FBBlockRead                                                              }
{                                                                          }
{ Deze routine doet een BlockRead uit het read-ahead buffer.               }
{ Returns FALSE when not enough bytes are available, otherwise returns the }
{ requested number of bytes and returns TRUE.                              }
{                                                                          }
FUNCTION FBBlockRead (VAR Invoer : FBufferType; VAR Opslag; Bytes : WORD) : BOOLEAN;

VAR Gedaan : WORD;

BEGIN
     Gedaan:=0;

     { wordt er meer gevraagt dan er in de file kan zitten? }
     WITH Invoer DO
     BEGIN
          { RAWI 970226: was >= }
          IF (Bytes > (EndPos-CurPos)) AND Eof THEN
          BEGIN
               FBBlockRead:=FALSE;
               Exit;
          END;

          REPEAT
                IF (Bytes-Gedaan) > (EndPos-CurPos) THEN
                BEGIN
                     Move (Buffer^[CurPos],Opslag,EndPos-CurPos);
                     Gedaan:=Gedaan+(EndPos-CurPos);

                     IF (NOT FBufferFill (Invoer)) THEN
                     BEGIN
                          FBBLockRead:=FALSE;
                          LogMessage (liFatal,'[FBBlockRead] Buffer read failed');
                          Exit;
                     END;
                END ELSE
                BEGIN
                     Move (Buffer^[CurPos],Opslag,Bytes-Gedaan);
                     CurPos:=CurPos+(Bytes-Gedaan);
                     Gedaan:=Gedaan+(Bytes-Gedaan );
                END; { if}

          UNTIL (Gedaan >= Bytes);
     END; { with }

     FBBlockRead:=TRUE;
END;


{---------------------------------------------------------------------------}
{ FBBlockReadWhatsLeft                                                      }
{                                                                           }
{ Deze routine leest een blok uit de file voor zover er nog wat in zit. Als }
{ er minder in zit dan we willen hebben, dan wordt de rest terug gegeven.   }
{ Het resultaat van deze functie is het werkelijk aantal teruggegeven       }
{ tekens.                                                                   }
{ Omdat de kludges niet goed verwerkt worden bij het exporteren van een     }
{ bericht in blokken, wordt het einde van het blok nu ook bepaald door een  }
{ CR in de file.                                                            }
{                                                                           }
FUNCTION FBBlockReadWhatsLeft (VAR Invoer : FBufferType; VAR Opslag; Bytes : WORD) : WORD;

VAR DoCopy : WORD;

BEGIN
     WITH Invoer DO
          IF Eof AND (EndPos = CurPos) THEN
             FBBlockReadWhatsLeft:=0  { einde bereikt, niets meer over! }
          ELSE BEGIN
               IF (Bytes > (EndPos-CurPos)) THEN
               BEGIN
                    FOR DoCopy:=CurPos TO EndPos DO
                        IF (Buffer^[DoCopy] = #13) THEN
                           Break;

                    Bytes:=DoCopy-CurPos+1;
                    Move (Buffer^[CurPos],Opslag,Bytes);
                    FBBlockReadWhatsLeft:=Bytes;

                    IF (NOT FBufferFill (Invoer)) THEN
                       LogMessage (liFatal,'[FBBlockReadWhatsLeft] Buffer refill failed');
               END ELSE
               BEGIN
                    FOR DoCopy:=CurPos TO CurPos+Bytes DO
                        IF (Buffer^[DoCopy] = #13) THEN
                           Break;

                    Bytes:=DoCopy-CurPos+1;
                    Move (Buffer^[CurPos],Opslag,Bytes);
                    CurPos:=CurPos+Bytes;
                    FBBlockReadWhatsLeft:=Bytes;
               END;
          END;
END;


{--------------------------------------------------------------------------}
{ FBBlockPeek                                                              }
{                                                                          }
{ Deze routine doet een BlockRead uit het read-ahead buffer, maar verhoogd }
{ de ophaal pointer niet. Bij de eerstevolgende read kan de data dus als-  }
{ nog ingelezen worden. Dit is handig om te kijken of een file een bepaal- }
{ de header heeft, bijvoorbeeld CunBatch enzo...                           }
{ De peek moet uitgevoerd worden op het huidige buffer. Als daar niet      }
{ genoeg in zit, dan werkt de peek niet. Door een Open wordt het buffer    }
{ al voor de eerste keer gevuld.                                           }
{                                                                          }
FUNCTION FBBlockPeek (VAR Invoer : FBufferType; VAR Opslag; Bytes : WORD) : BOOLEAN;
BEGIN
     WITH Invoer DO
     BEGIN
          { moeten genoeg bytes nog in de file zitten voor de peek }
          IF (Bytes >= (EndPos-CurPos)) AND Eof THEN
          BEGIN
               FBBlockPeek:=FALSE;
               Exit;
          END;

          { peek moet binnen dit buffer gebeuren }
          IF (Bytes > (EndPos-CurPos)) THEN
          BEGIN
               FBBlockPeek:=FALSE;
               Exit;
          END;

          {$R-} Move (Buffer^[CurPos],Opslag,Bytes); {$R+}
     END; { with }

     FBBlockPeek:=TRUE;
END;


{--------------------------------------------------------------------------}
{ FBSeek                                                                   }
{                                                                          }
{ Flusht de buffer en verplaatst de filepointer naar de positie die        }
{ opgegeven werd.                                                          }
{                                                                          }
FUNCTION FBSeek (VAR Invoer : FBufferType; Positie : LONGINT) : BOOLEAN;

VAR IORes : BYTE;

BEGIN
     {$I-} Seek (Invoer.Bestand,Positie); {$I+}
     IORes:=IOResult;

     IF (IORes <> 0) THEN
     BEGIN
          FBSeek:=FALSE;
          Exit;
     END;

     FBSeek:=FBufferFill (Invoer);
END;


{--------------------------------------------------------------------------}
{ FBufferOpen                                                              }
{                                                                          }
{ Opent een file, en creert een buffer waaruit gelezen kan worden door     }
{ speciale routines. (zie hierboven) Als het openen gelukt is wordt TRUE   }
{ terug gegeven, anders FALSE.                                             }
{                                                                          }
{ File zit in Buffer file                                                  }
{ Naam   : verwijzing naar file                                            }
{ Size   : grootte van het read-ahead buffer in bytes                      }
{                                                                          }
FUNCTION FBufferOpen (VAR Invoer : FBufferType; Naam : STRING; Size,FirstRead : WORD) : BOOLEAN;

VAR IORes  : BYTE;
    Inlees : INTEGER;

BEGIN
     Invoer.Buffer:=NIL; { RWI950322 ivm controle bij FreeMem }
     Invoer.Filename:=Naam;

     Assign (Invoer.Bestand,Naam);
     FileMode:=fmReadWrite+fmDenyNone;
     {$I-} Reset (Invoer.Bestand,1); {$I-} IORes:=IOResult;
     IF (IORes <> 0) THEN
     BEGIN
          LastFBufferError:=IORes;
          FBufferOpen:=FALSE;
          Exit;
     END;

     {$IFDEF LogFileIO}PostOpenF (Invoer.Bestand);{$ENDIF}

     { Vraag geheugen aan }
     Invoer.Size:=Size;
     IF (Size <= 65000) AND (Size < _MaxAvail) THEN
     BEGIN
          GetMem (Invoer.Buffer,Invoer.Size);
          {$IFDEF LogGetMem} LogGetMem (Invoer.Buffer,Invoer.Size,'FBufferOpen'); {$ENDIF}
          PeekMem;
     END ELSE
     BEGIN
          LogMessage (liFatal,'[FBufferOpen] Unable to allocate enough memory for buffer');
          FBufferOpen:=FALSE;
          {$IFDEF LogFileIO}PreCloseF (Invoer.Bestand);{$ENDIF}
          Close (Invoer.Bestand);
          Exit;
     END;

     { Buffer first init Ok }
     Invoer.Curpos:=0;
     Invoer.Eof:=FALSE;

     IF (FirstRead > Size) THEN
     BEGIN
          LogMessage (liDebug,'[FBufferOpen] FirstRead > Size!!');
          FirstRead:=Size;
     END;

     IF (FirstRead <> 0) THEN
        Invoer.Size:=FirstRead; { voor FBufferFill }

     IF (NOT FBufferFill (Invoer)) THEN
     BEGIN
          Invoer.Size:=Size; { herstellen, ook ivm FreeMem }
          LogMessage (liFatal,'[FBufferOpen] Got failure from FBufferFill');
          FBufferOpen:=FALSE;
          {$IFDEF LogFileIO}PreCloseF (Invoer.Bestand);{$ENDIF}
          Close (Invoer.Bestand);
          Exit;
     END;

     Invoer.Size:=Size; { herstellen }

     PeekFiles;

     FBufferOpen:=TRUE;
END;


{--------------------------------------------------------------------------}
{ FBufferClose                                                             }
{                                                                          }
{ Deze routine sluit de file en geeft het geheugen van de buffer weer      }
{ vrij.                                                                    }
{                                                                          }
PROCEDURE FBufferClose (VAR Invoer : FBufferType);

VAR IORes : BYTE;

BEGIN
     WITH Invoer DO
     BEGIN
          { controle op NIL was toch wel belangrijk... }
          IF (Buffer <> NIL) THEN
          BEGIN
               FreeMem (Buffer,Size);
               Buffer:=NIL;
          END;

          { RWI 950322: toevoeging met IORes en $I-/+ want de fout van deze }
          {             Close werd niet verwerk (als de file niet open was) }
          {             en kwam ergens anders in het programma dan eens op! }
          {$IFDEF LogFileIO}PreCloseF (Bestand);{$ENDIF}
          {$I-} Close (Bestand); {$I+} IORes:=IOResult;
          PeekFiles;

          Size:=0;
          CurPos:=0;
          EndPos:=0;
          Eof:=TRUE;
     END; { case }
END;


{--------------------------------------------------------------------------}
{ FBSeekWrite                                                              }
{                                                                          }
{ Deze routine schrijft een blok naar disk op de opgegeven positie en zet  }
{ daarna de lees pointer en zet daarna de file pointer terug naar de       }
{ oude positie zodat er gewoon doorgelezen kan worden.                     }
{                                                                          }
FUNCTION FBSeekWrite (VAR FB : FBufferType; VAR Pos : LONGINT; VAR Data; Length : WORD) : BOOLEAN;

VAR IORes  : BYTE;
    OldPos : LONGINT;

BEGIN
     {$I-} OldPos:=FilePos (FB.Bestand); {$I+} IORes:=IOResult;
     IF (IORes <> 0) THEN
     BEGIN
          LogDiskIOError (IORes,'[FBSeekWrite] Failed to get file position');
          Exit;
     END;

     {$I-} Seek (FB.Bestand,Pos); {$I+} IORes:=IOResult;
     IF (IORes = 0) THEN
     BEGIN
          {$I-} BlockWrite (FB.Bestand,Data,Length); {$I+} IORes:=IOResult;
          Pos:=FilePos (FB.Bestand);
     END;

     IF (IORes <> 0) THEN
        LogDiskIOError (IORes,'[FBSeekWrite] Failed to write block');

     FBSeekWrite:=(IORes = 0);

     {$I-} Seek (FB.Bestand,OldPos); {$I+} IORes:=IOResult; { ignore }
END;


{--------------------------------------------------------------------------}
{ FBSkipReadNul                                                            }
{                                                                          }
{ This routine scans the rest of the file until it finds a #0. It returns  }
{ TRUE when the NUL is found, otherwise FALSE (end of file). The FBuffer   }
{ is ready for reading the next byte when it has found the #0.             }
{                                                                          }
FUNCTION FBSkipReadNul (VAR FB : FBufferType) : BOOLEAN;

VAR Ch : CHAR;

BEGIN
     FBSkipReadNul:=FALSE; { assume no NUL found }

     WITH FB DO
     BEGIN
          REPEAT
                { check the read data for a #0 }
                WHILE (CurPos < EndPos) DO
                BEGIN
                     IF (Buffer^[CurPos] = #0) THEN
                     BEGIN
                          FBSkipReadNul:=TRUE; { found! }
                          Inc (CurPos);
                          Exit; { ## EXIT ## }
                     END;

                     Inc (CurPos);
                END; { while }

                { read a new block }
                IF (NOT FBufferFill (FB)) THEN
                BEGIN
                     LogMessage (liFatal,'[FBSkipReadNul] Read error on byte read');
                     Exit; { ## EXIT ## }
                END;

          UNTIL Eof AND (CurPos = EndPos);
     END; { with }

     { returns with FALSE }
END;


{--------------------------------------------------------------------------}
{ FBGetFilename                                                            }
{                                                                          }
{ This routine returns the file name assigned to the FBufferType.          }
{                                                                          }
FUNCTION FBGetFilename (VAR FB : FBufferType) : STRING;
BEGIN
     FBGetFilename:=StrPas (FileRec (FB.Bestand).Name);
END;


{ no unit initialization block }
END.
