/*************************************************************************
 *
 *  $RCSfile: stream.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: mba $ $Date: 2001/02/06 10:45:49 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This 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 library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _STREAM_HXX
#define _STREAM_HXX

#ifndef _SOLAR_H
#include <tools/solar.h>
#endif
#ifndef _STRING_HXX
#include <tools/string.hxx>
#endif
#ifndef _EINF_HXX
#include <tools/errinf.hxx>
#endif
#ifndef _REF_HXX
#include <tools/ref.hxx>
#endif
#ifndef _RTTI_HXX
#include <tools/rtti.hxx>
#endif

class StreamData;

// ------------------------
// - FileFormat-Functions -
// ------------------------

inline rtl_TextEncoding GetStoreCharSet( rtl_TextEncoding eEncoding, USHORT nVersion = SOFFICE_FILEFORMAT_50 )
{
	if ( eEncoding == RTL_TEXTENCODING_ISO_8859_1 )
		return RTL_TEXTENCODING_MS_1252;
	else
		return eEncoding;
}

// ---------------
// - StreamTypes -
// ---------------

typedef USHORT StreamMode;

// read, write, create,... options
#define STREAM_READ 					0x0001	// allow read accesses
#define STREAM_WRITE					0x0002	// allow write accesses
// file i/o
#define STREAM_NOCREATE 				0x0004	// 1 == Dont create file
#define STREAM_TRUNC					0x0008	// Truncate _existing_ file to zero length
#define STREAM_COPY_ON_SYMLINK			0x0010	// copy-on-write for symlinks (UNX)

#define STREAM_READWRITEBITS			(STREAM_READ | STREAM_WRITE | \
										 STREAM_NOCREATE | STREAM_TRUNC)

// sharing options
#define STREAM_SHARE_DENYNONE			0x0100
#define STREAM_SHARE_DENYREAD			0x0200	// overrides denynone
#define STREAM_SHARE_DENYWRITE			0x0400	// overrides denynone
#define STREAM_SHARE_DENYALL			0x0800	// overrides denyread,write,none

#define STREAM_SHAREBITS				(STREAM_SHARE_DENYNONE | STREAM_SHARE_DENYREAD |\
										 STREAM_SHARE_DENYWRITE | STREAM_SHARE_DENYALL)

#define STREAM_READWRITE				(STREAM_READ | STREAM_WRITE)
#define STREAM_SHARE_DENYREADWRITE		(STREAM_SHARE_DENYREAD | STREAM_SHARE_DENYWRITE)

#define STREAM_STD_READ 				(STREAM_READ | STREAM_SHARE_DENYNONE | STREAM_NOCREATE)
#define STREAM_STD_WRITE				(STREAM_WRITE | STREAM_SHARE_DENYALL)
#define STREAM_STD_READWRITE			(STREAM_READWRITE | STREAM_SHARE_DENYALL)

#define STREAM_SEEK_TO_BEGIN			0L
#define STREAM_SEEK_TO_END				0xFFFFFFFFL

#define NUMBERFORMAT_INT_BIGENDIAN		(UINT16)0x0000
#define NUMBERFORMAT_INT_LITTLEENDIAN	(UINT16)0xFFFF

#define COMPRESSMODE_FULL				(UINT16)0xFFFF
#define COMPRESSMODE_NONE				(UINT16)0x0000
#define COMPRESSMODE_ZBITMAP			(UINT16)0x0001
#define COMPRESSMODE_NATIVE 			(UINT16)0x0010

#define JUSTIFY_RIGHT					0x00
#define JUSTIFY_LEFT					0x01

#define STREAM_IO_DONTKNOW				0
#define STREAM_IO_READ					1
#define STREAM_IO_WRITE 				2

#define ID_STREAM						1
#define ID_FILESTREAM					2
#define ID_MEMORYSTREAM 				3
#define ID_SHAREDMEMORYSTREAM			4
#define ID_STORAGESTREAM				5
#define ID_PERSISTSTREAM				6

class SvStream;
typedef SvStream& (*SvStrPtr)( SvStream& );

// forward declaration with internal linkage
inline SvStream& operator<<( SvStream& rStr, SvStrPtr f );

// ---------------
// - SvLockBytes -
// ---------------

enum LockType {};

struct SvLockBytesStat
{
	ULONG nSize;

	SvLockBytesStat(): nSize(0) {}
};

enum SvLockBytesStatFlag { SVSTATFLAG_DEFAULT };

class SvLockBytes: public virtual SvRefBase
{
	SvStream * m_pStream;
	BOOL m_bOwner;
	BOOL m_bSync;

protected:
	void close();

public:
	TYPEINFO();

	SvLockBytes(): m_pStream(0), m_bOwner(FALSE), m_bSync(FALSE) {}

	SvLockBytes(SvStream * pTheStream, BOOL bTheOwner = FALSE):
		m_pStream(pTheStream), m_bOwner(bTheOwner), m_bSync(FALSE) {}

	virtual ~SvLockBytes() { close(); }

	virtual const SvStream * GetStream() const { return m_pStream; }

	virtual void SetSynchronMode(BOOL bTheSync = TRUE) { m_bSync = bTheSync; }

	virtual BOOL IsSynchronMode() const { return m_bSync; }

	virtual ErrCode ReadAt(ULONG nPos, void * pBuffer, ULONG nCount,
						   ULONG * pRead) const;

	virtual ErrCode WriteAt(ULONG nPos, const void * pBuffer, ULONG nCount,
							ULONG * pWritten);

	virtual ErrCode Flush() const;

	virtual ErrCode SetSize(ULONG nSize);

	virtual ErrCode LockRegion(ULONG, ULONG, LockType);

	virtual ErrCode UnlockRegion(ULONG, ULONG, LockType);

	virtual ErrCode Stat(SvLockBytesStat * pStat, SvLockBytesStatFlag) const;
};

SV_DECL_IMPL_REF(SvLockBytes);

// -------------------
// - SvOpenLockBytes -
// -------------------

class SvOpenLockBytes: public SvLockBytes
{
public:
	TYPEINFO();

	SvOpenLockBytes(): SvLockBytes(0, FALSE) {}

	SvOpenLockBytes(SvStream * pStream, BOOL bOwner):
		SvLockBytes(pStream, bOwner) {}

	virtual ErrCode FillAppend(const void * pBuffer, ULONG nCount,
							   ULONG * pWritten) = 0;

	virtual ULONG Tell() const = 0;

	virtual ULONG Seek(ULONG nPos) = 0;

	virtual void Terminate() = 0;
};

SV_DECL_IMPL_REF(SvOpenLockBytes);

// --------------------
// - SvAsyncLockBytes -
// --------------------

class SvAsyncLockBytes: public SvOpenLockBytes
{
	ULONG m_nSize;
	BOOL m_bTerminated;

public:
	TYPEINFO();

	SvAsyncLockBytes(SvStream * pStream, BOOL bOwner):
		SvOpenLockBytes(pStream, bOwner), m_nSize(0), m_bTerminated(FALSE) {}

	virtual ErrCode ReadAt(ULONG nPos, void * pBuffer, ULONG nCount,
						   ULONG * pRead) const;

	virtual ErrCode WriteAt(ULONG nPos, const void * pBuffer, ULONG nCount,
							ULONG * pWritten);

	virtual ErrCode FillAppend(const void * pBuffer, ULONG nCount,
							   ULONG * pWritten);

	virtual ULONG Tell() const { return m_nSize; }

	virtual ULONG Seek(ULONG nPos);

	virtual void Terminate() { m_bTerminated = TRUE; }
};

SV_DECL_IMPL_REF(SvAsyncLockBytes);

// ----------
// - Stream -
// ----------

class SvStream
{
private:
	// LockBytes Interface
	void*			pImp;			// unused
	SvLockBytesRef	xLockBytes; 	// Default Implmentierung
	ULONG			nActPos;		//

	// Puffer-Verwaltung
	BYTE*			pRWBuf; 		// Zeigt auf Read/Write-Puffer
	BYTE*			pBufPos;		// pRWBuf + nBufActualPos
	USHORT			nBufSize;		// Allozierte Groesse des Puffers
	USHORT			nBufActualLen;	// Laenge des beschriebenen Teils des Puffers
									// Entspricht nBufSize, wenn EOF nicht
									// ueberschritten wurde
	USHORT			nBufActualPos;	// aktuelle Position im Puffer (0..nBufSize-1)
	USHORT			nBufFree;		// freier Platz im Puffer fuer IO vom Typ eIOMode
	int 			eIOMode:2;		// STREAM_IO_*

	// Error-Codes, Konvertierung, Komprimierung, ...
	int 			bIsDirty:1; 	// TRUE: Stream != Pufferinhalt
	int 			bIsConsistent:1;// FALSE: Buffer enthaelt Daten, die NICHT
									// per PutData in den abgeleiteten Stream
									// geschrieben werden duerfen (siehe PutBack)
	int 			bSwap:1;
	int 			bIsEof:1;
	ULONG			nError;
	UINT16			nNumberFormatInt;
	UINT16			nCompressMode;
	LineEnd 		eLineDelimiter;
	CharSet 		eStreamCharSet;
//	CharSet 		eTargetCharSet;

	// Verschluesselung
	ByteString		aKey;			// aKey.Len != 0  -> Verschluesselung
	unsigned char	nCryptMask;

	// Formatierung von Strings
	char			cFiller;
	BYTE			nRadix;
	BYTE			nPrecision;
	BYTE			nWidth;
	BYTE			nPrintfParams;
	BYTE			nJustification;
	ByteString		aFormatString;

	// Userdata
	long			nVersion;		// for external use

	// Hilfsmethoden
	void			CreateFormatString();
	void			ImpInit();
					SvStream ( const SvStream& rStream ); // not implemented
	SvStream&		operator=( const SvStream& rStream ); // not implemented

protected:
	ULONG			nBufFilePos;	// Fileposition von pBuf[0]
	USHORT			eStreamMode;
	BOOL			bIsWritable;

	virtual ULONG	GetData( void* pData, ULONG nSize );
	virtual ULONG	PutData( const void* pData, ULONG nSize );
	virtual ULONG	SeekPos( ULONG nPos );
	virtual void	FlushData();
	virtual void	SetSize( ULONG nSize );

	void			ClearError();
	void			ClearBuffer();

	// verschluesselt & schreibt blockweise
	ULONG			CryptAndWriteBuffer( const void* pStart, ULONG nLen );
	BOOL			EncryptBuffer( void* pStart, ULONG nLen );

	void			SyncSvStream( ULONG nNewStreamPos ); // SvStream <- Medium
	void			SyncSysStream(); // SvStream -> Medium

public:
					SvStream();
					SvStream( SvLockBytes *pLockBytes);
	virtual 		~SvStream();

	ErrCode 		SetLockBytes( SvLockBytesRef& rBytes );
	SvLockBytes*	GetLockBytes() const { return xLockBytes; }

	ULONG			GetError() const { return ERRCODE_TOERROR(nError); }
	ULONG			GetErrorCode() const { return nError; }

	void			SetError( ULONG nErrorCode );
	virtual void	ResetError();

	void			SetNumberFormatInt( UINT16 nNewFormat );
	UINT16			GetNumberFormatInt() const { return nNumberFormatInt; }
					/// Enable/disable swapping of endians, may be needed for Unicode import/export
	inline void		SetEndianSwap( BOOL bVal );
					// returns status of endian swap flag
	BOOL			IsEndianSwap() const { return 0 != bSwap; }

	void			SetCompressMode( UINT16 nNewMode )
						{ nCompressMode = nNewMode; }
	UINT16			GetCompressMode() const { return nCompressMode; }

	void			SetKey( const ByteString& rKey );
	const ByteString&	GetKey() const { return aKey; }

	void			SetStreamCharSet( CharSet eCharSet )
						{ eStreamCharSet = eCharSet; }
	CharSet 		GetStreamCharSet() const { return eStreamCharSet; }
//	void			SetTargetCharSet( CharSet eCharSet )
//						{ eTargetCharSet = eCharSet; }
//	CharSet 		GetTargetCharSet() const { return eTargetCharSet; }

	void			SetLineDelimiter( LineEnd eLineEnd )
						{ eLineDelimiter = eLineEnd; }
	LineEnd 		GetLineDelimiter() const { return eLineDelimiter; }

	SvStream&		operator>>( USHORT& rUShort );
	SvStream&		operator>>( ULONG& rULong );
	SvStream&		operator>>( long& rLong );
	SvStream&		operator>>( short& rShort );
	SvStream&		operator>>( int& rInt );
	SvStream&		operator>>( unsigned int& rUInt );
	SvStream&		operator>>( signed char& rChar );
	SvStream&		operator>>( char& rChar );
	SvStream&		operator>>( unsigned char& rChar );
	SvStream&		operator>>( float& rFloat );
	SvStream&		operator>>( double& rDouble );
#ifdef ENABLE_BYTESTRING_STREAM_OPERATORS
	SvStream&		operator>>( ByteString& rString ) { return ReadByteString(rString); }
#endif
#ifdef ENABLE_STRING_STREAM_OPERATORS
	SvStream&		operator>>( UniString& rString ) { return ReadByteString(rString); }
#endif
	SvStream&		operator>>( SvStream& rStream );

	SvStream&		operator<<( USHORT nUShort );
	SvStream&		operator<<( ULONG nULong );
	SvStream&		operator<<( long nLong );
	SvStream&		operator<<( short nShort );
	SvStream&		operator<<( int nInt );
	SvStream&		operator<<( unsigned int nUInt );
	SvStream&		operator<<( signed char nChar );
	SvStream&		operator<<( char nChar );
	SvStream&		operator<<( unsigned char nChar );
	SvStream&		operator<<( float nFloat );
	SvStream&		operator<<( const double& rDouble );
	SvStream&		operator<<( const char* pBuf );
	SvStream&		operator<<( const unsigned char* pBuf );
#ifdef ENABLE_BYTESTRING_STREAM_OPERATORS
	SvStream&		operator<<( const ByteString& rString ) { return WriteByteString( rString ); }
#endif
#ifdef ENABLE_STRING_STREAM_OPERATORS
	SvStream&		operator<<( const UniString& rString ) { return WriteByteString(rString); }
#endif
	SvStream&		operator<<( SvStream& rStream );

	SvStream&		ReadByteString( UniString& rStr, rtl_TextEncoding eSrcCharSet );
	SvStream&		ReadByteString( UniString& rStr ) { return ReadByteString( rStr, GetStreamCharSet() ); }
	SvStream&       ReadByteString( ByteString& rStr );
	SvStream&		WriteByteString( const UniString& rStr, rtl_TextEncoding eDestCharSet );
	SvStream&		WriteByteString( const UniString& rStr ) { return WriteByteString( rStr, GetStreamCharSet() ); }
	SvStream&       WriteByteString( const ByteString& rStr );

	void			SetRadix( BYTE nRad )
						{ nRadix = nRad; CreateFormatString(); }
	BYTE			GetRadix() const { return nRadix; }
	void			SetPrecision( BYTE nPrec )
						{ nPrecision = nPrec; CreateFormatString(); }
	BYTE			GetPrecision() const { return nPrecision; }
	void			SetWidth( BYTE nWid)
						{ nWidth = nWid; CreateFormatString(); }
	BYTE			GetWidth() const { return nWidth; }
	void			SetFiller( char cFil )
						{ cFiller = cFil; CreateFormatString(); }
	char			GetFiller() const { return cFiller; }
	void			SetJustification( BYTE nJus )
						 { nJustification = nJus; CreateFormatString(); }
	BYTE			GetJustification() const { return nJustification; }

	SvStream&		ReadNumber( short& rShort );
	SvStream&		ReadNumber( USHORT& rUShort );
	SvStream&		ReadNumber( long& rLong );
	SvStream&		ReadNumber( ULONG& rULong );
	SvStream&		ReadNumber( int& rInt );
	SvStream&		ReadNumber( unsigned int& rUInt );
	SvStream&		ReadNumber( float& rFloat );
	SvStream&		ReadNumber( double& rDouble );

	SvStream&		WriteNumber( short nShort );
	SvStream&		WriteNumber( USHORT nUShort );
	SvStream&		WriteNumber( long nLong );
	SvStream&		WriteNumber( ULONG nULong );
	SvStream&		WriteNumber( int nInt );
	SvStream&		WriteNumber( unsigned int nUInt );
	SvStream&		WriteNumber( float nFloat );
	SvStream&		WriteNumber( const double& rDouble );

	ULONG			Read( void* pData, ULONG nSize );
	ULONG			Write( const void* pData, ULONG nSize );
	ULONG			Seek( ULONG nPos );
	ULONG			SeekRel( long nPos );
	ULONG			Tell() const { return nBufFilePos+nBufActualPos;  }
	void			Flush();
	BOOL			IsEof() const { return bIsEof; }
	// next Tell() <= nSize
	BOOL			SetStreamSize( ULONG nSize );

					/// Read in the stream to a zero character and put all
					/// read chracters in the Bytestring. The String interface
					/// convert the BytString with the given encoding to a String
	BOOL			ReadCString( ByteString& rStr );
	BOOL 			ReadCString( String& rStr, rtl_TextEncoding eToEncode );
	BOOL 			ReadCString( String& rStr ) { return ReadCString( rStr, GetStreamCharSet()); }

	BOOL			ReadLine( ByteString& rStr );
	BOOL			WriteLine( const ByteString& rStr );
	BOOL			WriteLines( const ByteString& rStr );

	BOOL			ReadByteStringLine( String& rStr, rtl_TextEncoding eSrcCharSet );
	BOOL			ReadByteStringLine( String& rStr ) { return ReadByteStringLine( rStr, GetStreamCharSet()); }
	BOOL			WriteByteStringLine( const String& rStr, rtl_TextEncoding eDestCharSet );
	BOOL			WriteByteStringLine( const String& rStr ) { return WriteByteStringLine( rStr, GetStreamCharSet()); }
	BOOL			WriteByteStringLines( const String& rStr, rtl_TextEncoding eDestCharSet );
	BOOL			WriteByteStringLines( const String& rStr ) { return WriteByteStringLine( rStr, GetStreamCharSet()); }

					/// Switch to no endian swapping and write 0xfeff
	BOOL			StartWritingUnicodeText();
					/// Read 16bit, if 0xfeff do nothing, if 0xfffe switch
					/// endian swapping, if none of them put back
	BOOL			StartReadingUnicodeText();

					/// Read a line of Unicode
	BOOL			ReadUniStringLine( String& rStr );
					/// Read a line of Unicode if eSrcCharSet==RTL_TEXTENCODING_UNICODE,
					/// otherwise read a line of Bytecode and convert from eSrcCharSet
	BOOL			ReadUniOrByteStringLine( String& rStr, rtl_TextEncoding eSrcCharSet );
	BOOL			ReadUniOrByteStringLine( String& rStr )
						{ return ReadUniOrByteStringLine( rStr, GetStreamCharSet() ); }
					/// Write a sequence of Unicode characters
	BOOL			WriteUnicodeText( const String& rStr );
					/// Write a sequence of Unicode characters if eDestCharSet==RTL_TEXTENCODING_UNICODE,
					/// otherwise write a sequence of Bytecodes converted to eDestCharSet
	BOOL			WriteUnicodeOrByteText( const String& rStr, rtl_TextEncoding eDestCharSet );
	BOOL			WriteUnicodeOrByteText( const String& rStr )
						{ return WriteUnicodeOrByteText( rStr, GetStreamCharSet() ); }
					/// Write a line of Unicode and append line end (endlu())
	BOOL			WriteUniStringLine( const String& rStr );
					/// Write multiple lines of Unicode (with CovertLineEnd) and append line end (endlu())
	BOOL			WriteUniStringLines( const String& rStr );
					/// Write a line of Unicode if eDestCharSet==RTL_TEXTENCODING_UNICODE,
					/// otherwise write a line of Bytecode converted to eDestCharSet
	BOOL			WriteUniOrByteStringLine( const String& rStr, rtl_TextEncoding eDestCharSet );
	BOOL			WriteUniOrByteStringLine( const String& rStr )
						{ return WriteUniOrByteStringLine( rStr, GetStreamCharSet() ); }
					/// Write multiple lines of Unicode if eDestCharSet==RTL_TEXTENCODING_UNICODE,
					/// otherwise write multiple lines of Bytecode converted to eDestCharSet,
					/// CovertLineEnd is applied.
	BOOL			WriteUniOrByteStringLines( const String& rStr, rtl_TextEncoding eDestCharSet );
	BOOL			WriteUniOrByteStringLines( const String& rStr )
						{ return WriteUniOrByteStringLines( rStr, GetStreamCharSet() ); }
					/// Write a Unicode character if eDestCharSet==RTL_TEXTENCODING_UNICODE,
					/// otherwise write as Bytecode converted to eDestCharSet.
					/// This may result in more than one byte being written
					/// if a multi byte encoding (e.g. UTF7, UTF8) is chosen.
	BOOL			WriteUniOrByteChar( sal_Unicode ch, rtl_TextEncoding eDestCharSet );
	BOOL			WriteUniOrByteChar( sal_Unicode ch )
						{ return WriteUniOrByteChar( ch, GetStreamCharSet() ); }

	void			SetBufferSize( USHORT nBufSize );
	USHORT			GetBufferSize() const { return nBufSize; }

	void			RefreshBuffer();
	SvStream&		PutBack( char aCh );
	void			EatWhite();

	BOOL			IsWritable() const { return bIsWritable; }
	StreamMode		GetStreamMode() const { return eStreamMode; }
	virtual USHORT	IsA() const;

	long			GetVersion() { return nVersion; }
	void			SetVersion( long n ) { nVersion = n; }

	/** Add a mark to indicate to which position in the stream you want to be
		able to seek back.

		@descr	If you set a mark at nPos, you indicate to the stream that you
		won't issue seek operations to any position 'before' nPos.  This can
		be exploited by 'transient streams' that do not permanently store
		their data; they can discard any buffered data up to nPos.

		@descr	However, if the stream is already positioned past nPos, this
		method is not guaranteed to have the desired effect.  A 'transient
		stream' may have already discarded the buffered data at nPos, so that
		a seek operation to nPos will fail nonetheless.

		@descr	There can be more than one mark for a stream, indicating that
		you want to be able to seek back in the stream as far as the 'lowest'
		off all the marks.	There can even be multiple marks at the same
		position (and they must all be individually removed with
		RemoveMark()).

		@param nPos  The position in the stream at which to add a mark.
	 */
	virtual void	AddMark(ULONG nPos);

	/** Remove a mark introduced with AddMark().

		@descr	If you no longer need to seek back to some position for which
		you added a mark, you should remove that mark.	(And a 'transient
		stream' that does not permanently store its data can then potentially
		discard some of its buffered data.)

		@descr	Removing one mark does not have any effects on any other
		marks.	Especially, if you have multiple marks at the same position,
		you must call this method multiple times to effectively 'unmark' that
		position.

		@descr	If you specify a position for which there is no mark, this
		method simply has no effect.

		@param nPos  The position in the stream at which to remove the mark.
	 */
	virtual void	RemoveMark(ULONG nPos);

	friend SvStream& operator<<( SvStream& rStr, SvStrPtr f ); // fuer Manips
};

