sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: // DBMS server stream buffer classes
sl@0: // 
sl@0: //
sl@0: 
sl@0: 
sl@0: 
sl@0: #include "SD_STD.H"
sl@0: 
sl@0: HDbsBuf* HDbsBuf::NewLC(const RDbsObject& aObject,TDbsFunction aFunction,TIpcArgs& aArgs)
sl@0: 	{
sl@0: 	HDbsBuf* self=new(ELeave) HDbsBuf;
sl@0: 	self->PushL();
sl@0: 	self->ConstructL(aObject,aFunction,aArgs);
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: HDbsBuf* HDbsBuf::NewL(const RDbsObject& aObject,TDbsFunction aFunction,TIpcArgs& aArgs)
sl@0: 	{
sl@0: 	HDbsBuf* self=NewLC(aObject,aFunction,aArgs);
sl@0: 	CleanupStack::Pop();
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: void HDbsBuf::ConstructL(const RDbsObject& aObject,TDbsFunction aFunction,TIpcArgs& aArgs)
sl@0: 	{
sl@0: 	TPckg<TDbsStreamBuf> pckg(iBuf);
sl@0: 	aArgs.Set(3,&pckg);
sl@0: 	iIpc.OpenL(aObject,aFunction,aArgs);
sl@0: 	TUint8* base=iBuf.iData;
sl@0: 	// if reading we already have one buffer-full of data
sl@0: 	TInt avail=Max(0,Min(iBuf.iExt,KDbsStreamBufSize));
sl@0: 	SetBuf(ERead,base,base+avail);
sl@0: 	SetPos(ERead,avail);
sl@0: 	SetBuf(EWrite,base,base);
sl@0: 	SetPos(EWrite,0);
sl@0: 	}
sl@0: 
sl@0: TInt HDbsBuf::UnderflowL(TInt)
sl@0: //
sl@0: // Fill the buffer's read area.
sl@0: //
sl@0: 	{
sl@0: 	// when handle is null there is no data to read from server
sl@0: 	if(!iIpc.Handle())
sl@0: 		return 0;
sl@0: 
sl@0: 	__ASSERT(Avail(ERead)==0);
sl@0: 	TUint8* base=iBuf.iData;
sl@0: 	IpcWriteL(base,Lag(EWrite));
sl@0: 	SetBuf(EWrite,base,base);
sl@0: //
sl@0: 	TInt len=IpcReadL(base,iBuf.ESize);
sl@0: 	SetBuf(ERead,base,base+len);
sl@0: 	return len;
sl@0: 	}
sl@0: 
sl@0: void HDbsBuf::OverflowL()
sl@0: //
sl@0: // Set up the buffer's write area.
sl@0: //
sl@0: 	{
sl@0: 	__ASSERT(Avail(EWrite)==0);
sl@0: 	TUint8* base=iBuf.iData;
sl@0: 	MovePos(ERead,Lag(ERead));
sl@0: 	SetBuf(ERead,base,base);
sl@0: //
sl@0: 	IpcWriteL(base,Lag(EWrite));
sl@0: 	SetBuf(EWrite,base,base+iBuf.ESize);
sl@0: 	}
sl@0: 
sl@0: void HDbsBuf::DoRelease()
sl@0: 	{
sl@0: 	delete this;
sl@0: 	}
sl@0: 
sl@0: void HDbsBuf::DoSynchL()
sl@0: //
sl@0: // Synchronise this buffer with its file, giving up on outstanding writes in case of failure.
sl@0: //
sl@0: 	{
sl@0: 	TUint8* base=iBuf.iData;
sl@0: 	MovePos(ERead,Lag(ERead));
sl@0: 	TInt lag=Lag(EWrite);
sl@0: 	SetBuf(ERead|EWrite,base,base);
sl@0: 	iBuf.iExt=-1;
sl@0: 	IpcWriteL(base,lag);
sl@0: 	iIpc.SendReceiveL(EDbsStreamSynch);
sl@0: 	}
sl@0: 
sl@0: TInt HDbsBuf::DoReadL(TAny* aPtr,TInt aMaxLength)
sl@0: //
sl@0: // Read direct from ipc if asked to transfer more than a bufferful.
sl@0: //
sl@0: 	{
sl@0: 	__ASSERT(aMaxLength>=0);
sl@0: 	__ASSERT(aMaxLength>0);
sl@0: 	TInt avail=Avail(ERead);
sl@0: 	__ASSERT(avail>=0&&Avail(EWrite)>=0);
sl@0: 	if (avail>0)
sl@0: 		{
sl@0: 		TInt len=Min(aMaxLength,avail);
sl@0: 		TUint8* ptr=Ptr(ERead);
sl@0: 		aPtr=Mem::Copy(aPtr,ptr,len);
sl@0: 		SetPtr(ERead,ptr+len);
sl@0: 		aMaxLength-=len;
sl@0: 		if (aMaxLength==0)
sl@0: 			return len; // that's it
sl@0: 		}
sl@0: 	__ASSERT(Avail(ERead)==0);
sl@0: 	if (aMaxLength<iBuf.ESize)
sl@0: 		return avail+TStreamBuf::DoReadL(aPtr,aMaxLength);
sl@0: //
sl@0: 	// when handle is null there is no more data to read from server
sl@0: 	if(!iIpc.Handle())
sl@0: 		return avail;
sl@0: 
sl@0: 	TUint8* base=iBuf.iData;
sl@0: 	IpcWriteL(base,Lag(EWrite));
sl@0: 	SetBuf(ERead|EWrite,base,base);
sl@0: 	return avail+IpcReadL(aPtr,aMaxLength);
sl@0: 	}
sl@0: 
sl@0: void HDbsBuf::DoWriteL(const TAny* aPtr,TInt aLength)
sl@0: //
sl@0: // Write direct to ipc if asked to transfer more than a bufferful.
sl@0: //
sl@0: 	{
sl@0: 	__ASSERT(aLength>=0);
sl@0: 	__ASSERT(aLength>0);
sl@0: 	TInt avail=Avail(EWrite);
sl@0: 	__ASSERT(Avail(ERead)>=0&&avail>=0);
sl@0: 	if (avail>0)
sl@0: 		{
sl@0: 		TInt len=Min(aLength,avail);
sl@0: 		SetPtr(EWrite,Mem::Copy(Ptr(EWrite),aPtr,len));
sl@0: 		aLength-=len;
sl@0: 		if (aLength==0)
sl@0: 			return; // done
sl@0: //
sl@0: 		aPtr=(TUint8*)aPtr+len;
sl@0: 		}
sl@0: 	__ASSERT(Avail(EWrite)==0);
sl@0: 	if (aLength<iBuf.ESize)
sl@0: 		TStreamBuf::DoWriteL(aPtr,aLength);
sl@0: 	else
sl@0: 		{
sl@0: 		TUint8* base=iBuf.iData;
sl@0: 		IpcWriteL(base,Lag(EWrite));
sl@0: 		MovePos(ERead,Lag(ERead));
sl@0: 		SetBuf(ERead|EWrite,base,base);
sl@0: 		IpcWriteL(aPtr,aLength);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: TStreamPos HDbsBuf::DoSeekL(TMark aMark,TStreamLocation aLocation,TInt anOffset)
sl@0: //
sl@0: // Position the mark(s) indicated by aMark at anOffset from aLocation.
sl@0: //
sl@0: 	{
sl@0: 	TUint8* base=iBuf.iData;
sl@0: 	TInt end=EndL();
sl@0: //
sl@0: 	switch (aLocation)
sl@0: 		{
sl@0: 	case EStreamBeginning:
sl@0: 		break;
sl@0: 	case EStreamMark:
sl@0: 		switch (aMark)
sl@0: 			{
sl@0: 		case ERead:
sl@0: 			anOffset+=Mark(ERead);
sl@0: 			break;
sl@0: 		case EWrite:
sl@0: 			anOffset+=Mark(EWrite);
sl@0: 			break;
sl@0: 		default:
sl@0: 			Panic(EDbsStreamMarkInvalid);
sl@0: 			break;
sl@0: 			}
sl@0: 		break;
sl@0: 	case EStreamEnd:
sl@0: 		anOffset+=end;
sl@0: 		break;
sl@0: 	default:
sl@0: 		Panic(EDbsStreamLocationInvalid);
sl@0: 		break;
sl@0: 		}
sl@0: 	TInt r=KErrNone;
sl@0: 	if (anOffset<0)
sl@0: 		{
sl@0: 		anOffset=0;
sl@0: 		r=KErrEof;
sl@0: 		}
sl@0: 	else if (anOffset>end)
sl@0: 		{
sl@0: 		anOffset=end;
sl@0: 		r=KErrEof;
sl@0: 		}
sl@0: //
sl@0: 	__ASSERT_ALWAYS(!(aMark&~(ERead|EWrite)),Panic(EDbsStreamMarkInvalid));
sl@0: 	if (aMark&ERead)
sl@0: 		{
sl@0: 		TInt lag=anOffset-Pos(ERead);
sl@0: 		if (lag>=base-End(ERead)&&lag<=0)
sl@0: 			SetPtr(ERead,End(ERead)+lag);
sl@0: 		else
sl@0: 			{
sl@0: 			SetPos(ERead,anOffset);
sl@0: 			SetBuf(ERead,base,base);
sl@0: 			}
sl@0: 		}
sl@0: 	if (aMark&EWrite&&anOffset!=Mark(EWrite))
sl@0: 		{
sl@0: 		IpcWriteL(base,Lag(EWrite));
sl@0: 		SetPos(EWrite,anOffset);
sl@0: 		SetBuf(EWrite,base,base);
sl@0: 		}
sl@0: 	__LEAVE_IF_ERROR(r);
sl@0: 	return TStreamPos(anOffset);
sl@0: 	}
sl@0: 
sl@0: TInt HDbsBuf::IpcReadL(TAny* aPtr,TInt aMaxLength)
sl@0: //
sl@0: // Read from the server at the current read position.
sl@0: //
sl@0: 	{
sl@0: 	__ASSERT(aMaxLength>=0);
sl@0: 	if (aMaxLength==0)
sl@0: 		return 0;
sl@0: //
sl@0: 	TPtr8 des((TUint8*)aPtr,aMaxLength);
sl@0: 	TInt pos=Pos(ERead);
sl@0: 		
sl@0: 	TInt len=iIpc.SendReceiveL(EDbsStreamRead,TIpcArgs(pos,&des,aMaxLength));
sl@0: 	pos+=len;
sl@0: 	if (len<aMaxLength)
sl@0: 		iBuf.iExt=pos; // end-of-file encountered
sl@0: 	SetPos(ERead,pos);
sl@0: 	return len;
sl@0: 	}
sl@0: 
sl@0: void HDbsBuf::IpcWriteL(const TAny* aPtr,TInt aLength)
sl@0: //
sl@0: // Write to the server at the current write position.
sl@0: //
sl@0: 	{
sl@0: 	__ASSERT(aLength>=0);
sl@0: 	if (aLength==0)
sl@0: 		return;
sl@0: //
sl@0: 	TPtrC8 ptr((TUint8*)aPtr,aLength);
sl@0: 	TInt ext=iBuf.iExt;
sl@0: 	iBuf.iExt=-1;
sl@0: 	TInt pos=Pos(EWrite);
sl@0: 	iIpc.SendReceiveL(EDbsStreamWrite,TIpcArgs(pos,&ptr));
sl@0: 	pos+=aLength;
sl@0: 	if (ext>=0&&pos>ext)
sl@0: 		iBuf.iExt=pos;
sl@0: 	SetPos(EWrite,pos);
sl@0: 	}
sl@0: 
sl@0: TInt HDbsBuf::EndL()
sl@0: //
sl@0: // Determine the end of the stream
sl@0: //
sl@0: 	{
sl@0: 	TInt ext=iBuf.iExt;
sl@0: 	if (ext<0)
sl@0: 		iBuf.iExt=ext=iIpc.SendReceiveL(EDbsStreamSize);
sl@0: 	return Max(ext,Mark(EWrite));
sl@0: 	}
sl@0: 
sl@0: // Class HDbsReadBuf
sl@0: 
sl@0: inline HDbsReadBuf::HDbsReadBuf(const TDesC8& aDes)
sl@0: 	{
sl@0: 	TUint8* ptr=CONST_CAST(TUint8*,aDes.Ptr());
sl@0: 	Set(ptr,ptr+aDes.Length(),ERead);
sl@0: 	}
sl@0: 
sl@0: HDbsReadBuf* HDbsReadBuf::NewL(const TDesC8& aDes)
sl@0: 	{
sl@0: 	return new(ELeave) HDbsReadBuf(aDes);
sl@0: 	}
sl@0: 
sl@0: void HDbsReadBuf::DoRelease()
sl@0: 	{
sl@0: 	delete this;
sl@0: 	}
sl@0: 
sl@0: // Class HDbsStream
sl@0: TInt HDbsStream::ReadL(const RMessage2& aMessage)
sl@0: 	{
sl@0: 	TInt pos=aMessage.Int0();
sl@0: 	if (pos!=iRPos)
sl@0: 		iHost.SeekL(iHost.ERead,EStreamBeginning,pos);
sl@0: 	iRPos=-1;
sl@0: 	TInt len=aMessage.Int2();
sl@0: 	pos+=len;
sl@0: 	TInt tfr=len;
sl@0: 	for (;;)
sl@0: 		{
sl@0: 		TUint8 buf[KDbsStreamIoSize];
sl@0: 		TInt read=iHost.ReadL(buf,Min(tfr,KDbsStreamIoSize));
sl@0: 		if (read==0)
sl@0: 			break;
sl@0: 		aMessage.WriteL(1,TPtrC8(buf,read),len-tfr);
sl@0: 		tfr-=read;
sl@0: 		if (tfr==0)
sl@0: 			break;
sl@0: 		if (read<KDbsStreamIoSize)
sl@0: 			break;
sl@0: 		}
sl@0: 	iRPos=pos-tfr;
sl@0: 	return len-tfr;
sl@0: 	}
sl@0: 
sl@0: void HDbsStream::WriteL(const RMessage2& aMessage)
sl@0: 	{
sl@0: 	TInt pos=aMessage.Int0();
sl@0: 	if (pos!=iWPos)
sl@0: 		iHost.SeekL(iHost.EWrite,EStreamBeginning,pos);
sl@0: 	iWPos=-1;
sl@0: 	TInt offset=0;
sl@0: 	TBuf8<KDbsStreamIoSize> buf;
sl@0: 	for (;;)
sl@0: 		{
sl@0: 		aMessage.ReadL(1,buf,offset);
sl@0: 		TInt len=buf.Length();
sl@0: 		if (len==0)
sl@0: 			break;
sl@0: 		iHost.WriteL(buf.Ptr(),len);
sl@0: 		offset+=len;
sl@0: 		if (len<KDbsStreamIoSize)
sl@0: 			break;
sl@0: 		}
sl@0: 	iWPos=pos+offset;
sl@0: 	}
sl@0: 
sl@0: // Class HBufBuf
sl@0: 
sl@0: void HBufBuf::DoRelease()
sl@0: 	{
sl@0: 	delete this;
sl@0: 	}
sl@0: 
sl@0: HBufBuf* HBufBuf::NewLC()
sl@0: 	{
sl@0: 	HBufBuf* self=new(ELeave) HBufBuf;
sl@0: 	self->PushL();
sl@0: 	self->iBuf=CBufSeg::NewL(EGranularity);
sl@0: 	self->Set(*self->iBuf,0,ERead|EWrite);
sl@0: 	return self;
sl@0: 	}
sl@0: