/* -*- 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"
#include <cstdlib>
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<uno_Sequence *>(std::malloc( 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<char *>(pDest) + pMemberOffsets[nDescr],
static_cast<char *>(pSource) + pMemberOffsets[nDescr],
ppTypeRefs[nDescr], mapping );
}
}
else
{
while (nDescr--)
{
::uno_type_copyData(
static_cast<char *>(pDest) + pMemberOffsets[nDescr],
static_cast<char *>(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<sal_Unicode *>(pDestAny->pData) = *static_cast<sal_Unicode *>(pSource);
break;
case typelib_TypeClass_BOOLEAN:
pDestAny->pData = &pDestAny->pReserved;
*static_cast<sal_Bool *>(pDestAny->pData) = bool(*static_cast<sal_Bool *>(pSource));
break;
case typelib_TypeClass_BYTE:
pDestAny->pData = &pDestAny->pReserved;
*static_cast<sal_Int8 *>(pDestAny->pData) = *static_cast<sal_Int8 *>(pSource);
break;
case typelib_TypeClass_SHORT:
case typelib_TypeClass_UNSIGNED_SHORT:
pDestAny->pData = &pDestAny->pReserved;
*static_cast<sal_Int16 *>(pDestAny->pData) = *static_cast<sal_Int16 *>(pSource);
break;
case typelib_TypeClass_LONG:
case typelib_TypeClass_UNSIGNED_LONG:
pDestAny->pData = &pDestAny->pReserved;
*static_cast<sal_Int32 *>(pDestAny->pData) = *static_cast<sal_Int32 *>(pSource);
break;
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
if (sizeof(void *) >= sizeof(sal_Int64))
pDestAny->pData = &pDestAny->pReserved;
else
pDestAny->pData = std::malloc( sizeof(sal_Int64) );
*static_cast<sal_Int64 *>(pDestAny->pData) = *static_cast<sal_Int64 *>(pSource);
break;
case typelib_TypeClass_FLOAT:
if (sizeof(void *) >= sizeof(float))
pDestAny->pData = &pDestAny->pReserved;
else
pDestAny->pData = std::malloc( sizeof(float) );
*static_cast<float *>(pDestAny->pData) = *static_cast<float *>(pSource);
break;
case typelib_TypeClass_DOUBLE:
if (sizeof(void *) >= sizeof(double))
pDestAny->pData = &pDestAny->pReserved;
else
pDestAny->pData = std::malloc( sizeof(double) );
*static_cast<double *>(pDestAny->pData) = *static_cast<double *>(pSource);
break;
case typelib_TypeClass_STRING:
::rtl_uString_acquire( *static_cast<rtl_uString **>(pSource) );
pDestAny->pData = &pDestAny->pReserved;
*static_cast<rtl_uString **>(pDestAny->pData) = *static_cast<rtl_uString **>(pSource);
break;
case typelib_TypeClass_TYPE:
TYPE_ACQUIRE( *static_cast<typelib_TypeDescriptionReference **>(pSource) );
pDestAny->pData = &pDestAny->pReserved;
*static_cast<typelib_TypeDescriptionReference **>(pDestAny->pData) = *static_cast<typelib_TypeDescriptionReference **>(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<sal_Int32 *>(pDestAny->pData) = *static_cast<sal_Int32 *>(pSource);
break;
case typelib_TypeClass_STRUCT:
case typelib_TypeClass_EXCEPTION:
if (pTypeDescr)
{
pDestAny->pData = std::malloc( pTypeDescr->nSize );
_copyConstructStruct(
pDestAny->pData, pSource,
reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr),
acquire, mapping );
}
else
{
TYPELIB_DANGER_GET( &pTypeDescr, pType );
pDestAny->pData = std::malloc( pTypeDescr->nSize );
_copyConstructStruct(
pDestAny->pData, pSource,
reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr),
acquire, mapping );
TYPELIB_DANGER_RELEASE( pTypeDescr );
}
break;
case typelib_TypeClass_SEQUENCE:
pDestAny->pData = &pDestAny->pReserved;
if (pTypeDescr)
{
*static_cast<uno_Sequence **>(pDestAny->pData) = copyConstructSequence(
*static_cast<uno_Sequence **>(pSource),
reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType,
acquire, mapping );
}
else
{
TYPELIB_DANGER_GET( &pTypeDescr, pType );
*static_cast<uno_Sequence **>(pDestAny->pData) = copyConstructSequence(
*static_cast<uno_Sequence **>(pSource),
reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType,
acquire, mapping );
TYPELIB_DANGER_RELEASE( pTypeDescr );
}
break;
case typelib_TypeClass_INTERFACE:
pDestAny->pData = &pDestAny->pReserved;
if (mapping)
{
pDestAny->pReserved = _map( *static_cast<void **>(pSource), pType, pTypeDescr, mapping );
}
else
{
_acquire( pDestAny->pReserved = *static_cast<void **>(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<uno_Any *>(pSource)->pType;
if (typelib_TypeClass_VOID == pType->eTypeClass)
{
CONSTRUCT_EMPTY_ANY( pDestAny );
return;
}
pTypeDescr = nullptr;
pSource = static_cast<uno_Any *>(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<sal_Unicode *>(pDestAny->pData) = '\0';
break;
case typelib_TypeClass_BOOLEAN:
pDestAny->pData = &pDestAny->pReserved;
*static_cast<sal_Bool *>(pDestAny->pData) = false;
break;
case typelib_TypeClass_BYTE:
pDestAny->pData = &pDestAny->pReserved;
*static_cast<sal_Int8 *>(pDestAny->pData) = 0;
break;
case typelib_TypeClass_SHORT:
case typelib_TypeClass_UNSIGNED_SHORT:
pDestAny->pData = &pDestAny->pReserved;
*static_cast<sal_Int16 *>(pDestAny->pData) = 0;
break;
case typelib_TypeClass_LONG:
case typelib_TypeClass_UNSIGNED_LONG:
pDestAny->pData = &pDestAny->pReserved;
*static_cast<sal_Int32 *>(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 = std::malloc( sizeof(sal_Int64) );
*static_cast<sal_Int64 *>(pDestAny->pData) = 0;
break;
case typelib_TypeClass_FLOAT:
if (sizeof(void *) >= sizeof(float))
pDestAny->pData = &pDestAny->pReserved;
else
pDestAny->pData = std::malloc( sizeof(float) );
*static_cast<float *>(pDestAny->pData) = 0.0;
break;
case typelib_TypeClass_DOUBLE:
if (sizeof(void *) >= sizeof(double))
pDestAny->pData = &pDestAny->pReserved;
else
pDestAny->pData = std::malloc( sizeof(double) );
*static_cast<double *>(pDestAny->pData) = 0.0;
break;
case typelib_TypeClass_STRING:
pDestAny->pData = &pDestAny->pReserved;
*static_cast<rtl_uString **>(pDestAny->pData) = nullptr;
::rtl_uString_new( static_cast<rtl_uString **>(pDestAny->pData) );
break;
case typelib_TypeClass_TYPE:
pDestAny->pData = &pDestAny->pReserved;
*static_cast<typelib_TypeDescriptionReference **>(pDestAny->pData) = _getVoidType();
break;
case typelib_TypeClass_ENUM:
pDestAny->pData = &pDestAny->pReserved;
if (pTypeDescr)
{
*static_cast<sal_Int32 *>(pDestAny->pData) = reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->nDefaultEnumValue;
}
else
{
TYPELIB_DANGER_GET( &pTypeDescr, pType );
*static_cast<sal_Int32 *>(pDestAny->pData) = reinterpret_cast<typelib_EnumTypeDescription *>(pTypeDescr)->nDefaultEnumValue;
TYPELIB_DANGER_RELEASE( pTypeDescr );
}
break;
case typelib_TypeClass_STRUCT:
case typelib_TypeClass_EXCEPTION:
if (pTypeDescr)
{
pDestAny->pData = std::malloc( pTypeDescr->nSize );
_defaultConstructStruct(
pDestAny->pData, reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr) );
}
else
{
TYPELIB_DANGER_GET( &pTypeDescr, pType );
pDestAny->pData = std::malloc( pTypeDescr->nSize );
_defaultConstructStruct(
pDestAny->pData, reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr) );
TYPELIB_DANGER_RELEASE( pTypeDescr );
}
break;
case typelib_TypeClass_SEQUENCE:
pDestAny->pData = &pDestAny->pReserved;
*static_cast<uno_Sequence **>(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<uno_Any *>(pDest->elements);
uno_Any * pSourceElements = reinterpret_cast<uno_Any *>(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<typelib_CompoundTypeDescription *>(
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<typelib_IndirectTypeDescription *>(
pElementTypeDescr)->pType;
uno_Sequence ** pDestElements =
reinterpret_cast<uno_Sequence **>(pDest->elements);
uno_Sequence ** pSourceElements =
reinterpret_cast<uno_Sequence **>(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<void **>(pSource->elements);
typelib_TypeDescription * pElementTypeDescr = nullptr;
TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
for ( sal_Int32 nPos = nElements; nPos--; )
{
reinterpret_cast<void **>(pElements)[nPos] = nullptr;
if (pSourceElements[nPos])
{
(*mapping->mapInterface)(
mapping, reinterpret_cast<void **>(pElements) + nPos,
pSourceElements[nPos],
reinterpret_cast<typelib_InterfaceTypeDescription *>(
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<sal_Unicode *>(pDest) = *static_cast<sal_Unicode *>(pSource);
break;
case typelib_TypeClass_BOOLEAN:
*static_cast<sal_Bool *>(pDest) = bool(*static_cast<sal_Bool *>(pSource));
break;
case typelib_TypeClass_BYTE:
*static_cast<sal_Int8 *>(pDest) = *static_cast<sal_Int8 *>(pSource);
break;
case typelib_TypeClass_SHORT:
case typelib_TypeClass_UNSIGNED_SHORT:
*static_cast<sal_Int16 *>(pDest) = *static_cast<sal_Int16 *>(pSource);
break;
case typelib_TypeClass_LONG:
case typelib_TypeClass_UNSIGNED_LONG:
*static_cast<sal_Int32 *>(pDest) = *static_cast<sal_Int32 *>(pSource);
break;
case typelib_TypeClass_HYPER:
case typelib_TypeClass_UNSIGNED_HYPER:
*static_cast<sal_Int64 *>(pDest) = *static_cast<sal_Int64 *>(pSource);
break;
case typelib_TypeClass_FLOAT:
*static_cast<float *>(pDest) = *static_cast<float *>(pSource);
break;
case typelib_TypeClass_DOUBLE:
*static_cast<double *>(pDest) = *static_cast<double *>(pSource);
break;
case typelib_TypeClass_STRING:
::rtl_uString_acquire( *static_cast<rtl_uString **>(pSource) );
*static_cast<rtl_uString **>(pDest) = *static_cast<rtl_uString **>(pSource);
break;
case typelib_TypeClass_TYPE:
TYPE_ACQUIRE( *static_cast<typelib_TypeDescriptionReference **>(pSource) );
*static_cast<typelib_TypeDescriptionReference **>(pDest) = *static_cast<typelib_TypeDescriptionReference **>(pSource);
break;
case typelib_TypeClass_ANY:
_copyConstructAny(
static_cast<uno_Any *>(pDest), static_cast<uno_Any *>(pSource)->pData,
static_cast<uno_Any *>(pSource)->pType, nullptr,
acquire, mapping );
break;
case typelib_TypeClass_ENUM:
*static_cast<sal_Int32 *>(pDest) = *static_cast<sal_Int32 *>(pSource);
break;
case typelib_TypeClass_STRUCT:
case typelib_TypeClass_EXCEPTION:
if (pTypeDescr)
{
_copyConstructStruct(
pDest, pSource,
reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr),
acquire, mapping );
}
else
{
TYPELIB_DANGER_GET( &pTypeDescr, pType );
_copyConstructStruct(
pDest, pSource,
reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr),
acquire, mapping );
TYPELIB_DANGER_RELEASE( pTypeDescr );
}
break;
case typelib_TypeClass_SEQUENCE:
if (mapping)
{
if (pTypeDescr)
{
*static_cast<uno_Sequence **>(pDest) = icopyConstructSequence(
*static_cast<uno_Sequence **>(pSource),
reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType,
acquire, mapping );
}
else
{
TYPELIB_DANGER_GET( &pTypeDescr, pType );
*static_cast<uno_Sequence **>(pDest) = icopyConstructSequence(
*static_cast<uno_Sequence **>(pSource),
reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType,
acquire, mapping );
TYPELIB_DANGER_RELEASE( pTypeDescr );
}
}
else
{
osl_atomic_increment( &(*static_cast<uno_Sequence **>(pSource))->nRefCount );
*static_cast<uno_Sequence **>(pDest) = *static_cast<uno_Sequence **>(pSource);
}
break;
case typelib_TypeClass_INTERFACE:
if (mapping)
*static_cast<void **>(pDest) = _map( *static_cast<void **>(pSource), pType, pTypeDescr, mapping );
else
_acquire( *static_cast<void **>(pDest) = *static_cast<void **>(pSource), acquire );
break;
default:
break;
}
}
}
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V522 There might be dereferencing of a potential null pointer.
↑ V522 There might be dereferencing of a potential null pointer.