inline SvStream& operator<<( SvStream& rStr, SvStrPtr f )
{
	(*f)(rStr);
	return rStr;
}

inline SvStream& SvStream::ReadNumber( short& rShort )
{
	long nTmp;
	ReadNumber( nTmp );
	rShort = (short)nTmp;
	return *this;
}

inline SvStream& SvStream::ReadNumber( USHORT& rUShort )
{
	ULONG nTmp;
	ReadNumber( nTmp );
	rUShort = (USHORT)nTmp;
	return *this;
}

inline SvStream& SvStream::ReadNumber( int& rInt )
{
	long nTmp;
	ReadNumber( nTmp );
	rInt = (int)nTmp;
	return *this;
}

inline SvStream& SvStream::ReadNumber( unsigned int& rUInt )
{
	ULONG nTmp;
	ReadNumber( nTmp );
	rUInt = (unsigned int)nTmp;
	return *this;
}

inline SvStream& SvStream::ReadNumber( float& rFloat )
{
	double nTmp;
	ReadNumber( nTmp );
	rFloat = (float)nTmp;
	return *this;
}

inline SvStream& SvStream::WriteNumber( short nShort )
{
	WriteNumber( (long)nShort );
	return *this;
}

inline SvStream& SvStream::WriteNumber( USHORT nUShort )
{
	WriteNumber( (ULONG)nUShort );
	return *this;
}

