From d0d7894fdbc70d377cc4dcbc084525e85632c78e Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Thu, 18 Sep 2008 09:48:55 +0000 Subject: [PATCH] 2008-09-18 11:48 UTC+0200 Viktor Szakats (harbour.01 syenar hu) * contrib/hbmisc/fileread.prg * Changed to use natic CLASS syntax. --- harbour/ChangeLog | 4 + harbour/contrib/hbmisc/fileread.prg | 202 +++++++++++++--------------- 2 files changed, 101 insertions(+), 105 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 201f45a01f..58fe6c6fdc 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,10 @@ 2008-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2008-09-18 11:48 UTC+0200 Viktor Szakats (harbour.01 syenar hu) + * contrib/hbmisc/fileread.prg + * Changed to use natic CLASS syntax. + 2008-09-18 11:25 UTC+0200 Viktor Szakats (harbour.01 syenar hu) * make_rpm.sh ! Attempt to detect libcurl. diff --git a/harbour/contrib/hbmisc/fileread.prg b/harbour/contrib/hbmisc/fileread.prg index b6d1957623..34c82ef20c 100644 --- a/harbour/contrib/hbmisc/fileread.prg +++ b/harbour/contrib/hbmisc/fileread.prg @@ -8,6 +8,8 @@ Donated to the public domain on 2001-04-03 by David G. Holm */ +#include "hbclass.ch" + #include "fileio.ch" #define oF_ERROR_MIN 1 @@ -18,37 +20,35 @@ #define oF_ERROR_MAX 4 #define oF_DEFAULT_READ_SIZE 4096 -FUNCTION TFileRead() - STATIC s_oClass +CREATE CLASS TFileRead - IF s_oClass == NIL - s_oClass := HBClass():New( "TFile" ) // New class - s_oClass:AddClassData( "cFile" ) // The filename - s_oClass:AddClassData( "nHan" ) // The open file handle - s_oClass:AddClassData( "lEOF" ) // The end of file reached flag - s_oClass:AddClassData( "nError" ) // The current file error code - s_oClass:AddClassData( "nLastOp" ) // The last operation done (for error messages) - s_oClass:AddClassData( "cBuffer" ) // The readahead buffer - s_oClass:AddClassData( "nReadSize" ) // How much to add to the readahead buffer on - // each read from the file + VAR cFile // The filename + VAR nHan // The open file handle + VAR lEOF // The end of file reached flag + VAR nError // The current file error code + VAR nLastOp // The last operation done (for error messages) + VAR cBuffer // The readahead buffer + VAR nReadSize // How much to add to the readahead buffer on + // each read from the file - s_oClass:AddMethod( "New", @f_new() ) // Create a new class instance - s_oClass:AddMethod( "Open", @f_open() ) // Open the file for reading - s_oClass:AddMethod( "Close", @f_close() ) // Close the file when done - s_oClass:AddMethod( "ReadLine", @f_read() ) // Read a line from the file - s_oClass:AddMethod( "Name", @f_name() ) // Retunrs the file name - s_oClass:AddMethod( "IsOpen", @f_is_open() ) // Returns .T. if file is open - s_oClass:AddMethod( "MoreToRead", @f_more() ) // Returns .T. if more to be read - s_oClass:AddMethod( "Error", @f_error() ) // Returns .T. if error occurred - s_oClass:AddMethod( "ErrorNo", @f_error_no() ) // Returns current error code - s_oClass:AddMethod( "ErrorMsg", @f_error_msg() ) // Returns formatted error message - s_oClass:Create() - ENDIF + METHOD New( cFile, nSize ) // Create a new class instance + METHOD Open( nMode ) // Open the file for reading + METHOD Close() // Close the file when done + METHOD ReadLine() // Read a line from the file + METHOD Name() // Retunrs the file name + METHOD IsOpen() // Returns .T. if file is open + METHOD MoreToRead() // Returns .T. if more to be read + METHOD Error() // Returns .T. if error occurred + METHOD ErrorNo() // Returns current error code + METHOD ErrorMsg( cText ) // Returns formatted error message - RETURN s_oClass:Instance() + PROTECTED: -STATIC FUNCTION f_new( cFile, nSize ) - LOCAL oSelf := Qself() + METHOD EOL_pos() + +END CLASS + +METHOD New( cFile, nSize ) CLASS TFileRead IF nSize == NIL .OR. nSize < 1 // The readahead size can be set to as little as 1 byte, or as much as @@ -56,119 +56,117 @@ STATIC FUNCTION f_new( cFile, nSize ) nSize := oF_DEFAULT_READ_SIZE ENDIF - oSelf:cFile := cFile // Save the file name - oSelf:nHan := -1 // It's not open yet - oSelf:lEOF := .T. // So it must be at EOF - oSelf:nError := 0 // But there haven't been any errors - oSelf:nLastOp := oF_CREATE_OBJECT // Because we just created the class - oSelf:cBuffer := "" // and nothing has been read yet - oSelf:nReadSize := nSize // But will be in this size chunks + ::cFile := cFile // Save the file name + ::nHan := -1 // It's not open yet + ::lEOF := .T. // So it must be at EOF + ::nError := 0 // But there haven't been any errors + ::nLastOp := oF_CREATE_OBJECT // Because we just created the class + ::cBuffer := "" // and nothing has been read yet + ::nReadSize := nSize // But will be in this size chunks - RETURN oSelf + RETURN Self -STATIC FUNCTION f_open( nMode ) - LOCAL oSelf := Qself() +METHOD Open( nMode ) CLASS TFileRead - IF oSelf:nHan == -1 + IF ::nHan == -1 // Only open the file if it isn't already open. IF nMode == NIL nMode := FO_READ + FO_SHARED // Default to shared read-only mode ENDIF - oSelf:nLastOp := oF_OPEN_FILE - oSelf:nHan := FOPEN( oSelf:cFile, nMode ) // Try to open the file - IF oSelf:nHan == -1 - oSelf:nError := FERROR() // It didn't work - oSelf:lEOF := .T. // So force EOF + ::nLastOp := oF_OPEN_FILE + ::nHan := FOPEN( ::cFile, nMode ) // Try to open the file + IF ::nHan == -1 + ::nError := FERROR() // It didn't work + ::lEOF := .T. // So force EOF ELSE - oSelf:nError := 0 // It worked - oSelf:lEOF := .F. // So clear EOF + ::nError := 0 // It worked + ::lEOF := .F. // So clear EOF ENDIF ELSE // The file is already open, so rewind to the beginning. - IF FSEEK( oSelf:nHan, 0 ) == 0 - oSelf:lEOF := .F. // Definitely not at EOF + IF FSEEK( ::nHan, 0 ) == 0 + ::lEOF := .F. // Definitely not at EOF ELSE - oSelf:nError := FERROR() // Save error code if not at BOF + ::nError := FERROR() // Save error code if not at BOF ENDIF - oSelf:cBuffer := "" // Clear the readahead buffer + ::cBuffer := "" // Clear the readahead buffer ENDIF - RETURN oSelf + RETURN Self -STATIC FUNCTION f_read() - LOCAL oSelf := Qself() +METHOD ReadLine() CLASS TFileRead LOCAL cLine := "" LOCAL nPos - oSelf:nLastOp := oF_READ_FILE + ::nLastOp := oF_READ_FILE - IF oSelf:nHan == -1 - oSelf:nError := -1 // Set unknown error if file not open + IF ::nHan == -1 + ::nError := -1 // Set unknown error if file not open ELSE // Is there a whole line in the readahead buffer? - nPos := f_EOL_pos( oSelf ) - WHILE ( nPos <= 0 .OR. nPos > LEN( oSelf:cBuffer ) - 3 ) .AND. !oSelf:lEOF + nPos := ::EOL_pos() + WHILE ( nPos <= 0 .OR. nPos > LEN( ::cBuffer ) - 3 ) .AND. !::lEOF // Either no or maybe, but there is possibly more to be read. // Maybe means that we found either a CR or an LF, but we don't // have enough characters to discriminate between the three types // of end of line conditions that the class recognizes (see below). - cLine := FREADSTR( oSelf:nHan, oSelf:nReadSize ) + cLine := FREADSTR( ::nHan, ::nReadSize ) IF EMPTY( cLine ) // There was nothing more to be read. Why? (Error or EOF.) - oSelf:nError := FERROR() - IF oSelf:nError == 0 + ::nError := FERROR() + IF ::nError == 0 // Because the file is at EOF. - oSelf:lEOF := .T. + ::lEOF := .T. ENDIF ELSE // Add what was read to the readahead buffer. - oSelf:cBuffer += cLine + ::cBuffer += cLine cLine := "" ENDIF // Is there a whole line in the readahead buffer yet? - nPos := f_EOL_pos( oSelf ) + nPos := ::EOL_pos() END WHILE // Is there a whole line in the readahead buffer? IF nPos <= 0 // No, which means that there is nothing left in the file either, so // return the entire buffer contents as the last line in the file. - cLine := oSelf:cBuffer - oSelf:cBuffer := "" + cLine := ::cBuffer + ::cBuffer := "" ELSE // Yes. Is there anything in the line? IF nPos > 1 // Yes, so return the contents. - cLine := LEFT( oSelf:cBuffer, nPos - 1 ) + cLine := LEFT( ::cBuffer, nPos - 1 ) ELSE // No, so return an empty string. cLine := "" ENDIF // Deal with multiple possible end of line conditions. DO CASE - CASE SUBSTR( oSelf:cBuffer, nPos, 3 ) == CHR( 13 ) + CHR( 13 ) + CHR( 10 ) + CASE SUBSTR( ::cBuffer, nPos, 3 ) == CHR( 13 ) + CHR( 13 ) + CHR( 10 ) // It's a messed up DOS newline (such as that created by a program // that uses "\r\n" as newline when writing to a text mode file, // which causes the '\n' to expand to "\r\n", giving "\r\r\n"). nPos += 3 - CASE SUBSTR( oSelf:cBuffer, nPos, 2 ) == CHR( 13 ) + CHR( 10 ) + CASE SUBSTR( ::cBuffer, nPos, 2 ) == CHR( 13 ) + CHR( 10 ) // It's a standard DOS newline nPos += 2 OTHERWISE // It's probably a Mac or Unix newline nPos++ ENDCASE - oSelf:cBuffer := SUBSTR( oSelf:cBuffer, nPos ) + ::cBuffer := SUBSTR( ::cBuffer, nPos ) ENDIF ENDIF RETURN cLine -STATIC FUNCTION f_EOL_pos( oFile ) +METHOD EOL_pos() CLASS TFileRead LOCAL nCRpos, nLFpos, nPos // Look for both CR and LF in the file read buffer. - nCRpos := AT( CHR( 13 ), oFile:cBuffer ) - nLFpos := AT( CHR( 10 ), oFile:cBuffer ) + nCRpos := AT( CHR( 13 ), ::cBuffer ) + nLFpos := AT( CHR( 10 ), ::cBuffer ) DO CASE CASE nCRpos == 0 // If there's no CR, use the LF position. @@ -183,68 +181,62 @@ STATIC FUNCTION f_EOL_pos( oFile ) RETURN nPos -STATIC FUNCTION f_close() - LOCAL oSelf := Qself() +METHOD Close() CLASS TFileRead - oSelf:nLastOp := oF_CLOSE_FILE - oSelf:lEOF := .T. + ::nLastOp := oF_CLOSE_FILE + ::lEOF := .T. // Is the file already closed. - IF oSelf:nHan == -1 + IF ::nHan == -1 // Yes, so indicate an unknown error. - oSelf:nError := -1 + ::nError := -1 ELSE // No, so close it already! - FCLOSE( oSelf:nHan ) - oSelf:nError := FERROR() - oSelf:nHan := -1 // The file is no longer open - oSelf:lEOF := .T. // So force an EOF condition + FCLOSE( ::nHan ) + ::nError := FERROR() + ::nHan := -1 // The file is no longer open + ::lEOF := .T. // So force an EOF condition ENDIF - RETURN oSelf + RETURN Self -STATIC FUNCTION f_name() - LOCAL oSelf := Qself() +METHOD Name() CLASS TFileRead // Returns the filename associated with this class instance. - RETURN oSelf:cFile + RETURN ::cFile -STATIC FUNCTION f_is_open() - LOCAL oSelf := Qself() +METHOD IsOpen() CLASS TFileRead // Returns .T. if the file is open. - RETURN oSelf:nHan != -1 + RETURN ::nHan != -1 -STATIC FUNCTION f_more() - LOCAL oSelf := Qself() +METHOD MoreToRead() CLASS TFileRead // Returns .T. if there is more to be read from either the file or the // readahead buffer. Only when both are exhausted is there no more to read. - RETURN !oSelf:lEOF .OR. !EMPTY( oSelf:cBuffer ) + RETURN !::lEOF .OR. !EMPTY( ::cBuffer ) -STATIC FUNCTION f_error() - LOCAL oSelf := Qself() +METHOD Error() CLASS TFileRead // Returns .T. if an error was recorded. - RETURN oSelf:nError != 0 + RETURN ::nError != 0 -STATIC FUNCTION f_error_no() - LOCAL oSelf := Qself() +METHOD ErrorNo() CLASS TFileRead // Returns the last error code that was recorded. - RETURN oSelf:nError + RETURN ::nError -STATIC FUNCTION f_error_msg( cText ) +METHOD ErrorMsg( cText ) CLASS TFileRead STATIC s_cAction := {"on", "creating object for", "opening", "reading from", "closing"} - LOCAL oSelf := Qself() + LOCAL cMessage, nTemp // Has an error been recorded? - IF oSelf:nError == 0 + IF ::nError == 0 // No, so report that. - cMessage := "No errors have been recorded for " + oSelf:cFile + cMessage := "No errors have been recorded for " + ::cFile ELSE // Yes, so format a nice error message, while avoiding a bounds error. - IF oSelf:nLastOp < oF_ERROR_MIN .OR. oSelf:nLastOp > oF_ERROR_MAX + IF ::nLastOp < oF_ERROR_MIN .OR. ::nLastOp > oF_ERROR_MAX nTemp := 1 ELSE - nTemp := oSelf:nLastOp + 1 + nTemp := ::nLastOp + 1 ENDIF - cMessage := iif( EMPTY( cText ), "", cText ) + "Error " + ALLTRIM( STR( oSelf:nError ) ) + " " + s_cAction[ nTemp ] + " " + oSelf:cFile + cMessage := iif( EMPTY( cText ), "", cText ) + "Error " + ALLTRIM( STR( ::nError ) ) + " " + s_cAction[ nTemp ] + " " + ::cFile ENDIF RETURN cMessage