/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_io.hxx"


// streams
#include <hash_map>
#include <vector>

#include <com/sun/star/io/XObjectInputStream.hpp>
#include <com/sun/star/io/XObjectOutputStream.hpp>
#include <com/sun/star/io/XActiveDataSource.hpp>
#include <com/sun/star/io/XActiveDataSink.hpp>
#include <com/sun/star/io/XMarkableStream.hpp>
#include <com/sun/star/io/XConnectable.hpp>
#include <com/sun/star/io/UnexpectedEOFException.hpp>
#include <com/sun/star/io/WrongFormatException.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>

#include <cppuhelper/weak.hxx>      // OWeakObject
#include <cppuhelper/factory.hxx>
#include <cppuhelper/implbase4.hxx>
#include <cppuhelper/typeprovider.hxx>
#include <cppuhelper/queryinterface.hxx>

#include <osl/mutex.hxx>

#include <string.h>


using namespace ::cppu;
using namespace ::osl;
using namespace ::std;
using namespace ::rtl;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;

#include "factreg.hxx"

namespace io_stm {

class ODataInputStream :
	public WeakImplHelper4 <
                              XDataInputStream,
	                          XActiveDataSink,
                              XConnectable,
			                  XServiceInfo
                           >
{
public:
	ODataInputStream( )
		: m_bValidStream( sal_False )
		{
			g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
		}

	~ODataInputStream();
public: // XInputStream
    virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
    														throw (	NotConnectedException,
    																	BufferSizeExceededException,
    																	RuntimeException);
    virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
    														throw (	NotConnectedException,
    																	BufferSizeExceededException,
    																	RuntimeException);
    virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) 				throw (	NotConnectedException,
    																	BufferSizeExceededException,
    																	RuntimeException);
    virtual sal_Int32 SAL_CALL available(void) 							throw (	NotConnectedException,
    																	RuntimeException);
    virtual void SAL_CALL closeInput(void) 							throw (	NotConnectedException,
    																	RuntimeException);

public: // XDataInputStream
    virtual sal_Int8 SAL_CALL readBoolean(void) throw (IOException, RuntimeException);
    virtual sal_Int8 SAL_CALL readByte(void) throw (IOException, RuntimeException);
    virtual sal_Unicode SAL_CALL readChar(void) throw (IOException, RuntimeException);
    virtual sal_Int16 SAL_CALL readShort(void) throw (IOException, RuntimeException);
    virtual sal_Int32 SAL_CALL readLong(void) throw (IOException, RuntimeException);
    virtual sal_Int64 SAL_CALL readHyper(void) throw (IOException, RuntimeException);
    virtual float SAL_CALL readFloat(void) throw (IOException, RuntimeException);
    virtual double SAL_CALL readDouble(void) throw (IOException, RuntimeException);
    virtual OUString SAL_CALL readUTF(void) throw (IOException, RuntimeException);



public: // XActiveDataSink
    virtual void SAL_CALL setInputStream(const Reference< XInputStream > & aStream)
		throw (RuntimeException);
    virtual Reference< XInputStream > SAL_CALL getInputStream(void) throw (RuntimeException);

public: // XConnectable
    virtual void SAL_CALL setPredecessor(const Reference < XConnectable >& aPredecessor) throw (RuntimeException);
    virtual Reference < XConnectable > SAL_CALL getPredecessor(void) throw (RuntimeException);
    virtual void SAL_CALL setSuccessor(const Reference < XConnectable >& aSuccessor) throw (RuntimeException);
    virtual Reference < XConnectable > SAL_CALL getSuccessor(void) throw (RuntimeException) ;


public: // XServiceInfo
    OUString                     SAL_CALL getImplementationName() throw ();
    Sequence< OUString >         SAL_CALL getSupportedServiceNames(void) throw ();
	sal_Bool                        SAL_CALL supportsService(const OUString& ServiceName) throw ();

protected:

	Reference < XConnectable > 	m_pred;
	Reference < XConnectable > 	m_succ;
	Reference < XInputStream > 	m_input;
	sal_Bool m_bValidStream;
};

ODataInputStream::~ODataInputStream()
{
	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
}

// XInputStream
sal_Int32 ODataInputStream::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
	throw (	NotConnectedException,
			BufferSizeExceededException,
			RuntimeException)
{
 	sal_Int32 nRead;

 	if( m_bValidStream )
	{
 		nRead = m_input->readBytes( aData , nBytesToRead );
 	}
 	else
	{
 		throw NotConnectedException( );
 	}

 	return nRead;
}

sal_Int32 ODataInputStream::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
	throw (	NotConnectedException,
			BufferSizeExceededException,
			RuntimeException)
{
 	sal_Int32 nRead;
 	if( m_bValidStream ) {
 		nRead = m_input->readSomeBytes( aData , nMaxBytesToRead );
 	}
 	else {
 		throw NotConnectedException( );
 	}

 	return nRead;
}
void ODataInputStream::skipBytes(sal_Int32 nBytesToSkip)
	throw (	NotConnectedException,
			BufferSizeExceededException,
			RuntimeException)
{
 	if( m_bValidStream ) {
 		m_input->skipBytes( nBytesToSkip );
 	}
 	else
	{
 		throw NotConnectedException( );
 	}
}


sal_Int32 ODataInputStream::available(void)
	throw (	NotConnectedException,
			RuntimeException)
{
 	sal_Int32 nAvail;

 	if( m_bValidStream )
	{
 		nAvail = m_input->available( );
 	}
 	else
	{
 		throw NotConnectedException( );
 	}
 	return nAvail;
}

void ODataInputStream::closeInput(void )
	throw (	NotConnectedException,
			RuntimeException)
{
 	if( m_bValidStream ) {
 		m_input->closeInput( );
 		setInputStream( Reference< XInputStream > () );
 		setPredecessor( Reference < XConnectable >() );
 		setSuccessor( Reference < XConnectable >() );
 		m_bValidStream = sal_False;
 	}
 	else
	{
 		throw NotConnectedException( );
 	}
}




//== XDataInputStream ===========================================

// XDataInputStream
sal_Int8 ODataInputStream::readBoolean(void) throw (IOException, RuntimeException)
{
	return readByte();
}