inline SvStream& SvStream::WriteNumber( int nInt )
{
	WriteNumber( (long)nInt );
	return *this;
}

inline SvStream& SvStream::WriteNumber( unsigned int nUInt )
{
	WriteNumber( (ULONG)nUInt );
	return *this;
}

inline SvStream& SvStream::WriteNumber( float nFloat )
{
	double nTemp = nFloat;
	WriteNumber( nTemp );
	return *this;
}

inline void SvStream::SetEndianSwap( BOOL bVal )
{
#ifdef __BIGENDIAN
	SetNumberFormatInt( bVal ? NUMBERFORMAT_INT_LITTLEENDIAN : NUMBERFORMAT_INT_BIGENDIAN );
#else
	SetNumberFormatInt( bVal ? NUMBERFORMAT_INT_BIGENDIAN : NUMBERFORMAT_INT_LITTLEENDIAN );
#endif
}

SvStream& endl( SvStream& rStr );
/// same as endl() but Unicode
SvStream& endlu( SvStream& rStr );
/// call endlu() if eStreamCharSet==RTL_TEXTECODING_UNICODE otherwise endl()
SvStream& endlub( SvStream& rStr );

// --------------
// - FileStream -
// --------------

class SvFileStream : public SvStream
{
	friend class ImpEaMgr;
	friend class CORmFileStream;

private:
	StreamData* 		pInstanceData;
	String				aFilename;
	USHORT				nLockCounter;
	BOOL				bIsOpen;
	ULONG				GetFileHandle() const;

protected:

	virtual ULONG	GetData( void* pData, ULONG nSize );
	virtual ULONG	PutData( const void* pData, ULONG nSize );
	virtual ULONG	SeekPos( ULONG nPos );
	virtual void	SetSize( ULONG nSize );
	virtual void	FlushData();

public:
					// Schaltet bei fehlgeschlagenem Schreiboeffnen auf Lesen zurueck
					SvFileStream( const String& rFileName, StreamMode eOpenMode );
					SvFileStream();
					~SvFileStream();

	virtual void	ResetError();

	BOOL			LockRange( ULONG nByteOffset, ULONG nBytes );
	BOOL			UnlockRange( ULONG nByteOffset, ULONG nBytes );
	BOOL			LockFile();
	BOOL			UnlockFile();

	void			Open( const String& rFileName, StreamMode eOpenMode );
	void			Close();
	void			ReOpen(); // Aufruf nach Close, FilePointer == 0
	BOOL			IsOpen() const { return bIsOpen; }
	BOOL			IsLocked() const { return ( nLockCounter!=0 ); }
	virtual USHORT	IsA() const;

	const String&	GetFileName() const { return aFilename; }
};

// ----------------
// - MemoryStream -
// ----------------

class SvMemoryStream : public SvStream
{
protected:
	ULONG			nSize;
	ULONG			nResize;
	ULONG			nPos;
	ULONG			nEndOfData;
	BYTE*			pBuf;
	BOOL			bOwnsData;

