forked from amazingfate/loongoffice
535 lines
17 KiB
C++
535 lines
17 KiB
C++
/*************************************************************************
|
|
*
|
|
* $RCSfile: sequence.cxx,v $
|
|
*
|
|
* $Revision: 1.3 $
|
|
*
|
|
* last change: $Author: kz $ $Date: 2004-03-23 10:23:48 $
|
|
*
|
|
* 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): _______________________________________
|
|
*
|
|
*
|
|
************************************************************************/
|
|
|
|
#include "sequence.hxx"
|
|
|
|
#ifndef INCLUDED_DATA_FLAGS_HXX
|
|
#include "flags.hxx"
|
|
#endif
|
|
#ifndef CONFIGMGR_UPDATEACCESSOR_HXX
|
|
#include "updateaccessor.hxx"
|
|
#endif
|
|
|
|
#ifndef INCLUDED_ALGORITHM
|
|
#include <algorithm>
|
|
#define INCLUDED_ALGORITHM
|
|
#endif
|
|
|
|
#ifndef INCLUDED_STRING_H
|
|
#include <string.h>
|
|
#define INCLUDED_STRING_H
|
|
#endif
|
|
|
|
namespace configmgr
|
|
{
|
|
//-----------------------------------------------------------------------------
|
|
namespace sharable
|
|
{
|
|
//-----------------------------------------------------------------------------
|
|
namespace Type = data::Type;
|
|
namespace uno = ::com::sun::star::uno;
|
|
typedef AnyData::TypeCode TypeCode;
|
|
using memory::Allocator;
|
|
using memory::Accessor;
|
|
using memory::Pointer;
|
|
//-----------------------------------------------------------------------------
|
|
static
|
|
sal_uInt32 implGetElementSize(TypeCode _aElementType)
|
|
{
|
|
OSL_ASSERT(_aElementType == (_aElementType & Type::mask_basetype));
|
|
switch (_aElementType)
|
|
{
|
|
|
|
case Type::value_boolean: return sizeof(sal_Bool);
|
|
|
|
case Type::value_short: return sizeof(sal_Int16);
|
|
|
|
case Type::value_int: return sizeof(sal_Int32);
|
|
|
|
case Type::value_long: return sizeof(sal_Int64);
|
|
|
|
case Type::value_double: return sizeof(double);
|
|
|
|
case Type::value_string: return sizeof(String);
|
|
|
|
case Type::value_binary: return sizeof(Vector);
|
|
|
|
case Type::value_any: // results from value_invalid
|
|
default:
|
|
OSL_ENSURE( false, "Invalid type code" );
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
static inline
|
|
sal_uInt32 implGetHeaderSize(sal_uInt32 _nElemSize)
|
|
{
|
|
// pad header to elem size, if larger (for safe alignment)
|
|
OSL_ASSERT(_nElemSize > sizeof(sal_Int32) || sizeof(sal_Int32) % _nElemSize== 0);
|
|
return _nElemSize > sizeof(sal_Int32) ? _nElemSize : sizeof(sal_Int32);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
static
|
|
inline
|
|
sal_Int32& implGetSize(Allocator const& _anAllocator, Sequence _aSeq)
|
|
{
|
|
OSL_ASSERT(_aSeq != 0);
|
|
void * pBase = _anAllocator.access(_aSeq);
|
|
return * static_cast<sal_Int32 *>(pBase);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
static
|
|
inline
|
|
sal_Int32 implGetSize(Accessor const& _anAccessor, Sequence _aSeq)
|
|
{
|
|
OSL_ASSERT(_aSeq != 0);
|
|
void const * pBase = _anAccessor.access( Pointer(_aSeq) );
|
|
return * static_cast<sal_Int32 const *>(pBase);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
static
|
|
Sequence implSeqAlloc(Allocator const& _anAllocator, sal_Int32 _nElements, sal_uInt32 _nElemSize)
|
|
{
|
|
sal_uInt32 nTotalSize = implGetHeaderSize(_nElemSize) + _nElements * _nElemSize;
|
|
|
|
Sequence aResult = _anAllocator.allocate(nTotalSize);
|
|
|
|
implGetSize(_anAllocator,aResult) = _nElements;
|
|
|
|
return aResult;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static
|
|
void allocSeqData(Allocator const& _anAllocator, Address _aDestAddr,
|
|
TypeCode _aElementType,
|
|
sal_Int32 _nElements, sal_uInt32 _nElementSize,
|
|
void const * _pSourceData)
|
|
{
|
|
OSL_ASSERT(_aElementType == (_aElementType & Type::mask_basetype));
|
|
OSL_ASSERT(_nElementSize == implGetElementSize(_aElementType));
|
|
switch (_aElementType)
|
|
{
|
|
case Type::value_boolean:
|
|
case Type::value_short:
|
|
case Type::value_int:
|
|
case Type::value_long:
|
|
case Type::value_double:
|
|
::memcpy(_anAllocator.access(_aDestAddr),_pSourceData,_nElements * _nElementSize);
|
|
break;
|
|
|
|
case Type::value_string:
|
|
{
|
|
OSL_ASSERT(_nElementSize == sizeof(String));
|
|
|
|
rtl::OUString const * pSource = static_cast<rtl::OUString const *>(_pSourceData);
|
|
|
|
while (--_nElements >= 0)
|
|
{
|
|
String aElement = allocString(_anAllocator,*pSource);
|
|
|
|
String * pDest = static_cast<String*>( _anAllocator.access(_aDestAddr) );
|
|
*pDest = aElement;
|
|
|
|
++pSource;
|
|
_aDestAddr += sizeof *pDest;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Type::value_binary:
|
|
{
|
|
OSL_ASSERT(_nElementSize == sizeof(Vector));
|
|
|
|
typedef uno::Sequence< sal_Int8 > BinSequence;
|
|
BinSequence const * pSource = static_cast<BinSequence const *>(_pSourceData);
|
|
|
|
while (--_nElements >= 0)
|
|
{
|
|
Vector aElement = allocBinary(_anAllocator,*pSource);
|
|
|
|
Vector * pDest = static_cast<Vector*>( _anAllocator.access(_aDestAddr) );
|
|
*pDest = aElement;
|
|
|
|
++pSource;
|
|
_aDestAddr += sizeof *pDest;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Type::value_any:
|
|
default:
|
|
OSL_ENSURE(false, "Invalid element type");
|
|
break;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
Sequence allocSequence(Allocator const& _anAllocator, TypeCode _aElementType, ::sal_Sequence const * _pSeqData)
|
|
{
|
|
OSL_ENSURE(_aElementType == (_aElementType & Type::mask_valuetype), "Invalid type code");
|
|
|
|
OSL_ENSURE(_pSeqData, "ERROR: Trying to allocate from a NULL sequence");
|
|
if (_pSeqData == NULL) return 0;
|
|
|
|
// OSL_ASSERT(_aElementType == (_aElementType & Type::mask_basetype));
|
|
_aElementType &= Type::mask_basetype;
|
|
|
|
sal_uInt32 const nElementSize = implGetElementSize(_aElementType);
|
|
sal_Int32 const nElements = _pSeqData->nElements;
|
|
|
|
Sequence aResult = implSeqAlloc(_anAllocator,nElements,nElementSize);
|
|
|
|
if (aResult)
|
|
allocSeqData( _anAllocator, aResult + implGetHeaderSize(nElementSize),
|
|
_aElementType, nElements, nElementSize,
|
|
_pSeqData->elements);
|
|
|
|
return aResult;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
Sequence allocBinary(Allocator const& _anAllocator, uno::Sequence<sal_Int8> const & _aBinaryValue)
|
|
{
|
|
sal_uInt32 const nElementSize = 1;
|
|
sal_Int32 const nLength = _aBinaryValue.getLength();
|
|
|
|
Sequence aResult = implSeqAlloc(_anAllocator,nLength,nElementSize);
|
|
|
|
if (aResult)
|
|
{
|
|
Address aElementBaseAddr = aResult + implGetHeaderSize(nElementSize);
|
|
::memcpy(_anAllocator.access(aElementBaseAddr), _aBinaryValue.getConstArray(), nLength);
|
|
}
|
|
|
|
return aResult;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sequence copySequence(Allocator const& _anAllocator, TypeCode _aElementType, Sequence _aSeq)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sequence copyBinary(Allocator const& _anAllocator, Sequence _aSeq)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
static
|
|
void freeSeqData(Allocator const& _anAllocator, Address _aDataAddr,
|
|
TypeCode _aElementType, sal_Int32 _nElements)
|
|
{
|
|
OSL_ASSERT(_aElementType == (_aElementType & Type::mask_basetype));
|
|
|
|
switch (_aElementType)
|
|
{
|
|
case Type::value_boolean:
|
|
case Type::value_short:
|
|
case Type::value_int:
|
|
case Type::value_long:
|
|
case Type::value_double:
|
|
// nothing to do
|
|
break;
|
|
|
|
case Type::value_string:
|
|
{
|
|
String * pElements = static_cast<String*>( _anAllocator.access(_aDataAddr) );
|
|
|
|
for (sal_Int32 i = 0; i < _nElements; ++i)
|
|
{
|
|
freeString(_anAllocator,pElements[i]);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Type::value_binary:
|
|
{
|
|
Vector * pElements = static_cast<Vector*>( _anAllocator.access(_aDataAddr) );
|
|
|
|
for (sal_Int32 i = 0; i < _nElements; ++i)
|
|
{
|
|
freeBinary(_anAllocator,pElements[i]);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Type::value_any:
|
|
default:
|
|
OSL_ENSURE(false, "Invalid element type");
|
|
break;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void freeSequence(Allocator const& _anAllocator, TypeCode _aElementType, Sequence _aSeq)
|
|
{
|
|
OSL_ENSURE(_aElementType == (_aElementType & Type::mask_valuetype), "Invalid type code");
|
|
|
|
OSL_ENSURE(_aSeq, "ERROR: Trying to free a NULL sequence");
|
|
if (_aSeq == 0) return;
|
|
|
|
// OSL_ASSERT(_aElementType == (_aElementType & Type::mask_basetype));
|
|
_aElementType &= Type::mask_basetype;
|
|
|
|
sal_uInt32 nHeaderSize = implGetHeaderSize( implGetElementSize( _aElementType ) );
|
|
|
|
freeSeqData(_anAllocator,_aSeq + nHeaderSize, _aElementType, implGetSize(_anAllocator,_aSeq));
|
|
|
|
_anAllocator.deallocate(_aSeq);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void freeBinary(memory::Allocator const& _anAllocator, Sequence _aSeq)
|
|
{
|
|
OSL_ENSURE(_aSeq, "ERROR: Trying to free a NULL sequence");
|
|
if (_aSeq == 0) return;
|
|
|
|
_anAllocator.deallocate(_aSeq);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static inline
|
|
sal_Sequence * implCreateSequence(void const * _pElements, TypeCode _aElementType, sal_Int32 _nElements)
|
|
{
|
|
uno::Type aUnoType = getUnoType( _aElementType | Type::flag_sequence );
|
|
|
|
sal_Sequence * pResult = NULL;
|
|
::uno_type_sequence_construct( &pResult, aUnoType.getTypeLibType(),
|
|
const_cast< void * >( _pElements ),
|
|
_nElements, NULL );
|
|
|
|
OSL_ASSERT(pResult->nRefCount == 1);
|
|
return pResult;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
static
|
|
sal_Sequence * readSeqData(Accessor const & _anAccessor, Address _aDataAddr, TypeCode _aElementType, sal_Int32 _nElements)
|
|
{
|
|
OSL_ASSERT(_aElementType == (_aElementType & Type::mask_basetype));
|
|
|
|
void const * pElementData = _anAccessor.validate( Pointer(_aDataAddr) );
|
|
switch (_aElementType)
|
|
{
|
|
case Type::value_boolean:
|
|
case Type::value_short:
|
|
case Type::value_int:
|
|
case Type::value_long:
|
|
case Type::value_double:
|
|
return implCreateSequence(pElementData,_aElementType,_nElements);
|
|
|
|
case Type::value_string:
|
|
{
|
|
uno::Sequence<rtl::OUString> aResult(_nElements);
|
|
rtl::OUString * pResult = aResult.getArray();
|
|
|
|
String const * pElements = static_cast<String const *>( pElementData );
|
|
|
|
for (sal_Int32 i = 0; i < _nElements; ++i)
|
|
{
|
|
pResult[i] = readString(_anAccessor,pElements[i]);
|
|
}
|
|
|
|
sal_Sequence * pRet = aResult.get();
|
|
++pRet->nRefCount;
|
|
return pRet;
|
|
}
|
|
|
|
case Type::value_binary:
|
|
{
|
|
typedef uno::Sequence< sal_Int8 > BinSequence;
|
|
|
|
uno::Sequence<BinSequence> aResult(_nElements);
|
|
BinSequence * pResult = aResult.getArray();
|
|
|
|
Vector const * pElements = static_cast<Vector const *>( pElementData );
|
|
|
|
for (sal_Int32 i = 0; i < _nElements; ++i)
|
|
{
|
|
pResult[i] = readBinary(_anAccessor,pElements[i]);
|
|
}
|
|
|
|
sal_Sequence * pRet = aResult.get();
|
|
++pRet->nRefCount;
|
|
return pRet;
|
|
}
|
|
break;
|
|
|
|
case Type::value_any:
|
|
default:
|
|
OSL_ENSURE(false, "Invalid element type");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
::sal_Sequence * readSequence(Accessor const& _anAccessor, TypeCode _aElementType, Sequence _aSeq)
|
|
{
|
|
OSL_ENSURE(_aElementType == (_aElementType & Type::mask_valuetype), "Invalid type code");
|
|
|
|
OSL_ENSURE(_aSeq, "ERROR: Trying to read from a NULL sequence");
|
|
if (_aSeq == 0) return NULL;
|
|
|
|
// OSL_ASSERT(_aElementType == (_aElementType & Type::mask_basetype));
|
|
_aElementType &= Type::mask_basetype;
|
|
|
|
sal_uInt32 nHeaderSize = implGetHeaderSize( implGetElementSize( _aElementType ) );
|
|
|
|
return readSeqData(_anAccessor,_aSeq + nHeaderSize, _aElementType, implGetSize(_anAccessor,_aSeq));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
uno::Any readAnySequence(Accessor const& _anAccessor, TypeCode _aElementType, Sequence _aSeq)
|
|
{
|
|
sal_Sequence * pRawSequence = readSequence(_anAccessor, _aElementType, _aSeq);
|
|
|
|
uno::Any aResult;
|
|
|
|
if (pRawSequence != NULL)
|
|
switch (_aElementType & Type::mask_basetype)
|
|
{
|
|
case Type::value_string:
|
|
{
|
|
uno::Sequence< rtl::OUString > aSequence(pRawSequence,SAL_NO_ACQUIRE);
|
|
aResult <<=aSequence ;
|
|
}
|
|
break;
|
|
|
|
case Type::value_boolean:
|
|
{
|
|
uno::Sequence< sal_Bool > aSequence(pRawSequence,SAL_NO_ACQUIRE);
|
|
aResult <<=aSequence ;
|
|
}
|
|
break;
|
|
|
|
case Type::value_short:
|
|
{
|
|
uno::Sequence< sal_Int16 > aSequence(pRawSequence,SAL_NO_ACQUIRE);
|
|
aResult <<=aSequence ;
|
|
}
|
|
break;
|
|
|
|
case Type::value_int:
|
|
{
|
|
uno::Sequence< sal_Int32 > aSequence(pRawSequence,SAL_NO_ACQUIRE);
|
|
aResult <<=aSequence ;
|
|
}
|
|
break;
|
|
|
|
case Type::value_long:
|
|
{
|
|
uno::Sequence< sal_Int64 > aSequence(pRawSequence,SAL_NO_ACQUIRE);
|
|
aResult <<=aSequence ;
|
|
}
|
|
break;
|
|
|
|
case Type::value_double:
|
|
{
|
|
uno::Sequence< double > aSequence(pRawSequence,SAL_NO_ACQUIRE);
|
|
aResult <<=aSequence ;
|
|
}
|
|
break;
|
|
|
|
case Type::value_binary:
|
|
{
|
|
uno::Sequence< uno::Sequence< sal_Int8 > > aSequence(pRawSequence,SAL_NO_ACQUIRE);
|
|
aResult <<=aSequence ;
|
|
}
|
|
break;
|
|
|
|
case Type::value_any: // from value_invalid ??
|
|
default:
|
|
OSL_ENSURE( false, "Invalid type code" );
|
|
break;
|
|
}
|
|
|
|
OSL_ASSERT(!aResult.hasValue() || aResult.getValueType() == getUnoType(_aElementType | Type::flag_sequence));
|
|
|
|
return aResult;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
uno::Sequence<sal_Int8> readBinary(Accessor const& _anAccessor, Sequence _aSeq)
|
|
{
|
|
OSL_ENSURE(_aSeq, "ERROR: Trying to read from a NULL sequence");
|
|
if (_aSeq == 0) return uno::Sequence<sal_Int8>();
|
|
|
|
sal_Int32 const nElements = implGetSize(_anAccessor,_aSeq);
|
|
|
|
void const * const pElementData = _anAccessor.validate( Pointer(_aSeq + implGetHeaderSize(1)) );
|
|
|
|
sal_Int8 const * const pBinaryData = static_cast<sal_Int8 const *>(pElementData);
|
|
|
|
uno::Sequence< sal_Int8 > aSequence(pBinaryData,nElements);
|
|
|
|
return aSequence;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
} // namespace
|
|
|