sal_Int8 ODataInputStream::readByte(void)	 throw (IOException, RuntimeException)
{
	Sequence<sal_Int8> aTmp(1);
	if( 1 != readBytes( aTmp, 1 ) )
	{
		throw UnexpectedEOFException();
	}
	return aTmp.getArray()[0];
}

sal_Unicode ODataInputStream::readChar(void) throw (IOException, RuntimeException)
{
	Sequence<sal_Int8> aTmp(2);
	if( 2 != readBytes( aTmp, 2 ) )
	{
		throw UnexpectedEOFException();
	}

	const sal_uInt8 * pBytes = ( const sal_uInt8 * )aTmp.getConstArray();
	return ((sal_Unicode)pBytes[0] << 8) + pBytes[1];
}

sal_Int16 ODataInputStream::readShort(void) throw (IOException, RuntimeException)
{
	Sequence<sal_Int8> aTmp(2);
	if( 2 != readBytes( aTmp, 2 ) )
	{
		throw UnexpectedEOFException();
	}

	const sal_uInt8 * pBytes = ( const sal_uInt8 * ) aTmp.getConstArray();
	return ((sal_Int16)pBytes[0] << 8) + pBytes[1];
}


sal_Int32 ODataInputStream::readLong(void) throw (IOException, RuntimeException)
{
	Sequence<sal_Int8> aTmp(4);
	if( 4 != readBytes( aTmp, 4 ) )
	{
		throw UnexpectedEOFException( );
	}

	const sal_uInt8 * pBytes = ( const sal_uInt8 * ) aTmp.getConstArray();
	return ((sal_Int32)pBytes[0] << 24) + ((sal_Int32)pBytes[1] << 16) + ((sal_Int32)pBytes[2] << 8) + pBytes[3];
}


sal_Int64 ODataInputStream::readHyper(void) throw (IOException, RuntimeException)
{
	Sequence<sal_Int8> aTmp(8);
	if( 8 != readBytes( aTmp, 8 ) )
	{
		throw UnexpectedEOFException( );
	}

	const sal_uInt8 * pBytes = ( const sal_uInt8 * ) aTmp.getConstArray();
	return
		(((sal_Int64)pBytes[0]) << 56) +
		(((sal_Int64)pBytes[1]) << 48) +
		(((sal_Int64)pBytes[2]) << 40) +
		(((sal_Int64)pBytes[3]) << 32) +
		(((sal_Int64)pBytes[4]) << 24) +
		(((sal_Int64)pBytes[5]) << 16) +
		(((sal_Int64)pBytes[6]) << 8) +
		pBytes[7];
}

float ODataInputStream::readFloat(void) throw (IOException, RuntimeException)
{
	union { float f; sal_uInt32 n; } a;
	a.n = readLong();
	return a.f;
}

double ODataInputStream::readDouble(void) throw (IOException, RuntimeException)
{
	sal_uInt32 n = 1;
	union { double d; struct { sal_uInt32 n1; sal_uInt32 n2; } ad; } a;
	if( *(sal_uInt8 *)&n == 1 )
	{
		// little endian
		a.ad.n2 = readLong();
		a.ad.n1 = readLong();
	}
	else
	{
		// big endian
		a.ad.n1 = readLong();
		a.ad.n2 = readLong();
	}
	return a.d;
}

OUString ODataInputStream::readUTF(void) throw (IOException, RuntimeException)
{
	sal_uInt16				nShortLen = (sal_uInt16)readShort();
	sal_Int32				nUTFLen;

	if( ((sal_uInt16)0xffff) == nShortLen )
	{
		// is interpreted as a sign, that string is longer than 64k
		// incompatible to older XDataInputStream-routines, when strings are exactly 64k
		nUTFLen = readLong();
	}
	else
	{
		nUTFLen = ( sal_Int32 ) nShortLen;
	}

	Sequence<sal_Unicode>	aBuffer( nUTFLen );
	sal_Unicode *			pStr = aBuffer.getArray();

	sal_Int32 nCount = 0;
	sal_Int32 nStrLen = 0;
	while( nCount < nUTFLen )
	{
	    sal_uInt8 c = (sal_uInt8)readByte();
	    sal_uInt8 char2, char3;
	    switch( c >> 4 )
		{
	        case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
				// 0xxxxxxx
				nCount++;
				pStr[nStrLen++] = c;
				break;

	        case 12: case 13:
				// 110x xxxx   10xx xxxx
				nCount += 2;
				if( ! ( nCount <= nUTFLen ) )
				{
					throw WrongFormatException( );
				}

				char2 = (sal_uInt8)readByte();
				if( ! ( (char2 & 0xC0) == 0x80 ) )
				{
					throw WrongFormatException( );
				}

				pStr[nStrLen++] = (sal_Unicode(c & 0x1F) << 6) | (char2 & 0x3F);
				break;

	        case 14:
		    // 1110 xxxx  10xx xxxx  10xx xxxx
				nCount += 3;
				if( !( nCount <= nUTFLen) )
				{
					throw WrongFormatException( );
				}

				char2 = (sal_uInt8)readByte();
				char3 = (sal_uInt8)readByte();

				if( (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) ) {
					throw WrongFormatException( );
				}
				pStr[nStrLen++] = (sal_Unicode(c & 0x0F) << 12) |
								(sal_Unicode(char2 & 0x3F) << 6) |
								(char3 & 0x3F);
				break;

	        default:
				// 10xx xxxx,  1111 xxxx
				throw WrongFormatException();
				//throw new UTFDataFormatException();
		}
	}
	return OUString( pStr, nStrLen );
}



// XActiveDataSource
void ODataInputStream::setInputStream(const Reference< XInputStream > & aStream)
	throw (RuntimeException)
{

	if( m_input != aStream ) {
		m_input = aStream;

		Reference < XConnectable > pred( m_input , UNO_QUERY );
		setPredecessor( pred );
	}

	m_bValidStream = m_input.is();
}

Reference< XInputStream > ODataInputStream::getInputStream(void) throw (RuntimeException)
{
	return m_input;
}



// XDataSink
void ODataInputStream::setSuccessor( const Reference < XConnectable > &r ) throw (RuntimeException)
{
     /// if the references match, nothing needs to be done
     if( m_succ != r ) {
         /// store the reference for later use
         m_succ = r;

         if( m_succ.is() ) {
              /// set this instance as the sink !
              m_succ->setPredecessor( Reference< XConnectable > (
				  SAL_STATIC_CAST( XConnectable * , this ) ) );
         }
     }
}