	virtual ULONG	GetData( void* pData, ULONG nSize );
	virtual ULONG	PutData( const void* pData, ULONG nSize );
	virtual ULONG	SeekPos( ULONG nPos );
	virtual void	SetSize( ULONG nSize );
	virtual void	FlushData();

	// AllocateMemory muss folgende Variable mitpflegen:
	// - pBuf: Adresse des neuen Blocks
	virtual BOOL	AllocateMemory( ULONG nSize );

	// ReAllocateMemory muss folgende Variablen mitpflegen:
	// - pBuf: Adresse des neuen Blocks
	// - nEndOfData: Muss auf nNewSize-1L gesetzt werden, wenn ausserhalb des Blocks
	//				 Muss auf 0 gesetzt werden, wenn neuer Block 0 Byte gross
	// - nSize: Neue Groesse des Blocks
	// - nPos: Muss auf 0 gesetzt werden, wenn ausserhalb des Blocks
	virtual BOOL	ReAllocateMemory( long nDiff );

	// wird aufgerufen, wenn dem Stream der Speicher gehoert oder wenn
	// der Speicher in der Groesse veraendert wird.
	// FreeMemory muss folgende Variablen mitpflegen:
	// - in abgeleiteten Klassen muessen ggf. Handles genullt werden
	virtual void	FreeMemory();

