| /************************************************************** |
| * |
| * 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_cppu.hxx" |
| #include <rtl/memory.h> |
| #include <rtl/alloc.h> |
| #include <osl/diagnose.h> |
| #include <osl/interlck.h> |
| #include <typelib/typedescription.h> |
| #include <uno/data.h> |
| #include <uno/dispatcher.h> |
| #include <uno/sequence2.h> |
| |
| #include "constr.hxx" |
| #include "copy.hxx" |
| #include "destr.hxx" |
| |
| |
| using namespace cppu; |
| |
| namespace cppu |
| { |
| |
| //------------------------------------------------------------------------------ |
| static inline uno_Sequence * reallocSeq( |
| uno_Sequence * pReallocate, sal_Size nElementSize, sal_Int32 nElements ) |
| { |
| OSL_ASSERT( nElements >= 0 ); |
| uno_Sequence * pNew = 0; |
| sal_uInt32 nSize = calcSeqMemSize( nElementSize, nElements ); |
| if (nSize > 0) |
| { |
| if (pReallocate == 0) |
| { |
| pNew = (uno_Sequence *) rtl_allocateMemory( nSize ); |
| } |
| else |
| { |
| pNew = (uno_Sequence *) rtl_reallocateMemory( pReallocate, nSize ); |
| } |
| if (pNew != 0) |
| { |
| // header init |
| pNew->nRefCount = 1; |
| pNew->nElements = nElements; |
| } |
| } |
| return pNew; |
| } |
| |
| //------------------------------------------------------------------------------ |
| static inline bool idefaultConstructElements( |
| uno_Sequence ** ppSeq, |
| typelib_TypeDescriptionReference * pElementType, |
| sal_Int32 nStartIndex, sal_Int32 nStopIndex, |
| sal_Int32 nAlloc = -1 ) // >= 0 means (re)alloc memory for nAlloc elements |
| { |
| uno_Sequence * pSeq = *ppSeq; |
| switch (pElementType->eTypeClass) |
| { |
| case typelib_TypeClass_CHAR: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(sal_Unicode), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_zeroMemory( |
| pSeq->elements + (sizeof(sal_Unicode) * nStartIndex), |
| sizeof(sal_Unicode) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_BOOLEAN: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(sal_Bool), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_zeroMemory( |
| pSeq->elements + (sizeof(sal_Bool) * nStartIndex), |
| sizeof(sal_Bool) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_BYTE: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(sal_Int8), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_zeroMemory( |
| pSeq->elements + (sizeof(sal_Int8) * nStartIndex), |
| sizeof(sal_Int8) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_SHORT: |
| case typelib_TypeClass_UNSIGNED_SHORT: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(sal_Int16), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_zeroMemory( |
| pSeq->elements + (sizeof(sal_Int16) * nStartIndex), |
| sizeof(sal_Int16) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_LONG: |
| case typelib_TypeClass_UNSIGNED_LONG: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_zeroMemory( |
| pSeq->elements + (sizeof(sal_Int32) * nStartIndex), |
| sizeof(sal_Int32) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_HYPER: |
| case typelib_TypeClass_UNSIGNED_HYPER: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(sal_Int64), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_zeroMemory( |
| pSeq->elements + (sizeof(sal_Int64) * nStartIndex), |
| sizeof(sal_Int64) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_FLOAT: |
| { |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(float), nAlloc ); |
| if (pSeq != 0) |
| { |
| float * pElements = (float *) pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| pElements[nPos] = 0.0; |
| } |
| } |
| break; |
| } |
| case typelib_TypeClass_DOUBLE: |
| { |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(double), nAlloc ); |
| if (pSeq != 0) |
| { |
| double * pElements = (double *) pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| pElements[nPos] = 0.0; |
| } |
| } |
| break; |
| } |
| case typelib_TypeClass_STRING: |
| { |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(rtl_uString *), nAlloc ); |
| if (pSeq != 0) |
| { |
| rtl_uString ** pElements = (rtl_uString **) pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| pElements[nPos] = 0; |
| rtl_uString_new( &pElements[nPos] ); |
| } |
| } |
| break; |
| } |
| case typelib_TypeClass_TYPE: |
| { |
| if (nAlloc >= 0) |
| { |
| pSeq = reallocSeq( |
| pSeq, sizeof(typelib_TypeDescriptionReference *), nAlloc ); |
| } |
| if (pSeq != 0) |
| { |
| typelib_TypeDescriptionReference ** pElements = |
| (typelib_TypeDescriptionReference **) pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| pElements[nPos] = _getVoidType(); |
| } |
| } |
| break; |
| } |
| case typelib_TypeClass_ANY: |
| { |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(uno_Any), nAlloc ); |
| if (pSeq != 0) |
| { |
| uno_Any * pElements = (uno_Any *) pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| CONSTRUCT_EMPTY_ANY( &pElements[nPos] ); |
| } |
| } |
| break; |
| } |
| case typelib_TypeClass_ENUM: |
| { |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc ); |
| if (pSeq != 0) |
| { |
| typelib_TypeDescription * pElementTypeDescr = 0; |
| TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); |
| sal_Int32 eEnum = |
| ((typelib_EnumTypeDescription *) |
| pElementTypeDescr)->nDefaultEnumValue; |
| TYPELIB_DANGER_RELEASE( pElementTypeDescr ); |
| |
| sal_Int32 * pElements = (sal_Int32 *) pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| pElements[nPos] = eEnum; |
| } |
| } |
| break; |
| } |
| case typelib_TypeClass_STRUCT: |
| case typelib_TypeClass_EXCEPTION: |
| { |
| typelib_TypeDescription * pElementTypeDescr = 0; |
| TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); |
| sal_Int32 nElementSize = pElementTypeDescr->nSize; |
| |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, nElementSize, nAlloc ); |
| if (pSeq != 0) |
| { |
| char * pElements = pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| _defaultConstructStruct( |
| pElements + (nElementSize * nPos), |
| (typelib_CompoundTypeDescription *)pElementTypeDescr ); |
| } |
| } |
| |
| TYPELIB_DANGER_RELEASE( pElementTypeDescr ); |
| break; |
| } |
| case typelib_TypeClass_ARRAY: |
| { |
| typelib_TypeDescription * pElementTypeDescr = 0; |
| TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); |
| sal_Int32 nElementSize = pElementTypeDescr->nSize; |
| |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, nElementSize, nAlloc ); |
| if (pSeq != 0) |
| { |
| char * pElements = pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| _defaultConstructArray( |
| pElements + (nElementSize * nPos), |
| (typelib_ArrayTypeDescription *)pElementTypeDescr ); |
| } |
| } |
| |
| TYPELIB_DANGER_RELEASE( pElementTypeDescr ); |
| break; |
| } |
| case typelib_TypeClass_UNION: |
| { |
| typelib_TypeDescription * pElementTypeDescr = 0; |
| TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); |
| sal_Int32 nElementSize = pElementTypeDescr->nSize; |
| |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, nElementSize, nAlloc ); |
| if (pSeq != 0) |
| { |
| sal_Int32 nValueOffset = |
| ((typelib_UnionTypeDescription *) |
| pElementTypeDescr)->nValueOffset; |
| sal_Int64 nDefaultDiscr = |
| ((typelib_UnionTypeDescription *) |
| pElementTypeDescr)->nDefaultDiscriminant; |
| |
| typelib_TypeDescription * pDefaultTypeDescr = 0; |
| TYPELIB_DANGER_GET( |
| &pDefaultTypeDescr, |
| ((typelib_UnionTypeDescription *) |
| pElementTypeDescr)->pDefaultTypeRef ); |
| |
| char * pElements = pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| char * pMem = pElements + (nElementSize * nPos); |
| ::uno_constructData( |
| (char *)pMem + nValueOffset, pDefaultTypeDescr ); |
| *(sal_Int64 *)pMem = nDefaultDiscr; |
| } |
| TYPELIB_DANGER_RELEASE( pDefaultTypeDescr ); |
| } |
| |
| TYPELIB_DANGER_RELEASE( pElementTypeDescr ); |
| break; |
| } |
| case typelib_TypeClass_SEQUENCE: |
| { |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(uno_Sequence *), nAlloc ); |
| if (pSeq != 0) |
| { |
| uno_Sequence ** pElements = |
| (uno_Sequence **) pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| pElements[nPos] = createEmptySequence(); |
| } |
| } |
| break; |
| } |
| case typelib_TypeClass_INTERFACE: // either C++ or C-UNO interface |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(void *), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_zeroMemory( |
| pSeq->elements + (sizeof(void *) * nStartIndex), |
| sizeof(void *) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| default: |
| OSL_ENSURE( 0, "### unexpected element type!" ); |
| pSeq = 0; |
| break; |
| } |
| |
| if (pSeq == 0) |
| { |
| OSL_ASSERT( nAlloc >= 0 ); // must have been an allocation failure |
| return false; |
| } |
| else |
| { |
| *ppSeq = pSeq; |
| return true; |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| static inline bool icopyConstructFromElements( |
| uno_Sequence ** ppSeq, void * pSourceElements, |
| typelib_TypeDescriptionReference * pElementType, |
| sal_Int32 nStartIndex, sal_Int32 nStopIndex, |
| uno_AcquireFunc acquire, |
| sal_Int32 nAlloc = -1 ) // >= 0 means (re)alloc memory for nAlloc elements |
| { |
| uno_Sequence * pSeq = *ppSeq; |
| switch (pElementType->eTypeClass) |
| { |
| case typelib_TypeClass_CHAR: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(sal_Unicode), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_copyMemory( |
| pSeq->elements + (sizeof(sal_Unicode) * nStartIndex), |
| (char *)pSourceElements + (sizeof(sal_Unicode) * nStartIndex), |
| sizeof(sal_Unicode) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_BOOLEAN: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(sal_Bool), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_copyMemory( |
| pSeq->elements + (sizeof(sal_Bool) * nStartIndex), |
| (char *)pSourceElements + (sizeof(sal_Bool) * nStartIndex), |
| sizeof(sal_Bool) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_BYTE: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(sal_Int8), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_copyMemory( |
| pSeq->elements + (sizeof(sal_Int8) * nStartIndex), |
| (char *)pSourceElements + (sizeof(sal_Int8) * nStartIndex), |
| sizeof(sal_Int8) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_SHORT: |
| case typelib_TypeClass_UNSIGNED_SHORT: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(sal_Int16), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_copyMemory( |
| pSeq->elements + (sizeof(sal_Int16) * nStartIndex), |
| (char *)pSourceElements + (sizeof(sal_Int16) * nStartIndex), |
| sizeof(sal_Int16) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_LONG: |
| case typelib_TypeClass_UNSIGNED_LONG: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_copyMemory( |
| pSeq->elements + (sizeof(sal_Int32) * nStartIndex), |
| (char *)pSourceElements + (sizeof(sal_Int32) * nStartIndex), |
| sizeof(sal_Int32) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_HYPER: |
| case typelib_TypeClass_UNSIGNED_HYPER: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(sal_Int64), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_copyMemory( |
| pSeq->elements + (sizeof(sal_Int64) * nStartIndex), |
| (char *)pSourceElements + (sizeof(sal_Int64) * nStartIndex), |
| sizeof(sal_Int64) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_FLOAT: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(float), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_copyMemory( |
| pSeq->elements + (sizeof(float) * nStartIndex), |
| (char *)pSourceElements + (sizeof(float) * nStartIndex), |
| sizeof(float) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_DOUBLE: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(double), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_copyMemory( |
| pSeq->elements + (sizeof(double) * nStartIndex), |
| (char *)pSourceElements + (sizeof(double) * nStartIndex), |
| sizeof(double) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_ENUM: |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc ); |
| if (pSeq != 0) |
| { |
| ::rtl_copyMemory( |
| pSeq->elements + (sizeof(sal_Int32) * nStartIndex), |
| (char *)pSourceElements + (sizeof(sal_Int32) * nStartIndex), |
| sizeof(sal_Int32) * (nStopIndex - nStartIndex) ); |
| } |
| break; |
| case typelib_TypeClass_STRING: |
| { |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(rtl_uString *), nAlloc ); |
| if (pSeq != 0) |
| { |
| rtl_uString ** pDestElements = (rtl_uString **) pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| ::rtl_uString_acquire( |
| ((rtl_uString **)pSourceElements)[nPos] ); |
| pDestElements[nPos] = ((rtl_uString **)pSourceElements)[nPos]; |
| } |
| } |
| break; |
| } |
| case typelib_TypeClass_TYPE: |
| { |
| if (nAlloc >= 0) |
| { |
| pSeq = reallocSeq( |
| pSeq, sizeof(typelib_TypeDescriptionReference *), nAlloc ); |
| } |
| if (pSeq != 0) |
| { |
| typelib_TypeDescriptionReference ** pDestElements = |
| (typelib_TypeDescriptionReference **) pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| TYPE_ACQUIRE( |
| ((typelib_TypeDescriptionReference **) |
| pSourceElements)[nPos] ); |
| pDestElements[nPos] = |
| ((typelib_TypeDescriptionReference **) |
| pSourceElements)[nPos]; |
| } |
| } |
| break; |
| } |
| case typelib_TypeClass_ANY: |
| { |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(uno_Any), nAlloc ); |
| if (pSeq != 0) |
| { |
| uno_Any * pDestElements = (uno_Any *) pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| uno_Any * pSource = (uno_Any *)pSourceElements + nPos; |
| _copyConstructAny( |
| &pDestElements[nPos], |
| pSource->pData, |
| pSource->pType, 0, |
| acquire, 0 ); |
| } |
| } |
| break; |
| } |
| case typelib_TypeClass_STRUCT: |
| case typelib_TypeClass_EXCEPTION: |
| { |
| typelib_TypeDescription * pElementTypeDescr = 0; |
| TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); |
| sal_Int32 nElementSize = pElementTypeDescr->nSize; |
| |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, nElementSize, nAlloc ); |
| if (pSeq != 0) |
| { |
| char * pDestElements = pSeq->elements; |
| |
| typelib_CompoundTypeDescription * pTypeDescr = |
| (typelib_CompoundTypeDescription *)pElementTypeDescr; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| char * pDest = |
| pDestElements + (nElementSize * nPos); |
| char * pSource = |
| (char *)pSourceElements + (nElementSize * nPos); |
| |
| if (pTypeDescr->pBaseTypeDescription) |
| { |
| // copy base value |
| _copyConstructStruct( |
| pDest, pSource, |
| pTypeDescr->pBaseTypeDescription, acquire, 0 ); |
| } |
| |
| // then copy members |
| typelib_TypeDescriptionReference ** ppTypeRefs = |
| pTypeDescr->ppTypeRefs; |
| sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets; |
| sal_Int32 nDescr = pTypeDescr->nMembers; |
| |
| while (nDescr--) |
| { |
| ::uno_type_copyData( |
| pDest + pMemberOffsets[nDescr], |
| pSource + pMemberOffsets[nDescr], |
| ppTypeRefs[nDescr], acquire ); |
| } |
| } |
| } |
| |
| TYPELIB_DANGER_RELEASE( pElementTypeDescr ); |
| break; |
| } |
| case typelib_TypeClass_UNION: |
| { |
| typelib_TypeDescription * pElementTypeDescr = 0; |
| TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); |
| sal_Int32 nElementSize = pElementTypeDescr->nSize; |
| |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, nElementSize, nAlloc ); |
| if (pSeq != 0) |
| { |
| char * pDestElements = pSeq->elements; |
| |
| sal_Int32 nValueOffset = |
| ((typelib_UnionTypeDescription *) |
| pElementTypeDescr)->nValueOffset; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| char * pDest = |
| pDestElements + (nElementSize * nPos); |
| char * pSource = |
| (char *)pSourceElements + (nElementSize * nPos); |
| |
| typelib_TypeDescriptionReference * pSetType = _unionGetSetType( |
| pSource, pElementTypeDescr ); |
| ::uno_type_copyData( |
| pDest + nValueOffset, |
| pSource + nValueOffset, |
| pSetType, acquire ); |
| *(sal_Int64 *)pDest = *(sal_Int64 *)pSource; |
| typelib_typedescriptionreference_release( pSetType ); |
| } |
| } |
| |
| TYPELIB_DANGER_RELEASE( pElementTypeDescr ); |
| break; |
| } |
| case typelib_TypeClass_SEQUENCE: // sequence of sequence |
| { |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(uno_Sequence *), nAlloc ); |
| if (pSeq != 0) |
| { |
| typelib_TypeDescription * pElementTypeDescr = 0; |
| TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); |
| typelib_TypeDescriptionReference * pSeqElementType = |
| ((typelib_IndirectTypeDescription *) pElementTypeDescr)->pType; |
| uno_Sequence ** pDestElements = (uno_Sequence **) pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| uno_Sequence * pNew = icopyConstructSequence( |
| ((uno_Sequence **) pSourceElements)[nPos], |
| pSeqElementType, acquire, 0 ); |
| OSL_ASSERT( pNew != 0 ); |
| // ought never be a memory allocation problem, |
| // because of reference counted sequence handles |
| pDestElements[ nPos ] = pNew; |
| } |
| TYPELIB_DANGER_RELEASE( pElementTypeDescr ); |
| } |
| break; |
| } |
| case typelib_TypeClass_INTERFACE: |
| { |
| if (nAlloc >= 0) |
| pSeq = reallocSeq( pSeq, sizeof(void *), nAlloc ); |
| if (pSeq != 0) |
| { |
| void ** pDestElements = (void **) pSeq->elements; |
| for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos ) |
| { |
| _acquire( pDestElements[nPos] = |
| ((void **)pSourceElements)[nPos], acquire ); |
| } |
| } |
| break; |
| } |
| default: |
| OSL_ENSURE( 0, "### unexpected element type!" ); |
| pSeq = 0; |
| break; |
| } |
| |
| if (pSeq == 0) |
| { |
| OSL_ASSERT( nAlloc >= 0 ); // must have been an allocation failure |
| return false; |
| } |
| else |
| { |
| *ppSeq = pSeq; |
| return true; |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| static inline bool ireallocSequence( |
| uno_Sequence ** ppSequence, |
| typelib_TypeDescriptionReference * pElementType, |
| sal_Int32 nSize, |
| uno_AcquireFunc acquire, uno_ReleaseFunc release ) |
| { |
| bool ret = true; |
| uno_Sequence * pSeq = *ppSequence; |
| sal_Int32 nElements = pSeq->nElements; |
| |
| if (pSeq->nRefCount > 1 || |
| // not mem-copyable elements? |
| typelib_TypeClass_ANY == pElementType->eTypeClass || |
| typelib_TypeClass_STRUCT == pElementType->eTypeClass || |
| typelib_TypeClass_EXCEPTION == pElementType->eTypeClass) |
| { |
| // split sequence and construct new one from scratch |
| uno_Sequence * pNew = 0; |
| |
| sal_Int32 nRest = nSize - nElements; |
| sal_Int32 nCopy = (nRest > 0 ? nElements : nSize); |
| |
| if (nCopy >= 0) |
| { |
| ret = icopyConstructFromElements( |
| &pNew, pSeq->elements, pElementType, |
| 0, nCopy, acquire, |
| nSize ); // alloc to nSize |
| } |
| if (ret && nRest > 0) |
| { |
| ret = idefaultConstructElements( |
| &pNew, pElementType, |
| nCopy, nSize, |
| nCopy >= 0 ? -1 /* no mem allocation */ : nSize ); |
| } |
| |
| if (ret) |
| { |
| // destruct sequence |
| if (osl_decrementInterlockedCount( &pSeq->nRefCount ) == 0) |
| { |
| if (nElements > 0) |
| { |
| idestructElements( |
| pSeq->elements, pElementType, |
| 0, nElements, release ); |
| } |
| rtl_freeMemory( pSeq ); |
| } |
| *ppSequence = pNew; |
| } |
| } |
| else |
| { |
| OSL_ASSERT( pSeq->nRefCount == 1 ); |
| if (nSize > nElements) // default construct the rest |
| { |
| ret = idefaultConstructElements( |
| ppSequence, pElementType, |
| nElements, nSize, |
| nSize ); // realloc to nSize |
| } |
| else // or destruct the rest and realloc mem |
| { |
| sal_Int32 nElementSize = idestructElements( |
| pSeq->elements, pElementType, |
| nSize, nElements, release ); |
| // warning: it is assumed that the following will never fail, |
| // else this leads to a sequence null handle |
| *ppSequence = reallocSeq( pSeq, nElementSize, nSize ); |
| OSL_ASSERT( *ppSequence != 0 ); |
| ret = (*ppSequence != 0); |
| } |
| } |
| |
| return ret; |
| } |
| |
| } |
| |
| extern "C" |
| { |
| |
| //############################################################################## |
| sal_Bool SAL_CALL uno_type_sequence_construct( |
| uno_Sequence ** ppSequence, typelib_TypeDescriptionReference * pType, |
| void * pElements, sal_Int32 len, |
| uno_AcquireFunc acquire ) |
| SAL_THROW_EXTERN_C() |
| { |
| bool ret; |
| if (len) |
| { |
| typelib_TypeDescription * pTypeDescr = 0; |
| TYPELIB_DANGER_GET( &pTypeDescr, pType ); |
| |
| typelib_TypeDescriptionReference * pElementType = |
| ((typelib_IndirectTypeDescription *)pTypeDescr)->pType; |
| |
| *ppSequence = 0; |
| if (pElements == 0) |
| { |
| ret = idefaultConstructElements( |
| ppSequence, pElementType, |
| 0, len, |
| len ); // alloc to len |
| } |
| else |
| { |
| ret = icopyConstructFromElements( |
| ppSequence, pElements, pElementType, |
| 0, len, acquire, |
| len ); // alloc to len |
| } |
| |
| TYPELIB_DANGER_RELEASE( pTypeDescr ); |
| } |
| else |
| { |
| *ppSequence = createEmptySequence(); |
| ret = true; |
| } |
| |
| OSL_ASSERT( (*ppSequence != 0) == ret ); |
| return ret; |
| } |
| |
| //############################################################################## |
| sal_Bool SAL_CALL uno_sequence_construct( |
| uno_Sequence ** ppSequence, typelib_TypeDescription * pTypeDescr, |
| void * pElements, sal_Int32 len, |
| uno_AcquireFunc acquire ) |
| SAL_THROW_EXTERN_C() |
| { |
| bool ret; |
| if (len > 0) |
| { |
| typelib_TypeDescriptionReference * pElementType = |
| ((typelib_IndirectTypeDescription *)pTypeDescr)->pType; |
| |
| *ppSequence = 0; |
| if (pElements == 0) |
| { |
| ret = idefaultConstructElements( |
| ppSequence, pElementType, |
| 0, len, |
| len ); // alloc to len |
| } |
| else |
| { |
| ret = icopyConstructFromElements( |
| ppSequence, pElements, pElementType, |
| 0, len, acquire, |
| len ); // alloc to len |
| } |
| } |
| else |
| { |
| *ppSequence = createEmptySequence(); |
| ret = true; |
| } |
| |
| OSL_ASSERT( (*ppSequence != 0) == ret ); |
| return ret; |
| } |
| |
| //############################################################################## |
| sal_Bool SAL_CALL uno_type_sequence_realloc( |
| uno_Sequence ** ppSequence, typelib_TypeDescriptionReference * pType, |
| sal_Int32 nSize, uno_AcquireFunc acquire, uno_ReleaseFunc release ) |
| SAL_THROW_EXTERN_C() |
| { |
| OSL_ENSURE( ppSequence, "### null ptr!" ); |
| OSL_ENSURE( nSize >= 0, "### new size must be at least 0!" ); |
| |
| bool ret = true; |
| if (nSize != (*ppSequence)->nElements) |
| { |
| typelib_TypeDescription * pTypeDescr = 0; |
| TYPELIB_DANGER_GET( &pTypeDescr, pType ); |
| ret = ireallocSequence( |
| ppSequence, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType, |
| nSize, acquire, release ); |
| TYPELIB_DANGER_RELEASE( pTypeDescr ); |
| } |
| return ret; |
| } |
| |
| //############################################################################## |
| sal_Bool SAL_CALL uno_sequence_realloc( |
| uno_Sequence ** ppSequence, typelib_TypeDescription * pTypeDescr, |
| sal_Int32 nSize, uno_AcquireFunc acquire, uno_ReleaseFunc release ) |
| SAL_THROW_EXTERN_C() |
| { |
| OSL_ENSURE( ppSequence, "### null ptr!" ); |
| OSL_ENSURE( nSize >= 0, "### new size must be at least 0!" ); |
| |
| bool ret = true; |
| if (nSize != (*ppSequence)->nElements) |
| { |
| ret = ireallocSequence( |
| ppSequence, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType, |
| nSize, acquire, release ); |
| } |
| return ret; |
| } |
| |
| //############################################################################## |
| sal_Bool SAL_CALL uno_type_sequence_reference2One( |
| uno_Sequence ** ppSequence, |
| typelib_TypeDescriptionReference * pType, |
| uno_AcquireFunc acquire, uno_ReleaseFunc release ) |
| SAL_THROW_EXTERN_C() |
| { |
| OSL_ENSURE( ppSequence, "### null ptr!" ); |
| bool ret = true; |
| uno_Sequence * pSequence = *ppSequence; |
| if (pSequence->nRefCount > 1) |
| { |
| uno_Sequence * pNew = 0; |
| if (pSequence->nElements > 0) |
| { |
| typelib_TypeDescription * pTypeDescr = 0; |
| TYPELIB_DANGER_GET( &pTypeDescr, pType ); |
| |
| ret = icopyConstructFromElements( |
| &pNew, pSequence->elements, |
| ((typelib_IndirectTypeDescription *)pTypeDescr)->pType, |
| 0, pSequence->nElements, acquire, |
| pSequence->nElements ); // alloc nElements |
| if (ret) |
| { |
| idestructSequence( *ppSequence, pType, pTypeDescr, release ); |
| *ppSequence = pNew; |
| } |
| |
| TYPELIB_DANGER_RELEASE( pTypeDescr ); |
| } |
| else |
| { |
| pNew = allocSeq( 0, 0 ); |
| ret = (pNew != 0); |
| if (ret) |
| { |
| // easy destruction of empty sequence: |
| if (osl_decrementInterlockedCount( &pSequence->nRefCount ) == 0) |
| rtl_freeMemory( pSequence ); |
| *ppSequence = pNew; |
| } |
| } |
| } |
| return ret; |
| } |
| |
| //############################################################################## |
| sal_Bool SAL_CALL uno_sequence_reference2One( |
| uno_Sequence ** ppSequence, |
| typelib_TypeDescription * pTypeDescr, |
| uno_AcquireFunc acquire, uno_ReleaseFunc release ) |
| SAL_THROW_EXTERN_C() |
| { |
| OSL_ENSURE( ppSequence, "### null ptr!" ); |
| bool ret = true; |
| uno_Sequence * pSequence = *ppSequence; |
| if (pSequence->nRefCount > 1) |
| { |
| uno_Sequence * pNew = 0; |
| if (pSequence->nElements > 0) |
| { |
| ret = icopyConstructFromElements( |
| &pNew, pSequence->elements, |
| ((typelib_IndirectTypeDescription *)pTypeDescr)->pType, |
| 0, pSequence->nElements, acquire, |
| pSequence->nElements ); // alloc nElements |
| if (ret) |
| { |
| idestructSequence( |
| pSequence, pTypeDescr->pWeakRef, pTypeDescr, release ); |
| *ppSequence = pNew; |
| } |
| } |
| else |
| { |
| pNew = allocSeq( 0, 0 ); |
| ret = (pNew != 0); |
| if (ret) |
| { |
| // easy destruction of empty sequence: |
| if (osl_decrementInterlockedCount( &pSequence->nRefCount ) == 0) |
| rtl_freeMemory( pSequence ); |
| *ppSequence = pNew; |
| } |
| } |
| |
| } |
| return ret; |
| } |
| |
| //############################################################################## |
| void SAL_CALL uno_sequence_assign( |
| uno_Sequence ** ppDest, |
| uno_Sequence * pSource, |
| typelib_TypeDescription * pTypeDescr, |
| uno_ReleaseFunc release ) |
| SAL_THROW_EXTERN_C() |
| { |
| if (*ppDest != pSource) |
| { |
| ::osl_incrementInterlockedCount( &pSource->nRefCount ); |
| idestructSequence( *ppDest, pTypeDescr->pWeakRef, pTypeDescr, release ); |
| *ppDest = pSource; |
| } |
| } |
| |
| //############################################################################## |
| void SAL_CALL uno_type_sequence_assign( |
| uno_Sequence ** ppDest, |
| uno_Sequence * pSource, |
| typelib_TypeDescriptionReference * pType, |
| uno_ReleaseFunc release ) |
| SAL_THROW_EXTERN_C() |
| { |
| if (*ppDest != pSource) |
| { |
| ::osl_incrementInterlockedCount( &pSource->nRefCount ); |
| idestructSequence( *ppDest, pType, 0, release ); |
| *ppDest = pSource; |
| } |
| } |
| |
| } |