Reference < XConnectable > ODataInputStream::getSuccessor() throw (RuntimeException)
{
	return m_succ;
}


// XDataSource
void ODataInputStream::setPredecessor( const Reference < XConnectable > &r )
	throw (RuntimeException)
{
	if( r != m_pred ) {
		m_pred = r;
		if( m_pred.is() ) {
			m_pred->setSuccessor( Reference< XConnectable > (
				SAL_STATIC_CAST( XConnectable * , this ) ) );
		}
	}
}
Reference < XConnectable > ODataInputStream::getPredecessor() throw (RuntimeException)
{
	return m_pred;
}

// XServiceInfo
OUString ODataInputStream::getImplementationName() throw ()
{
    return ODataInputStream_getImplementationName();
}

// XServiceInfo
sal_Bool ODataInputStream::supportsService(const OUString& ServiceName) throw ()
{
    Sequence< OUString > aSNL = getSupportedServiceNames();
    const OUString * pArray = aSNL.getConstArray();

    for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
        if( pArray[i] == ServiceName )
            return sal_True;

    return sal_False;
}

// XServiceInfo
Sequence< OUString > ODataInputStream::getSupportedServiceNames(void) throw ()
{
    return ODataInputStream_getSupportedServiceNames();
}

/***
*
* registration information
*
*
****/

Reference< XInterface > SAL_CALL ODataInputStream_CreateInstance( const Reference < XComponentContext > & ) throw( Exception)
{
	ODataInputStream *p = new ODataInputStream;
	return Reference< XInterface > ( (OWeakObject * ) p );
}

OUString ODataInputStream_getImplementationName()
{
	return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.io.stm.DataInputStream" ) );
}

Sequence<OUString> ODataInputStream_getSupportedServiceNames(void)
{
	Sequence<OUString> aRet(1);
	aRet.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.DataInputStream" ) );
	return aRet;
}




class ODataOutputStream :
	public WeakImplHelper4 <
			 XDataOutputStream,
			 XActiveDataSource,
			 XConnectable,
 	         XServiceInfo >
{
public:
	ODataOutputStream()
		: m_bValidStream( sal_False )
		{
			g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
		}
	~ODataOutputStream();

public: // XOutputStream
    virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData)
		throw (	NotConnectedException,
				BufferSizeExceededException,
				RuntimeException);
    virtual void SAL_CALL flush(void)
		throw (	NotConnectedException,
				BufferSizeExceededException,
				RuntimeException);
    virtual void SAL_CALL closeOutput(void)
		throw (	NotConnectedException,
				BufferSizeExceededException,
				RuntimeException);

public: // XDataOutputStream
    virtual void SAL_CALL writeBoolean(sal_Bool Value) throw (IOException, RuntimeException);
    virtual void SAL_CALL writeByte(sal_Int8 Value) throw (IOException, RuntimeException);
    virtual void SAL_CALL writeChar(sal_Unicode Value) throw (IOException, RuntimeException);
    virtual void SAL_CALL writeShort(sal_Int16 Value) throw (IOException, RuntimeException);
    virtual void SAL_CALL writeLong(sal_Int32 Value) throw (IOException, RuntimeException);
    virtual void SAL_CALL writeHyper(sal_Int64 Value) throw (IOException, RuntimeException);
    virtual void SAL_CALL writeFloat(float Value) throw (IOException, RuntimeException);
    virtual void SAL_CALL writeDouble(double Value) throw (IOException, RuntimeException);
    virtual void SAL_CALL writeUTF(const OUString& Value) throw (IOException, RuntimeException);

public: // XActiveDataSource
    virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream)
		throw (RuntimeException);
	virtual Reference < XOutputStream > SAL_CALL getOutputStream(void) throw (RuntimeException);

public: // XConnectable
    virtual void SAL_CALL setPredecessor(const Reference < XConnectable >& aPredecessor)
		throw (RuntimeException);
	virtual Reference < XConnectable > SAL_CALL getPredecessor(void)
		throw (RuntimeException);
	virtual void SAL_CALL setSuccessor(const Reference < XConnectable >& aSuccessor)
		throw (RuntimeException);
    virtual Reference < XConnectable > SAL_CALL getSuccessor(void)
		throw (RuntimeException);

public: // XServiceInfo
    OUString                     SAL_CALL getImplementationName() throw ();
    Sequence< OUString >         SAL_CALL getSupportedServiceNames(void) throw ();
    sal_Bool                     SAL_CALL supportsService(const OUString& ServiceName) throw ();

protected:
	Reference < XConnectable > 	m_succ;
	Reference < XConnectable >	m_pred;
	Reference<  XOutputStream > m_output;
	sal_Bool m_bValidStream;
};

ODataOutputStream::~ODataOutputStream()
{
	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
}


// XOutputStream
void ODataOutputStream::writeBytes(const Sequence< sal_Int8 >& aData)
	throw (	NotConnectedException,
			BufferSizeExceededException,
			RuntimeException)
{
	if( m_bValidStream )
	{
		m_output->writeBytes( aData );
	}
	else {
		throw NotConnectedException( );
	}
}

void ODataOutputStream::flush(void)
	throw (	NotConnectedException,
			BufferSizeExceededException,
			RuntimeException)
{
	if( m_bValidStream )
	{
		m_output->flush();
	}
	else
	{
		throw NotConnectedException();
	}

}


void ODataOutputStream::closeOutput(void)
	throw (	NotConnectedException,
			BufferSizeExceededException,
			RuntimeException)
{
	if( m_bValidStream )
	{
		m_output->closeOutput();
		setOutputStream( Reference< XOutputStream > () );
		setPredecessor( Reference < XConnectable >() );
		setSuccessor( Reference < XConnectable >() );
	}
	else
	{
		throw NotConnectedException();
	}
}

// XDataOutputStream
void ODataOutputStream::writeBoolean(sal_Bool Value)
	throw (	IOException,
			RuntimeException)
{
	if( Value )
	{
		writeByte( 1 );
	}
	else
	{
		writeByte( 0 );
	}
}