					SvMemoryStream(void*) { }	// Fuer unsere Subklassen

public:
					SvMemoryStream( void* pBuf, ULONG nSize, StreamMode eMode);
					SvMemoryStream( ULONG nInitSize=512, ULONG nResize=64 );
					~SvMemoryStream();

	virtual void	ResetError();

	ULONG			GetSize() const { return nSize; }
	const void* 	GetData() { Flush(); return pBuf; }
	operator const	void*() { Flush(); return pBuf; }
	virtual USHORT	IsA() const;

	void*			SwitchBuffer( ULONG nInitSize=512, ULONG nResize=64 );
	void*			SetBuffer( void* pBuf, ULONG nSize,
							   BOOL bOwnsData=TRUE, ULONG nEOF=0 );

	void			ObjectOwnsMemory( BOOL bOwn ) { bOwnsData = bOwn; }
	BOOL			IsObjectMemoryOwner() { return bOwnsData; }
	void			SetResizeOffset( ULONG nNewResize ) { nResize = nNewResize; }
	ULONG			GetResizeOffset() const { return nResize; }
};

// ----------------------
// - SharedMemoryStream -
// ----------------------

class SvSharedMemoryStream : public SvMemoryStream
{
	void*			aHandle;
protected:

	// Die 3 Memory-Routinen arbeiten mit den Membervariablen
	// pBuf und aHandle (plattformabhaengig)
	virtual BOOL	AllocateMemory( ULONG nSize );
	virtual BOOL	ReAllocateMemory( long nDiff );
	virtual void	FreeMemory();

