home *** CD-ROM | disk | FTP | other *** search
/ Delphi Developer's Kit 1996 / Delphi Developer's Kit 1996.iso / power / acc_obj0 / u_egb_0a.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-12-22  |  10.2 KB  |  262 lines

  1. UNIT U_EGB_0a;                           {Last mod by JFH on 07/20/95}
  2.  
  3. { DEFINITION OF SOME BASIC FILE IO CLASSES }
  4.  
  5. { Includes:
  6.   tBufferedFileScanner -- Buffered file reader class returns a
  7.       pointer to data in its buffer.
  8.   tBufTextFileScanner -- Text file reader class returns a pointer
  9.       to data in its buffer.  The text records can be longer than
  10.       a string type can hold.
  11.   tBufTextStringFileReader -- Uses tBufTextFileScanner to return an
  12.       actual string rather than a pointer.
  13.   t123RecScanner -- This reads the type-length word record header
  14.       system of Lotus.  (I have found this useful for several
  15.       applications.)
  16.  
  17. { What could have been included:
  18.   (1) Buffered file reader for returning the data rather than a
  19.       pointer.
  20.   (2) An abstract type that would have taken an byte position within
  21.       the file and a number of bytes to be fetched and returned a
  22.       pointer or the data.
  23.   (3) A simple version controlled fixed length record file system
  24.       that would allow the records to have new fields added to the
  25.       end of the records, such that new programs could read old data
  26.       and new data could be used by old programs.
  27.   (4) A partitioned file system that would all navagating through
  28.       huge variable length record files without having to scan record
  29.       by record.
  30.  
  31. { Pgm. 07/15/95 by John F Herbster }
  32.  
  33. {=====} interface {====================================================}
  34.  
  35. USES SysUtils; {for pByteArray and tFilename}
  36.  
  37. TYPE
  38.   tBufferedFileScanner = class
  39.     Constructor Create
  40.       (const aPath: tFilename; aSizeOfClusters,aMaxRecLgh: word);
  41.     { creates the object to read file named in aPath, gets a buffer,
  42.       opens the file, and sets up the pointers. }
  43.     Function EOF: boolean;
  44.     { rtns true if the read position is at or beyond the end of file.}
  45.     Function LocNextFixedLghRec
  46.         (var pRec: pByteArray; const NbrReqd: word): boolean;
  47.     { brings the next NbrReqd bytes of data into its buffer and rtns
  48.       true and a byte array pointer to the data if found.  The data
  49.       itself is not transfered and the pointer will be invalid after
  50.       another call to this object.  If all of the requested data can-
  51.       not be found, then false is returned. }
  52.     Function LocNextVarLghRec
  53.         (var pRec: pByteArray; var NbrFound: word): boolean; virtual;
  54.     { brings in up to the MaxLghRec number of bytes of data into its
  55.       buffer and if at least one byte was found, then rtns true, a
  56.       byte array pointer to the data, and the number of bytes found,
  57.       up to the MaxLghRec number.  The data itself is not transfered
  58.       and the pointer will be invalid after another call to this
  59.       object.  If all of the requested data cannot be found, then
  60.       false is returned. }
  61.     Destructor Destroy;                         override;
  62.     protected
  63.     Chan: file;
  64.     SizeOfFile, fPrevPos, fCurPos: longint;
  65.     SizeOfCluster, MaxLghRec, SizeOfBuf, DataLimInBuf,
  66.     PrevIndex,CurIndex: word;
  67.     pBuf: pByteArray;
  68.     Procedure RefillBuffer;
  69.     end;
  70.  
  71. TYPE
  72.   tBufTextFileScanner = class (tBufferedFileScanner)
  73.     LnNbr: longint;
  74.     Constructor Create
  75.       (const aPath: tFilename; aSizeOfClusters,aMaxRecLgh: word);
  76.     { creates the object to read text file named in aPath, gets a
  77.       buffer, opens the file, and sets up the pointers. }
  78.     Function LocNextVarLghRec
  79.       (var pRec: pByteArray; var NbrFound: word): boolean; override;
  80.     { brings in up to the MaxLghRec number of bytes of data into its
  81.       buffer and searches for the CR.  If the CR was found, then rtns
  82.       true, a byte array pointer to the data, and the number of bytes
  83.       found, not including the CR.  The data itself is not transfered
  84.       and the pointer will be invalid after another call to this
  85.       object.  If a CR cannot be found with in the MaxLghRec number
  86.       of bytes then false is returned. (Note possible problem here
  87.       if last line has no last CR!!)}
  88.     end;
  89.  
  90. TYPE
  91.   tBufTextStringFileReader = class (tBufTextFileScanner)
  92.     Constructor Create
  93.       (const aPath: tFilename; aSizeOfClusters: word);
  94.     { creates the object to read text file named in aPath, gets a
  95.       buffer, opens the file, and sets up the pointers. }
  96.     Function GotLine (var Line: string): boolean;
  97.     { brings in up to 256 bytes of data into the buffer and searches
  98.       for the CR.  If the CR was found, then rtns true and the line
  99.       found, not including the CR or LF in a Pascal string.  If a CR
  100.       cannot be found with in the 256 bytes then false is returned.
  101.       (Note possible problem here if last line has no last CR!!)}
  102.     end;
  103.  
  104. TYPE
  105.   t123Header = record RecTypeH, RecLghH: word end;
  106.   p123Header = ^t123Header;
  107.   tBuf123RecScanner = class (tBufferedFileScanner)
  108.     Constructor Create
  109.       (const aPath: tFilename; aBufferSize,  MaxLghRec: word);
  110.     { creates the object to read text file named in aPath, gets a
  111.       buffer, opens the file, and sets up the pointers. }
  112.     Function LocNextRec
  113.         (var RecType, RecLgh: word; var pRec: pByteArray): boolean;
  114.     { brings in up to MaxLghRec bytes into buffer and returns the
  115.       type of the record, the length of the record, and pointer to
  116.       the data part of the record (just past header). }
  117.     end;
  118.  
  119. {=====} IMPLEMENTATION {===============================================}
  120.  
  121. Constructor tBufferedFileScanner.Create
  122.   (const aPath: tFilename; aSizeOfClusters,aMaxRecLgh: word);
  123.   Begin
  124.   Inherited Create;
  125.   Assign (Chan,aPath); Reset(Chan,1); SizeOfFile:=FileSize(Chan);
  126.   SizeOfCluster:=aSizeOfClusters; MaxLghRec:=aMaxRecLgh;
  127.   SizeOfBuf:=SizeOfCluster+MaxLghRec; GetMem(pBuf,SizeOfBuf);
  128.   End;
  129.  
  130. Destructor tBufferedFileScanner.Destroy;
  131.   Begin
  132.   If SizeOfBuf>0
  133.     then FreeMem(PBuf,SizeOfBuf);
  134.   Inherited Destroy;
  135.   End;
  136.  
  137. Function tBufferedFileScanner.EOF: boolean;
  138.   Begin Result:=fCurPos<SizeOfFile End;
  139.  
  140. Procedure tBufferedFileScanner.RefillBuffer;
  141.   Var n,i: word;
  142.   Begin
  143.     n:=DataLimInBuf-CurIndex;   {# bytes to move}
  144.     i:=MaxLghRec-n;             {Dest. for first}
  145.     If n>0 then Move(pBuf^[CurIndex],pBuf^[i],n);
  146.     CurIndex:=i;                {New buffer index}
  147.     BlockRead(Chan,pBuf^[MaxLghRec],SizeOfCluster,n);
  148.     DataLimInBuf:=MaxLghRec+n;  {New limit of data in buf.}
  149.   End;
  150.  
  151. Function tBufferedFileScanner.LocNextFixedLghRec
  152.     (var pRec: pByteArray; const NbrReqd: word): boolean;
  153.   Begin
  154.   If (fCurPos<0) or (fCurPos+NbrReqd>SizeOfFile)
  155.     then begin Result:=false; EXIT end;
  156.   If CurIndex+NbrReqd>DataLimInBuf
  157.       then RefillBuffer;
  158.   fPrevPos:=fCurPos;   fCurPos:=fCurPos+NbrReqd;
  159.   PrevIndex:=CurIndex; CurIndex:=CurIndex+NbrReqd;
  160.   Result:=true;
  161.   pRec:=@pBuf^[PrevIndex];
  162.   End;
  163.  
  164. Function tBufferedFileScanner.LocNextVarLghRec
  165.       (var pRec: pByteArray; var NbrFound: word): boolean;
  166.   Begin
  167.   If (fCurPos<0) or (fCurPos+1>SizeOfFile)
  168.     then begin Result:=false; EXIT end;
  169.   If CurIndex+MaxLghRec>DataLimInBuf
  170.       then RefillBuffer;
  171.   If DataLimInBuf-CurIndex<MaxLghRec
  172.     then NbrFound:=DataLimInBuf-CurIndex
  173.     else NbrFound:=MaxLghRec;
  174.   PrevIndex:=CurIndex; CurIndex:=CurIndex+NbrFound;
  175.   fPrevPos:=fCurPos;   fCurPos:=fCurPos+NbrFound;
  176.   Result:=true;
  177.   pRec:=@pBuf^[PrevIndex];
  178.   End;
  179.  
  180. Constructor tBufTextFileScanner.Create
  181.   (const aPath: tFilename; aSizeOfClusters,aMaxRecLgh: word);
  182.   Begin Inherited Create(aPath,aSizeOfClusters,aMaxRecLgh+2) End;
  183.  
  184. Function tBufTextFileScanner.LocNextVarLghRec
  185.       (var pRec: pByteArray; var NbrFound: word): boolean;
  186.   Var n,i,j: word; Const CR=byte(^M); LF=byte(^J);
  187.   Begin
  188.     If Inherited LocNextVarLghRec(pRec,n)
  189.       then begin {Scan for the CR-LF.}
  190.         i:=PrevIndex; j:=i+n;  {Limit for search.}
  191.         While (i<j) and (pBuf^[i]<>CR) do inc(i); {Inc till at CR}
  192.         If i>=j {Past the end?}
  193.           then begin {If not located, then revert to previous pos.}
  194.             Result:=false;
  195.             CurIndex:=PrevIndex; fCurPos:=fPrevPos;
  196.             end
  197.           else begin
  198.             Result:=true; Inc(LnNbr);
  199.             NbrFound:=i-PrevIndex; CurIndex:=PrevIndex+NbrFound+1;
  200.             If (CurIndex<DataLimInBuf) and (pBuf^[CurIndex]=LF)
  201.               then inc(CurIndex);  {Allow LF to be optional.}
  202.             fCurPos:=fPrevPos+(CurIndex-PrevIndex);
  203.             end;
  204.         end
  205.       else Result:=false;
  206.   End;
  207.  
  208. Constructor tBufTextStringFileReader.Create
  209.   (const aPath: tFilename; aSizeOfClusters: word);
  210.   Begin Inherited Create(aPath,aSizeOfClusters,256) End;
  211.  
  212. Function tBufTextStringFileReader.GotLine (var Line: string): boolean;
  213. { brings in up to 256 bytes of data into the buffer and searches
  214.   for the CR.  If the CR was found, then rtns true and the line
  215.   found, not including the CR or LF in a Pascal string.  If a CR
  216.   cannot be found with in the 256 bytes then false is returned.
  217.   (Note possible problem here if last line has no last CR!!)}
  218.   Var pRec: pByteArray; NbrFound: word;
  219.   Begin
  220.   If LocNextVarLghRec(pRec,NbrFound)
  221.     then begin
  222.       Result:=true;
  223.       byte(Line[0]):=NbrFound;
  224.       Move(pRec^,Line[1],NbrFound);
  225.       end
  226.     else Result:=false;
  227.   End;
  228.  
  229. Constructor tBuf123RecScanner.Create
  230.   (const aPath: tFilename; aBufferSize,  MaxLghRec: word);
  231. { creates the object to read text file named in aPath, gets a
  232.   buffer, opens the file, and sets up the pointers. }
  233.   Begin
  234.     Inherited Create(aPath,aBufferSize,MaxLghRec+SizeOf(t123Header));
  235.   End;
  236.  
  237. Function tBuf123RecScanner.LocNextRec
  238.     (var RecType, RecLgh: word; var pRec: pByteArray): boolean;
  239. { brings in up to MaxLghRec bytes into buffer and returns the
  240.   type of the record, the length of the record, and pointer to
  241.   the data part of the record (just past header). }
  242.   Var p: pByteArray; n: word;
  243.   Begin
  244.     If LocNextVarLghRec(p,n)
  245.       then with p123Header(p)^ do begin
  246.         If RecLghH<=n-2
  247.           then begin
  248.             Result:=true;
  249.             RecType:=RecTypeH;
  250.             RecLgh:=RecLghH;
  251.             fCurPos:=fPrevPos+RecLgh+SizeOf(t123Header);
  252.             CurIndex:=PrevIndex+RecLgh+SizeOf(t123Header);
  253.             pRec:=@pByteArray(p)^[SizeOf(t123Header)];
  254.             end
  255.           else Result:=false;
  256.         end
  257.       else Result:=false;
  258.   End;
  259.  
  260. {=====} end. {=========================================================}
  261.  
  262.