void ODataOutputStream::writeByte(sal_Int8 Value)
	throw (	IOException,
			RuntimeException)
{
	Sequence<sal_Int8> aTmp( 1 );
	aTmp.getArray()[0] = Value;
	writeBytes( aTmp );
}

void ODataOutputStream::writeChar(sal_Unicode Value)
	throw (	IOException,
			RuntimeException)
{
	Sequence<sal_Int8> aTmp( 2 );
	sal_Int8 * pBytes = ( sal_Int8 * ) aTmp.getArray();
	pBytes[0] = sal_Int8(Value >> 8);
	pBytes[1] = sal_Int8(Value);
	writeBytes( aTmp );
}


void ODataOutputStream::writeShort(sal_Int16 Value)
	throw (	IOException,
			RuntimeException)
{
	Sequence<sal_Int8> aTmp( 2 );
	sal_Int8 * pBytes = aTmp.getArray();
	pBytes[0] = sal_Int8(Value >> 8);
	pBytes[1] = sal_Int8(Value);
	writeBytes( aTmp );
}

void ODataOutputStream::writeLong(sal_Int32 Value)
	throw (	IOException,
			RuntimeException)
{
	Sequence<sal_Int8> aTmp( 4 );
	sal_Int8 * pBytes = aTmp.getArray();
	pBytes[0] = sal_Int8(Value >> 24);
	pBytes[1] = sal_Int8(Value >> 16);
	pBytes[2] = sal_Int8(Value >> 8);
	pBytes[3] = sal_Int8(Value);
	writeBytes( aTmp );
}

void ODataOutputStream::writeHyper(sal_Int64 Value)
	throw (	IOException,
			RuntimeException)
{
	Sequence<sal_Int8> aTmp( 8 );
	sal_Int8 * pBytes = aTmp.getArray();
	pBytes[0] = sal_Int8(Value >> 56);
	pBytes[1] = sal_Int8(Value >> 48);
	pBytes[2] = sal_Int8(Value >> 40);
	pBytes[3] = sal_Int8(Value >> 32);
	pBytes[4] = sal_Int8(Value >> 24);
	pBytes[5] = sal_Int8(Value >> 16);
	pBytes[6] = sal_Int8(Value >> 8);
	pBytes[7] = sal_Int8(Value);
	writeBytes( aTmp );
}


void ODataOutputStream::writeFloat(float Value)
	throw (	IOException,
			RuntimeException)
{
	union { float f; sal_uInt32 n; } a;
	a.f = Value;
	writeLong( a.n );
}

void ODataOutputStream::writeDouble(double Value)
	throw (	IOException,
			RuntimeException)
{
	sal_uInt32 n = 1;
	union { double d; struct { sal_uInt32 n1; sal_uInt32 n2; } ad; } a;
	a.d = Value;
	if( *(sal_Int8 *)&n == 1 )
	{
		// little endian
		writeLong( a.ad.n2 );
		writeLong( a.ad.n1 );
	}
	else
	{
		// big endian
		writeLong( a.ad.n1 );
		writeLong( a.ad.n2 );
	}
}

void ODataOutputStream::writeUTF(const OUString& Value)
	throw (	IOException,
			RuntimeException)
{
	sal_Int32 nStrLen = Value.getLength();
	const sal_Unicode * pStr = Value.getStr();
	sal_Int32 nUTFLen = 0;
	sal_Int32 i;

	for( i = 0 ; i < nStrLen ; i++ )
	{
	    sal_uInt16 c = pStr[i];
	    if( (c >= 0x0001) && (c <= 0x007F) )
		{
			nUTFLen++;
	    }
		else if( c > 0x07FF )
		{
			nUTFLen += 3;
	    }
		else
		{
			nUTFLen += 2;
	    }
	}


	// compatibility mode for older implementations, where it was not possible
	// to write blocks bigger than 64 k. Note that there is a tradeoff. Blocks,
	// that are exactly 64k long can not be read by older routines when written
	// with these routines and the other way round !!!!!
	if( nUTFLen >= 0xFFFF ) {
		writeShort( (sal_Int16)-1 );
		writeLong( nUTFLen );
	}
	else {
		writeShort( ((sal_uInt16)nUTFLen) );
	}
	for( i = 0 ; i < nStrLen ; i++ )
	{
	    sal_uInt16 c = pStr[i];
	    if( (c >= 0x0001) && (c <= 0x007F) )
		{
			writeByte(sal_Int8(c));
	    }
		else if( c > 0x07FF )
		{
			writeByte(sal_Int8(0xE0 | ((c >> 12) & 0x0F)));
			writeByte(sal_Int8(0x80 | ((c >>  6) & 0x3F)));
			writeByte(sal_Int8(0x80 | ((c >>  0) & 0x3F)));
			//written += 2;
	    }
		else
		{
			writeByte(sal_Int8(0xC0 | ((c >>  6) & 0x1F)));
			writeByte(sal_Int8(0x80 | ((c >>  0) & 0x3F)));
			//written += 1;
	    }
	}
	//written += strlen + 2;
}

// XActiveDataSource
void ODataOutputStream::setOutputStream(const Reference< XOutputStream > & aStream)
	throw (RuntimeException)
{
	if( m_output != aStream ) {
		m_output = aStream;
		m_bValidStream = m_output.is();

		Reference < XConnectable > succ( m_output , UNO_QUERY );
		setSuccessor( succ );
	}
}

Reference< XOutputStream > ODataOutputStream::getOutputStream(void)
	throw (RuntimeException)
{
	return m_output;
}




// XDataSink
void ODataOutputStream::setSuccessor( const Reference < XConnectable > &r )
	throw (RuntimeException)
{
     /// if the references match, nothing needs to be done
     if( m_succ != r )
	 {
         /// store the reference for later use
         m_succ = r;

         if( m_succ.is() )
		 {
              /// set this instance as the sink !
              m_succ->setPredecessor( Reference < XConnectable > (
				  SAL_STATIC_CAST( XConnectable * , this  ) ));
         }
     }
}
Reference < XConnectable > ODataOutputStream::getSuccessor()	throw (RuntimeException)
{
	return m_succ;
}