	virtual ULONG	GetData( void* pData, ULONG nSize );
	virtual ULONG	PutData( const void* pData, ULONG nSize );

public:
					SvSharedMemoryStream( void* pBuf, ULONG nSize, StreamMode eMode );
					SvSharedMemoryStream( ULONG nInitSize=4000, ULONG nResize=4000 );
					~SvSharedMemoryStream();

	const void* 	GetData();
	operator const	void*();
	virtual USHORT	IsA() const;

	void*			SwitchBuffer( ULONG nInitSize=4000, ULONG nResize=4000 );

	// setzt Stream auf einen nicht vergroesserbaren Speicherblock
	// MAC: Identisch mit SetHandle
	// WNT: der Block wird als mit MapViewOfFile erzeugt angenommen
	void*			SetBuffer( void* pBuf, ULONG nSize,
							   BOOL bOwnsMem = TRUE, ULONG nEOF = 0 );

	// setzt den Stream auf einen nicht vergroesserbaren Speicherblock,
	// der (plattformabhaengig) vom Stream in den Adressraum gemappt wird.
	// Achtung: Wenn die Applikation nachtraeglich den Besitz an dem
	// Speicher uebernimmt, muss sie das Mapping selbst loeschen!
	// (unter Windows NT: UnmapViewOfFile(pBuf))
	// OS/2,DOS,WIN16,UNIX: Nicht implementiert
	void*			SetHandle( void* aHandle, ULONG nSize,
							   BOOL bOwnsHandle = TRUE, ULONG nEOF = 0);

	void*			GetHandle() const { return aHandle; }
};

// --------------------
// - SvDataCopyStream -
// --------------------

// AB 10.5.1996: Diese Klasse bildet die Basis fuer Klassen, die mittels
// SvData (SO2\DTRANS.HXX/CXX) transportiert werden sollen, z.B. Graphik
// Die abgeleiteten Klassen muessen die virtuellen Funktionen ueberladen.

class SvDataCopyStream
{
public:
	/*-----------------MM 30.04.96 11:01-----------------
	 mehrfaches Aufrufen von Load und Assign erlaubt
	--------------------------------------------------*/
					TYPEINFO();
	virtual 		~SvDataCopyStream(){}
	virtual void	Load( SvStream & ) = 0;
	virtual void	Save( SvStream & ) = 0;
	virtual void	Assign( const SvDataCopyStream & );
};

#endif // _STREAM_HXX
