/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: flbytes.cxx,v $ * $Revision: 1.6 $ * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org 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 version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svtools.hxx" #include #include #ifndef _SVSTDARR_ULONGS_DECL #define _SVSTDARR_ULONGS #include #undef _SVSTDARR_ULONGS #endif namespace unnamed_svtools_flbytes {} using namespace unnamed_svtools_flbytes; // unnamed namespaces don't work well yet //============================================================================ namespace unnamed_svtools_flbytes { inline ULONG MyMin( long a, long b ) { return Max( long( Min( a , b ) ), 0L ); } } //============================================================================ // // SvFillLockBytes // //============================================================================ TYPEINIT1(SvFillLockBytes, SvLockBytes); //============================================================================ SvFillLockBytes::SvFillLockBytes( SvLockBytes* pLockBytes ) : xLockBytes( pLockBytes ), nFilledSize( 0 ), bTerminated( FALSE ) { } //============================================================================ ErrCode SvFillLockBytes::ReadAt( ULONG nPos, void* pBuffer, ULONG nCount, ULONG *pRead ) const { if( bTerminated ) return xLockBytes->ReadAt( nPos, pBuffer, nCount, pRead ); else { ULONG nWanted = nPos + nCount; if( IsSynchronMode() ) { while( nWanted > nFilledSize && !bTerminated ) Application::Yield(); return xLockBytes->ReadAt( nPos, pBuffer, nCount, pRead ); } else { ULONG nRead = MyMin( nCount, long( nFilledSize ) - nPos ); ULONG nErr = xLockBytes->ReadAt( nPos, pBuffer, nRead, pRead ); return ( !nCount || nRead == nCount || nErr ) ? nErr : ERRCODE_IO_PENDING; } } } //============================================================================ ErrCode SvFillLockBytes::WriteAt( ULONG nPos, const void* pBuffer, ULONG nCount, ULONG *pWritten ) { if( bTerminated ) return xLockBytes->WriteAt( nPos, pBuffer, nCount, pWritten ); else { ULONG nWanted = nPos + nCount; if( IsSynchronMode() ) { while( nWanted > nFilledSize && !bTerminated ) Application::Yield(); return xLockBytes->WriteAt( nPos, pBuffer, nCount, pWritten ); } else { ULONG nRead = MyMin( nCount, long( nFilledSize ) - nPos ); ULONG nErr = xLockBytes->WriteAt( nPos, pBuffer, nRead, pWritten ); return ( !nCount || nRead == nCount || nErr ) ? nErr : ERRCODE_IO_PENDING; } } } //============================================================================ ErrCode SvFillLockBytes::Flush() const { return xLockBytes->Flush( ); } //============================================================================ ErrCode SvFillLockBytes::SetSize( ULONG nSize ) { return xLockBytes->SetSize( nSize ); } //============================================================================ ErrCode SvFillLockBytes::LockRegion( ULONG nPos, ULONG nCount, LockType eType) { return xLockBytes->LockRegion( nPos, nCount, eType ); } //============================================================================ ErrCode SvFillLockBytes::UnlockRegion( ULONG nPos, ULONG nCount, LockType eType) { return xLockBytes->UnlockRegion( nPos, nCount, eType ); } //============================================================================ ErrCode SvFillLockBytes::Stat( SvLockBytesStat* pStat, SvLockBytesStatFlag eFlag) const { return xLockBytes->Stat( pStat, eFlag ); } //============================================================================ ErrCode SvFillLockBytes::FillAppend( const void* pBuffer, ULONG nCount, ULONG *pWritten ) { ErrCode nRet = xLockBytes->WriteAt( nFilledSize, pBuffer, nCount, pWritten ); nFilledSize += *pWritten; return nRet; } //============================================================================ void SvFillLockBytes::Terminate() { bTerminated = TRUE; } //============================================================================ SV_DECL_IMPL_REF_LIST( SvLockBytes, SvLockBytes* ) //============================================================================ // // SvSyncLockBytes // //============================================================================ TYPEINIT1(SvSyncLockBytes, SvOpenLockBytes); //============================================================================ // virtual ErrCode SvSyncLockBytes::ReadAt(ULONG nPos, void * pBuffer, ULONG nCount, ULONG * pRead) const { for (ULONG nReadTotal = 0;;) { ULONG nReadCount = 0; ErrCode nError = m_xAsyncLockBytes->ReadAt(nPos, pBuffer, nCount, &nReadCount); nReadTotal += nReadCount; if (nError != ERRCODE_IO_PENDING || !IsSynchronMode()) { if (pRead) *pRead = nReadTotal; return nError; } nPos += nReadCount; pBuffer = static_cast< sal_Char * >(pBuffer) + nReadCount; nCount -= nReadCount; Application::Yield(); } } //============================================================================ // virtual ErrCode SvSyncLockBytes::WriteAt(ULONG nPos, const void * pBuffer, ULONG nCount, ULONG * pWritten) { for (ULONG nWrittenTotal = 0;;) { ULONG nWrittenCount = 0; ErrCode nError = m_xAsyncLockBytes->WriteAt(nPos, pBuffer, nCount, &nWrittenCount); nWrittenTotal += nWrittenCount; if (nError != ERRCODE_IO_PENDING || !IsSynchronMode()) { if (pWritten) *pWritten = nWrittenTotal; return nError; } nPos += nWrittenCount; pBuffer = static_cast< sal_Char const * >(pBuffer) + nWrittenCount; nCount -= nWrittenCount; Application::Yield(); } } //============================================================================ // // SvCompositeLockBytes // //============================================================================ struct SvCompositeLockBytes_Impl { SvLockBytesMemberList aLockBytes; SvULongs aPositions; SvULongs aOffsets; BOOL bPending; ULONG RelativeOffset( ULONG nPos ) const; ErrCode ReadWrite_Impl( ULONG nPos, void* pBuffer, ULONG nCount, ULONG* pProcessed, BOOL bRead ); SvCompositeLockBytes_Impl() : bPending( FALSE ){} }; //============================================================================ ULONG SvCompositeLockBytes_Impl::RelativeOffset( ULONG nPos ) const { const SvULongs& rPositions = aPositions; const SvULongs& rOffsets = aOffsets; USHORT nMinPos = 0; USHORT nListCount = rPositions.Count(); // Erster Lockbytes, der bearbeitet werden muss while( nMinPos + 1 < nListCount && rPositions[ nMinPos + 1 ] <= nPos ) nMinPos ++; ULONG nSectionStart = rPositions[ nMinPos ]; if( nSectionStart > nPos ) return ULONG_MAX; return rOffsets[ nMinPos ] + nPos - nSectionStart; } //============================================================================ ErrCode SvCompositeLockBytes_Impl::ReadWrite_Impl( ULONG nPos, void* pBuffer, ULONG nCount, ULONG* pProcessed, BOOL bRead ) { ErrCode nErr = ERRCODE_NONE; SvULongs& rPositions = aPositions; SvULongs& rOffsets = aOffsets; SvLockBytesMemberList& rLockBytes = aLockBytes; ULONG nBytes = nCount; USHORT nListCount = rPositions.Count(); USHORT nMinPos = 0; // Erster Lockbytes, der bearbeitet werden muss while( nMinPos + 1 < nListCount && rPositions[ nMinPos + 1 ] <= nPos ) nMinPos ++; ULONG nSectionStart = rPositions[ nMinPos ]; if( nSectionStart > nPos ) { // Es wird aus fuehrendem Leerbereich gearbeitet *pProcessed = 0; return ERRCODE_IO_CANTREAD; } ULONG nDone; while( nMinPos < nListCount ) { ULONG nToProcess; ULONG nSectionStop; if( nMinPos + 1 < nListCount ) { nSectionStop = rPositions[ nMinPos + 1 ]; nToProcess = MyMin( long( nSectionStop ) - nPos, nBytes ); } else { nToProcess = nBytes; nSectionStop = 0; } ULONG nAbsPos = nPos - nSectionStart + rOffsets[ nMinPos ]; SvLockBytes* pLB = rLockBytes.GetObject( nMinPos ); if( bRead ) nErr = pLB->ReadAt( nAbsPos, pBuffer, nToProcess, &nDone ); else nErr = pLB->WriteAt( nAbsPos, pBuffer, nToProcess, &nDone ); nBytes -= nDone; if( nErr || nDone < nToProcess || !nBytes ) { *pProcessed = nCount - nBytes; // Wenn aus dem letzten LockBytes nichts mehr gelesen wurde und // bPending gesetzt ist, Pending zurueck if( !nDone && nMinPos == nListCount - 1 ) return bPending ? ERRCODE_IO_PENDING : nErr; else return nErr; } pBuffer = static_cast< sal_Char * >(pBuffer) + nDone; nPos += nDone; nSectionStart = nSectionStop; nMinPos++; } return nErr; } //============================================================================ TYPEINIT1(SvCompositeLockBytes, SvLockBytes); //============================================================================ SvCompositeLockBytes::SvCompositeLockBytes() : pImpl( new SvCompositeLockBytes_Impl ) { } //============================================================================ SvCompositeLockBytes::~SvCompositeLockBytes() { delete pImpl; } //============================================================================ void SvCompositeLockBytes::SetIsPending( BOOL bSet ) { pImpl->bPending = bSet; } //============================================================================ ULONG SvCompositeLockBytes::RelativeOffset( ULONG nPos ) const { return pImpl->RelativeOffset( nPos ); } //============================================================================ ErrCode SvCompositeLockBytes::ReadAt( ULONG nPos, void* pBuffer, ULONG nCount, ULONG* pRead ) const { return pImpl->ReadWrite_Impl( nPos, pBuffer, nCount, pRead, TRUE ); } //============================================================================ ErrCode SvCompositeLockBytes::WriteAt( ULONG nPos, const void* pBuffer, ULONG nCount, ULONG* pWritten ) { return pImpl->ReadWrite_Impl( nPos, const_cast< void * >(pBuffer), nCount, pWritten, FALSE ); } //============================================================================ ErrCode SvCompositeLockBytes::Flush() const { SvLockBytesMemberList& rLockBytes = pImpl->aLockBytes; ErrCode nErr = ERRCODE_NONE; for( USHORT nCount = (USHORT)rLockBytes.Count(); !nErr && nCount--; ) nErr = rLockBytes.GetObject( nCount )->Flush(); return nErr; } //============================================================================ ErrCode SvCompositeLockBytes::SetSize( ULONG ) { DBG_ERROR( "not implemented" ); return ERRCODE_IO_NOTSUPPORTED; } //============================================================================ ErrCode SvCompositeLockBytes::LockRegion( ULONG, ULONG, LockType ) { DBG_ERROR( "not implemented" ); return ERRCODE_IO_NOTSUPPORTED; } //============================================================================ ErrCode SvCompositeLockBytes::UnlockRegion( ULONG, ULONG, LockType ) { DBG_ERROR( "not implemented" ); return ERRCODE_IO_NOTSUPPORTED; } //============================================================================ ErrCode SvCompositeLockBytes::Stat( SvLockBytesStat* pStat, SvLockBytesStatFlag eFlag) const { USHORT nMax = pImpl->aPositions.Count() - 1; SvLockBytesStat aStat; ErrCode nErr = pImpl->aLockBytes.GetObject( nMax )->Stat( &aStat, eFlag ); pStat->nSize = pImpl->aPositions[ nMax ] + aStat.nSize; return nErr; } //============================================================================ void SvCompositeLockBytes::Append( SvLockBytes* pLockBytes, ULONG nPos, ULONG nOffset ) { USHORT nCount = pImpl->aOffsets.Count(); pImpl->aLockBytes.Insert( pLockBytes, nCount ); pImpl->aPositions.Insert( nPos, nCount ); pImpl->aOffsets.Insert( nOffset, nCount ); } //============================================================================ SvLockBytes* SvCompositeLockBytes::GetLastLockBytes() const { return pImpl->aLockBytes.Count() ? pImpl->aLockBytes.GetObject( pImpl->aLockBytes.Count() - 1 ) : 0; }