// XDataSource
void ODataOutputStream::setPredecessor( const Reference < XConnectable > &r )	throw (RuntimeException)
{
	if( r != m_pred ) {
		m_pred = r;
		if( m_pred.is() ) {
			m_pred->setSuccessor( Reference< XConnectable > (
				SAL_STATIC_CAST( XConnectable * , this  ) ));
		}
	}
}
Reference < XConnectable > ODataOutputStream::getPredecessor()	throw (RuntimeException)
{
	return m_pred;
}



// XServiceInfo
OUString ODataOutputStream::getImplementationName() throw ()
{
    return ODataOutputStream_getImplementationName();
}

// XServiceInfo
sal_Bool ODataOutputStream::supportsService(const OUString& ServiceName) throw ()
{
    Sequence< OUString > aSNL = getSupportedServiceNames();
    const OUString * pArray = aSNL.getConstArray();

    for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
        if( pArray[i] == ServiceName )
            return sal_True;

    return sal_False;
}

// XServiceInfo
Sequence< OUString > ODataOutputStream::getSupportedServiceNames(void) throw ()
{
    return ODataOutputStream_getSupportedServiceNames();
}




Reference< XInterface > SAL_CALL ODataOutputStream_CreateInstance( const Reference < XComponentContext > & ) throw(Exception)
{
	ODataOutputStream *p = new ODataOutputStream;
	Reference< XInterface > xService = *p;
	return xService;
}


OUString ODataOutputStream_getImplementationName()
{
	return OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.io.stm.DataOutputStream" ) );
}

Sequence<OUString> ODataOutputStream_getSupportedServiceNames(void)
{
	Sequence<OUString> aRet(1);
	aRet.getArray()[0] =  OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.DataOutputStream" ) );
	return aRet;
}

//--------------------------------------
struct equalObjectContainer_Impl
{
	sal_Int32 operator()(const Reference< XInterface > & s1,
						 const Reference< XInterface > & s2) const
  	{
    	return s1 == s2;
	}
};

//-----------------------------------------------------------------------------
struct hashObjectContainer_Impl
{
	size_t operator()(const Reference< XInterface > & xRef) const
	{
		return (size_t)xRef.get();
	}
};

typedef hash_map
<
	Reference< XInterface >,
	sal_Int32,
	hashObjectContainer_Impl,
	equalObjectContainer_Impl
> ObjectContainer_Impl;

/*---------------------------------------------
*
*
*
*
*--------------------------------------------*/
class OObjectOutputStream :
			public ODataOutputStream,
			public XObjectOutputStream,
			public XMarkableStream
{
public:
	OObjectOutputStream()
		: m_nMaxId(0) ,
		  m_bValidMarkable(sal_False)
		{
			g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
		}

	~OObjectOutputStream();

public:
        Any             SAL_CALL queryInterface( const Type &type ) throw (::com::sun::star::uno::RuntimeException);
        void    SAL_CALL acquire() throw()                                       { ODataOutputStream::acquire(); }
        void    SAL_CALL release() throw()                                       { ODataOutputStream::release(); }

public:
	// XOutputStream
    virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData)
		throw (	NotConnectedException,
				BufferSizeExceededException,
				RuntimeException)
		{ ODataOutputStream::writeBytes( aData ); }

    virtual void SAL_CALL flush(void)
		throw (	NotConnectedException,
				BufferSizeExceededException,
				RuntimeException)
		{ ODataOutputStream::flush(); }

    virtual void SAL_CALL closeOutput(void)
		throw (	NotConnectedException,
				BufferSizeExceededException,
				RuntimeException)
		{ ODataOutputStream::closeOutput(); }

public:
	// XDataOutputStream
    virtual void SAL_CALL writeBoolean(sal_Bool Value) throw (IOException, RuntimeException)
    			{ ODataOutputStream::writeBoolean( Value ); }
    virtual void SAL_CALL writeByte(sal_Int8 Value) throw (IOException, RuntimeException)
    			{ ODataOutputStream::writeByte( Value ); }
    virtual void SAL_CALL writeChar(sal_Unicode Value) throw (IOException, RuntimeException)
    			{ ODataOutputStream::writeChar( Value ); }
    virtual void SAL_CALL writeShort(sal_Int16 Value) throw (IOException, RuntimeException)
    			{ ODataOutputStream::writeShort( Value ); }
    virtual void SAL_CALL writeLong(sal_Int32 Value) throw (IOException, RuntimeException)
    			{ ODataOutputStream::writeLong( Value ); }
    virtual void SAL_CALL writeHyper(sal_Int64 Value) throw (IOException, RuntimeException)
    			{ ODataOutputStream::writeHyper( Value ); }
    virtual void SAL_CALL writeFloat(float Value) throw (IOException, RuntimeException)
    			{ ODataOutputStream::writeFloat( Value ); }
    virtual void SAL_CALL writeDouble(double Value) throw (IOException, RuntimeException)
    			{ ODataOutputStream::writeDouble( Value ); }
    virtual void SAL_CALL writeUTF(const OUString& Value) throw (IOException, RuntimeException)
    			{ ODataOutputStream::writeUTF( Value );}

	// XObjectOutputStream
        virtual void SAL_CALL writeObject( const Reference< XPersistObject > & r ) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);

public: // XMarkableStream
    virtual sal_Int32 SAL_CALL createMark(void) 				throw (IOException, RuntimeException);
    virtual void SAL_CALL deleteMark(sal_Int32 Mark)			throw (IOException, IllegalArgumentException, RuntimeException);
    virtual void SAL_CALL jumpToMark(sal_Int32 nMark) 		throw (IOException, IllegalArgumentException, RuntimeException);
    virtual void SAL_CALL jumpToFurthest(void) 			throw (IOException, RuntimeException);
    virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark)
		throw (IOException, IllegalArgumentException, RuntimeException);

public: //XTypeProvider
	virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL
	        getTypes(  ) throw(::com::sun::star::uno::RuntimeException);
	virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL
            getImplementationId(  ) throw(::com::sun::star::uno::RuntimeException);

public: // XServiceInfo
    OUString                   SAL_CALL   getImplementationName() throw ();
    Sequence< OUString >       SAL_CALL   getSupportedServiceNames(void) throw ();
    sal_Bool                   SAL_CALL   supportsService(const OUString& ServiceName) throw ();

private:
	void connectToMarkable();
