Files
harbour-core/contrib/xhb/tfile.prg
Viktor Szakats 03ac58b17b 2017-09-08 18:22 UTC Viktor Szakats (vszakats users.noreply.github.com)
* bin/commit.hb
  * config/detect.mk
  * config/detfun.mk
  * config/detplat.mk
  * config/dir.mk
  * config/dirsh.mk
  * config/global.mk
  * config/globsh.mk
  * config/instsh.mk
  * config/lang.hb
  * config/lang2po.hb
  * config/po2lang.hb
  * config/postinst.hb
  * contrib/hbexpat/tests/tohash.prg
  * contrib/hbformat/utils/hbformat.ini
  * contrib/hbmisc/hbedit.prg
  * contrib/hbmxml/tests/testmxml.prg
  * contrib/hbnetio/utils/hbnetio/_console.prg
  * contrib/hbnetio/utils/hbnetio/_winsvc.prg
  * contrib/hbnetio/utils/hbnetio/hbnetio.prg
  * contrib/hbnetio/utils/hbnetio/netiomgm.hb
  * contrib/hbwin/tests/ole.prg
  * contrib/hbwin/tests/oletst2.js
  * contrib/hbwin/tests/oletst2.vbs
  * contrib/hbxpp/doc/en/binnumx.txt
  * contrib/hbxpp/doc/en/dbcmdx.txt
  * contrib/xhb/htmutil.prg
  * contrib/xhb/tfile.prg
  * contrib/xhb/tframe.prg
  * contrib/xhb/thtm.prg
  * ChangeLog.txt
  * debian/copyright
  * doc/class_tp.txt
  * doc/hdr_tpl.txt
  * doc/xhb-diff.txt
  * LICENSE.txt
  * package/harbour-wce.spec.in
  * package/harbour-win.spec.in
  * package/harbour.spec
  * package/mpkg_rpm_wce.sh
  * package/mpkg_rpm_win.sh
  * package/mpkg_rpm.sh
  * package/mpkg_src.sh
  * package/mpkg_ver.sh
  * src/rtl/achoice.prg
  * src/rtl/getsys53.prg
  * src/rtl/tgetlist.prg
  * src/rtl/tlabel.prg
  * src/rtl/tmenusys.prg
  * tests/hbdoc.prg
  * tests/langmsg.prg
  * tests/rto_get.prg
  * tests/rto_tb.prg
  + doc/en/ati.txt
  + doc/en/dirdrive.txt
  + doc/en/hashfunc.txt
  + doc/en/hbtoken.txt
  + doc/en/left.txt
  + doc/en/proc.txt
  + doc/en/strtran.txt
  + doc/en/transfrm.txt
  + doc/en/typefile.txt
  * doc/en/*
    * more partial sync with 3.4 fork
2017-09-08 18:25:11 +00:00

509 lines
10 KiB
Plaintext

/*
* Base fileIO class.
*
* Copyright 2000 Manos Aspradakis <maspr@otenet.gr>
* Copyright 2000 Luiz Rafael Culik <culik@sl.conex.net> (Porting this library to Harbour)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file LICENSE.txt. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA (or visit https://www.gnu.org/licenses/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries with other
* files to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
#include "hbclass.ch"
#include "fileio.ch"
#include "cgi.ch"
#translate FPOS( <f> ) => FSeek( <f>, 0, FS_RELATIVE )
CREATE CLASS TCgiFile
VAR Buffer INIT ""
VAR Name INIT ""
VAR Handle
VAR FileSize INIT 0
VAR BytesRead INIT 0
VAR cPage INIT ""
VAR nPage INIT 0
VAR nPageSize INIT 1024
VAR nRecord INIT 0
METHOD New( cName )
METHOD Open( nMode )
METHOD Close() INLINE FClose( ::Handle ), ;
::Handle := -999
METHOD Rename( c ) INLINE FRename( ::File, c ) == 0
METHOD Erase() INLINE FErase( ::File ) == 0
METHOD Exists() INLINE hb_FileExists( ::File )
METHOD Error() INLINE FError() != 0
METHOD Tell() INLINE FSeek( ::handle, 0, FS_RELATIVE )
METHOD Pointer() INLINE FPOS( ::handle )
METHOD ReadStr( n ) INLINE ::Buffer := ;
FReadStr( ::Handle, n )
METHOD Write( c, n ) INLINE FWrite( ::Handle, c, n )
METHOD WriteByte( nByte )
METHOD WriteInt( nInt )
METHOD WriteLong( nLong )
METHOD GetBuffer() INLINE ::Buffer
METHOD GoTop() INLINE FSeek( ::Handle, 0 )
METHOD GoBottom() INLINE FSeek( ::Handle, 0, FS_END )
METHOD Bof() INLINE( FPOS( ::Handle ) == 0 )
METHOD Eof() INLINE FPOS( ::Handle ) == ::FileSize
METHOD Seek( n, o ) INLINE FSeek( ::Handle, n, o )
METHOD Create( nAttr )
METHOD Size()
METHOD _Read( nSize, cBuff )
METHOD ReadAhead( nSize, cBuff )
METHOD ReadLine( nSize )
METHOD PrevLine( nBytes )
METHOD ReadByte()
METHOD ReadInt()
METHOD ReadLong()
METHOD Goto( nLine )
METHOD Skip( nLines )
METHOD MaxPages( nPageSize )
METHOD PrevPage( nBytes )
METHOD NextPage( nBytes )
ENDCLASS
METHOD New( cName ) CLASS TCgiFile
::Name := cName
::Buffer := ""
::Handle := 0
::FileSize := 0
::BytesRead := 0
::cPage := ""
::nPage := 0
::nPageSize := 1024
::nRecord := 0
RETURN Self
/*
** ::Open( [<nMode>] ) --> lSuccess
*/
METHOD Open( nMode ) CLASS TCgiFile
__defaultNIL( @nMode, FO_EXCLUSIVE )
::Handle := FOpen( ::Name, nMode )
IF ::Handle != F_ERROR
::Size()
ENDIF
RETURN ::Handle != F_ERROR
/*
** ::Create( [<nAttrib>] ) --> lSuccess
*/
METHOD Create( nAttr ) CLASS TCgiFile
LOCAL nSuccess
__defaultNIL( @nAttr, 0 )
nSuccess := FCreate( ::Name, nAttr )
::Handle := nSuccess
RETURN nSuccess != F_ERROR
/*
** ::Size() --> nFileSize
**
** RETURNs the size in bytes of the current file.
*/
METHOD Size() CLASS TCgiFile
LOCAL nCurrent
LOCAL nLength
nCurrent := FPOS( ::Handle )
nLength := FSeek( ::Handle, 0, FS_END )
FSeek( ::Handle, nCurrent )
::FileSize := nLength
RETURN nLength
/*
** ::Read( [<nSize>], [@<cBuff>] ) --> nBytesRead
*/
METHOD _Read( nSize, cBuff ) CLASS TCgiFile
__defaultNIL( @nSize, 1024 )
__defaultNIL( @cBuff, Space( nSize ) )
::BytesRead := FRead( ::Handle, @cBuff, nSize )
::Buffer := cBuff
RETURN cBuff // nBytesRead )
/*
** ::ReadAhead( [<nSize>], [@<cBuff>] ) --> nBytesRead
**
** Read forward in the file without moving the pointer.
*/
METHOD ReadAhead( nSize, cBuff ) CLASS TCgiFile
LOCAL nCurrent
__defaultNIL( @nSize, 1024 )
__defaultNIL( @cBuff, Space( nSize ) )
// --> save position in file
nCurrent := FPOS( ::Handle )
// --> read ahead
::BytesRead := FRead( ::Handle, @cBuff, nSize )
// --> RETURN to saved position
FSeek( ::Handle, nCurrent )
RETURN cBuff
/*
** ::ReadLine( [<nBytes>] ) --> cLine
*/
METHOD Readline( nSize ) CLASS TCgiFile
LOCAL cString
LOCAL nCurrent
LOCAL nCr
__defaultNIL( @nSize, 1024 )
IF nSize <= 0
RETURN ""
ENDIF
nCurrent := FSeek( ::Handle, 0, FS_RELATIVE )
cString := FReadStr( ::Handle, nSize )
nCr := At( Chr( 13 ), cString )
FSeek( ::Handle, nCurrent, FS_SET )
FSeek( ::Handle, nCr + 1, FS_RELATIVE )
::Buffer := SubStr( cString, 1, nCr - 1 )
::nRecord++
RETURN ::Buffer
/*
** ::ReadByte() --> nByte or -1 if unsuccessfull
*/
METHOD ReadByte() CLASS TCgiFile
LOCAL nBytes
LOCAL cBuff := Space( 1 )
nBytes := FRead( ::Handle, @cBuff, hb_BLen( cBuff ) )
RETURN iif( nBytes > 0, Asc( cBuff ), -1 )
/*
** ::ReadInt() --> nUnsignedInt or -1 if unsuccessfull
*/
METHOD ReadInt() CLASS TCgiFile
LOCAL nBytes
LOCAL cBuff := Space( 2 )
nBytes := FRead( ::Handle, @cBuff, hb_BLen( cBuff ) )
RETURN iif( nBytes > 0, Bin2I( cBuff ), -1 )
/*
** ::ReadLong() --> nLong or -1 if unsuccessfull
*/
METHOD ReadLong() CLASS TCgiFile
LOCAL nBytes
LOCAL cBuff := Space( 4 )
nBytes := FRead( ::Handle, @cBuff, hb_BLen( cBuff ) )
RETURN iif( nBytes > 0, Bin2L( cBuff ), -1 )
/*
** ::WriteByte( nByte ) --> lSuccess
*/
METHOD WriteByte( nByte ) CLASS TCgiFile
LOCAL lSuccess := ( FWrite( ::nHandle, hb_BCode( nByte ), 1 ) == 1 )
RETURN lSuccess
/*
** ::WriteInt( nInt ) --> lSuccess
*/
METHOD WriteInt( nInt ) CLASS TCgiFile
LOCAL lSuccess := ( FWrite( ::nHandle, I2Bin( nInt ), 2 ) == 2 )
RETURN lSuccess
/*
** ::WriteLong( nLong ) --> lSuccess
*/
METHOD WriteLong( nLong ) CLASS TCgiFile
LOCAL lSuccess := ( FWrite( ::nHandle, L2Bin( nLong ), 4 ) == 4 )
RETURN lSuccess
/*
** ::GOTO( <nLine> ) --> nPrevPos
**
** Skips to line <nLine> from top. RETURNs previous position in file.
**
*/
METHOD Goto( nLine ) CLASS TCgiFile
LOCAL nCount := 1
LOCAL nPos := FPOS( ::Handle )
::GoTop()
IF nLine < 0 // don't accept < 0
RETURN nPos
ELSEIF nLine == 0
nLine := 1
::nRecord := 1
::GoTop()
RETURN nPos
ENDIF
WHILE ! ::Eof()
::ReadLine()
IF nCount == nLine
EXIT
ENDIF
nCount++
ENDDO
RETURN nPos
/*
** ::Skip( [<nLines>] ) --> nPrevPos
**
** Skips to line <nLine> from top. RETURNs previous position in file.
**
*/
METHOD Skip( nLines ) CLASS TCgiFile
LOCAL nCount := 0
LOCAL nPos := FPOS( ::Handle )
__defaultNIL( @nLines, 1 )
IF nLines <= 0 // don't accept < 0
RETURN nPos
ENDIF
WHILE ! ::Eof()
IF nCount == nLines
EXIT
ENDIF
::ReadLine()
nCount++
ENDDO
RETURN nPos
/*
** ::MaxPages( <nPageSize> ) --> nMaxPages
*/
METHOD MaxPages( nPageSize ) CLASS TCgiFile
__defaultNIL( @nPageSize, ::nPageSize )
RETURN ::Size() / nPageSize
/*
** ::PrevPage( [<nBytes>] ) --> cPage
*/
METHOD PrevPage( nBytes ) CLASS TCgiFile
__defaultNIL( @nBytes, 1024 )
IF nBytes <= 0
RETURN ""
ENDIF
IF ! ::Bof()
FSeek( ::Handle, - nBytes, FS_RELATIVE )
::cPage := FReadStr( ::Handle, nBytes )
FSeek( ::Handle, - nBytes, FS_RELATIVE )
::nPage --
ENDIF
RETURN ::cPage
/*
** ::NextPage( [<nBytes>] ) --> cPage
*/
METHOD NextPage( nBytes ) CLASS TCgiFile
__defaultNIL( @nBytes, 1024 )
IF nBytes <= 0
RETURN ""
ENDIF
IF ! ::Eof()
::cPage := FReadStr( ::Handle, nBytes )
::nPage++
ENDIF
RETURN ::cPage
/*
** ::PrevLine( [<nBytes>] ) --> ::Buffer
*/
METHOD PrevLine( nBytes ) CLASS TCgiFile
LOCAL fHandle := ::Handle
LOCAL nOrigPos := FPOS( fHandle )
LOCAL nMaxRead
LOCAL nNewPos
LOCAL lMoved
LOCAL cBuff
LOCAL nWhereCrLf
LOCAL nPrev
LOCAL cTemp
__defaultNIL( @nBytes, 256 )
IF nOrigPos == 0
lMoved := .F.
ELSE
lMoved := .T.
// Check preceeding 2 chars for CR+LF
FSeek( fHandle, -2, FS_RELATIVE )
cTemp := Space( 2 )
FRead( fHandle, @cTemp, hb_BLen( cTemp ) )
IF cTemp == CRLF()
FSeek( fHandle, -2, FS_RELATIVE )
ENDIF
nMaxRead := Min( nBytes, FPOS( fHandle ) )
cBuff := Space( nMaxRead )
nNewPos := FSeek( fHandle, -nMaxRead, FS_RELATIVE )
FRead( fHandle, @cBuff, nMaxRead )
nWhereCrLf := RAt( CRLF(), cBuff )
IF nWhereCrLf == 0
nPrev := nNewPos
::Buffer := cBuff
ELSE
nPrev := nNewPos + nWhereCrLf + 1
::Buffer := SubStr( cBuff, nWhereCrLf + 2 )
ENDIF
FSeek( fHandle, nPrev, FS_SET )
ENDIF
RETURN iif( lMoved, ::Buffer, "" )