"Fossies" - the Fresh Open Source Software Archive

Member "seed7/lib/strifile.s7i" (7 Jul 2020, 9730 Bytes) of package /linux/misc/seed7_05_20210223.tgz:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 
    2 (********************************************************************)
    3 (*                                                                  *)
    4 (*  strifile.s7i  Implementation type for files stored in a string  *)
    5 (*  Copyright (C) 2008  Thomas Mertes                               *)
    6 (*                                                                  *)
    7 (*  This file is part of the Seed7 Runtime Library.                 *)
    8 (*                                                                  *)
    9 (*  The Seed7 Runtime Library is free software; you can             *)
   10 (*  redistribute it and/or modify it under the terms of the GNU     *)
   11 (*  Lesser General Public License as published by the Free Software *)
   12 (*  Foundation; either version 2.1 of the License, or (at your      *)
   13 (*  option) any later version.                                      *)
   14 (*                                                                  *)
   15 (*  The Seed7 Runtime Library is distributed in the hope that it    *)
   16 (*  will be useful, but WITHOUT ANY WARRANTY; without even the      *)
   17 (*  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR *)
   18 (*  PURPOSE.  See the GNU Lesser General Public License for more    *)
   19 (*  details.                                                        *)
   20 (*                                                                  *)
   21 (*  You should have received a copy of the GNU Lesser General       *)
   22 (*  Public License along with this program; if not, write to the    *)
   23 (*  Free Software Foundation, Inc., 51 Franklin Street,             *)
   24 (*  Fifth Floor, Boston, MA  02110-1301, USA.                       *)
   25 (*                                                                  *)
   26 (********************************************************************)
   27 
   28 
   29 (**
   30  *  [[file|File]] implementation type for files stored in a [[string]].
   31  *)
   32 const type: strifile is sub null_file struct
   33     var string: content is "";
   34     var integer: position is 1;
   35   end struct;
   36 
   37 type_implements_interface(strifile, file);
   38 
   39 
   40 (**
   41  *  Open a ''strifile'' with the given string content.
   42  *  @return the file opened.
   43  *)
   44 const func file: openStrifile (in string: content) is func
   45   result
   46     var file: newFile is STD_NULL;
   47   local
   48     var strifile: new_strifile is strifile.value;
   49   begin
   50     new_strifile.content := content;
   51     newFile := toInterface(new_strifile);
   52   end func;
   53 
   54 
   55 (**
   56  *  Open a ''strifile'' with an empty string content.
   57  *  @return the file opened.
   58  *)
   59 const func file: openStrifile is func
   60   result
   61     var file: newFile is STD_NULL;
   62   local
   63     var strifile: new_strifile is strifile.value;
   64   begin
   65     newFile := toInterface(new_strifile);
   66   end func;
   67 
   68 
   69 (**
   70  *  Write the [[string]] ''stri'' to ''outStrifile''.
   71  *)
   72 const proc: write (inout strifile: outStrifile, in string: stri) is func
   73   begin
   74     if outStrifile.position = succ(length(outStrifile.content)) then
   75       outStrifile.content &:= stri;
   76     elsif outStrifile.position <= length(outStrifile.content) then
   77       if pred(outStrifile.position) <= length(outStrifile.content) - length(stri) then
   78         outStrifile.content @:= [outStrifile.position] stri;
   79       else
   80         outStrifile.content := outStrifile.content[.. pred(outStrifile.position)];
   81         outStrifile.content &:= stri;
   82       end if;
   83     elsif outStrifile.position > length(outStrifile.content) then
   84       outStrifile.content &:=
   85           "\0;" mult pred(outStrifile.position - length(outStrifile.content)) &
   86           stri;
   87     end if;
   88     outStrifile.position +:= length(stri);
   89   end func;
   90 
   91 
   92 const proc: moveLeft (inout strifile: outStrifile, in string: stri) is func
   93   begin
   94     if outStrifile.position > length(stri) then
   95       outStrifile.position -:= length(stri);
   96     else
   97       outStrifile.position := 1;
   98     end if;
   99   end func;
  100 
  101 
  102 (**
  103  *  Read a character from ''inStrifile''.
  104  *  @return the character read, or [[char#EOF|EOF]] at the end of the file.
  105  *)
  106 const func char: getc (inout strifile: inStrifile) is func
  107   result
  108     var char: charRead is ' ';
  109   begin
  110     if inStrifile.position <= length(inStrifile.content) then
  111       charRead := inStrifile.content[inStrifile.position];
  112       incr(inStrifile.position);
  113     else
  114       charRead := EOF;
  115     end if;
  116   end func;
  117 
  118 
  119 (**
  120  *  Read a [[string]] with maximum length from ''inStrifile''.
  121  *  @return the string read.
  122  *  @exception RANGE_ERROR The parameter ''maxLength'' is negative.
  123  *)
  124 const func string: gets (inout strifile: inStrifile, in integer: maxLength) is func
  125   result
  126     var string: striRead is "";
  127   begin
  128     if maxLength < 0 then
  129       raise RANGE_ERROR;
  130     elsif maxLength <= succ(length(inStrifile.content) - inStrifile.position) then
  131       striRead := inStrifile.content[inStrifile.position len maxLength];
  132       inStrifile.position +:= maxLength;
  133     else
  134       striRead := inStrifile.content[inStrifile.position ..];
  135       inStrifile.position := succ(length(inStrifile.content));
  136     end if;
  137   end func;
  138 
  139 
  140 (**
  141  *  Read a word from ''inStrifile''.
  142  *  Before reading the word it skips spaces and tabs. The function
  143  *  accepts words ending with " ", "\t", "\n", or [[char#EOF|EOF]].
  144  *  The word ending characters are not copied into the string.
  145  *  When the function is left inStrifile.bufferChar contains ' ',
  146  *  '\t', '\n' or [[char#EOF|EOF]].
  147  *  @return the word read.
  148  *)
  149 const func string: getwd (inout strifile: inStrifile) is func
  150   result
  151     var string: stri is "";
  152   local
  153     const set of char: space_or_tab is {' ', '\t'};
  154     const set of char: space_tab_or_nl is {' ', '\t', '\n'};
  155     var integer: wordStartPos is 0;
  156     var integer: wordEndPos is 0;
  157   begin
  158     wordStartPos := inStrifile.position;
  159     while wordStartPos <= length(inStrifile.content) and
  160         inStrifile.content[wordStartPos] in space_or_tab do
  161       incr(wordStartPos);
  162     end while;
  163     if wordStartPos > length(inStrifile.content) then
  164       inStrifile.position := wordStartPos;
  165       inStrifile.bufferChar := EOF;
  166     else
  167       wordEndPos := succ(wordStartPos);
  168       while wordEndPos <= length(inStrifile.content) and
  169           inStrifile.content[wordEndPos] not in space_tab_or_nl do
  170         incr(wordEndPos);
  171       end while;
  172       if wordEndPos <= length(inStrifile.content) then
  173         stri := inStrifile.content[wordStartPos .. pred(wordEndPos)];
  174         inStrifile.position := succ(wordEndPos);
  175         inStrifile.bufferChar := inStrifile.content[wordEndPos];
  176       else
  177         stri := inStrifile.content[wordStartPos ..];
  178         inStrifile.position := succ(length(inStrifile.content));
  179         inStrifile.bufferChar := EOF;
  180       end if;
  181     end if;
  182   end func;
  183 
  184 
  185 (**
  186  *  Read a line from ''inStrifile''.
  187  *  A strifile works as if all lines end with '\n'.
  188  *  The line ending character is not copied into the string. When
  189  *  the function is left inStrifile.bufferChar contains '\n' or
  190  *  [[char#EOF|EOF]].
  191  *  @return the line read.
  192  *)
  193 const func string: getln (inout strifile: inStrifile) is func
  194   result
  195     var string: stri is "";
  196   local
  197     var integer: newlinePos is 0;
  198   begin
  199     newlinePos := pos(inStrifile.content, '\n', inStrifile.position);
  200     if newlinePos <> 0 then
  201       stri := inStrifile.content[inStrifile.position .. pred(newlinePos)];
  202       inStrifile.position := succ(newlinePos);
  203       inStrifile.bufferChar := '\n';
  204     else
  205       stri := inStrifile.content[inStrifile.position ..];
  206       inStrifile.position := succ(length(inStrifile.content));
  207       inStrifile.bufferChar := EOF;
  208     end if;
  209   end func;
  210 
  211 
  212 (**
  213  *  Determine the end-of-file indicator.
  214  *  The end-of-file indicator is set if at least one request to read
  215  *  from the file failed.
  216  *  @return TRUE if the end-of-file indicator is set, FALSE otherwise.
  217  *)
  218 const func boolean: eof (in strifile: inStrifile) is
  219   return inStrifile.position > length(inStrifile.content);
  220 
  221 
  222 (**
  223  *  Determine if at least one character can be read successfully.
  224  *  This function allows a file to be handled like an iterator.
  225  *  @return FALSE if ''getc'' would return [[char#EOF|EOF]],
  226  *          TRUE otherwise.
  227  *)
  228 const func boolean: hasNext (in strifile: inStrifile) is
  229   return inStrifile.position <= length(inStrifile.content);
  230 
  231 
  232 (**
  233  *  Obtain the length of a ''aStrifile''.
  234  *  The file length is measured in characters.
  235  *  @return the length of a file.
  236  *)
  237 const func integer: length (in strifile: aStrifile) is
  238   return length(aStrifile.content);
  239 
  240 
  241 (**
  242  *  Truncate ''aStrifile'' to the given ''length''.
  243  *  If the file previously was larger than ''length'', the extra data is lost.
  244  *  If the file previously was shorter, it is extended, and the extended
  245  *  part is filled with null bytes ('\0;').
  246  *  The file length is measured in characters.
  247  *)
  248 const proc: truncate (inout strifile: aStrifile, in integer: length) is func
  249   begin
  250     if length < 0 then
  251       raise RANGE_ERROR;
  252     elsif length(aStrifile.content) > length then
  253       aStrifile.content := aStrifile.content[.. length];
  254     elsif length(aStrifile.content) < length then
  255       aStrifile.content := aStrifile.content &
  256           "\0;" mult (length - length(aStrifile.content));
  257     end if;
  258   end func;
  259 
  260 
  261 (**
  262  *  Set the current file position.
  263  *  The file position is measured in characters from the start of the file.
  264  *  The first character in the file has the position 1.
  265  *)
  266 const proc: seek (inout strifile: aStrifile, in integer: position) is func
  267   begin
  268     aStrifile.position := position;
  269   end func;
  270 
  271 
  272 (**
  273  *  Obtain the current file position of ''aStrifile''.
  274  *  The file position is measured in characters from the start of the file.
  275  *  The first character in the file has the position 1.
  276  *  @return the current file position.
  277  *)
  278 const func integer: tell (in strifile: aStrifile) is
  279   return aStrifile.position;