private:
	ObjectContainer_Impl	            m_mapObject;
	sal_Int32							m_nMaxId;
	Reference< XMarkableStream > 		m_rMarkable;
	sal_Bool 							m_bValidMarkable;
};

OObjectOutputStream::~OObjectOutputStream()
{
	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
}

Any OObjectOutputStream::queryInterface( const Type &aType ) throw (::com::sun::star::uno::RuntimeException)
{
	Any a = ::cppu::queryInterface(
		aType ,
		SAL_STATIC_CAST( XMarkableStream * , this ),
		SAL_STATIC_CAST( XObjectOutputStream * , this ) );
	if( a.hasValue() )
	{
		return a;
	}

	return ODataOutputStream::queryInterface( aType );

}
void OObjectOutputStream::writeObject( const Reference< XPersistObject > & xPObj ) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
{

	connectToMarkable();
	sal_Bool bWriteObj = sal_False;
	// create Mark to write length of info
	sal_uInt32 nInfoLenMark = m_rMarkable->createMark();

	// length of the info data (is later rewritten)
	OObjectOutputStream::writeShort( 0 );

	// write the object identifier
	if( xPObj.is() )
	{
		Reference< XInterface > rX( xPObj , UNO_QUERY );

		ObjectContainer_Impl::const_iterator aIt
			= m_mapObject.find( rX );
		if( aIt == m_mapObject.end() )
		{
			// insert new object in hash table
			m_mapObject[ rX ] = ++m_nMaxId;
			ODataOutputStream::writeLong( m_nMaxId );
			ODataOutputStream::writeUTF( xPObj->getServiceName() );
			bWriteObj = sal_True;
		}
		else
		{
			ODataOutputStream::writeLong( (*aIt).second );
			OUString aName;
			ODataOutputStream::writeUTF( aName );
		}
	}
	else
	{
		ODataOutputStream::writeLong( 0 );
		OUString aName;
		ODataOutputStream::writeUTF( aName );
	}

	sal_uInt32 nObjLenMark = m_rMarkable->createMark();
	ODataOutputStream::writeLong( 0 );

	sal_Int32 nInfoLen = m_rMarkable->offsetToMark( nInfoLenMark );
	m_rMarkable->jumpToMark( nInfoLenMark );
	// write length of the info data
	ODataOutputStream::writeShort( (sal_Int16)nInfoLen );
	// jump to the end of the stream
	m_rMarkable->jumpToFurthest();

	if( bWriteObj )
		xPObj->write( Reference< XObjectOutputStream > (
			SAL_STATIC_CAST( XObjectOutputStream * , this ) ) );

	sal_Int32 nObjLen = m_rMarkable->offsetToMark( nObjLenMark ) -4;
	m_rMarkable->jumpToMark( nObjLenMark );
	// write length of the info data
	ODataOutputStream::writeLong( nObjLen );
	// jump to the end of the stream
	m_rMarkable->jumpToFurthest();

	m_rMarkable->deleteMark( nObjLenMark );
	m_rMarkable->deleteMark( nInfoLenMark );
}



void OObjectOutputStream::connectToMarkable(void)
{
	if( ! m_bValidMarkable ) {
		if( ! m_bValidStream )
		{
			throw NotConnectedException();
		}

		// find the markable stream !
		Reference< XInterface > rTry(m_output);
		while( sal_True ) {
			if( ! rTry.is() )
			{
				throw NotConnectedException();
			}
			Reference < XMarkableStream > markable( rTry , UNO_QUERY );
			if( markable.is() )
			{
				m_rMarkable = markable;
				break;
			}
			Reference < XActiveDataSource > source( rTry , UNO_QUERY );
			rTry = source;
		}
		m_bValidMarkable = sal_True;
	}
}


sal_Int32 OObjectOutputStream::createMark(void)
	throw (IOException, RuntimeException)
{
	connectToMarkable();	// throws an exception, if a markable is not connected !

	return m_rMarkable->createMark();
}

void OObjectOutputStream::deleteMark(sal_Int32 Mark)
	throw (IOException, IllegalArgumentException, RuntimeException)
{
	if( ! m_bValidMarkable )
	{
		throw NotConnectedException();
	}
	m_rMarkable->deleteMark( Mark );
}

void OObjectOutputStream::jumpToMark(sal_Int32 nMark)
	throw (IOException, IllegalArgumentException, RuntimeException)
{
	if( ! m_bValidMarkable )
	{
		throw NotConnectedException();
	}
	m_rMarkable->jumpToMark( nMark );
}


void OObjectOutputStream::jumpToFurthest(void)
	throw (IOException, RuntimeException)
{
	connectToMarkable();
	m_rMarkable->jumpToFurthest();
}

sal_Int32 OObjectOutputStream::offsetToMark(sal_Int32 nMark)
	throw (IOException, IllegalArgumentException, RuntimeException)
{
	if( ! m_bValidMarkable )
	{
		throw NotConnectedException();
	}
	return m_rMarkable->offsetToMark( nMark );
}




Reference< XInterface > SAL_CALL OObjectOutputStream_CreateInstance( const Reference < XComponentContext > & )
	throw(Exception)
{
	OObjectOutputStream *p = new OObjectOutputStream;
	return  Reference< XInterface > ( SAL_STATIC_CAST( OWeakObject * , p ) );
}

OUString OObjectOutputStream_getImplementationName()
{
	return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.io.stm.ObjectOutputStream" ) );
}

Sequence<OUString> OObjectOutputStream_getSupportedServiceNames(void)
{
	Sequence<OUString> aRet(1);
	aRet.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.ObjectOutputStream" ) );
	return aRet;
}

Sequence< Type > SAL_CALL OObjectOutputStream::getTypes(void) throw( RuntimeException )
{
	static OTypeCollection *pCollection = 0;
	if( ! pCollection )
	{
		MutexGuard guard( Mutex::getGlobalMutex() );
		if( ! pCollection )
		{
			static OTypeCollection collection(
				getCppuType( (Reference< XMarkableStream > * ) 0 ),
				getCppuType( (Reference< XObjectOutputStream > * ) 0 ),
				ODataOutputStream::getTypes() );
			pCollection = &collection;
		}
	}
	return (*pCollection).getTypes();
}

