/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * 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 . */ #ifndef INCLUDED_CPPU_SOURCE_UNO_COPY_HXX #define INCLUDED_CPPU_SOURCE_UNO_COPY_HXX #include "prim.hxx" #include "constr.hxx" namespace cppu { //#### copy construction ########################################################################### inline uno_Sequence * allocSeq( sal_Int32 nElementSize, sal_Int32 nElements ) { OSL_ASSERT( nElements >= 0 && nElementSize >= 0 ); uno_Sequence * pSeq = nullptr; sal_uInt32 nSize = calcSeqMemSize( nElementSize, nElements ); if (nSize > 0) { pSeq = static_cast(rtl_allocateMemory( nSize )); if (pSeq != nullptr) { // header init pSeq->nRefCount = 1; pSeq->nElements = nElements; } } return pSeq; } void copyConstructStruct( void * pDest, void * pSource, typelib_CompoundTypeDescription * pTypeDescr, uno_AcquireFunc acquire, uno_Mapping * mapping ); inline void _copyConstructStruct( void * pDest, void * pSource, typelib_CompoundTypeDescription * pTypeDescr, uno_AcquireFunc acquire, uno_Mapping * mapping ) { if (pTypeDescr->pBaseTypeDescription) { // copy base value copyConstructStruct( pDest, pSource, pTypeDescr->pBaseTypeDescription, acquire, mapping ); } // then copy members typelib_TypeDescriptionReference ** ppTypeRefs = pTypeDescr->ppTypeRefs; sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets; sal_Int32 nDescr = pTypeDescr->nMembers; if (mapping) { while (nDescr--) { ::uno_type_copyAndConvertData( static_cast(pDest) + pMemberOffsets[nDescr], static_cast(pSource) + pMemberOffsets[nDescr], ppTypeRefs[nDescr], mapping ); } } else { while (nDescr--) { ::uno_type_copyData( static_cast(pDest) + pMemberOffsets[nDescr], static_cast(pSource) + pMemberOffsets[nDescr], ppTypeRefs[nDescr], acquire ); } } } uno_Sequence * copyConstructSequence( uno_Sequence * pSource, typelib_TypeDescriptionReference * pElementType, uno_AcquireFunc acquire, uno_Mapping * mapping ); inline void _copyConstructAnyFromData( uno_Any * pDestAny, void * pSource, typelib_TypeDescriptionReference * pType, typelib_TypeDescription * pTypeDescr, uno_AcquireFunc acquire, uno_Mapping * mapping ) { TYPE_ACQUIRE( pType ); pDestAny->pType = pType; switch (pType->eTypeClass) { case typelib_TypeClass_CHAR: pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = *static_cast(pSource); break; case typelib_TypeClass_BOOLEAN: pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = bool(*static_cast(pSource)); break; case typelib_TypeClass_BYTE: pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = *static_cast(pSource); break; case typelib_TypeClass_SHORT: case typelib_TypeClass_UNSIGNED_SHORT: pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = *static_cast(pSource); break; case typelib_TypeClass_LONG: case typelib_TypeClass_UNSIGNED_LONG: pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = *static_cast(pSource); break; case typelib_TypeClass_HYPER: case typelib_TypeClass_UNSIGNED_HYPER: if (sizeof(void *) >= sizeof(sal_Int64)) pDestAny->pData = &pDestAny->pReserved; else pDestAny->pData = ::rtl_allocateMemory( sizeof(sal_Int64) ); *static_cast(pDestAny->pData) = *static_cast(pSource); break; case typelib_TypeClass_FLOAT: if (sizeof(void *) >= sizeof(float)) pDestAny->pData = &pDestAny->pReserved; else pDestAny->pData = ::rtl_allocateMemory( sizeof(float) ); *static_cast(pDestAny->pData) = *static_cast(pSource); break; case typelib_TypeClass_DOUBLE: if (sizeof(void *) >= sizeof(double)) pDestAny->pData = &pDestAny->pReserved; else pDestAny->pData = ::rtl_allocateMemory( sizeof(double) ); *static_cast(pDestAny->pData) = *static_cast(pSource); break; case typelib_TypeClass_STRING: ::rtl_uString_acquire( *static_cast(pSource) ); pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = *static_cast(pSource); break; case typelib_TypeClass_TYPE: TYPE_ACQUIRE( *static_cast(pSource) ); pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = *static_cast(pSource); break; case typelib_TypeClass_ANY: OSL_FAIL( "### unexpected nested any!" ); break; case typelib_TypeClass_ENUM: pDestAny->pData = &pDestAny->pReserved; // enum is forced to 32bit long *static_cast(pDestAny->pData) = *static_cast(pSource); break; case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION: if (pTypeDescr) { pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); _copyConstructStruct( pDestAny->pData, pSource, reinterpret_cast(pTypeDescr), acquire, mapping ); } else { TYPELIB_DANGER_GET( &pTypeDescr, pType ); pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); _copyConstructStruct( pDestAny->pData, pSource, reinterpret_cast(pTypeDescr), acquire, mapping ); TYPELIB_DANGER_RELEASE( pTypeDescr ); } break; case typelib_TypeClass_SEQUENCE: pDestAny->pData = &pDestAny->pReserved; if (pTypeDescr) { *static_cast(pDestAny->pData) = copyConstructSequence( *static_cast(pSource), reinterpret_cast(pTypeDescr)->pType, acquire, mapping ); } else { TYPELIB_DANGER_GET( &pTypeDescr, pType ); *static_cast(pDestAny->pData) = copyConstructSequence( *static_cast(pSource), reinterpret_cast(pTypeDescr)->pType, acquire, mapping ); TYPELIB_DANGER_RELEASE( pTypeDescr ); } break; case typelib_TypeClass_INTERFACE: pDestAny->pData = &pDestAny->pReserved; if (mapping) { pDestAny->pReserved = _map( *static_cast(pSource), pType, pTypeDescr, mapping ); } else { _acquire( pDestAny->pReserved = *static_cast(pSource), acquire ); } break; default: OSL_ASSERT(false); break; } } inline void _copyConstructAny( uno_Any * pDestAny, void * pSource, typelib_TypeDescriptionReference * pType, typelib_TypeDescription * pTypeDescr, uno_AcquireFunc acquire, uno_Mapping * mapping ) { if (typelib_TypeClass_VOID == pType->eTypeClass) { CONSTRUCT_EMPTY_ANY( pDestAny ); } else { if (typelib_TypeClass_ANY == pType->eTypeClass) { if (pSource) { pType = static_cast(pSource)->pType; if (typelib_TypeClass_VOID == pType->eTypeClass) { CONSTRUCT_EMPTY_ANY( pDestAny ); return; } pTypeDescr = nullptr; pSource = static_cast(pSource)->pData; } else { CONSTRUCT_EMPTY_ANY( pDestAny ); return; } } if (pSource) { _copyConstructAnyFromData( pDestAny, pSource, pType, pTypeDescr, acquire, mapping ); } else // default construct { TYPE_ACQUIRE( pType ); pDestAny->pType = pType; switch (pType->eTypeClass) { case typelib_TypeClass_CHAR: pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = '\0'; break; case typelib_TypeClass_BOOLEAN: pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = false; break; case typelib_TypeClass_BYTE: pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = 0; break; case typelib_TypeClass_SHORT: case typelib_TypeClass_UNSIGNED_SHORT: pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = 0; break; case typelib_TypeClass_LONG: case typelib_TypeClass_UNSIGNED_LONG: pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = 0; break; case typelib_TypeClass_HYPER: case typelib_TypeClass_UNSIGNED_HYPER: if (sizeof(void *) >= sizeof(sal_Int64)) pDestAny->pData = &pDestAny->pReserved; else pDestAny->pData = ::rtl_allocateMemory( sizeof(sal_Int64) ); *static_cast(pDestAny->pData) = 0; break; case typelib_TypeClass_FLOAT: if (sizeof(void *) >= sizeof(float)) pDestAny->pData = &pDestAny->pReserved; else pDestAny->pData = ::rtl_allocateMemory( sizeof(float) ); *static_cast(pDestAny->pData) = 0.0; break; case typelib_TypeClass_DOUBLE: if (sizeof(void *) >= sizeof(double)) pDestAny->pData = &pDestAny->pReserved; else pDestAny->pData = ::rtl_allocateMemory( sizeof(double) ); *static_cast(pDestAny->pData) = 0.0; break; case typelib_TypeClass_STRING: pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = nullptr; ::rtl_uString_new( static_cast(pDestAny->pData) ); break; case typelib_TypeClass_TYPE: pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = _getVoidType(); break; case typelib_TypeClass_ENUM: pDestAny->pData = &pDestAny->pReserved; if (pTypeDescr) { *static_cast(pDestAny->pData) = reinterpret_cast(pTypeDescr)->nDefaultEnumValue; } else { TYPELIB_DANGER_GET( &pTypeDescr, pType ); *static_cast(pDestAny->pData) = reinterpret_cast(pTypeDescr)->nDefaultEnumValue; TYPELIB_DANGER_RELEASE( pTypeDescr ); } break; case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION: if (pTypeDescr) { pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); _defaultConstructStruct( pDestAny->pData, reinterpret_cast(pTypeDescr) ); } else { TYPELIB_DANGER_GET( &pTypeDescr, pType ); pDestAny->pData = ::rtl_allocateMemory( pTypeDescr->nSize ); _defaultConstructStruct( pDestAny->pData, reinterpret_cast(pTypeDescr) ); TYPELIB_DANGER_RELEASE( pTypeDescr ); } break; case typelib_TypeClass_SEQUENCE: pDestAny->pData = &pDestAny->pReserved; *static_cast(pDestAny->pData) = createEmptySequence(); break; case typelib_TypeClass_INTERFACE: pDestAny->pData = &pDestAny->pReserved; pDestAny->pReserved = nullptr; // either cpp or c-uno interface break; default: OSL_ASSERT(false); break; } } } } inline uno_Sequence * icopyConstructSequence( uno_Sequence * pSource, typelib_TypeDescriptionReference * pElementType, uno_AcquireFunc acquire, uno_Mapping * mapping ) { typelib_TypeClass eTypeClass = pElementType->eTypeClass; if (!mapping || (eTypeClass <= typelib_TypeClass_ENUM && eTypeClass != typelib_TypeClass_ANY)) { osl_atomic_increment( &pSource->nRefCount ); return pSource; } else // create new sequence { uno_Sequence * pDest; sal_Int32 nElements = pSource->nElements; if (nElements) { switch (eTypeClass) { case typelib_TypeClass_ANY: { pDest = allocSeq( sizeof (uno_Any), nElements ); if (pDest != nullptr) { uno_Any * pDestElements = reinterpret_cast(pDest->elements); uno_Any * pSourceElements = reinterpret_cast(pSource->elements); for ( sal_Int32 nPos = nElements; nPos--; ) { typelib_TypeDescriptionReference * pType = pSourceElements[nPos].pType; if (typelib_TypeClass_VOID == pType->eTypeClass) { CONSTRUCT_EMPTY_ANY( &pDestElements[nPos] ); } else { _copyConstructAnyFromData( &pDestElements[nPos], pSourceElements[nPos].pData, pType, nullptr, acquire, mapping ); } } } break; } case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION: { typelib_TypeDescription * pElementTypeDescr = nullptr; TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); sal_Int32 nElementSize = pElementTypeDescr->nSize; char * pSourceElements = pSource->elements; pDest = allocSeq( nElementSize, nElements ); if (pDest != nullptr) { char * pElements = pDest->elements; for ( sal_Int32 nPos = nElements; nPos--; ) { _copyConstructStruct( pElements + (nPos * nElementSize), pSourceElements + (nPos * nElementSize), reinterpret_cast( pElementTypeDescr), acquire, mapping ); } } TYPELIB_DANGER_RELEASE( pElementTypeDescr ); break; } case typelib_TypeClass_SEQUENCE: // sequence of sequence { // coverity[suspicious_sizeof] - sizeof(uno_Sequence*) is correct here pDest = allocSeq( sizeof (uno_Sequence *), nElements ); if (pDest != nullptr) { typelib_TypeDescription * pElementTypeDescr = nullptr; TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); typelib_TypeDescriptionReference * pSeqElementType = reinterpret_cast( pElementTypeDescr)->pType; uno_Sequence ** pDestElements = reinterpret_cast(pDest->elements); uno_Sequence ** pSourceElements = reinterpret_cast(pSource->elements); for ( sal_Int32 nPos = nElements; nPos--; ) { uno_Sequence * pNew = copyConstructSequence( pSourceElements[nPos], pSeqElementType, acquire, mapping ); OSL_ASSERT( pNew != nullptr ); // 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: { pDest = allocSeq( sizeof (void *), nElements ); if (pDest != nullptr) { char * pElements = pDest->elements; void ** pSourceElements = reinterpret_cast(pSource->elements); typelib_TypeDescription * pElementTypeDescr = nullptr; TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType ); for ( sal_Int32 nPos = nElements; nPos--; ) { reinterpret_cast(pElements)[nPos] = nullptr; if (pSourceElements[nPos]) { (*mapping->mapInterface)( mapping, reinterpret_cast(pElements) + nPos, pSourceElements[nPos], reinterpret_cast( pElementTypeDescr) ); } } TYPELIB_DANGER_RELEASE( pElementTypeDescr ); } break; } default: OSL_FAIL( "### unexpected sequence element type!" ); pDest = nullptr; break; } } else // empty sequence { pDest = allocSeq( 0, 0 ); } return pDest; } } inline void _copyConstructData( void * pDest, void * pSource, typelib_TypeDescriptionReference * pType, typelib_TypeDescription * pTypeDescr, uno_AcquireFunc acquire, uno_Mapping * mapping ) { switch (pType->eTypeClass) { case typelib_TypeClass_CHAR: *static_cast(pDest) = *static_cast(pSource); break; case typelib_TypeClass_BOOLEAN: *static_cast(pDest) = bool(*static_cast(pSource)); break; case typelib_TypeClass_BYTE: *static_cast(pDest) = *static_cast(pSource); break; case typelib_TypeClass_SHORT: case typelib_TypeClass_UNSIGNED_SHORT: *static_cast(pDest) = *static_cast(pSource); break; case typelib_TypeClass_LONG: case typelib_TypeClass_UNSIGNED_LONG: *static_cast(pDest) = *static_cast(pSource); break; case typelib_TypeClass_HYPER: case typelib_TypeClass_UNSIGNED_HYPER: *static_cast(pDest) = *static_cast(pSource); break; case typelib_TypeClass_FLOAT: *static_cast(pDest) = *static_cast(pSource); break; case typelib_TypeClass_DOUBLE: *static_cast(pDest) = *static_cast(pSource); break; case typelib_TypeClass_STRING: ::rtl_uString_acquire( *static_cast(pSource) ); *static_cast(pDest) = *static_cast(pSource); break; case typelib_TypeClass_TYPE: TYPE_ACQUIRE( *static_cast(pSource) ); *static_cast(pDest) = *static_cast(pSource); break; case typelib_TypeClass_ANY: _copyConstructAny( static_cast(pDest), static_cast(pSource)->pData, static_cast(pSource)->pType, nullptr, acquire, mapping ); break; case typelib_TypeClass_ENUM: *static_cast(pDest) = *static_cast(pSource); break; case typelib_TypeClass_STRUCT: case typelib_TypeClass_EXCEPTION: if (pTypeDescr) { _copyConstructStruct( pDest, pSource, reinterpret_cast(pTypeDescr), acquire, mapping ); } else { TYPELIB_DANGER_GET( &pTypeDescr, pType ); _copyConstructStruct( pDest, pSource, reinterpret_cast(pTypeDescr), acquire, mapping ); TYPELIB_DANGER_RELEASE( pTypeDescr ); } break; case typelib_TypeClass_SEQUENCE: if (mapping) { if (pTypeDescr) { *static_cast(pDest) = icopyConstructSequence( *static_cast(pSource), reinterpret_cast(pTypeDescr)->pType, acquire, mapping ); } else { TYPELIB_DANGER_GET( &pTypeDescr, pType ); *static_cast(pDest) = icopyConstructSequence( *static_cast(pSource), reinterpret_cast(pTypeDescr)->pType, acquire, mapping ); TYPELIB_DANGER_RELEASE( pTypeDescr ); } } else { osl_atomic_increment( &(*static_cast(pSource))->nRefCount ); *static_cast(pDest) = *static_cast(pSource); } break; case typelib_TypeClass_INTERFACE: if (mapping) *static_cast(pDest) = _map( *static_cast(pSource), pType, pTypeDescr, mapping ); else _acquire( *static_cast(pDest) = *static_cast(pSource), acquire ); break; default: break; } } } #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */