home *** CD-ROM | disk | FTP | other *** search
- /***
- *
- * Fileio.prg
- * Sample user-defined functions to process binary files
- * Copyright, Nantucket Corporation, 1990
- *
- * NOTE: compile with /n/w/a/m
- */
-
- #include "Fileio.ch"
-
- /***
- * FGets( <nHandle>, [<nLines>], [<nLineLength>], [<cDelim>] ) --> cBuffer
- * Read one or more lines from a text file
- *
- */
- FUNCTION FGets(nHandle, nLines, nLineLength, cDelim)
- RETURN FReadLn(nHandle, nLines, nLineLength, cDelim)
-
- /***
- * FPuts( <nHandle>, <cString>, [<nLength>], [<cDelim>] ) --> nBytes
- * Write a line to a text file
- *
- */
- FUNCTION FPuts(nHandle, cString, nLength, cDelim)
- RETURN FWriteLn(nHandle, cString, nLength, cDelim)
-
- /***
- * DirEval( <cMask>, <bAction> ) --> aArray
- * Apply a code block to each file matching a skeleton
- *
- * Tim Wong
- */
- FUNCTION DirEval( cMask, bAction )
- RETURN AEVAL( DIRECTORY(cMask), bAction )
-
- /***
- * FileTop( <nHandle> ) --> nPos
- * Position the file pointer to the first byte in a binary file and return
- * the new file position (i.e., 0).
- *
- */
- FUNCTION FileTop(nHandle)
- RETURN FSEEK(nHandle, 0)
-
- /***
- * FileBottom( <nHandle> ) --> nPos
- * Position the file pointer to the last byte in a binary file and return
- * the new file position
- *
- */
- FUNCTION FileBottom(nHandle)
- RETURN FSEEK(nHandle, 0, FS_END)
-
- /***
- * FilePos( <nHandle> ) --> nPos
- * Report the current position of the file pointer in a binary file
- *
- */
- FUNCTION FilePos(nHandle)
- RETURN FSEEK(nHandle, 0, FS_RELATIVE)
-
- /***
- * FileSize( <nHandle> ) --> nBytes
- * Return the size of a binary file
- *
- */
- FUNCTION FileSize( nHandle )
- LOCAL nCurrent, nLength
-
- // Get file position
- nCurrent := FilePos(nHandle)
-
- // Get file length
- nLength := FSEEK(nHandle, 0, FS_END)
-
- // Reset file position
- FSEEK(nHandle, nCurrent)
-
- RETURN nLength
-
- /***
- * FReadLn( <nHandle>, [<nLines>], [<nLineLength>], [<cDelim>] ) --> cLines
- * Read one or more lines from a text file
- *
- * NOTE: Line length includes delimiter, so max line read is
- * (nLineLength - LEN( cDelim ))
- *
- * NOTE: Return value includes delimiters, if delimiter was read
- *
- * NOTE: nLines defaults to 1, nLineLength to 80 and cDelim to CRLF
- *
- * NOTE: FERROR() must be checked to see if FReadLn() was successful
- *
- * NOTE: FReadLn() returns "" when EOF is reached
- *
- */
- FUNCTION FReadLn( nHandle, nLines, nLineLength, cDelim )
- LOCAL nCurPos, nFileSize, nChrsToRead, nChrsRead
- LOCAL cBuffer, cLines
- LOCAL nCount
- LOCAL nEOLPos
-
- IF nLines == NIL
- nLines := 1
- ENDIF
-
- IF nLineLength == NIL
- nLineLength := 80
- ENDIF
-
- IF cDelim == NIL
- cDelim := CHR(13) + CHR(10)
- ENDIF
-
- nCurPos := FilePos( nHandle )
- nFileSize := FileSize( nHandle )
-
- // Make sure no attempt is made to read past EOF
- nChrsToRead := MIN( nLineLength, nFileSize - nCurPos )
-
- cLines := ''
- nCount := 1
- DO WHILE (nCount <= nLines) .AND. ( nChrsToRead != 0 )
- cBuffer := SPACE( nChrsToRead )
- nChrsRead := FREAD( nHandle, @cBuffer, nChrsToRead )
-
- // Check for error condition
- IF ! (nChrsRead == nChrsToRead)
- // Error!
- // In order to stay conceptually compatible with the other
- // low-level file functions, force the user to check FERROR()
- // (which was set by the FREAD() above) to discover this fact
- //
- nChrsToRead := 0
- ENDIF
-
- nEOLPos := AT( cDelim, cBuffer )
-
- // Update buffer and current file position
- IF nEOLPos == 0
- cLines += LEFT( cBuffer, nChrsRead )
- nCurPos += nChrsRead
- ELSE
- cLines += LEFT( cBuffer, ( nEOLPos + LEN( cDelim ) ) - 1 )
- nCurPos += ( nEOLPos + LEN( cDelim ) ) - 1
- FSEEK( nHandle, nCurPos, FS_SET )
- ENDIF
-
- // Make sure we don't try to read past EOF
- IF (nFileSize - nCurPos) < nLineLength
- nChrsToRead := (nFileSize - nCurPos)
- ENDIF
-
- nCount++
- ENDDO
-
- RETURN cLines
-
- /***
- * FileEval( <nHandle>, [<nLineLength>], [<cDelim>], ;
- * <bBlock>,
- * [<bForCondition>],
- * [<bWhileCondition>],
- * [<nNextLines>],
- * [<nLine>],
- * [<lRest>] ) --> NIL
- * Apply a code block to lines in a binary file using DBEVAL() as a model.
- * If the intent is to modify the file, the output must be written to a
- * temporary file and copied over the original when done.
- *
- * NOTE: <bBlock>, <bForCondition> and <bWhileCondition> are passed a
- * line of the file
- *
- * NOTE: The defaults for nLineLength and cDelim are the same as those
- * for FReadLn()
- *
- * NOTE: The default for the rest of the parameters is that same as for
- * DBEVAL().
- *
- * NOTE: Any past EOF requests (nLine > last line in file, etc.) are ignored
- * and no error is generated. The file pointer will be left at EOF.
- *
- * NOTE: Check FERROR() to see if it was successful
- *
- * Author: Craig Ogg
- *
- */
- PROCEDURE FileEval( nHandle, nLineLength, cDelim, bBlock, bFor, bWhile, ;
- nNextLines, nLine, lRest )
- LOCAL cLine
- LOCAL lEOF := .F.
- LOCAL nPrevPos
-
- IF bWhile == NIL
- bWhile := {|| .T.}
- ENDIF
-
- IF bFor == NIL
- bFor := {|| .T.}
- ENDIF
-
- // lRest == .T. means stay where I am. Anything else means start from
- // the top of the file
- //
- IF ! ( ( VALTYPE(lRest) == 'L' ) .AND. ( lRest == .T. ) )
- FileTop( nHandle )
- ENDIF
-
- BEGIN SEQUENCE
- IF nLine != NIL
- // Process only that one record
- nNextLines := 1
-
- FileTop( nHandle )
-
- IF nLine > 1
- cLine := FReadLn( nHandle, 1, nLineLength, cDelim )
- IF FERROR() != 0
- BREAK
- ENDIF
-
- lEOF := ( cLine == "" )
- nLine--
- ENDIF
-
- // Move to that record (nLine will equal 1 when we are there)
- DO WHILE ( ! lEOF ) .AND. (nLine > 1)
- cLine := FReadLn( nHandle, 1, nLineLength, cDelim )
- IF FERROR() != 0
- BREAK
- ENDIF
-
- lEOF := ( cLine == "" )
- nLine--
- ENDDO
- ENDIF
-
- // Save starting position
- nPrevPos := FilePos( nHandle)
-
- // If there is more to read from here, get the first line for comparison
- // and potential processing
- //
- IF ( ! lEOF ) .AND. (nNextLines == NIL .OR. nNextLines > 0)
- cLine := FReadLn( nHandle, 1, nLineLength, cDelim )
- IF FERROR() != 0
- BREAK
- ENDIF
-
- lEOF := ( cLine == "" )
- ENDIF
-
- DO WHILE ( ! lEOF ) .AND. EVAL( bWhile, cLine ) ;
- .AND. (nNextLines == NIL .OR. nNextLines > 0)
-
- IF EVAL( bFor, cLine )
- EVAL( bBlock, cLine )
- ENDIF
-
- // Save start of line
- nPrevPos := FilePos( nHandle )
-
- // Read next line
- cLine := FReadLn( nHandle, 1, nLineLength, cDelim )
- IF FERROR() != 0
- BREAK
- ENDIF
-
- lEOF := ( cLine == "" )
-
- IF nNextLines != NIL
- nNextLines--
- ENDIF
- ENDDO
-
- // If the reason for ending was that I ran past the WHILE or the number
- // of lines specified, back up to the beginning of the line that failed
- // so that there is no gap in processing
- //
- IF ( ! EVAL( bWhile, cLine ) ) .OR. ;
- ( (nNextLines != NIL) .AND. (nNextLines == 0) )
-
- FSEEK( nHandle, nPrevPos, FS_SET )
- ENDIF
- END SEQUENCE
-
- RETURN
-
-
- /***
- * FEof( <nHandle> ) --> lBoundary
- * Determine if the current file pointer position is the last
- * byte in the file
- *
- */
- FUNCTION FEof( nHandle )
- RETURN (IF(FileSize(nHandle) == FilePos(nHandle), .T., .F. ))
-
-
- /***
- * FWriteLn( <nHandle>, <cString>, [<nLength>], [<cDelim>] ) --> nBytes
- * Write a line to a text file at the current file pointer position.
- *
- * NOTE: Check FERROR() for the error
- *
- * NOTE: nLength defaults to length of entire string + delim, cDelim
- * defaults to CHR(13) + CHR(10)
- *
- * NOTE: Return value includes length of delimiter
- *
- */
- FUNCTION FWriteLn( nHandle, cString, nLength, cDelim )
-
- IF cDelim == NIL
- cString += CHR(13) + CHR(10)
- ELSE
- cString += cDelim
- ENDIF
-
- RETURN FWRITE( nHandle, cString, nLength )
-
-