Sequence< sal_Int8 > SAL_CALL OObjectOutputStream::getImplementationId(  ) throw( RuntimeException)
{
	static OImplementationId *pId = 0;
	if( ! pId )
	{
		MutexGuard guard( Mutex::getGlobalMutex() );
		if( ! pId )
		{
			static OImplementationId id( sal_False );
			pId = &id;
		}
	}
	return (*pId).getImplementationId();
}


// XServiceInfo
OUString OObjectOutputStream::getImplementationName() throw ()
{
    return ODataInputStream_getImplementationName();
}

// XServiceInfo
sal_Bool OObjectOutputStream::supportsService(const OUString& ServiceName) throw ()
{
    Sequence< OUString > aSNL = getSupportedServiceNames();
    const OUString * pArray = aSNL.getConstArray();

    for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
        if( pArray[i] == ServiceName )
            return sal_True;

    return sal_False;
}

// XServiceInfo
Sequence< OUString > OObjectOutputStream::getSupportedServiceNames(void) throw ()
{
	return OObjectOutputStream_getSupportedServiceNames();
}





class OObjectInputStream :
	public ODataInputStream,
	public XObjectInputStream,
	public XMarkableStream
{
public:
	OObjectInputStream( const Reference < XComponentContext > &r)
		: m_rSMgr( r->getServiceManager() )
		, m_rCxt( r )
		, m_bValidMarkable(sal_False)
		{
			g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
		}
	~OObjectInputStream();

public:
        Any             SAL_CALL queryInterface( const Type &type ) throw();
        void    SAL_CALL acquire() throw()                                       { ODataInputStream::acquire(); }
        void    SAL_CALL release() throw()                                       { ODataInputStream::release(); }

public: // XInputStream
    virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
		throw (	NotConnectedException,
				BufferSizeExceededException,
				RuntimeException)
		{ return ODataInputStream::readBytes( aData , nBytesToRead ); }

    virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
		throw (	NotConnectedException,
				BufferSizeExceededException,
				RuntimeException)
		{ return ODataInputStream::readSomeBytes( aData, nMaxBytesToRead ); }

    virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip)
		throw (	NotConnectedException,
				BufferSizeExceededException,
				RuntimeException)
		{ ODataInputStream::skipBytes( nBytesToSkip ); }

    virtual sal_Int32 SAL_CALL available(void)
		throw (	NotConnectedException,
				RuntimeException)
		{ return ODataInputStream::available(); }

    virtual void SAL_CALL closeInput(void)
		throw (	NotConnectedException,
				RuntimeException)
		{ ODataInputStream::closeInput(); }

public: // XDataInputStream
    virtual sal_Int8 SAL_CALL readBoolean(void) throw (IOException, RuntimeException)
    			{ return ODataInputStream::readBoolean(); }
    virtual sal_Int8 SAL_CALL readByte(void) throw (IOException, RuntimeException)
    			{ return ODataInputStream::readByte(); }
    virtual sal_Unicode SAL_CALL readChar(void) throw (IOException, RuntimeException)
    			{ return ODataInputStream::readChar(); }
    virtual sal_Int16 SAL_CALL readShort(void) throw (IOException, RuntimeException)
    			{ return ODataInputStream::readShort(); }
    virtual sal_Int32 SAL_CALL readLong(void) throw (IOException, RuntimeException)
    			{ return ODataInputStream::readLong(); }
    virtual sal_Int64 SAL_CALL readHyper(void) throw (IOException, RuntimeException)
    			{ return ODataInputStream::readHyper(); }
    virtual float SAL_CALL readFloat(void) throw (IOException, RuntimeException)
    			{ return ODataInputStream::readFloat(); }
    virtual double SAL_CALL readDouble(void) throw (IOException, RuntimeException)
		{ return ODataInputStream::readDouble(); }
    virtual OUString SAL_CALL readUTF(void) throw (IOException, RuntimeException)
    			{ return ODataInputStream::readUTF(); }

public: // XObjectInputStream
        virtual Reference< XPersistObject > SAL_CALL readObject( ) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);

public: // XMarkableStream
    virtual sal_Int32 SAL_CALL createMark(void)
		throw (IOException, RuntimeException);
	virtual void SAL_CALL deleteMark(sal_Int32 Mark)			throw (IOException, IllegalArgumentException, RuntimeException);
	virtual void SAL_CALL jumpToMark(sal_Int32 nMark) 		throw (IOException, IllegalArgumentException, RuntimeException);
	virtual void SAL_CALL jumpToFurthest(void) 			throw (IOException, RuntimeException);
	virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark)
		throw (IOException, IllegalArgumentException, RuntimeException);

public: //XTypeProvider
	virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL
	        getTypes(  ) throw(::com::sun::star::uno::RuntimeException);
	virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL
            getImplementationId(  ) throw(::com::sun::star::uno::RuntimeException);

public: // XServiceInfo
    OUString                     SAL_CALL getImplementationName() throw ();
	Sequence< OUString >         SAL_CALL getSupportedServiceNames(void) throw ();
    sal_Bool                     SAL_CALL supportsService(const OUString& ServiceName) throw ();

private:
	void connectToMarkable();
private:
	Reference < XMultiComponentFactory > m_rSMgr;
	Reference < XComponentContext >     m_rCxt;
	sal_Bool 				m_bValidMarkable;
	Reference < XMarkableStream > m_rMarkable;
	vector < Reference<  XPersistObject > > m_aPersistVector;

};

OObjectInputStream::~OObjectInputStream()
{
	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
}

Any OObjectInputStream::queryInterface( const Type &aType ) throw ()
{
	Any a = ::cppu::queryInterface(
		aType ,
		SAL_STATIC_CAST( XMarkableStream * , this ),
		SAL_STATIC_CAST( XObjectInputStream * , this ) );
	if( a.hasValue() )
	{
		return a;
	}

	return ODataInputStream::queryInterface( aType );

}

