home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Think Class Libraries / CTextFile 1.1 / CTextFile.p < prev    next >
Encoding:
Text File  |  1994-11-30  |  11.2 KB  |  355 lines  |  [TEXT/PJMM]

  1. unit CTextFile;
  2. {CTextFile v1.1 © 1992 by William Studenmund. For distribution info,}
  3. {please see attached About file. This class impliments a TEXT file à la}
  4. {THINK Pascal. Only String reading & writing is supported.}
  5. interface
  6. implementation
  7.     uses
  8.         TCL, TextFileIntf;
  9.  
  10.     procedure CTextFile.ITextFile;
  11.     begin    {CTextFile.ITextFile}
  12.         inherited IDataFile;
  13.         BufferLen := 0;
  14.         BufferPos := 0;
  15.         ForceEOL := false;
  16.         LastWroteCR := false;
  17.         MoreInFile := false;
  18.         HaveAccessed := false;
  19.         LongLine := false;
  20.         OpenForInput := false;
  21.     end;    {CTextFile.ITextFile}
  22.  
  23.     procedure CTextFile.ReadBuffer;
  24.         var
  25.             wasLocked: boolean;
  26.             thePoint: ptr;
  27.             count: longint;
  28.     begin    {CTextFile.ReadBuffer}
  29.         if not OpenForInput then
  30.             FailOSErr(OpWrErr)
  31.         else if not MoreInFile then
  32.             FailOSErr(EOFErr);
  33.  
  34.         wasLocked := inherited Lock(TRUE);
  35.  
  36.         thePoint := @theBuffer;
  37.         if LengthLeft < TextBufferSize then
  38.             count := LengthLeft
  39.         else
  40.             count := TextBufferSize;
  41.         inherited ReadSome(thePoint, count);    {Inherited for speed. Remove if ReadSome might be overridden!}
  42.  
  43.         BufferLen := count;
  44.         LengthLeft := LengthLeft - count;
  45.         BufferPos := 0;
  46.         HaveAccessed := true;
  47.         if (count <> TextBufferSize) or (LengthLeft = 0) then
  48.             MoreInFile := false;
  49.  
  50.         wasLocked := inherited Lock(wasLocked)
  51.     end;    {CTextFile.ReadBuffer}
  52.  
  53.     function CTextFile.EOF: boolean;
  54. {Figures out if we've gotten to the end of the file; ie. if the current pointer is at the end of the file.}
  55. {Since write files are output only, they are always at the end. For a read file, we are at the end if we are at the end }
  56. {of the buffer, and there are no more data to be read into the computer.}
  57.     begin    {CTextFile.EOF}
  58.         if not OpenForInput then
  59.             EOF := true
  60.         else if MoreInFile then
  61.             EOF := false
  62.         else
  63.             EOF := BufferPos = BufferLen
  64.     end;    {CTextFile.EOF}
  65.  
  66.     function CTextFile.EOL: boolean;
  67.     begin    {CTextFile.EOL}
  68.         if not OpenForInput then
  69.             EOL := LastWroteCR
  70.         else begin
  71.                 if not HaveAccessed then
  72.                     if MoreInFile then
  73.                         self.ReadBuffer
  74.                     else
  75.                         FailOSErr(EOFErr);    {Empty file}
  76.  
  77.                 if BufferPos = BufferLen then
  78.                     FailOSErr(EOFErr);        {We're at the end of the file.}
  79.  
  80.                 if not ForceEOL then
  81.                     EOL := theBuffer[BufferPos] = TextEOLChar
  82.                 else
  83.                     EOL := true;    {if Force EOL}
  84.             end
  85.     end;    {CTextFile.EOL}
  86.  
  87.     function CTextFile.isLongLine: boolean;
  88.     begin    {CTextFile.isLongLine}
  89.         isLongLine := LongLine
  90.     end;    {CTextFile.isLongLine}
  91.  
  92.     function CTextFile.getLengthLeft: longint;
  93.     begin    {CTextFile.getLengthLeft}
  94.         getLengthLeft := LengthLeft;
  95.     end;    {CTextFile.getLengthLeft}
  96.  
  97.     function CTextFile.Peek: char;
  98. {This function attempts to impliment the read aspect of f^ for a Pascal data file. No}
  99. {effort was made to impliment the write aspect of f^ as write & writeln are implimented,}
  100. {along with all the inherited data writing functions.}
  101.     begin    {CTextFile.Peek}
  102.         if BufferPos = BufferLen then
  103.             FailOSErr(EOFErr)        {We're at the end of the file.}
  104.         else if ForceEOL then
  105.             Peek := TextSpaceChar
  106.         else begin
  107.                 if not BufferHasData then
  108.                     self.ReadBuffer;
  109.                 Peek := theBuffer[BufferPos]
  110.             end    {if ForceEOL}
  111.     end;    {CTextFile.Peek}
  112.  
  113.     procedure CTextFile.Read (var theString: string; HowMuch: integer);
  114. {Reads in a number of bytes to a pascal string, theString. NB: theString should be locked (I think).}
  115. {The number of bytes read depends upon HowMuch. If 0 ≤ HowMuch ≤255, then that many bytes are read.}
  116. {If HowMuch >255 (as a signed #), then 255 bytes are read. If HowMuch<0, then as many bytes are read as there}
  117. {are characters in the string.  The number of bytes read is returned in the length of the string. If there are more}
  118. {characters on the line than are requested, then LongLine is set. If there are exactly the requested bytes, but the char.}
  119. {following is a CR, LongLine is NOT set, and EOL will reply true. NB: This routine will NOT read past a CR! (nor will the}
  120. {internal Pascal Read procedure)}
  121.         var
  122.             lpos, lblen, c, rqlen: integer;
  123.     begin    {CTextFile.Read}
  124.         if not OpenForInput then    {Reading from an output stream}
  125.             FailOSErr(OpWrErr)
  126.         else if not HaveAccessed then
  127.             if MoreInFile then    {Try to load some of the file the first time before EOF checking}
  128.                 self.ReadBuffer
  129.             else
  130.                 FailOSErr(EOFErr);    {Empty file}
  131.         if BufferPos = BufferLen then    {EOF}
  132.             FailOSErr(EOFErr)
  133.         else if ForceEOL then begin    {Last read we EOLed at the end of the file. We left things in a fake sence of}
  134.                 ForceEOL := false;                    {calm. Now, with this read, we hit the end.}
  135.                 BufferPos := BufferLen;
  136.                 theString := '';
  137.                 LongLine := false
  138.             end
  139.         else begin    {to actually read}
  140.                 if HowMuch < 0 then
  141.                     rqlen := ord(theString[0])    {Wanting the length of the string}
  142.                 else if HowMuch > 255 then
  143.                     rqlen := 255    {Wanted more than can read!}
  144.                 else
  145.                     rqlen := HowMuch;    {Exactly how much was wanted}
  146.  
  147.                 lpos := BufferPos;
  148.                 lblen := BufferLen;
  149.                 LongLine := false;
  150.                 c := 0;
  151.                 while theBuffer[lpos] <> TextEOLChar do begin
  152.                         c := c + 1;
  153.                         if c > rqlen then begin    {Check to see if we ran out of string space}
  154.                                 c := rqlen;                    {We did}
  155.                                 LongLine := true;
  156.                                 leave    {the While loop}
  157.                             end;
  158.                         theString[c] := theBuffer[lpos];
  159.                         lpos := lpos + 1;
  160.                         if lpos = lblen then                {oops! the buffer's empty}
  161.                             if MoreInFile then begin    {but there's more in the file}
  162.                                     self.ReadBuffer;
  163.                                     lpos := BufferPos;
  164.                                     lblen := BufferLen;
  165.                                 end
  166.                             else begin            {But the file's now empty!}
  167.                                     ForceEOL := true;
  168.                                     lpos := lblen - 1;        {Make it NOT look like an EOF condition!}
  169.                                     leave    {the While loop}
  170.                                 end;    {if}
  171.                     end;    {while got characters to read}
  172.  
  173.                 BufferPos := lpos;
  174.                 theString[0] := char(c);
  175.             end    {if open for input}
  176.     end;    {CTextFile.Read}
  177.  
  178. {•••••     •••••}
  179.  
  180.     procedure CTextFile.ReadLn (var theString: string);
  181. {Reads either a full line, or the first 255 characters of a line into theString. This procedure attempts to impliment}
  182. {Pascal's ReadLn procedure, but for Mac Data files. Lines exactly 255 characters long (255 char, then CR), will be}
  183. {read properly. Longer lines will set LongLine upon exit.}
  184.         var
  185.             lpos, lblen, c: integer;
  186.             aborted: boolean;
  187.     begin    {CTextFile.ReadLn}
  188.         if not OpenForInput then
  189.             FailOSErr(OpWrErr)
  190.         else if not HaveAccessed then
  191.             if MoreInFile then    {Try to load some of the file the first time before EOF checking}
  192.                 self.ReadBuffer
  193.             else
  194.                 FailOSErr(EOFErr);{Empty file}
  195. {Break the if structure here so that we can pre-read and then read from eh file}
  196.         if BufferPos = BufferLen then
  197.             FailOSErr(EOFErr)
  198.         else if ForceEOL then begin    {Last read we EOLed at the end of the file. We left things in a fake sence of}
  199.                 ForceEOL := false;                    {calm. Now, with this read, we hit the end.}
  200.                 BufferPos := BufferLen;
  201.                 theString := '';
  202.                 LongLine := false
  203.             end
  204.         else begin    {to actually read}
  205.                 lpos := BufferPos;
  206.                 lblen := BufferLen;
  207.                 LongLine := false;
  208.                 aborted := false;
  209.                 c := 0;
  210.                 while theBuffer[lpos] <> TextEOLChar do begin
  211.                         c := c + 1;
  212.                         if c = 256 then begin    {Check to see if we ran out of string space}
  213.                                 c := 255;
  214.                                 LongLine := true;
  215.                                 aborted := true;
  216.                                 leave    {the While loop}
  217.                             end;
  218.                         theString[c] := theBuffer[lpos];
  219.                         lpos := lpos + 1;
  220.                         if lpos = lblen then                {oops! the buffer's empty}
  221.                             if MoreInFile then begin    {but there's more in the file}
  222.                                     self.ReadBuffer;
  223.                                     lpos := BufferPos;
  224.                                     lblen := BufferLen;
  225.                                 end
  226.                             else begin            {But the file's now empty!}
  227.                                     ForceEOL := true;
  228.                                     lpos := lblen - 1;        {Make it NOT look like an EOF condition!}
  229.                                     aborted := true;
  230.                                     leave    {the While loop}
  231.                                 end;    {if}
  232.                     end;    {while got characters to read}
  233.  
  234.                 if not aborted then begin    {deal with the CR at the end}
  235.                         lpos := lpos + 1;
  236.                         if lpos = lblen then                {Well! The buffer's empty}
  237.                             if MoreInFile then begin    {but there's more in the file}
  238.                                     self.ReadBuffer;
  239.                                     lpos := BufferPos;
  240.                                     lblen := BufferLen;
  241.                                 end
  242.                             else begin            {But the file's now empty!}
  243. {do nothing. the last char. in the buffer was the end of}
  244. {the last line, so leave lpos pointing to the EOF condition.}
  245.                                 end;    {if}
  246.                     end;    {if aborted}
  247.  
  248.                 BufferPos := lpos;
  249.                 theString[0] := char(c);
  250.             end    {if open for input}
  251.     end;    {CTextFile.ReadLn}
  252.  
  253.     procedure CTextFile.Write (var theString: string);
  254.         var
  255.             count: longint;
  256.             thePoint: ptr;
  257.     begin    {CTextFile.Write}
  258.         if OpenForInput then
  259.             FailOSErr(WrPermErr)
  260.         else begin
  261.                 count := length(theString);
  262.                 thePoint := @theString[1];
  263.                 inherited writesome(thePoint, count);    {Inherited for speed. Remove if WriteSome might be overridden!}
  264.  
  265.                 HaveAccessed := true;
  266.                 LastWroteCR := theString[count] = TextEOLChar;    {If the last char. of the string was an EOL char.}
  267.             end    {if open for input}
  268.     end;    {CTextFile.Write}
  269.  
  270.     procedure CTextFile.WriteLn (var theString: string);
  271.         var
  272.             count: longint;
  273.             thePoint: ptr;
  274.             s: string[1];
  275.     begin    {CTextFile.WriteLn}
  276.         if OpenForInput then
  277.             FailOSErr(WrPermErr)
  278.         else begin
  279.                 count := length(theString);
  280.                 thePoint := @theString[1];
  281.                 inherited writesome(thePoint, count);    {Inherited for speed. Remove if WriteSome might be overridden!}
  282.  
  283.                 s := TextEOLChar;
  284.                 count := 1;
  285.                 thePoint := @s[1];
  286.                 inherited writesome(thePoint, count);    {Inherited for speed. Remove if WriteSome might be overridden!}
  287.  
  288.                 HaveAccessed := true;
  289.                 LastWroteCR := true;
  290.             end    {if open for input}
  291.     end;    {CTextFile.WriteLn}
  292.  
  293.     procedure CTextFile.Open (permission: SignedByte);
  294.     begin    {CTextFile.Open}
  295.         bufferHasData := false;
  296.         HaveAccessed := false;
  297.         ForceEOL := false;
  298.         BufferLen := 0;
  299.         BufferPos := 0;
  300.  
  301.         if permission = fsCurPerm then
  302.             permission := fsRdPerm
  303.         else if (permission = fsRdWrPerm) or (permission = fsRdWrShPerm) then
  304.             FailOSErr(PermErr);    {Only exclusive read or write modes supported}
  305.  
  306.         if permission = fsWrPerm then
  307.             if not self.ExistsOnDisk then
  308.                 CreateNew(gSignature, 'TEXT');
  309.  
  310.         inherited open(permission);
  311.  
  312.         if permission = fsRdPerm then begin
  313.                 OpenForInput := true;
  314.                 theLength := GetLength;
  315.                 LengthLeft := theLength;
  316.                 if theLength > 0 then
  317.                     MoreInFile := true
  318.                 else
  319.                     MoreInFile := false;
  320.             end    {begin if read permission}
  321.         else
  322.             OpenForInput := false;
  323.     end;    {CTextFile.Open}
  324.  
  325.     procedure CTextFile.Reset;        {Pascal way of opening file for read-only seuential access}
  326.     begin
  327.         Close;    {Close the file first. OK if the file wasn't open to begin with.}
  328.         Open(fsRdPerm)
  329.     end;    {CTextFile.Reset}
  330.  
  331.     procedure CTextFile.Rewrite;    {Pascal way of opening an empty file for write-only access}
  332.     begin
  333.         Close;    {Close the file first. OK if the file wasn't open to begin with.}
  334.         Open(fsWrPerm);
  335. {•  SetMark(0, fsFromStart);•}
  336.         SetLength(0);                        {Zero the file out.}
  337.     end;    {CTextFile.Rewrite}
  338.  
  339.     procedure CTextFile.OpenForAppending;    {Custom method of opening a file to append to it.}
  340.     begin
  341.         Close;    {Close the file first. OK if the file wasn't open to begin with.}
  342.         Open(fsWrPerm);
  343.         SetMark(0, fsFromLEOF);        {Go to the end.}
  344.     end;    {CTextFile.OpenForAppending}
  345.  
  346.     procedure CTextFile.Seek (thePlace: longint);    {Pascal way of setting "the Mark." Provided since it's in the Language def.}
  347.     begin
  348.         SetMark(thePlace, fsFromStart)
  349.     end;    {CTextFile.Seek}
  350.  
  351.     function CTextFile.Filepos: longint;                        {Pascal way of getting "the Mark"'s position.}
  352.     begin
  353.         Filepos := GetMark
  354.     end;    {CTextFile.Filepos}
  355. end.