(********************************************************************) (* *) (* file.s7i Interface type describing sequential files. *) (* Copyright (C) 1989 - 2013, 2019 Thomas Mertes *) (* *) (* This file is part of the Seed7 Runtime Library. *) (* *) (* The Seed7 Runtime Library is free software; you can *) (* redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) (* Foundation; either version 2.1 of the License, or (at your *) (* option) any later version. *) (* *) (* The Seed7 Runtime Library is distributed in the hope that it *) (* will be useful, but WITHOUT ANY WARRANTY; without even the *) (* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR *) (* PURPOSE. See the GNU Lesser General Public License for more *) (* details. *) (* *) (* You should have received a copy of the GNU Lesser General *) (* Public License along with this program; if not, write to the *) (* Free Software Foundation, Inc., 51 Franklin Street, *) (* Fifth Floor, Boston, MA 02110-1301, USA. *) (* *) (********************************************************************) (** * Interface type for sequential files. * The file interface is implemented with [[null_file]], * [[external_file]], [[utf8|utf8File]], [[utf16|utf16File]], * [[socket]], [[echo|echoFile]], [[line|lineFile]], * [[dir|dirFile]] and many other types. *) const type: file is sub object interface; (** * Write a [[string]] to a file. * @exception RANGE_ERROR - The string contains a character that * does not fit into the file specific representation * (e.g.: A byte-file allows just chars from '\0;' to '\255;'). *) const proc: write (inout file: outFile, in string: stri) is DYNAMIC; (** * Write end-of-line to a file. * The implementation function decides how writing end-of-line is * done. It can be done by writing '\n', but other solutions are also * possible. *) const proc: writeln (inout file: outFile) is DYNAMIC; (** * Write a [[string]] followed by end-of-line to a file. * The implementation function decides how writing end-of-line is * done. It can be done by writing '\n', but other solutions are also * possible. * @exception RANGE_ERROR - The string contains a character that * does not fit into the file specific representation * (e.g.: A byte-file allows just chars from '\0;' to '\255;'). *) const proc: writeln (inout file: outFile, in string: stri) is DYNAMIC; const proc: moveLeft (inout file: outFile, in string: stri) is DYNAMIC; const proc: erase (inout file: outFile, in string: stri) is DYNAMIC; const proc: backSpace (inout file: outFile, in string: stri) is func begin moveLeft(outFile, stri); erase(outFile, stri); moveLeft(outFile, stri); end func; const proc: cursorOn (inout file: outFile, in char: ch) is DYNAMIC; const proc: cursorOff (inout file: outFile, in char: ch) is DYNAMIC; (** * Close a file. *) const proc: close (inout file: aFile) is DYNAMIC; (** * Forces that all buffered data of ''outFile'' is sent to its destination. * Depending on the implementation type this causes data to be sent * to the file system, screen, network or other destination. *) const proc: flush (inout file: outFile) is DYNAMIC; (** * Read a character from a file. * @return the character read, or [[char#EOF|EOF]] at the end of the file. *) const func char: getc (inout file: inFile) is DYNAMIC; (** * Read a [[string]] with a maximum length from a file. * @return the string read. * @exception RANGE_ERROR The parameter ''maxLength'' is negative. *) const func string: gets (inout file: inFile, in integer: maxLength) is DYNAMIC; (** * Read a [[string]] from ''inFile'' until the ''terminator'' character is found. * If a ''terminator'' is found the string before the ''terminator'' is * returned and the ''terminator'' character is assigned to inFile.bufferChar. * The file position is advanced after the ''terminator'' character. * If no ''terminator'' is found the rest of ''inFile'' is returned and * [[char#EOF|EOF]] is assigned to the inFile.bufferChar. When the function * is left inFile.bufferChar contains either ''terminator'' or [[char#EOF|EOF]]. * @param inFile File from which the string is read. * @param terminator Character which terminates the string. * @return the string read without the ''terminator'' or the rest of the * file if no ''terminator'' is found. *) const func string: getTerminatedString (inout file: inFile, in char: terminator) is DYNAMIC; (** * Read a word from a file. * Before reading the word it skips spaces and tabs. The function * accepts words ending with " ", "\t", end-of-line or [[char#EOF|EOF]]. * The word ending characters are not copied into the string. * When the function is left inFile.bufferChar contains the * word ending character (' ', '\t', '\n' or [[char#EOF|EOF]]). * @return the word read. *) const func string: getwd (inout file: inFile) is DYNAMIC; (** * Read a line from a file. * The function reads a string up to end-of-line or [[char#EOF|EOF]]. * The line ending characters are not copied into the string. * When the function is left inFile.bufferChar contains the * line ending character ('\n' or [[char#EOF|EOF]]). * @return the line read. *) const func string: getln (inout file: inFile) is DYNAMIC; const func string: getk (in file: inFile) is DYNAMIC; const func boolean: eoln (in file: inFile) is DYNAMIC; (** * Determine the end-of-file indicator. * The end-of-file indicator is set if at least one request to read * from the file failed. * @return TRUE if the end-of-file indicator is set, FALSE otherwise. *) const func boolean: eof (in file: inFile) is DYNAMIC; (** * Determine if at least one character can be read successfully. * This function allows a file to be handled like an iterator. * @return FALSE if ''getc'' would return [[char#EOF|EOF]], * TRUE otherwise. *) const func boolean: hasNext (inout file: inFile) is DYNAMIC; (** * Determine if at least one character can be read without blocking. * Blocking means that ''getc'' would wait until a character is * received. Blocking can last for a period of unspecified length. * Regular files do not block. * @return TRUE if ''getc'' would not block, FALSE otherwise. *) const func boolean: inputReady (in file: inFile) is DYNAMIC; (** * Obtain the length of a file. * The file length is measured in bytes. * @return the length of a file. * @exception RANGE_ERROR The file length does not fit into * an integer value. * @exception FILE_ERROR The implementation type of ''aFile'' is * not seekable or a system function returns an error * or the file length reported by the system is negative. *) const func integer: length (inout file: aFile) is DYNAMIC; (** * Truncate ''aFile'' to the given ''length''. * If the file previously was larger than ''length'', the extra data is lost. * If the file previously was shorter, it is extended, and the extended * part is filled with null bytes ('\0;'). * @param aFile File to be truncated. * @param length Requested length of ''aFile'' in bytes. * @exception RANGE_ERROR The requested length is negative or * the length is not representable in the type * used by the system function. * @exception FILE_ERROR A system function returns an error. *) const proc: truncate (inout file: aFile, in integer: length) is DYNAMIC; (** * Determine if the file ''aFile'' is seekable. * If a file is seekable the functions ''seek'' and ''tell'' * can be used to set and and obtain the current file position. * @return TRUE, if ''aFile'' is seekable, FALSE otherwise. *) const func boolean: seekable (in file: aFile) is DYNAMIC; (** * Set the current file position. * The file position is measured in bytes from the start of the file. * The first byte in the file has the position 1. * @exception RANGE_ERROR The file position is negative or zero or * the file position is not representable in the system * file position type. * @exception FILE_ERROR The implementation type of ''aFile'' is * not seekable or a system function returns an error. *) const proc: seek (inout file: aFile, in integer: position) is DYNAMIC; (** * Obtain the current file position. * The file position is measured in bytes from the start of the file. * The first byte in the file has the position 1. * @return the current file position. * @exception RANGE_ERROR The file position does not fit into * an integer value. * @exception FILE_ERROR The implementation type of ''aFile'' is * not seekable or a system function returns an error * or the file position reported by the system is negative. *) const func integer: tell (in file: aFile) is DYNAMIC; (** * Compare two file values. * This function does neither compare file contents nor file names. * The order of two files is determined by comparing the memory * positions of their internal data representation. Therefore the * result of ''compare'' is arbitrary and may change if the * program is executed again. Inside a program the result of * ''compare'' is consistent and can be used to maintain hash * tables. * @return -1, 0 or 1 if the first argument is considered to be * respectively less than, equal to, or greater than the * second. *) const func integer: compare (in file: file1, in file: file2) is action "ITF_CMP"; (** * Compute the hash value of a file. * @return the hash value. *) const func integer: hashCode (in file: aFile) is action "ITF_HASHCODE"; const func char: (in file: aFile).bufferChar is DYNAMIC; const varfunc char: (inout file: aFile).bufferChar is DYNAMIC; (** * Read a word from ''inFile'' into ''aVar''. * Before reading the word it skips spaces and tabs. The function * accepts words ending with " ", "\t", end-of-line or [[char#EOF|EOF]]. * The word ending character is not copied into the string. * When the function is left inFile.bufferChar contains the * word ending character (' ', '\t', '\n' or [[char#EOF|EOF]]). *) const proc: read (inout file: inFile, inout string: aVar) is func begin aVar := getwd(inFile); end func; (** * Read a word from ''inFile'' into ''aVar'' or use ''defaultValue''. * Before reading the word it skips spaces and tabs. The function * accepts words ending with " ", "\t", end-of-line or [[char#EOF|EOF]]. * If the word is empty ''defaultValue'' is assigned to ''aVar''. * The word ending character is not copied into the string. * When the function is left inFile.bufferChar contains the * word ending character (' ', '\t', '\n' or [[char#EOF|EOF]]). *) const proc: read (inout file: inFile, inout string: aVar, in string: defaultValue) is func begin aVar := getwd(inFile); if aVar = "" then aVar := defaultValue; end if; end func; (** * Read a line from ''inFile'' into ''aVar''. * The function reads a string up to end-of-line or [[char#EOF|EOF]]. * The line ending character is not copied into the string. * When the function is left inFile.bufferChar contains the * line ending character ('\n' or [[char#EOF|EOF]]). *) const proc: readln (inout file: inFile, inout string: aVar) is func begin aVar := getln(inFile); end func; (** * Read a line from ''inFile'' into ''aVar'' or use ''defaultValue''. * The function reads a string up to end-of-line or [[char#EOF|EOF]]. * If the line is empty ''defaultValue'' is assigned to ''aVar''. * The line ending character is not copied into the string. * When the function is left inFile.bufferChar contains the * line ending character ('\n' or [[char#EOF|EOF]]). *) const proc: readln (inout file: inFile, inout string: aVar, in string: defaultValue) is func begin aVar := getln(inFile); if aVar = "" then aVar := defaultValue; end if; end func; (** * Discard a line from a file. * The function discards characters up to end-of-line or [[char#EOF|EOF]]. * When the function is left inFile.bufferChar contains the * line ending character ('\n' or [[char#EOF|EOF]]). *) const proc: readln (inout file: inFile) is func local var string: stri is ""; begin stri := getln(inFile); end func; (** * Skip ''numChars'' characters from ''inFile''. * When the function is left ''numChars'' have been skipped from * ''inFile'' or [[char#EOF|EOF]] has been reached. * @exception RANGE_ERROR The parameter ''numChars'' is negative. *) const proc: skip (inout file: inFile, in var integer: numChars) is func local var integer: skipped is 0; begin if numChars <> 0 then repeat skipped := length(gets(inFile, min(numChars, 1000000))); numChars -:= skipped; until numChars = 0 or skipped = 0; end if; end func;