Reference< XPersistObject >  OObjectInputStream::readObject() throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
{
	// check if chain contains a XMarkableStream
	connectToMarkable();

	Reference< XPersistObject > xLoadedObj;

	// create Mark to skip newer versions
	sal_uInt32 nMark = m_rMarkable->createMark();
	// length of the data
	sal_Int32 nLen = (sal_uInt16) ODataInputStream::readShort();
	if( nLen < 0xc )
	{
		throw WrongFormatException();
	}

	// read the object identifier
	sal_uInt32 nId = readLong();

	// the name of the persist model
	// MM ???
	OUString aName = readUTF();

	// Read the length of the object
	sal_Int32 nObjLen = readLong();
	if( ( 0 == nId && 0 != nObjLen ) )
	{
		throw WrongFormatException();
	}

	// skip data of new version
	skipBytes( nLen - m_rMarkable->offsetToMark( nMark ) );

	sal_Bool bLoadSuccesfull = sal_True;
	if( nId )
	{
		if( aName.getLength() )
		{
			// load the object
			Reference< XInterface > x = m_rSMgr->createInstanceWithContext( aName, m_rCxt );
			xLoadedObj = Reference< XPersistObject >( x, UNO_QUERY );
			if( xLoadedObj.is() )
			{
				sal_uInt32 nSize = m_aPersistVector.size();
				if( nSize <= nId )
				{
					// grow to the right size
					Reference< XPersistObject > xEmpty;
					m_aPersistVector.insert( m_aPersistVector.end(), (long)(nId - nSize + 1), xEmpty );
				}

				m_aPersistVector[nId] = xLoadedObj;
				xLoadedObj->read( Reference< XObjectInputStream >(
					SAL_STATIC_CAST( XObjectInputStream *, this ) ) );
			}
			else
			{
				// no service with this name could be instantiated
				bLoadSuccesfull = sal_False;
			}
		}
		else {
			if( m_aPersistVector.size() < nId )
			{
				// id unknown, load failure !
				bLoadSuccesfull = sal_False;
			}
			else
			{
				// Object has alread been read,
				xLoadedObj = m_aPersistVector[nId];
			}
		}
	}

	// skip to the position behind the object
	skipBytes( nObjLen + nLen - m_rMarkable->offsetToMark( nMark ) );
	m_rMarkable->deleteMark( nMark );

	if( ! bLoadSuccesfull )
	{
		throw WrongFormatException();
	}
	return xLoadedObj;
}


void OObjectInputStream::connectToMarkable()
{
	if( ! m_bValidMarkable ) {
		if( ! m_bValidStream )
		{
			throw NotConnectedException( );
		}

		// find the markable stream !
		Reference< XInterface > rTry(m_input);
		while( sal_True ) {
			if( ! rTry.is() )
			{
				throw NotConnectedException( );
			}
			Reference<  XMarkableStream > markable( rTry , UNO_QUERY );
			if( markable.is() )
			{
				m_rMarkable = markable;
				break;
			}
			Reference < XActiveDataSink > sink( rTry , UNO_QUERY );
			rTry = sink;
		}
		m_bValidMarkable = sal_True;
	}
}

sal_Int32 OObjectInputStream::createMark(void) 				throw (IOException, RuntimeException)
{
	connectToMarkable();	// throws an exception, if a markable is not connected !

	return m_rMarkable->createMark();
}

void OObjectInputStream::deleteMark(sal_Int32 Mark)			throw (IOException, IllegalArgumentException, RuntimeException)
{
	if( ! m_bValidMarkable )
	{
		throw NotConnectedException();
	}
	m_rMarkable->deleteMark( Mark );
}

void OObjectInputStream::jumpToMark(sal_Int32 nMark) 		throw (IOException, IllegalArgumentException, RuntimeException)
{
	if( ! m_bValidMarkable )
	{
		throw NotConnectedException();
	}
	m_rMarkable->jumpToMark( nMark );
}
void OObjectInputStream::jumpToFurthest(void) 			throw (IOException, RuntimeException)
{
	connectToMarkable();
	m_rMarkable->jumpToFurthest();
}

sal_Int32 OObjectInputStream::offsetToMark(sal_Int32 nMark)
	throw (IOException, IllegalArgumentException, RuntimeException)
{
	if( ! m_bValidMarkable )
	{
		throw NotConnectedException();
	}
	return m_rMarkable->offsetToMark( nMark );
}


Sequence< Type > SAL_CALL OObjectInputStream::getTypes(void) throw( RuntimeException )
{
	static OTypeCollection *pCollection = 0;
	if( ! pCollection )
	{
		MutexGuard guard( Mutex::getGlobalMutex() );
		if( ! pCollection )
		{
			static OTypeCollection collection(
				getCppuType( (Reference< XMarkableStream > * ) 0 ),
				getCppuType( (Reference< XObjectInputStream > * ) 0 ),
				ODataInputStream::getTypes() );
			pCollection = &collection;
		}
	}
	return (*pCollection).getTypes();
}

Sequence< sal_Int8 > SAL_CALL OObjectInputStream::getImplementationId(  ) throw( RuntimeException)
{
	static OImplementationId *pId = 0;
	if( ! pId )
	{
		MutexGuard guard( Mutex::getGlobalMutex() );
		if( ! pId )
		{
			static OImplementationId id( sal_False );
			pId = &id;
		}
	}
	return (*pId).getImplementationId();
}


// XServiceInfo
OUString OObjectInputStream::getImplementationName() throw ()
{
    return OObjectInputStream_getImplementationName();
}

// XServiceInfo
sal_Bool OObjectInputStream::supportsService(const OUString& ServiceName) throw ()
{
    Sequence< OUString > aSNL = getSupportedServiceNames();
    const OUString * pArray = aSNL.getConstArray();

    for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
        if( pArray[i] == ServiceName )
            return sal_True;

    return sal_False;
}

// XServiceInfo
Sequence< OUString > OObjectInputStream::getSupportedServiceNames(void) throw ()
{
    return OObjectInputStream_getSupportedServiceNames();
}




Reference< XInterface > SAL_CALL OObjectInputStream_CreateInstance( const Reference < XComponentContext > & rCtx ) throw(Exception)
{
	OObjectInputStream *p = new OObjectInputStream( rCtx );
	return Reference< XInterface> ( SAL_STATIC_CAST( OWeakObject *, p ) );
}

OUString OObjectInputStream_getImplementationName()
{
	return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.io.stm.ObjectInputStream" ) );
}

Sequence<OUString> OObjectInputStream_getSupportedServiceNames(void)
{
	Sequence<OUString> aRet(1);
	aRet.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.ObjectInputStream" ) );
	return aRet;
}

}
