diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /stoc/source/corereflection | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'stoc/source/corereflection')
-rw-r--r-- | stoc/source/corereflection/base.hxx | 424 | ||||
-rw-r--r-- | stoc/source/corereflection/crarray.cxx | 200 | ||||
-rw-r--r-- | stoc/source/corereflection/crbase.cxx | 248 | ||||
-rw-r--r-- | stoc/source/corereflection/crcomp.cxx | 358 | ||||
-rw-r--r-- | stoc/source/corereflection/crefl.cxx | 379 | ||||
-rw-r--r-- | stoc/source/corereflection/crenum.cxx | 206 | ||||
-rw-r--r-- | stoc/source/corereflection/criface.cxx | 916 | ||||
-rw-r--r-- | stoc/source/corereflection/lrucache.hxx | 209 | ||||
-rw-r--r-- | stoc/source/corereflection/reflection.component | 28 |
9 files changed, 2968 insertions, 0 deletions
diff --git a/stoc/source/corereflection/base.hxx b/stoc/source/corereflection/base.hxx new file mode 100644 index 000000000..16d42213d --- /dev/null +++ b/stoc/source/corereflection/base.hxx @@ -0,0 +1,424 @@ +/* -*- 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 . + */ +// #define TEST_LIST_CLASSES + +#ifndef INCLUDED_STOC_SOURCE_COREREFLECTION_BASE_HXX +#define INCLUDED_STOC_SOURCE_COREREFLECTION_BASE_HXX + +#include <sal/config.h> + +#include <o3tl/any.hxx> +#include <osl/mutex.hxx> +#include <uno/mapping.hxx> +#include <uno/dispatcher.h> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/component.hxx> +#include <rtl/ustring.hxx> +#include <rtl/ref.hxx> + +#include "lrucache.hxx" + +#ifdef TEST_LIST_CLASSES +#include <vector> +#include <algorithm> +#endif +#include <unordered_map> +#include <memory> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> + +#include <com/sun/star/reflection/XIdlReflection.hpp> + +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::reflection { class XIdlClass; } +namespace com::sun::star::reflection { class XIdlField; } +namespace com::sun::star::reflection { class XIdlMethod; } + +namespace stoc_corefl +{ + +#ifdef TEST_LIST_CLASSES +extern std::vector<OUString> g_aClassNames; +#endif + + +::osl::Mutex & getMutexAccess(); + + +inline bool td_equals( typelib_TypeDescription * pTD, typelib_TypeDescriptionReference * pType ) +{ + return (pTD->pWeakRef == pType || + (pTD->pTypeName->length == pType->pTypeName->length && + rtl_ustr_compare( pTD->pTypeName->buffer, pType->pTypeName->buffer ) == 0)); +} + +typedef std::unordered_map< OUString, css::uno::WeakReference< css::reflection::XIdlField > > OUString2Field; +typedef std::unordered_map< OUString, css::uno::WeakReference< css::reflection::XIdlMethod > > OUString2Method; + + +class IdlReflectionServiceImpl + : public ::cppu::OComponentHelper + , public css::reflection::XIdlReflection + , public css::container::XHierarchicalNameAccess + , public css::lang::XServiceInfo +{ + ::osl::Mutex _aComponentMutex; + css::uno::Reference< css::container::XHierarchicalNameAccess > _xTDMgr; + + // caching + LRU_CacheAnyByOUString _aElements; + + css::uno::Mapping _aCpp2Uno; + css::uno::Mapping _aUno2Cpp; + + inline css::uno::Reference< css::reflection::XIdlClass > constructClass( typelib_TypeDescription * pTypeDescr ); + +public: + /// @throws css::uno::RuntimeException + const css::uno::Mapping & getCpp2Uno(); + /// @throws css::uno::RuntimeException + const css::uno::Mapping & getUno2Cpp(); + /// @throws css::uno::RuntimeException + uno_Interface * mapToUno( const css::uno::Any & rObj, typelib_InterfaceTypeDescription * pTo ); + + // ctor/ dtor + explicit IdlReflectionServiceImpl( const css::uno::Reference< css::uno::XComponentContext > & xContext ); + virtual ~IdlReflectionServiceImpl() override; + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override; + virtual void SAL_CALL acquire() noexcept override; + virtual void SAL_CALL release() noexcept override; + + // some XComponent part from OComponentHelper + virtual void SAL_CALL dispose() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XTypeProvider + virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override; + + // XIdlReflection + virtual css::uno::Reference< css::reflection::XIdlClass > SAL_CALL forName( const OUString & rTypeName ) override; + virtual css::uno::Reference< css::reflection::XIdlClass > SAL_CALL getType( const css::uno::Any & rObj ) override; + + // XHierarchicalNameAccess + virtual css::uno::Any SAL_CALL getByHierarchicalName( const OUString & rName ) override; + virtual sal_Bool SAL_CALL hasByHierarchicalName( const OUString & rName ) override; + + /// @throws css::uno::RuntimeException + css::uno::Reference< css::reflection::XIdlClass > forType( typelib_TypeDescription * pTypeDescr ); + /// @throws css::uno::RuntimeException + css::uno::Reference< css::reflection::XIdlClass > forType( typelib_TypeDescriptionReference * pRef ); +}; + + +class IdlClassImpl + : public ::cppu::WeakImplHelper< css::reflection::XIdlClass > +{ + rtl::Reference<IdlReflectionServiceImpl> + m_xReflection; + + OUString _aName; + css::uno::TypeClass _eTypeClass; + + typelib_TypeDescription * _pTypeDescr; + +public: + typelib_TypeDescription * getTypeDescr() const + { return _pTypeDescr; } + IdlReflectionServiceImpl * getReflection() const + { return m_xReflection.get(); } + + // Ctor + IdlClassImpl( IdlReflectionServiceImpl * pReflection, + const OUString & rName, typelib_TypeClass eTypeClass, + typelib_TypeDescription * pTypeDescr ); + virtual ~IdlClassImpl() override; + + // XIdlClassImpl default implementation + virtual css::uno::TypeClass SAL_CALL getTypeClass() override; + virtual OUString SAL_CALL getName() override; + virtual sal_Bool SAL_CALL equals( const css::uno::Reference< css::reflection::XIdlClass >& xType ) override; + + virtual sal_Bool SAL_CALL isAssignableFrom( const css::uno::Reference< css::reflection::XIdlClass > & xType ) override; + virtual void SAL_CALL createObject( css::uno::Any & rObj ) override; + + // def impl ???? + virtual css::uno::Sequence< css::uno::Reference< css::reflection::XIdlClass > > SAL_CALL getClasses() override; + virtual css::uno::Reference< css::reflection::XIdlClass > SAL_CALL getClass( const OUString & rName ) override; + virtual css::uno::Sequence< css::uno::Reference< css::reflection::XIdlClass > > SAL_CALL getInterfaces() override; + + // structs, interfaces + virtual css::uno::Sequence< css::uno::Reference< css::reflection::XIdlClass > > SAL_CALL getSuperclasses() override; + // structs + virtual css::uno::Reference< css::reflection::XIdlField > SAL_CALL getField( const OUString & rName ) override; + virtual css::uno::Sequence< css::uno::Reference< css::reflection::XIdlField > > SAL_CALL getFields() override; + // interfaces + virtual css::uno::Uik SAL_CALL getUik() override; + virtual css::uno::Reference< css::reflection::XIdlMethod > SAL_CALL getMethod( const OUString & rName ) override; + virtual css::uno::Sequence< css::uno::Reference< css::reflection::XIdlMethod > > SAL_CALL getMethods() override; + // array + virtual css::uno::Reference< css::reflection::XIdlClass > SAL_CALL getComponentType() override; + virtual css::uno::Reference< css::reflection::XIdlArray > SAL_CALL getArray() override; +}; + + +class InterfaceIdlClassImpl + : public IdlClassImpl +{ + typedef std::pair< OUString, typelib_TypeDescription * > MemberInit; + + css::uno::Sequence< css::uno::Reference< css::reflection::XIdlClass > > _xSuperClasses; + + std::unique_ptr<MemberInit[]> _pSortedMemberInit; // first methods, then attributes + OUString2Field _aName2Field; + OUString2Method _aName2Method; + sal_Int32 _nMethods; + sal_Int32 _nAttributes; + + void initMembers(); + +public: + typelib_InterfaceTypeDescription * getTypeDescr() const + { return reinterpret_cast<typelib_InterfaceTypeDescription *>(IdlClassImpl::getTypeDescr()); } + + // ctor/ dtor + InterfaceIdlClassImpl( IdlReflectionServiceImpl * pReflection, + const OUString & rName, typelib_TypeClass eTypeClass, + typelib_TypeDescription * pTypeDescr ) + : IdlClassImpl( pReflection, rName, eTypeClass, pTypeDescr ) + , _nMethods( 0 ) + , _nAttributes( 0 ) + {} + virtual ~InterfaceIdlClassImpl() override; + + // IdlClassImpl modifications + virtual sal_Bool SAL_CALL isAssignableFrom( const css::uno::Reference< css::reflection::XIdlClass > & xType ) override; + virtual css::uno::Sequence< css::uno::Reference< css::reflection::XIdlClass > > SAL_CALL getSuperclasses() override; + virtual css::uno::Uik SAL_CALL getUik() override; + virtual css::uno::Reference< css::reflection::XIdlMethod > SAL_CALL getMethod( const OUString & rName ) override; + virtual css::uno::Sequence< css::uno::Reference< css::reflection::XIdlMethod > > SAL_CALL getMethods() override; + virtual css::uno::Reference< css::reflection::XIdlField > SAL_CALL getField( const OUString & rName ) override; + virtual css::uno::Sequence< css::uno::Reference< css::reflection::XIdlField > > SAL_CALL getFields() override; + virtual void SAL_CALL createObject( css::uno::Any & rObj ) override; +}; + + +class CompoundIdlClassImpl + : public IdlClassImpl +{ + css::uno::Reference< css::reflection::XIdlClass > + _xSuperClass; + std::optional< css::uno::Sequence< css::uno::Reference< css::reflection::XIdlField > > > + m_xFields; + OUString2Field _aName2Field; + +public: + typelib_CompoundTypeDescription * getTypeDescr() const + { return reinterpret_cast<typelib_CompoundTypeDescription *>(IdlClassImpl::getTypeDescr()); } + + // ctor/ dtor + CompoundIdlClassImpl( IdlReflectionServiceImpl * pReflection, + const OUString & rName, typelib_TypeClass eTypeClass, + typelib_TypeDescription * pTypeDescr ) + : IdlClassImpl( pReflection, rName, eTypeClass, pTypeDescr ) + {} + virtual ~CompoundIdlClassImpl() override; + + // IdlClassImpl modifications + virtual sal_Bool SAL_CALL isAssignableFrom( const css::uno::Reference< css::reflection::XIdlClass > & xType ) override; + virtual css::uno::Sequence< css::uno::Reference< css::reflection::XIdlClass > > SAL_CALL getSuperclasses() override; + virtual css::uno::Reference< css::reflection::XIdlField > SAL_CALL getField( const OUString & rName ) override; + virtual css::uno::Sequence< css::uno::Reference< css::reflection::XIdlField > > SAL_CALL getFields() override; +}; + + +class ArrayIdlClassImpl + : public IdlClassImpl + , public css::reflection::XIdlArray +{ +public: + typelib_IndirectTypeDescription * getTypeDescr() const + { return reinterpret_cast<typelib_IndirectTypeDescription *>(IdlClassImpl::getTypeDescr()); } + + // ctor + ArrayIdlClassImpl( IdlReflectionServiceImpl * pReflection, + const OUString & rName, typelib_TypeClass eTypeClass, + typelib_TypeDescription * pTypeDescr ) + : IdlClassImpl( pReflection, rName, eTypeClass, pTypeDescr ) + {} + + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override; + virtual void SAL_CALL acquire() noexcept override; + virtual void SAL_CALL release() noexcept override; + + // XTypeProvider + virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override; + + // IdlClassImpl modifications + virtual sal_Bool SAL_CALL isAssignableFrom( const css::uno::Reference< css::reflection::XIdlClass > & xType ) override; + virtual css::uno::Reference< css::reflection::XIdlClass > SAL_CALL getComponentType() override; + virtual css::uno::Reference< css::reflection::XIdlArray > SAL_CALL getArray() override; + + // XIdlArray + virtual void SAL_CALL realloc( css::uno::Any & rArray, sal_Int32 nLen ) override; + virtual sal_Int32 SAL_CALL getLen( const css::uno::Any & rArray ) override; + virtual css::uno::Any SAL_CALL get( const css::uno::Any & rArray, sal_Int32 nIndex ) override; + virtual void SAL_CALL set( css::uno::Any & rArray, sal_Int32 nIndex, const css::uno::Any & rNewValue ) override; +}; + + +class EnumIdlClassImpl + : public IdlClassImpl +{ + std::optional< css::uno::Sequence< css::uno::Reference< css::reflection::XIdlField > > > m_xFields; + OUString2Field _aName2Field; + +public: + typelib_EnumTypeDescription * getTypeDescr() const + { return reinterpret_cast<typelib_EnumTypeDescription *>(IdlClassImpl::getTypeDescr()); } + + // ctor/ dtor + EnumIdlClassImpl( IdlReflectionServiceImpl * pReflection, + const OUString & rName, typelib_TypeClass eTypeClass, + typelib_TypeDescription * pTypeDescr ) + : IdlClassImpl( pReflection, rName, eTypeClass, pTypeDescr ) + {} + virtual ~EnumIdlClassImpl() override; + + // IdlClassImpl modifications + virtual css::uno::Reference< css::reflection::XIdlField > SAL_CALL getField( const OUString & rName ) override; + virtual css::uno::Sequence< css::uno::Reference< css::reflection::XIdlField > > SAL_CALL getFields() override; + virtual void SAL_CALL createObject( css::uno::Any & rObj ) override; +}; + + +class IdlMemberImpl + : public ::cppu::WeakImplHelper< css::reflection::XIdlMember > +{ + rtl::Reference<IdlReflectionServiceImpl> + m_xReflection; + OUString _aName; + + typelib_TypeDescription * _pTypeDescr; + typelib_TypeDescription * _pDeclTypeDescr; + +protected: + css::uno::Reference< css::reflection::XIdlClass > _xDeclClass; + +public: + IdlReflectionServiceImpl * getReflection() const + { return m_xReflection.get(); } + typelib_TypeDescription * getTypeDescr() const + { return _pTypeDescr; } + typelib_TypeDescription * getDeclTypeDescr() const + { return _pDeclTypeDescr; } + + // ctor/ dtor + IdlMemberImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr ); + virtual ~IdlMemberImpl() override; + + // XIdlMember + virtual css::uno::Reference< css::reflection::XIdlClass > SAL_CALL getDeclaringClass() override; + virtual OUString SAL_CALL getName() override; +}; + + +// coerces to type descr pTo else queries for it: the interface pointer is returned via rDest +// ## type to XidlClass coercion possible +inline bool extract( + const css::uno::Any & rObj, typelib_InterfaceTypeDescription * pTo, + css::uno::Reference< css::uno::XInterface > & rDest, + IdlReflectionServiceImpl * pRefl ) +{ + rDest.clear(); + if (nullptr != pTo) + { + if (! rObj.hasValue()) + return true; + if (rObj.getValueTypeClass() == css::uno::TypeClass_INTERFACE) + { + return ::uno_type_assignData( + &rDest, pTo->aBase.pWeakRef, + const_cast< void * >( rObj.getValue() ), rObj.getValueTypeRef(), + reinterpret_cast< uno_QueryInterfaceFunc >(css::uno::cpp_queryInterface), + reinterpret_cast< uno_AcquireFunc >(css::uno::cpp_acquire), + reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release) ); + } + else if (auto t = o3tl::tryAccess<css::uno::Type>(rObj)) + { + rDest = pRefl->forType( t->getTypeLibType() ); + return rDest.is(); + } + } + return false; +} + +inline bool coerce_assign( + void * pDest, typelib_TypeDescription * pTD, const css::uno::Any & rSource, + IdlReflectionServiceImpl * pRefl ) +{ + if (pTD->eTypeClass == typelib_TypeClass_INTERFACE) + { + css::uno::Reference< css::uno::XInterface > xVal; + if (extract( rSource, reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD), xVal, pRefl )) + { + if (*static_cast<css::uno::XInterface **>(pDest)) + (*static_cast<css::uno::XInterface **>(pDest))->release(); + *static_cast<css::uno::XInterface **>(pDest) = xVal.get(); + if (*static_cast<css::uno::XInterface **>(pDest)) + (*static_cast<css::uno::XInterface **>(pDest))->acquire(); + return true; + } + return false; + } + else if (pTD->eTypeClass == typelib_TypeClass_ANY) + { + return uno_assignData( + pDest, pTD, + const_cast<css::uno::Any *>(&rSource), pTD, + reinterpret_cast< uno_QueryInterfaceFunc >(css::uno::cpp_queryInterface), + reinterpret_cast< uno_AcquireFunc >(css::uno::cpp_acquire), + reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release) ); + } + else + { + return uno_type_assignData( + pDest, pTD->pWeakRef, + const_cast<void *>(rSource.getValue()), rSource.getValueTypeRef(), + reinterpret_cast< uno_QueryInterfaceFunc >(css::uno::cpp_queryInterface), + reinterpret_cast< uno_AcquireFunc >(css::uno::cpp_acquire), + reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release) ); + } +} + +} + + +#endif // INCLUDED_STOC_SOURCE_COREREFLECTION_BASE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/stoc/source/corereflection/crarray.cxx b/stoc/source/corereflection/crarray.cxx new file mode 100644 index 000000000..8a402c489 --- /dev/null +++ b/stoc/source/corereflection/crarray.cxx @@ -0,0 +1,200 @@ +/* -*- 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 . + */ + +#include <typelib/typedescription.h> +#include <uno/data.h> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/typeprovider.hxx> + +#include "base.hxx" + +using namespace css::lang; +using namespace css::reflection; +using namespace css::uno; + +namespace stoc_corefl +{ + +// XInterface + +Any ArrayIdlClassImpl::queryInterface( const Type & rType ) +{ + Any aRet( ::cppu::queryInterface( rType, static_cast< XIdlArray * >( this ) ) ); + return (aRet.hasValue() ? aRet : IdlClassImpl::queryInterface( rType )); +} + +void ArrayIdlClassImpl::acquire() noexcept +{ + IdlClassImpl::acquire(); +} + +void ArrayIdlClassImpl::release() noexcept +{ + IdlClassImpl::release(); +} + +// XTypeProvider + +Sequence< Type > ArrayIdlClassImpl::getTypes() +{ + static cppu::OTypeCollection s_aTypes( + cppu::UnoType<XIdlArray>::get(), + IdlClassImpl::getTypes() ); + + return s_aTypes.getTypes(); +} + +Sequence< sal_Int8 > ArrayIdlClassImpl::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// XIdlArray + +void ArrayIdlClassImpl::realloc( Any & rArray, sal_Int32 nLen ) +{ + TypeClass eTC = rArray.getValueTypeClass(); + if (eTC != TypeClass_SEQUENCE) + { + throw IllegalArgumentException( + "expected sequence, but found " + rArray.getValueType().getTypeName(), + static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 ); + } + if (nLen < 0) + { + throw IllegalArgumentException( + "negative length given!", + static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 1 ); + } + + uno_Sequence ** ppSeq = const_cast<uno_Sequence **>(static_cast<uno_Sequence * const *>(rArray.getValue())); + uno_sequence_realloc( ppSeq, &getTypeDescr()->aBase, + nLen, + reinterpret_cast< uno_AcquireFunc >(cpp_acquire), + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + rArray.pData = ppSeq; +} + +sal_Int32 ArrayIdlClassImpl::getLen( const Any & rArray ) +{ + TypeClass eTC = rArray.getValueTypeClass(); + if (eTC != TypeClass_SEQUENCE) + { + throw IllegalArgumentException( + "expected sequence, but found " + rArray.getValueType().getTypeName(), + static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 ); + } + + return (*static_cast<uno_Sequence * const *>(rArray.getValue()))->nElements; +} + +Any ArrayIdlClassImpl::get( const Any & rArray, sal_Int32 nIndex ) +{ + TypeClass eTC = rArray.getValueTypeClass(); + if (eTC != TypeClass_SEQUENCE) + { + throw IllegalArgumentException( + "expected sequence, but found " + rArray.getValueType().getTypeName(), + static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 ); + } + + uno_Sequence * pSeq = *static_cast<uno_Sequence * const *>(rArray.getValue()); + if (pSeq->nElements <= nIndex) + { + throw ArrayIndexOutOfBoundsException( + "illegal index given, index " + OUString::number(nIndex) + " is < " + OUString::number(pSeq->nElements), + static_cast<XWeak *>(static_cast<OWeakObject *>(this)) ); + } + + Any aRet; + typelib_TypeDescription * pElemTypeDescr = nullptr; + TYPELIB_DANGER_GET( &pElemTypeDescr, getTypeDescr()->pType ); + uno_any_destruct( &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_any_construct( &aRet, &pSeq->elements[nIndex * pElemTypeDescr->nSize], + pElemTypeDescr, + reinterpret_cast< uno_AcquireFunc >(cpp_acquire) ); + TYPELIB_DANGER_RELEASE( pElemTypeDescr ); + return aRet; +} + + +void ArrayIdlClassImpl::set( Any & rArray, sal_Int32 nIndex, const Any & rNewValue ) +{ + TypeClass eTC = rArray.getValueTypeClass(); + if (eTC != TypeClass_SEQUENCE) + { + throw IllegalArgumentException( + "expected sequence, but found " + rArray.getValueType().getTypeName(), + static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 ); + } + + uno_Sequence * pSeq = *static_cast<uno_Sequence * const *>(rArray.getValue()); + if (pSeq->nElements <= nIndex) + { + throw ArrayIndexOutOfBoundsException( + "illegal index given, index " + OUString::number(nIndex) + " is < " + OUString::number(pSeq->nElements), + static_cast<XWeak *>(static_cast<OWeakObject *>(this)) ); + } + + uno_Sequence ** ppSeq = const_cast<uno_Sequence **>(static_cast<uno_Sequence * const *>(rArray.getValue())); + uno_sequence_reference2One( + ppSeq, &getTypeDescr()->aBase, + reinterpret_cast< uno_AcquireFunc >(cpp_acquire), + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + rArray.pData = ppSeq; + pSeq = *ppSeq; + + typelib_TypeDescription * pElemTypeDescr = nullptr; + TYPELIB_DANGER_GET( &pElemTypeDescr, getTypeDescr()->pType ); + + if (! coerce_assign( &pSeq->elements[nIndex * pElemTypeDescr->nSize], + pElemTypeDescr, rNewValue, getReflection() )) + { + TYPELIB_DANGER_RELEASE( pElemTypeDescr ); + throw IllegalArgumentException( + "sequence element is not assignable by given value!", + static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 2 ); + } + TYPELIB_DANGER_RELEASE( pElemTypeDescr ); +} + +// ArrayIdlClassImpl + +sal_Bool ArrayIdlClassImpl::isAssignableFrom( const Reference< XIdlClass > & xType ) +{ + return (xType.is() && + (equals( xType ) || + (xType->getTypeClass() == getTypeClass() && // must be sequence|array + getComponentType()->isAssignableFrom( xType->getComponentType() )))); +} + +Reference< XIdlClass > ArrayIdlClassImpl::getComponentType() +{ + return getReflection()->forType( getTypeDescr()->pType ); +} + +Reference< XIdlArray > ArrayIdlClassImpl::getArray() +{ + return this; +} + +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/stoc/source/corereflection/crbase.cxx b/stoc/source/corereflection/crbase.cxx new file mode 100644 index 000000000..75e802c96 --- /dev/null +++ b/stoc/source/corereflection/crbase.cxx @@ -0,0 +1,248 @@ +/* -*- 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 . + */ + +#include <uno/any2.h> + +#include "base.hxx" + +using namespace css::reflection; +using namespace css::uno; + +namespace stoc_corefl +{ + +#ifdef TEST_LIST_CLASSES +ClassNameVector g_aClassNames; +#endif + + +::osl::Mutex & getMutexAccess() +{ + static osl::Mutex s_aMutex; + + return s_aMutex; +} + + +IdlClassImpl::IdlClassImpl( IdlReflectionServiceImpl * pReflection, + const OUString & rName, typelib_TypeClass eTypeClass, + typelib_TypeDescription * pTypeDescr ) + : m_xReflection( pReflection ) + , _aName( rName ) + , _eTypeClass( static_cast<TypeClass>(eTypeClass) ) + , _pTypeDescr( pTypeDescr ) +{ + if (_pTypeDescr) + { + typelib_typedescription_acquire( _pTypeDescr ); + if (! _pTypeDescr->bComplete) + typelib_typedescription_complete( &_pTypeDescr ); + } + +#ifdef TEST_LIST_CLASSES + ClassNameVector::const_iterator iFind( std::find( g_aClassNames.begin(), g_aClassNames.end(), _aName ) ); + OSL_ENSURE( iFind == g_aClassNames.end(), "### idl class already exists!" ); + g_aClassNames.insert(g_aClassNames.begin(), _aName); +#endif +} + +IdlClassImpl::~IdlClassImpl() +{ + if (_pTypeDescr) + typelib_typedescription_release( _pTypeDescr ); + m_xReflection.clear(); + +#ifdef TEST_LIST_CLASSES + ClassNameVector::iterator iFind( std::find( g_aClassNames.begin(), g_aClassNames.end(), _aName ) ); + OSL_ENSURE( iFind != g_aClassNames.end(), "### idl class does not exist!" ); + g_aClassNames.erase( iFind ); +#endif +} + +// XIdlClassImpl default implementation + +TypeClass IdlClassImpl::getTypeClass() +{ + return _eTypeClass; +} + +OUString IdlClassImpl::getName() +{ + return _aName; +} + +sal_Bool IdlClassImpl::equals( const Reference< XIdlClass >& xType ) +{ + return (xType.is() && + (xType->getTypeClass() == _eTypeClass) && (xType->getName() == _aName)); +} + +const bool s_aAssignableFromTab[11][11] = +{ + /* from CH, BO, BY, SH, US, LO, UL, HY, UH, FL, DO */ +/* TypeClass_CHAR */ { true, false, false, false, false, false, false, false, false, false, false }, +/* TypeClass_BOOLEAN */ { false, true, false, false, false, false, false, false, false, false, false }, +/* TypeClass_BYTE */ { false, false, true, false, false, false, false, false, false, false, false }, +/* TypeClass_SHORT */ { false, false, true, true, true, false, false, false, false, false, false }, +/* TypeClass_UNSIGNED_SHORT */ { false, false, true, true, true, false, false, false, false, false, false }, +/* TypeClass_LONG */ { false, false, true, true, true, true, true, false, false, false, false }, +/* TypeClass_UNSIGNED_LONG */ { false, false, true, true, true, true, true, false, false, false, false }, +/* TypeClass_HYPER */ { false, false, true, true, true, true, true, true, true, false, false }, +/* TypeClass_UNSIGNED_HYPER */ { false, false, true, true, true, true, true, true, true, false, false }, +/* TypeClass_FLOAT */ { false, false, true, true, true, true, true, true, true, true, false }, +/* TypeClass_DOUBLE */ { false, false, true, true, true, true, true, true, true, true, true } +}; + +sal_Bool IdlClassImpl::isAssignableFrom( const Reference< XIdlClass > & xType ) +{ + TypeClass eAssign = getTypeClass(); + if (equals( xType ) || eAssign == TypeClass_ANY) // default shot + { + return true; + } + else + { + TypeClass eFrom = xType->getTypeClass(); + if (eAssign > TypeClass_VOID && eAssign < TypeClass_STRING && + eFrom > TypeClass_VOID && eFrom < TypeClass_STRING) + { + return s_aAssignableFromTab[static_cast<int>(eAssign)-1][static_cast<int>(eFrom)-1]; + } + } + return false; +} + +void IdlClassImpl::createObject( Any & rObj ) +{ + rObj.clear(); + uno_any_destruct( &rObj, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_any_construct( &rObj, nullptr, getTypeDescr(), nullptr ); +} + +// what TODO ???? + +Sequence< Reference< XIdlClass > > IdlClassImpl::getClasses() +{ + OSL_FAIL( "### unexpected use!" ); + return Sequence< Reference< XIdlClass > >(); +} + +Reference< XIdlClass > IdlClassImpl::getClass( const OUString & ) +{ + OSL_FAIL( "### unexpected use!" ); + return Reference< XIdlClass >(); +} + +Sequence< Reference< XIdlClass > > IdlClassImpl::getInterfaces() +{ +// OSL_FAIL( "### unexpected use!" ); + return Sequence< Reference< XIdlClass > >(); +} + +// structs, interfaces + +Sequence< Reference< XIdlClass > > IdlClassImpl::getSuperclasses() +{ + return Sequence< Reference< XIdlClass > >(); +} +// structs + +Reference< XIdlField > IdlClassImpl::getField( const OUString & ) +{ + return Reference< XIdlField >(); +} + +Sequence< Reference< XIdlField > > IdlClassImpl::getFields() +{ + return Sequence< Reference< XIdlField > >(); +} +// interfaces + +Uik IdlClassImpl::getUik() +{ + return Uik(); +} + +Reference< XIdlMethod > IdlClassImpl::getMethod( const OUString & ) +{ + return Reference< XIdlMethod >(); +} + +Sequence< Reference< XIdlMethod > > IdlClassImpl::getMethods() +{ + return Sequence< Reference< XIdlMethod > >(); +} +// array + +Reference< XIdlClass > IdlClassImpl::getComponentType() +{ + return Reference< XIdlClass >(); +} + +Reference< XIdlArray > IdlClassImpl::getArray() +{ + return Reference< XIdlArray >(); +} + + +IdlMemberImpl::IdlMemberImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, + typelib_TypeDescription * pDeclTypeDescr ) + : m_xReflection( pReflection ) + , _aName( rName ) + , _pTypeDescr( pTypeDescr ) + , _pDeclTypeDescr( pDeclTypeDescr ) +{ + typelib_typedescription_acquire( _pTypeDescr ); + if (! _pTypeDescr->bComplete) + typelib_typedescription_complete( &_pTypeDescr ); + typelib_typedescription_acquire( _pDeclTypeDescr ); + if (! _pDeclTypeDescr->bComplete) + typelib_typedescription_complete( &_pDeclTypeDescr ); +} + +IdlMemberImpl::~IdlMemberImpl() +{ + typelib_typedescription_release( _pDeclTypeDescr ); + typelib_typedescription_release( _pTypeDescr ); +} + +// XIdlMember + +Reference< XIdlClass > IdlMemberImpl::getDeclaringClass() +{ + if (! _xDeclClass.is()) + { + Reference< XIdlClass > xDeclClass( getReflection()->forType( getDeclTypeDescr() ) ); + ::osl::MutexGuard aGuard( getMutexAccess() ); + if (! _xDeclClass.is()) + _xDeclClass = xDeclClass; + } + return _xDeclClass; +} + +OUString IdlMemberImpl::getName() +{ + return _aName; +} + +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/stoc/source/corereflection/crcomp.cxx b/stoc/source/corereflection/crcomp.cxx new file mode 100644 index 000000000..51cf4a6f0 --- /dev/null +++ b/stoc/source/corereflection/crcomp.cxx @@ -0,0 +1,358 @@ +/* -*- 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 . + */ + +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/typeprovider.hxx> + +#include <com/sun/star/reflection/XIdlField.hpp> +#include <com/sun/star/reflection/XIdlField2.hpp> +#include <com/sun/star/uno/TypeClass.hpp> + +#include "base.hxx" + +using namespace css::lang; +using namespace css::reflection; +using namespace css::uno; + +namespace stoc_corefl +{ + +namespace { + +class IdlCompFieldImpl + : public IdlMemberImpl + , public XIdlField + , public XIdlField2 +{ + sal_Int32 _nOffset; + +public: + IdlCompFieldImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr, + sal_Int32 nOffset ) + : IdlMemberImpl( pReflection, rName, pTypeDescr, pDeclTypeDescr ) + , _nOffset( nOffset ) + {} + + // XInterface + virtual Any SAL_CALL queryInterface( const Type & rType ) override; + virtual void SAL_CALL acquire() noexcept override; + virtual void SAL_CALL release() noexcept override; + + // XTypeProvider + virtual Sequence< Type > SAL_CALL getTypes() override; + virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override; + + // XIdlMember + virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() override; + virtual OUString SAL_CALL getName() override; + // XIdlField + virtual Reference< XIdlClass > SAL_CALL getType() override; + virtual FieldAccessMode SAL_CALL getAccessMode() override; + virtual Any SAL_CALL get( const Any & rObj ) override; + virtual void SAL_CALL set( const Any & rObj, const Any & rValue ) override; + // XIdlField2: getType, getAccessMode and get are equal to XIdlField + virtual void SAL_CALL set( Any & rObj, const Any & rValue ) override; +}; + +} + +// XInterface + +Any IdlCompFieldImpl::queryInterface( const Type & rType ) +{ + Any aRet( ::cppu::queryInterface( rType, + static_cast< XIdlField * >( this ), + static_cast< XIdlField2 * >( this ) ) ); + return (aRet.hasValue() ? aRet : IdlMemberImpl::queryInterface( rType )); +} + +void IdlCompFieldImpl::acquire() noexcept +{ + IdlMemberImpl::acquire(); +} + +void IdlCompFieldImpl::release() noexcept +{ + IdlMemberImpl::release(); +} + +// XTypeProvider + +Sequence< Type > IdlCompFieldImpl::getTypes() +{ + static cppu::OTypeCollection s_aTypes( + cppu::UnoType<XIdlField2>::get(), + cppu::UnoType<XIdlField>::get(), + IdlMemberImpl::getTypes() ); + + return s_aTypes.getTypes(); +} + +Sequence< sal_Int8 > IdlCompFieldImpl::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// XIdlMember + +Reference< XIdlClass > IdlCompFieldImpl::getDeclaringClass() +{ + if (! _xDeclClass.is()) + { + ::osl::MutexGuard aGuard( getMutexAccess() ); + if (! _xDeclClass.is()) + { + typelib_CompoundTypeDescription * pTD = + reinterpret_cast<typelib_CompoundTypeDescription *>(getDeclTypeDescr()); + while (pTD) + { + typelib_TypeDescriptionReference ** ppTypeRefs = pTD->ppTypeRefs; + for ( sal_Int32 nPos = pTD->nMembers; nPos--; ) + { + if (td_equals( getTypeDescr(), ppTypeRefs[nPos] )) + { + _xDeclClass = getReflection()->forType( &pTD->aBase ); + return _xDeclClass; + } + } + pTD = pTD->pBaseTypeDescription; + } + } + } + return _xDeclClass; +} + +OUString IdlCompFieldImpl::getName() +{ + return IdlMemberImpl::getName(); +} + +// XIdlField + +Reference< XIdlClass > IdlCompFieldImpl::getType() +{ + return getReflection()->forType( getTypeDescr() ); +} + +FieldAccessMode IdlCompFieldImpl::getAccessMode() +{ + return FieldAccessMode_READWRITE; +} + +Any IdlCompFieldImpl::get( const Any & rObj ) +{ + if (rObj.getValueTypeClass() == css::uno::TypeClass_STRUCT || + rObj.getValueTypeClass() == css::uno::TypeClass_EXCEPTION) + { + typelib_TypeDescription * pObjTD = nullptr; + TYPELIB_DANGER_GET( &pObjTD, rObj.getValueTypeRef() ); + + typelib_TypeDescription * pTD = pObjTD; + typelib_TypeDescription * pDeclTD = getDeclTypeDescr(); + while (pTD && !typelib_typedescription_equals( pTD, pDeclTD )) + pTD = &reinterpret_cast<typelib_CompoundTypeDescription *>(pTD)->pBaseTypeDescription->aBase; + + OSL_ENSURE( pTD, "### illegal object type!" ); + if (pTD) + { + TYPELIB_DANGER_RELEASE( pObjTD ); + Any aRet; + uno_any_destruct( + &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_any_construct( + &aRet, const_cast<char *>(static_cast<char const *>(rObj.getValue()) + _nOffset), getTypeDescr(), + reinterpret_cast< uno_AcquireFunc >(cpp_acquire) ); + return aRet; + } + TYPELIB_DANGER_RELEASE( pObjTD ); + } + throw IllegalArgumentException( + "expected struct or exception, got " + rObj.getValueType().getTypeName(), + static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 ); +} + +void IdlCompFieldImpl::set( const Any & rObj, const Any & rValue ) +{ + if (rObj.getValueTypeClass() == css::uno::TypeClass_STRUCT || + rObj.getValueTypeClass() == css::uno::TypeClass_EXCEPTION) + { + typelib_TypeDescription * pObjTD = nullptr; + TYPELIB_DANGER_GET( &pObjTD, rObj.getValueTypeRef() ); + + typelib_TypeDescription * pTD = pObjTD; + typelib_TypeDescription * pDeclTD = getDeclTypeDescr(); + while (pTD && !typelib_typedescription_equals( pTD, pDeclTD )) + pTD = &reinterpret_cast<typelib_CompoundTypeDescription *>(pTD)->pBaseTypeDescription->aBase; + + OSL_ENSURE( pTD, "### illegal object type!" ); + if (pTD) + { + TYPELIB_DANGER_RELEASE( pObjTD ); + if (!coerce_assign( const_cast<char *>(static_cast<char const *>(rObj.getValue()) + _nOffset), getTypeDescr(), rValue, getReflection() )) + { + throw IllegalArgumentException( + "cannot assign value to destination", + static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 1 ); + } + return; + } + TYPELIB_DANGER_RELEASE( pObjTD ); + } + throw IllegalArgumentException( + "expected struct or exception, got " + rObj.getValueType().getTypeName(), + static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 ); +} + + +void IdlCompFieldImpl::set( Any & rObj, const Any & rValue ) +{ + if (rObj.getValueTypeClass() == css::uno::TypeClass_STRUCT || + rObj.getValueTypeClass() == css::uno::TypeClass_EXCEPTION) + { + typelib_TypeDescription * pObjTD = nullptr; + TYPELIB_DANGER_GET( &pObjTD, rObj.getValueTypeRef() ); + + typelib_TypeDescription * pTD = pObjTD; + typelib_TypeDescription * pDeclTD = getDeclTypeDescr(); + while (pTD && !typelib_typedescription_equals( pTD, pDeclTD )) + pTD = &reinterpret_cast<typelib_CompoundTypeDescription *>(pTD)->pBaseTypeDescription->aBase; + + OSL_ENSURE( pTD, "### illegal object type!" ); + if (pTD) + { + TYPELIB_DANGER_RELEASE( pObjTD ); + if (!coerce_assign( const_cast<char *>(static_cast<char const *>(rObj.getValue()) + _nOffset), getTypeDescr(), rValue, getReflection() )) + { + throw IllegalArgumentException( + "cannot assign to destination", + static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 1 ); + } + return; + } + TYPELIB_DANGER_RELEASE( pObjTD ); + } + throw IllegalArgumentException( + "expected struct or exception, got " + rObj.getValueType().getTypeName(), + static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 ); +} + + +CompoundIdlClassImpl::~CompoundIdlClassImpl() +{ +} + + +sal_Bool CompoundIdlClassImpl::isAssignableFrom( const Reference< XIdlClass > & xType ) +{ + if (xType.is()) + { + TypeClass eTC = xType->getTypeClass(); + if (eTC == TypeClass_STRUCT || eTC == TypeClass_EXCEPTION) + { + if (equals( xType )) + return true; + else + { + const Sequence< Reference< XIdlClass > > & rSeq = xType->getSuperclasses(); + if (rSeq.hasElements()) + { + OSL_ENSURE( rSeq.getLength() == 1, "### unexpected len of super classes!" ); + return isAssignableFrom( rSeq[0] ); + } + } + } + } + return false; +} + +Sequence< Reference< XIdlClass > > CompoundIdlClassImpl::getSuperclasses() +{ + if (! _xSuperClass.is()) + { + ::osl::MutexGuard aGuard( getMutexAccess() ); + if (! _xSuperClass.is()) + { + typelib_CompoundTypeDescription * pCompTypeDescr = getTypeDescr()->pBaseTypeDescription; + if (pCompTypeDescr) + _xSuperClass = getReflection()->forType( &pCompTypeDescr->aBase ); + } + } + if (_xSuperClass.is()) + return Sequence< Reference< XIdlClass > >( &_xSuperClass, 1 ); + else + return Sequence< Reference< XIdlClass > >(); +} + +Reference< XIdlField > CompoundIdlClassImpl::getField( const OUString & rName ) +{ + if (! m_xFields) + getFields(); // init fields + + const OUString2Field::const_iterator iFind( _aName2Field.find( rName ) ); + if (iFind != _aName2Field.end()) + return Reference< XIdlField >( (*iFind).second ); + else + return Reference< XIdlField >(); +} + +Sequence< Reference< XIdlField > > CompoundIdlClassImpl::getFields() +{ + ::osl::MutexGuard aGuard( getMutexAccess() ); + if (! m_xFields) + { + sal_Int32 nAll = 0; + typelib_CompoundTypeDescription * pCompTypeDescr = getTypeDescr(); + for ( ; pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + nAll += pCompTypeDescr->nMembers; + + Sequence< Reference< XIdlField > > aFields( nAll ); + Reference< XIdlField > * pSeq = aFields.getArray(); + + for ( pCompTypeDescr = getTypeDescr(); pCompTypeDescr; + pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + { + typelib_TypeDescriptionReference ** ppTypeRefs = pCompTypeDescr->ppTypeRefs; + rtl_uString ** ppNames = pCompTypeDescr->ppMemberNames; + sal_Int32 * pMemberOffsets = pCompTypeDescr->pMemberOffsets; + + for ( sal_Int32 nPos = pCompTypeDescr->nMembers; nPos--; ) + { + typelib_TypeDescription * pTD = nullptr; + TYPELIB_DANGER_GET( &pTD, ppTypeRefs[nPos] ); + OSL_ENSURE( pTD, "### cannot get field in struct!" ); + if (pTD) + { + OUString aName( ppNames[nPos] ); + _aName2Field[aName] = pSeq[--nAll] = new IdlCompFieldImpl( + getReflection(), aName, pTD, IdlClassImpl::getTypeDescr(), pMemberOffsets[nPos] ); + TYPELIB_DANGER_RELEASE( pTD ); + } + } + } + + m_xFields = std::move( aFields ); + } + return *m_xFields; +} + +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/stoc/source/corereflection/crefl.cxx b/stoc/source/corereflection/crefl.cxx new file mode 100644 index 000000000..af1854e7e --- /dev/null +++ b/stoc/source/corereflection/crefl.cxx @@ -0,0 +1,379 @@ +/* -*- 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 . + */ + +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <sal/log.hxx> + +#include <com/sun/star/reflection/XConstantTypeDescription.hpp> +#include <com/sun/star/reflection/XTypeDescription.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <o3tl/any.hxx> +#include <uno/lbnames.h> + +using namespace css; +using namespace css::uno; +using namespace css::lang; +using namespace css::reflection; +using namespace cppu; +using namespace osl; + + +#include "base.hxx" + + +namespace stoc_corefl +{ + +IdlReflectionServiceImpl::IdlReflectionServiceImpl( + const Reference< XComponentContext > & xContext ) + : OComponentHelper( _aComponentMutex ) +{ + xContext->getValueByName( + "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) >>= _xTDMgr; + OSL_ENSURE( _xTDMgr.is(), "### cannot get singleton \"TypeDescriptionManager\" from context!" ); +} + +IdlReflectionServiceImpl::~IdlReflectionServiceImpl() {} + +// XInterface + +Any IdlReflectionServiceImpl::queryInterface( const Type & rType ) +{ + Any aRet( ::cppu::queryInterface( + rType, + static_cast< XIdlReflection * >( this ), + static_cast< XHierarchicalNameAccess * >( this ), + static_cast< XServiceInfo * >( this ) ) ); + + return (aRet.hasValue() ? aRet : OComponentHelper::queryInterface( rType )); +} + +void IdlReflectionServiceImpl::acquire() noexcept +{ + OComponentHelper::acquire(); +} + +void IdlReflectionServiceImpl::release() noexcept +{ + OComponentHelper::release(); +} + +// XTypeProvider + +Sequence< Type > IdlReflectionServiceImpl::getTypes() +{ + static OTypeCollection s_aTypes( + cppu::UnoType<XIdlReflection>::get(), + cppu::UnoType<XHierarchicalNameAccess>::get(), + cppu::UnoType<XServiceInfo>::get(), + OComponentHelper::getTypes() ); + + return s_aTypes.getTypes(); +} + +Sequence< sal_Int8 > IdlReflectionServiceImpl::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// XComponent + +void IdlReflectionServiceImpl::dispose() +{ + OComponentHelper::dispose(); + + MutexGuard aGuard( _aComponentMutex ); + _aElements.clear(); +#ifdef TEST_LIST_CLASSES + OSL_ENSURE( g_aClassNames.empty(), "### idl classes still alive!" ); + for (auto const& className : g_aClassNames) + { + OUString aName(className); + } +#endif +} + +// XServiceInfo + +OUString IdlReflectionServiceImpl::getImplementationName() +{ + return "com.sun.star.comp.stoc.CoreReflection"; +} + +sal_Bool IdlReflectionServiceImpl::supportsService( const OUString & rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +Sequence< OUString > IdlReflectionServiceImpl::getSupportedServiceNames() +{ + Sequence< OUString > seqNames { "com.sun.star.reflection.CoreReflection" }; + return seqNames; +} + +// XIdlReflection + +Reference< XIdlClass > IdlReflectionServiceImpl::getType( const Any & rObj ) +{ + return (rObj.hasValue() ? forType( rObj.getValueTypeRef() ) : Reference< XIdlClass >()); +} + + +inline Reference< XIdlClass > IdlReflectionServiceImpl::constructClass( + typelib_TypeDescription * pTypeDescr ) +{ + OSL_ENSURE( pTypeDescr->eTypeClass != typelib_TypeClass_TYPEDEF, "### unexpected typedef!" ); + + switch (pTypeDescr->eTypeClass) + { + case typelib_TypeClass_VOID: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_FLOAT: + case typelib_TypeClass_DOUBLE: + case typelib_TypeClass_STRING: + case typelib_TypeClass_ANY: + return new IdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr ); + + case typelib_TypeClass_ENUM: + return new EnumIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr ); + + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + return new CompoundIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr ); + + case typelib_TypeClass_SEQUENCE: + return new ArrayIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr ); + + case typelib_TypeClass_INTERFACE: + return new InterfaceIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr ); + + case typelib_TypeClass_TYPE: + return new IdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr ); + + default: + SAL_INFO("stoc", "corereflection type unsupported: " << pTypeDescr->pTypeName); + return Reference< XIdlClass >(); + } +} + +Reference< XIdlClass > IdlReflectionServiceImpl::forName( const OUString & rTypeName ) +{ + Reference< XIdlClass > xRet; + Any aAny( _aElements.getValue( rTypeName ) ); + + if (aAny.hasValue()) + { + aAny >>= xRet; + } + else + { + // try to get _type_ by name + typelib_TypeDescription * pTD = nullptr; + typelib_typedescription_getByName( &pTD, rTypeName.pData ); + if (pTD) + { + xRet = constructClass( pTD ); + if (xRet.is()) + _aElements.setValue( rTypeName, Any( xRet ) ); // update + typelib_typedescription_release( pTD ); + } + } + + return xRet; +} + +// XHierarchicalNameAccess + +Any IdlReflectionServiceImpl::getByHierarchicalName( const OUString & rName ) +{ + Any aRet( _aElements.getValue( rName ) ); + if (! aRet.hasValue()) + { + aRet = _xTDMgr->getByHierarchicalName( rName ); + if (aRet.getValueTypeClass() == TypeClass_INTERFACE) + { + // type retrieved from tdmgr + OSL_ASSERT( (*o3tl::forceAccess<Reference<XInterface>>(aRet))->queryInterface( + cppu::UnoType<XTypeDescription>::get()).hasValue() ); + + css::uno::Reference< css::reflection::XConstantTypeDescription > + ctd; + if (aRet >>= ctd) + { + aRet = ctd->getConstantValue(); + } + else + { + // if you are interested in a type then CALL forName()!!! + // this way is NOT recommended for types, because this method looks for constants first + + // if td manager found some type, it will be in the cache (hopefully... we just got it) + // so the second retrieving via c typelib callback chain should succeed... + + // try to get _type_ by name + typelib_TypeDescription * pTD = nullptr; + typelib_typedescription_getByName( &pTD, rName.pData ); + + aRet.clear(); // kick XTypeDescription interface + + if (pTD) + { + Reference< XIdlClass > xIdlClass( constructClass( pTD ) ); + aRet.setValue( &xIdlClass, cppu::UnoType<XIdlClass>::get()); + typelib_typedescription_release( pTD ); + } + } + } + // else is enum member(?) + + // update + if (!aRet.hasValue()) + throw container::NoSuchElementException( rName ); + + _aElements.setValue( rName, aRet ); + } + return aRet; +} + +sal_Bool IdlReflectionServiceImpl::hasByHierarchicalName( const OUString & rName ) +{ + try + { + return getByHierarchicalName( rName ).hasValue(); + } + catch (container::NoSuchElementException &) + { + } + return false; +} + + +Reference< XIdlClass > IdlReflectionServiceImpl::forType( typelib_TypeDescription * pTypeDescr ) +{ + Reference< XIdlClass > xRet; + OUString aName( pTypeDescr->pTypeName ); + Any aAny( _aElements.getValue( aName ) ); + + if (aAny.hasValue()) + { + aAny >>= xRet; + } + else + { + xRet = constructClass( pTypeDescr ); + if (xRet.is()) + _aElements.setValue( aName, Any( xRet ) ); // update + } + + return xRet; +} + +Reference< XIdlClass > IdlReflectionServiceImpl::forType( typelib_TypeDescriptionReference * pRef ) +{ + typelib_TypeDescription * pTD = nullptr; + TYPELIB_DANGER_GET( &pTD, pRef ); + if (pTD) + { + Reference< XIdlClass > xRet = forType( pTD ); + TYPELIB_DANGER_RELEASE( pTD ); + return xRet; + } + throw RuntimeException( + "IdlReflectionServiceImpl::forType() failed!", + static_cast<XWeak *>(static_cast<OWeakObject *>(this)) ); +} + + +const Mapping & IdlReflectionServiceImpl::getCpp2Uno() +{ + if (! _aCpp2Uno.is()) + { + MutexGuard aGuard( getMutexAccess() ); + if (! _aCpp2Uno.is()) + { + _aCpp2Uno = Mapping( CPPU_CURRENT_LANGUAGE_BINDING_NAME, UNO_LB_UNO ); + OSL_ENSURE( _aCpp2Uno.is(), "### cannot get c++ to uno mapping!" ); + if (! _aCpp2Uno.is()) + { + throw RuntimeException( + "cannot get c++ to uno mapping!", + static_cast<XWeak *>(static_cast<OWeakObject *>(this)) ); + } + } + } + return _aCpp2Uno; +} + +const Mapping & IdlReflectionServiceImpl::getUno2Cpp() +{ + if (! _aUno2Cpp.is()) + { + MutexGuard aGuard( getMutexAccess() ); + if (! _aUno2Cpp.is()) + { + _aUno2Cpp = Mapping( UNO_LB_UNO, CPPU_CURRENT_LANGUAGE_BINDING_NAME ); + OSL_ENSURE( _aUno2Cpp.is(), "### cannot get uno to c++ mapping!" ); + if (! _aUno2Cpp.is()) + { + throw RuntimeException( + "cannot get uno to c++ mapping!", + static_cast<XWeak *>(static_cast<OWeakObject *>(this)) ); + } + } + } + return _aUno2Cpp; +} + +uno_Interface * IdlReflectionServiceImpl::mapToUno( + const Any & rObj, typelib_InterfaceTypeDescription * pTo ) +{ + Reference< XInterface > xObj; + if (extract( rObj, pTo, xObj, this )) + return static_cast<uno_Interface *>(getCpp2Uno().mapInterface( xObj.get(), pTo )); + + throw RuntimeException( + "illegal object given!", + static_cast<XWeak *>(static_cast<OWeakObject *>(this)) ); +} + +} + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_stoc_CoreReflection_get_implementation( + css::uno::XComponentContext * context, + css::uno::Sequence<css::uno::Any> const & arguments) +{ + SAL_WARN_IF( + arguments.hasElements(), "stoc", "unexpected singleton arguments"); + return cppu::acquire(new stoc_corefl::IdlReflectionServiceImpl(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/stoc/source/corereflection/crenum.cxx b/stoc/source/corereflection/crenum.cxx new file mode 100644 index 000000000..dae3449d3 --- /dev/null +++ b/stoc/source/corereflection/crenum.cxx @@ -0,0 +1,206 @@ +/* -*- 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 . + */ + +#include "base.hxx" + +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/typeprovider.hxx> + +#include <com/sun/star/reflection/XIdlField2.hpp> + +using namespace css::lang; +using namespace css::reflection; +using namespace css::uno; + +namespace stoc_corefl +{ + +namespace { + +class IdlEnumFieldImpl + : public IdlMemberImpl + , public XIdlField + , public XIdlField2 +{ + sal_Int32 _nValue; + +public: + IdlEnumFieldImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, sal_Int32 nValue ) + : IdlMemberImpl( pReflection, rName, pTypeDescr, pTypeDescr ) + , _nValue( nValue ) + {} + + // XInterface + virtual Any SAL_CALL queryInterface( const Type & rType ) override; + virtual void SAL_CALL acquire() noexcept override; + virtual void SAL_CALL release() noexcept override; + + // XTypeProvider + virtual Sequence< Type > SAL_CALL getTypes() override; + virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override; + + // XIdlMember + virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() override; + virtual OUString SAL_CALL getName() override; + // XIdlField + virtual Reference< XIdlClass > SAL_CALL getType() override; + virtual FieldAccessMode SAL_CALL getAccessMode() override; + virtual Any SAL_CALL get( const Any & rObj ) override; + virtual void SAL_CALL set( const Any & rObj, const Any & rValue ) override; + // XIdlField2: getType, getAccessMode and get are equal to XIdlField + virtual void SAL_CALL set( Any & rObj, const Any & rValue ) override; +}; + +} + +// XInterface + +Any IdlEnumFieldImpl::queryInterface( const Type & rType ) +{ + Any aRet( ::cppu::queryInterface( rType, + static_cast< XIdlField * >( this ), + static_cast< XIdlField2 * >( this ) ) ); + return (aRet.hasValue() ? aRet : IdlMemberImpl::queryInterface( rType )); +} + +void IdlEnumFieldImpl::acquire() noexcept +{ + IdlMemberImpl::acquire(); +} + +void IdlEnumFieldImpl::release() noexcept +{ + IdlMemberImpl::release(); +} + +// XTypeProvider + +Sequence< Type > IdlEnumFieldImpl::getTypes() +{ + static cppu::OTypeCollection s_aTypes( + cppu::UnoType<XIdlField2>::get(), + cppu::UnoType<XIdlField>::get(), + IdlMemberImpl::getTypes() ); + + return s_aTypes.getTypes(); +} + +Sequence< sal_Int8 > IdlEnumFieldImpl::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// XIdlMember + +Reference< XIdlClass > IdlEnumFieldImpl::getDeclaringClass() +{ + return IdlMemberImpl::getDeclaringClass(); +} + +OUString IdlEnumFieldImpl::getName() +{ + return IdlMemberImpl::getName(); +} + +// XIdlField + +Reference< XIdlClass > IdlEnumFieldImpl::getType() +{ + return getDeclaringClass(); +} + +FieldAccessMode IdlEnumFieldImpl::getAccessMode() +{ + return FieldAccessMode_READONLY; +} + +Any IdlEnumFieldImpl::get( const Any & ) +{ + return Any( &_nValue, getTypeDescr() ); +} + +void IdlEnumFieldImpl::set( const Any &, const Any & ) +{ + throw IllegalAccessException( + "cannot set enum field, it is constant", + static_cast<XWeak *>(static_cast<OWeakObject *>(this)) ); +} + +void IdlEnumFieldImpl::set( Any &, const Any & ) +{ + throw IllegalAccessException( + "cannot set enum field, it is constant", + static_cast<XWeak *>(static_cast<OWeakObject *>(this)) ); +} + + +EnumIdlClassImpl::~EnumIdlClassImpl() +{ +} + +// IdlClassImpl modifications + +Reference< XIdlField > EnumIdlClassImpl::getField( const OUString & rName ) +{ + if (! m_xFields) + getFields(); // init members + + const OUString2Field::const_iterator iFind( _aName2Field.find( rName ) ); + if (iFind != _aName2Field.end()) + return (*iFind).second; + else + return Reference< XIdlField >(); +} + +Sequence< Reference< XIdlField > > EnumIdlClassImpl::getFields() +{ + if (! m_xFields) + { + ::osl::MutexGuard aGuard( getMutexAccess() ); + if (! m_xFields) + { + sal_Int32 nFields = getTypeDescr()->nEnumValues; + Sequence< Reference< XIdlField > > aFields( nFields ); + Reference< XIdlField > * pSeq = aFields.getArray(); + + while (nFields--) + { + OUString aName( getTypeDescr()->ppEnumNames[nFields] ); + _aName2Field[aName] = pSeq[nFields] = new IdlEnumFieldImpl( + getReflection(), aName, IdlClassImpl::getTypeDescr(), getTypeDescr()->pEnumValues[nFields] ); + } + + m_xFields = std::move( aFields ); + } + } + return *m_xFields; +} + +void EnumIdlClassImpl::createObject( Any & rObj ) +{ + sal_Int32 eVal = + reinterpret_cast<typelib_EnumTypeDescription *>(IdlClassImpl::getTypeDescr())->nDefaultEnumValue; + rObj.setValue( &eVal, IdlClassImpl::getTypeDescr() ); +} + +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/stoc/source/corereflection/criface.cxx b/stoc/source/corereflection/criface.cxx new file mode 100644 index 000000000..88dcc29ff --- /dev/null +++ b/stoc/source/corereflection/criface.cxx @@ -0,0 +1,916 @@ +/* -*- 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 . + */ + +#include <sal/config.h> + +#include <cassert> +#include <cstddef> +#include <limits> + +#ifdef SAL_UNX +#include <sal/alloca.h> +#endif +#include <o3tl/any.hxx> +#include <typelib/typedescription.hxx> +#include <uno/data.h> + +#include "base.hxx" + +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/reflection/XIdlField2.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <cppuhelper/typeprovider.hxx> + +using namespace css::lang; +using namespace css::reflection; +using namespace css::uno; + +namespace { + +std::size_t multipleOf16(std::size_t n) { + assert(n <= std::numeric_limits<std::size_t>::max() - 15); + return (n + 15) & ~std::size_t(15); +} + +} + +namespace stoc_corefl +{ + +namespace { + +class IdlAttributeFieldImpl + : public IdlMemberImpl + , public XIdlField + , public XIdlField2 +{ +public: + typelib_InterfaceAttributeTypeDescription * getAttributeTypeDescr() const + { return reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>(getTypeDescr()); } + + IdlAttributeFieldImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr ) + : IdlMemberImpl( pReflection, rName, pTypeDescr, pDeclTypeDescr ) + {} + + // XInterface + virtual Any SAL_CALL queryInterface( const Type & rType ) override; + virtual void SAL_CALL acquire() noexcept override; + virtual void SAL_CALL release() noexcept override; + + // XTypeProvider + virtual Sequence< Type > SAL_CALL getTypes() override; + virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override; + + // XIdlMember + virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() override; + virtual OUString SAL_CALL getName() override; + // XIdlField + virtual Reference< XIdlClass > SAL_CALL getType() override; + virtual FieldAccessMode SAL_CALL getAccessMode() override; + virtual Any SAL_CALL get( const Any & rObj ) override; + virtual void SAL_CALL set( const Any & rObj, const Any & rValue ) override; + // XIdlField2: getType, getAccessMode and get are equal to XIdlField + virtual void SAL_CALL set( Any & rObj, const Any & rValue ) override; + +private: + void checkException( + uno_Any * exception, Reference< XInterface > const & context) const; +}; + +} + +// XInterface + +Any IdlAttributeFieldImpl::queryInterface( const Type & rType ) +{ + Any aRet( ::cppu::queryInterface( rType, + static_cast< XIdlField * >( this ), + static_cast< XIdlField2 * >( this ) ) ); + return (aRet.hasValue() ? aRet : IdlMemberImpl::queryInterface( rType )); +} + +void IdlAttributeFieldImpl::acquire() noexcept +{ + IdlMemberImpl::acquire(); +} + +void IdlAttributeFieldImpl::release() noexcept +{ + IdlMemberImpl::release(); +} + +// XTypeProvider + +Sequence< Type > IdlAttributeFieldImpl::getTypes() +{ + static cppu::OTypeCollection s_aTypes( + cppu::UnoType<XIdlField2>::get(), + cppu::UnoType<XIdlField>::get(), + IdlMemberImpl::getTypes() ); + + return s_aTypes.getTypes(); +} + +Sequence< sal_Int8 > IdlAttributeFieldImpl::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// XIdlMember + +Reference< XIdlClass > IdlAttributeFieldImpl::getDeclaringClass() +{ + if (! _xDeclClass.is()) + { + ::osl::MutexGuard aGuard( getMutexAccess() ); + if (! _xDeclClass.is()) + { + OUString aName(getAttributeTypeDescr()->aBase.aBase.pTypeName); + sal_Int32 i = aName.indexOf(':'); + OSL_ASSERT(i >= 0); + _xDeclClass = getReflection()->forName(aName.copy(0, i)); + } + } + return _xDeclClass; +} + +OUString IdlAttributeFieldImpl::getName() +{ + return IdlMemberImpl::getName(); +} + +// XIdlField + +Reference< XIdlClass > IdlAttributeFieldImpl::getType() +{ + return getReflection()->forType( + getAttributeTypeDescr()->pAttributeTypeRef ); +} + +FieldAccessMode IdlAttributeFieldImpl::getAccessMode() +{ + return (getAttributeTypeDescr()->bReadOnly + ? FieldAccessMode_READONLY : FieldAccessMode_READWRITE); +} + +Any IdlAttributeFieldImpl::get( const Any & rObj ) +{ + uno_Interface * pUnoI = getReflection()->mapToUno( + rObj, reinterpret_cast<typelib_InterfaceTypeDescription *>(getDeclTypeDescr()) ); + OSL_ENSURE( pUnoI, "### illegal destination object given!" ); + if (pUnoI) + { + TypeDescription aTD( getAttributeTypeDescr()->pAttributeTypeRef ); + typelib_TypeDescription * pTD = aTD.get(); + + uno_Any aExc; + uno_Any * pExc = &aExc; + void * pReturn = alloca( pTD->nSize ); + + (*pUnoI->pDispatcher)( pUnoI, getTypeDescr(), pReturn, nullptr, &pExc ); + (*pUnoI->release)( pUnoI ); + + checkException(pExc, *o3tl::doAccess<Reference<XInterface>>(rObj)); + Any aRet; + uno_any_destruct( + &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_any_constructAndConvert( &aRet, pReturn, pTD, getReflection()->getUno2Cpp().get() ); + uno_destructData( pReturn, pTD, nullptr ); + return aRet; + } + throw IllegalArgumentException( + "illegal object given!", + static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 ); +} + +void IdlAttributeFieldImpl::set( Any & rObj, const Any & rValue ) +{ + if (getAttributeTypeDescr()->bReadOnly) + { + throw IllegalAccessException( + "cannot set readonly attribute!", + static_cast<XWeak *>(static_cast<OWeakObject *>(this)) ); + } + + uno_Interface * pUnoI = getReflection()->mapToUno( + rObj, reinterpret_cast<typelib_InterfaceTypeDescription *>(getDeclTypeDescr()) ); + OSL_ENSURE( pUnoI, "### illegal destination object given!" ); + if (pUnoI) + { + TypeDescription aTD( getAttributeTypeDescr()->pAttributeTypeRef ); + typelib_TypeDescription * pTD = aTD.get(); + + // construct uno value to be set + void * pArgs[1]; + void * pArg = pArgs[0] = alloca( pTD->nSize ); + + bool bAssign; + if (pTD->eTypeClass == typelib_TypeClass_ANY) + { + uno_copyAndConvertData( pArg, const_cast< Any * >(&rValue), + pTD, getReflection()->getCpp2Uno().get() ); + bAssign = true; + } + else if (typelib_typedescriptionreference_equals( rValue.getValueTypeRef(), pTD->pWeakRef )) + { + uno_copyAndConvertData( pArg, const_cast< void * >(rValue.getValue()), + pTD, getReflection()->getCpp2Uno().get() ); + bAssign = true; + } + else if (pTD->eTypeClass == typelib_TypeClass_INTERFACE) + { + Reference< XInterface > xObj; + bAssign = extract( + rValue, reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD), xObj, + getReflection() ); + if (bAssign) + { + *static_cast<void **>(pArg) = getReflection()->getCpp2Uno().mapInterface( + xObj.get(), reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD) ); + } + } + else + { + typelib_TypeDescription * pValueTD = nullptr; + TYPELIB_DANGER_GET( &pValueTD, rValue.getValueTypeRef() ); + // construct temp uno val to do proper assignment: todo opt + void * pTemp = alloca( pValueTD->nSize ); + uno_copyAndConvertData( + pTemp, const_cast<void *>(rValue.getValue()), pValueTD, getReflection()->getCpp2Uno().get() ); + uno_constructData( + pArg, pTD ); + // assignment does simple conversion + bAssign = uno_assignData( + pArg, pTD, pTemp, pValueTD, nullptr, nullptr, nullptr ); + uno_destructData( + pTemp, pValueTD, nullptr ); + TYPELIB_DANGER_RELEASE( pValueTD ); + } + + if (bAssign) + { + uno_Any aExc; + uno_Any * pExc = &aExc; + (*pUnoI->pDispatcher)( pUnoI, getTypeDescr(), nullptr, pArgs, &pExc ); + (*pUnoI->release)( pUnoI ); + + uno_destructData( pArg, pTD, nullptr ); + checkException(pExc, *o3tl::doAccess<Reference<XInterface>>(rObj)); + return; + } + (*pUnoI->release)( pUnoI ); + + throw IllegalArgumentException( + "illegal value given!", + *o3tl::doAccess<Reference<XInterface>>(rObj), 1 ); + } + throw IllegalArgumentException( + "illegal destination object given!", + static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 ); +} + +void IdlAttributeFieldImpl::set( const Any & rObj, const Any & rValue ) +{ + IdlAttributeFieldImpl::set( const_cast< Any & >( rObj ), rValue ); +} + +void IdlAttributeFieldImpl::checkException( + uno_Any * exception, Reference< XInterface > const & context) const +{ + if (exception == nullptr) + return; + + Any e; + uno_any_destruct(&e, reinterpret_cast< uno_ReleaseFunc >(cpp_release)); + uno_type_any_constructAndConvert( + &e, exception->pData, exception->pType, + getReflection()->getUno2Cpp().get()); + uno_any_destruct(exception, nullptr); + if (!e.isExtractableTo( + cppu::UnoType<RuntimeException>::get())) + { + throw WrappedTargetRuntimeException( + "non-RuntimeException occurred when accessing an" + " interface type attribute", + context, e); + } + cppu::throwException(e); +} + +namespace { + +class IdlInterfaceMethodImpl + : public IdlMemberImpl + , public XIdlMethod +{ + std::optional<Sequence< Reference< XIdlClass > >> m_xExceptionTypes; + std::optional<Sequence< Reference< XIdlClass > >> m_xParamTypes; + std::optional<Sequence< ParamInfo >> m_xParamInfos; + +public: + typelib_InterfaceMethodTypeDescription * getMethodTypeDescr() const + { return reinterpret_cast<typelib_InterfaceMethodTypeDescription *>(getTypeDescr()); } + + IdlInterfaceMethodImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr ) + : IdlMemberImpl( pReflection, rName, pTypeDescr, pDeclTypeDescr ) + {} + + // XInterface + virtual Any SAL_CALL queryInterface( const Type & rType ) override; + virtual void SAL_CALL acquire() noexcept override; + virtual void SAL_CALL release() noexcept override; + + // XTypeProvider + virtual Sequence< Type > SAL_CALL getTypes() override; + virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override; + + // XIdlMember + virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() override; + virtual OUString SAL_CALL getName() override; + // XIdlMethod + virtual Reference< XIdlClass > SAL_CALL getReturnType() override; + virtual Sequence< Reference< XIdlClass > > SAL_CALL getParameterTypes() override; + virtual Sequence< ParamInfo > SAL_CALL getParameterInfos() override; + virtual Sequence< Reference< XIdlClass > > SAL_CALL getExceptionTypes() override; + virtual MethodMode SAL_CALL getMode() override; + virtual Any SAL_CALL invoke( const Any & rObj, Sequence< Any > & rArgs ) override; +}; + +} + +// XInterface + +Any IdlInterfaceMethodImpl::queryInterface( const Type & rType ) +{ + Any aRet( ::cppu::queryInterface( rType, static_cast< XIdlMethod * >( this ) ) ); + return (aRet.hasValue() ? aRet : IdlMemberImpl::queryInterface( rType )); +} + +void IdlInterfaceMethodImpl::acquire() noexcept +{ + IdlMemberImpl::acquire(); +} + +void IdlInterfaceMethodImpl::release() noexcept +{ + IdlMemberImpl::release(); +} + +// XTypeProvider + +Sequence< Type > IdlInterfaceMethodImpl::getTypes() +{ + static cppu::OTypeCollection s_aTypes( + cppu::UnoType<XIdlMethod>::get(), + IdlMemberImpl::getTypes() ); + + return s_aTypes.getTypes(); +} + +Sequence< sal_Int8 > IdlInterfaceMethodImpl::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// XIdlMember + +Reference< XIdlClass > IdlInterfaceMethodImpl::getDeclaringClass() +{ + if (! _xDeclClass.is()) + { + ::osl::MutexGuard aGuard( getMutexAccess() ); + if (! _xDeclClass.is()) + { + OUString aName(getMethodTypeDescr()->aBase.aBase.pTypeName); + sal_Int32 i = aName.indexOf(':'); + OSL_ASSERT(i >= 0); + _xDeclClass = getReflection()->forName(aName.copy(0, i)); + } + } + return _xDeclClass; +} + +OUString IdlInterfaceMethodImpl::getName() +{ + return IdlMemberImpl::getName(); +} + +// XIdlMethod + +Reference< XIdlClass > SAL_CALL IdlInterfaceMethodImpl::getReturnType() +{ + return getReflection()->forType( getMethodTypeDescr()->pReturnTypeRef ); +} + +Sequence< Reference< XIdlClass > > IdlInterfaceMethodImpl::getExceptionTypes() +{ + if (! m_xExceptionTypes) + { + ::osl::MutexGuard aGuard( getMutexAccess() ); + if (! m_xExceptionTypes) + { + sal_Int32 nExc = getMethodTypeDescr()->nExceptions; + Sequence< Reference< XIdlClass > > aTempExceptionTypes( nExc ); + Reference< XIdlClass > * pExceptionTypes = aTempExceptionTypes.getArray(); + + typelib_TypeDescriptionReference ** ppExc = + getMethodTypeDescr()->ppExceptions; + IdlReflectionServiceImpl * pRefl = getReflection(); + + while (nExc--) + pExceptionTypes[nExc] = pRefl->forType( ppExc[nExc] ); + + m_xExceptionTypes = std::move(aTempExceptionTypes); + } + } + return *m_xExceptionTypes; +} + +Sequence< Reference< XIdlClass > > IdlInterfaceMethodImpl::getParameterTypes() +{ + if (! m_xParamTypes) + { + ::osl::MutexGuard aGuard( getMutexAccess() ); + if (! m_xParamTypes) + { + sal_Int32 nParams = getMethodTypeDescr()->nParams; + Sequence< Reference< XIdlClass > > aTempParamTypes( nParams ); + Reference< XIdlClass > * pParamTypes = aTempParamTypes.getArray(); + + typelib_MethodParameter * pTypelibParams = + getMethodTypeDescr()->pParams; + IdlReflectionServiceImpl * pRefl = getReflection(); + + while (nParams--) + pParamTypes[nParams] = pRefl->forType( pTypelibParams[nParams].pTypeRef ); + + m_xParamTypes = std::move(aTempParamTypes); + } + } + return *m_xParamTypes; +} + +Sequence< ParamInfo > IdlInterfaceMethodImpl::getParameterInfos() +{ + if (! m_xParamInfos) + { + ::osl::MutexGuard aGuard( getMutexAccess() ); + if (! m_xParamInfos) + { + sal_Int32 nParams = getMethodTypeDescr()->nParams; + Sequence< ParamInfo > aTempParamInfos( nParams ); + ParamInfo * pParamInfos = aTempParamInfos.getArray(); + + typelib_MethodParameter * pTypelibParams = + getMethodTypeDescr()->pParams; + + if (m_xParamTypes) // use param types + { + const Reference< XIdlClass > * pParamTypes = m_xParamTypes->getConstArray(); + + while (nParams--) + { + const typelib_MethodParameter & rParam = pTypelibParams[nParams]; + ParamInfo & rInfo = pParamInfos[nParams]; + rInfo.aName = rParam.pName; + if (rParam.bIn) + rInfo.aMode = (rParam.bOut ? ParamMode_INOUT : ParamMode_IN); + else + rInfo.aMode = ParamMode_OUT; + rInfo.aType = pParamTypes[nParams]; + } + } + else // make also param types sequence if not already initialized + { + Sequence< Reference< XIdlClass > > aTempParamTypes( nParams ); + Reference< XIdlClass > * pParamTypes = aTempParamTypes.getArray(); + + IdlReflectionServiceImpl * pRefl = getReflection(); + + while (nParams--) + { + const typelib_MethodParameter & rParam = pTypelibParams[nParams]; + ParamInfo & rInfo = pParamInfos[nParams]; + rInfo.aName = rParam.pName; + if (rParam.bIn) + rInfo.aMode = (rParam.bOut ? ParamMode_INOUT : ParamMode_IN); + else + rInfo.aMode = ParamMode_OUT; + rInfo.aType = pParamTypes[nParams] = pRefl->forType( rParam.pTypeRef ); + } + + m_xParamTypes = std::move(aTempParamTypes); + } + + m_xParamInfos = std::move(aTempParamInfos); + } + } + return *m_xParamInfos; +} + +MethodMode SAL_CALL IdlInterfaceMethodImpl::getMode() +{ + return + getMethodTypeDescr()->bOneWay ? MethodMode_ONEWAY : MethodMode_TWOWAY; +} + +Any SAL_CALL IdlInterfaceMethodImpl::invoke( const Any & rObj, Sequence< Any > & rArgs ) +{ + if (auto ifc = o3tl::tryAccess<css::uno::Reference<css::uno::XInterface>>( + rObj)) + { + // acquire()/ release() + if (rtl_ustr_ascii_compare( getTypeDescr()->pTypeName->buffer, + "com.sun.star.uno.XInterface::acquire" ) == 0) + { + (*ifc)->acquire(); + return Any(); + } + else if (rtl_ustr_ascii_compare( getTypeDescr()->pTypeName->buffer, + "com.sun.star.uno.XInterface::release" ) == 0) + { + (*ifc)->release(); + return Any(); + } + } + + uno_Interface * pUnoI = getReflection()->mapToUno( + rObj, reinterpret_cast<typelib_InterfaceTypeDescription *>(getDeclTypeDescr()) ); + OSL_ENSURE( pUnoI, "### illegal destination object given!" ); + if (pUnoI) + { + sal_Int32 nParams = getMethodTypeDescr()->nParams; + if (rArgs.getLength() != nParams) + { + (*pUnoI->release)( pUnoI ); + throw IllegalArgumentException( + "expected " + OUString::number(nParams) + + " arguments, got " + OUString::number(rArgs.getLength()), + *o3tl::doAccess<Reference<XInterface>>(rObj), 1 ); + } + + Any * pCppArgs = rArgs.getArray(); + typelib_MethodParameter * pParams = getMethodTypeDescr()->pParams; + typelib_TypeDescription * pReturnType = nullptr; + TYPELIB_DANGER_GET( + &pReturnType, getMethodTypeDescr()->pReturnTypeRef ); + + // C/C++ ABIs typically assume that structs are padded at the end, and + // that those padding bytes may be written to (e.g., to write into the + // end of a "short" struct by writing the full contents of a "long" + // register); so create enough space here (assuming that no ABI requires + // padding larger than 16 byte boundaries): + void * pUnoReturn = (pReturnType->nSize == 0) ? nullptr : alloca( multipleOf16(pReturnType->nSize) ); + void ** ppUnoArgs = static_cast<void **>(alloca( sizeof(void *) * nParams *2 )); + typelib_TypeDescription ** ppParamTypes = reinterpret_cast<typelib_TypeDescription **>(ppUnoArgs + nParams); + + // convert arguments + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + ppParamTypes[nPos] = nullptr; + TYPELIB_DANGER_GET( ppParamTypes + nPos, pParams[nPos].pTypeRef ); + typelib_TypeDescription * pTD = ppParamTypes[nPos]; + + ppUnoArgs[nPos] = alloca( pTD->nSize ); + if (pParams[nPos].bIn) + { + bool bAssign; + if (typelib_typedescriptionreference_equals( + pCppArgs[nPos].getValueTypeRef(), pTD->pWeakRef )) + { + uno_type_copyAndConvertData( + ppUnoArgs[nPos], const_cast<void *>(pCppArgs[nPos].getValue()), + pCppArgs[nPos].getValueTypeRef(), getReflection()->getCpp2Uno().get() ); + bAssign = true; + } + else if (pTD->eTypeClass == typelib_TypeClass_ANY) + { + uno_type_any_constructAndConvert( + static_cast<uno_Any *>(ppUnoArgs[nPos]), const_cast<void *>(pCppArgs[nPos].getValue()), + pCppArgs[nPos].getValueTypeRef(), getReflection()->getCpp2Uno().get() ); + bAssign = true; + } + else if (pTD->eTypeClass == typelib_TypeClass_INTERFACE) + { + Reference< XInterface > xDest; + bAssign = extract( + pCppArgs[nPos], reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD), + xDest, getReflection() ); + if (bAssign) + { + *static_cast<void **>(ppUnoArgs[nPos]) = getReflection()->getCpp2Uno().mapInterface( + xDest.get(), reinterpret_cast<typelib_InterfaceTypeDescription *>(pTD) ); + } + } + else + { + typelib_TypeDescription * pValueTD = nullptr; + TYPELIB_DANGER_GET( &pValueTD, pCppArgs[nPos].getValueTypeRef() ); + // construct temp uno val to do proper assignment: todo opt + void * pTemp = alloca( pValueTD->nSize ); + uno_copyAndConvertData( + pTemp, const_cast<void *>(pCppArgs[nPos].getValue()), pValueTD, + getReflection()->getCpp2Uno().get() ); + uno_constructData( + ppUnoArgs[nPos], pTD ); + // assignment does simple conversion + bAssign = uno_assignData( + ppUnoArgs[nPos], pTD, pTemp, pValueTD, nullptr, nullptr, nullptr ); + uno_destructData( + pTemp, pValueTD, nullptr ); + TYPELIB_DANGER_RELEASE( pValueTD ); + } + + if (! bAssign) + { + IllegalArgumentException aExc( + "cannot coerce argument type during corereflection call:" + "\narg no.: " + OUString::number(nPos) + + " expected: \"" + OUString::unacquired(&pTD->pTypeName) + + "\" actual: \"" + OUString::unacquired(&pCppArgs[nPos].getValueTypeRef()->pTypeName) + + "\"", + *o3tl::doAccess<Reference<XInterface>>(rObj), static_cast<sal_Int16>(nPos) ); + + // cleanup + while (nPos--) + { + if (pParams[nPos].bIn) + uno_destructData( ppUnoArgs[nPos], ppParamTypes[nPos], nullptr ); + TYPELIB_DANGER_RELEASE( ppParamTypes[nPos] ); + } + TYPELIB_DANGER_RELEASE( pReturnType ); + (*pUnoI->release)( pUnoI ); + + throw aExc; + } + } + } + + uno_Any aUnoExc; + uno_Any * pUnoExc = &aUnoExc; + + (*pUnoI->pDispatcher)( + pUnoI, getTypeDescr(), pUnoReturn, ppUnoArgs, &pUnoExc ); + (*pUnoI->release)( pUnoI ); + + Any aRet; + if (pUnoExc) + { + // cleanup + while (nParams--) + { + if (pParams[nParams].bIn) + uno_destructData( ppUnoArgs[nParams], ppParamTypes[nParams], nullptr ); + TYPELIB_DANGER_RELEASE( ppParamTypes[nParams] ); + } + TYPELIB_DANGER_RELEASE( pReturnType ); + + InvocationTargetException aExc; + aExc.Context = *o3tl::doAccess<Reference<XInterface>>(rObj); + aExc.Message = "exception occurred during invocation!"; + uno_any_destruct( + &aExc.TargetException, + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_type_copyAndConvertData( + &aExc.TargetException, pUnoExc, cppu::UnoType<Any>::get().getTypeLibType(), + getReflection()->getUno2Cpp().get() ); + uno_any_destruct( pUnoExc, nullptr ); + throw aExc; + } + else + { + // reconvert arguments and cleanup + while (nParams--) + { + if (pParams[nParams].bOut) // write back + { + uno_any_destruct( + &pCppArgs[nParams], + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_any_constructAndConvert( + &pCppArgs[nParams], ppUnoArgs[nParams], ppParamTypes[nParams], + getReflection()->getUno2Cpp().get() ); + } + uno_destructData( ppUnoArgs[nParams], ppParamTypes[nParams], nullptr ); + TYPELIB_DANGER_RELEASE( ppParamTypes[nParams] ); + } + uno_any_destruct( + &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_any_constructAndConvert( + &aRet, pUnoReturn, pReturnType, + getReflection()->getUno2Cpp().get() ); + uno_destructData( pUnoReturn, pReturnType, nullptr ); + TYPELIB_DANGER_RELEASE( pReturnType ); + } + return aRet; + } + throw IllegalArgumentException( + "illegal destination object given!", + static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 ); +} + + +InterfaceIdlClassImpl::~InterfaceIdlClassImpl() +{ + for ( sal_Int32 nPos = _nMethods + _nAttributes; nPos--; ) + typelib_typedescription_release( _pSortedMemberInit[nPos].second ); +} + + +Sequence< Reference< XIdlClass > > InterfaceIdlClassImpl::getSuperclasses() +{ + ::osl::MutexGuard aGuard(getMutexAccess()); + if (!_xSuperClasses.hasElements()) { + typelib_InterfaceTypeDescription * pType = getTypeDescr(); + _xSuperClasses.realloc(pType->nBaseTypes); + auto pSuperClasses = _xSuperClasses.getArray(); + for (sal_Int32 i = 0; i < pType->nBaseTypes; ++i) { + pSuperClasses[i] = getReflection()->forType( + &pType->ppBaseTypes[i]->aBase); + OSL_ASSERT(_xSuperClasses[i].is()); + } + } + return _xSuperClasses; +} + +void InterfaceIdlClassImpl::initMembers() +{ + sal_Int32 nAll = getTypeDescr()->nAllMembers; + std::unique_ptr<MemberInit[]> pSortedMemberInit(new MemberInit[nAll]); + typelib_TypeDescriptionReference ** ppAllMembers = getTypeDescr()->ppAllMembers; + + for ( sal_Int32 nPos = 0; nPos < nAll; ++nPos ) + { + sal_Int32 nIndex; + if (ppAllMembers[nPos]->eTypeClass == typelib_TypeClass_INTERFACE_METHOD) + { + // methods to front + nIndex = _nMethods; + ++_nMethods; + } + else + { + ++_nAttributes; + nIndex = (nAll - _nAttributes); + // attributes at the back + } + + typelib_TypeDescription * pTD = nullptr; + typelib_typedescriptionreference_getDescription( &pTD, ppAllMembers[nPos] ); + assert(pTD && "### cannot get type description!"); + pSortedMemberInit[nIndex].first = reinterpret_cast<typelib_InterfaceMemberTypeDescription *>(pTD)->pMemberName; + pSortedMemberInit[nIndex].second = pTD; + } + + _pSortedMemberInit = std::move(pSortedMemberInit); +} + +sal_Bool InterfaceIdlClassImpl::isAssignableFrom( const Reference< XIdlClass > & xType ) +{ + if (xType.is() && xType->getTypeClass() == TypeClass_INTERFACE) + { + if (equals( xType )) + return true; + else + { + const Sequence< Reference< XIdlClass > > & rSeq = xType->getSuperclasses(); + if (std::any_of(rSeq.begin(), rSeq.end(), + [this](const Reference<XIdlClass>& rType){ return isAssignableFrom(rType); })) + return true; + } + } + return false; +} + +Uik InterfaceIdlClassImpl::getUik() +{ + return Uik(0, 0, 0, 0, 0); + // Uiks are deprecated and this function must not be called +} + +Sequence< Reference< XIdlMethod > > InterfaceIdlClassImpl::getMethods() +{ + ::osl::MutexGuard aGuard( getMutexAccess() ); + if (! _pSortedMemberInit) + initMembers(); + + // create methods sequence + Sequence< Reference< XIdlMethod > > aRet( _nMethods ); + Reference< XIdlMethod > * pRet = aRet.getArray(); + for ( sal_Int32 nPos = _nMethods; nPos--; ) + { + + /*_aName2Method[_pSortedMemberInit[nPos].first] = */pRet[nPos] = new IdlInterfaceMethodImpl( + getReflection(), _pSortedMemberInit[nPos].first, + _pSortedMemberInit[nPos].second, IdlClassImpl::getTypeDescr() ); + } + return aRet; +} + +Sequence< Reference< XIdlField > > InterfaceIdlClassImpl::getFields() +{ + ::osl::MutexGuard aGuard( getMutexAccess() ); + if (! _pSortedMemberInit) + initMembers(); + + // create fields sequence + Sequence< Reference< XIdlField > > aRet( _nAttributes ); + Reference< XIdlField > * pRet = aRet.getArray(); + for ( sal_Int32 nPos = _nAttributes; nPos--; ) + { + /*_aName2Field[_pSortedMemberInit[_nMethods+nPos].first] = */pRet[_nAttributes-nPos-1] = + new IdlAttributeFieldImpl( + getReflection(), _pSortedMemberInit[_nMethods+nPos].first, + _pSortedMemberInit[_nMethods+nPos].second, IdlClassImpl::getTypeDescr() ); + } + return aRet; +} + +Reference< XIdlMethod > InterfaceIdlClassImpl::getMethod( const OUString & rName ) +{ + ::osl::MutexGuard aGuard( getMutexAccess() ); + if (! _pSortedMemberInit) + initMembers(); + + Reference< XIdlMethod > xRet; + + // try weak map + const OUString2Method::const_iterator iFind( _aName2Method.find( rName ) ); + if (iFind != _aName2Method.end()) + xRet = (*iFind).second; // harden ref + + if (! xRet.is()) + { + for ( sal_Int32 nPos = _nMethods; nPos--; ) + { + if (_pSortedMemberInit[nPos].first == rName) + { + _aName2Method[rName] = xRet = new IdlInterfaceMethodImpl( + getReflection(), rName, + _pSortedMemberInit[nPos].second, IdlClassImpl::getTypeDescr() ); + break; + } + } + } + return xRet; +} + +Reference< XIdlField > InterfaceIdlClassImpl::getField( const OUString & rName ) +{ + ::osl::MutexGuard aGuard( getMutexAccess() ); + if (! _pSortedMemberInit) + initMembers(); + + Reference< XIdlField > xRet; + + // try weak map + const OUString2Field::const_iterator iFind( _aName2Field.find( rName ) ); + if (iFind != _aName2Field.end()) + xRet = (*iFind).second; // harden ref + + if (! xRet.is()) + { + for ( sal_Int32 nPos = _nAttributes; nPos--; ) + { + if (_pSortedMemberInit[_nMethods+nPos].first == rName) + { + _aName2Field[rName] = xRet = new IdlAttributeFieldImpl( + getReflection(), rName, + _pSortedMemberInit[_nMethods+nPos].second, IdlClassImpl::getTypeDescr() ); + break; + } + } + } + return xRet; +} + +void InterfaceIdlClassImpl::createObject( Any & rObj ) +{ + // interfaces cannot be constructed + rObj.clear(); +} + +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/stoc/source/corereflection/lrucache.hxx b/stoc/source/corereflection/lrucache.hxx new file mode 100644 index 000000000..d5eebe804 --- /dev/null +++ b/stoc/source/corereflection/lrucache.hxx @@ -0,0 +1,209 @@ +/* -*- 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_STOC_SOURCE_COREREFLECTION_LRUCACHE_HXX +#define INCLUDED_STOC_SOURCE_COREREFLECTION_LRUCACHE_HXX + +// __CACHE_DIAGNOSE forces cache size to 4 and works only for OUString keys +// #define __CACHE_DIAGNOSE 1 + +#include <rtl/ustring.hxx> + +#include <memory> +#include <mutex> +#include <unordered_map> + +namespace com::sun::star::uno { class Any; } + +/** Implementation of a least recently used (lru) cache. + <br> +*/ +template< class t_Key, class t_Val, class t_KeyHash > +class LRU_Cache +{ + struct CacheEntry + { + t_Key aKey; + t_Val aVal; + CacheEntry * pPred; + CacheEntry * pSucc; + }; + typedef std::unordered_map< t_Key, CacheEntry *, t_KeyHash > t_Key2Element; + + mutable std::mutex _aCacheMutex; + sal_Int32 _nCachedElements; + t_Key2Element _aKey2Element; + + std::unique_ptr<CacheEntry[]> _pBlock; + mutable CacheEntry * _pHead; + mutable CacheEntry * _pTail; + inline void toFront( CacheEntry * pEntry ) const; + +public: + /** Constructor: + <br> + @param nCachedElements number of elements to be cached; default param set to 128 + */ + explicit inline LRU_Cache(); + + /** Retrieves a value from the cache. Returns default constructed value, + if none was found. + <br> + @param rKey a key + @return value + */ + inline t_Val getValue( const t_Key & rKey ) const; + /** Sets a value to be cached for given key. + <br> + @param rKey a key + @param rValue a value + */ + inline void setValue( const t_Key & rKey, const t_Val & rValue ); + /** Clears the cache, thus releasing all cached elements and keys. + <br> + */ + inline void clear(); +}; + +template< class t_Key, class t_Val, class t_KeyHash > +inline LRU_Cache< t_Key, t_Val, t_KeyHash >::LRU_Cache() +#ifdef __CACHE_DIAGNOSE + : _nCachedElements( 4 ) +#else + : _nCachedElements( 256 ) +#endif + , _pBlock( nullptr ) + , _pHead( nullptr ) + , _pTail( nullptr ) +{ + _pBlock.reset(new CacheEntry[_nCachedElements]); + _pHead = _pBlock.get(); + _pTail = _pBlock.get() + _nCachedElements - 1; + for (sal_Int32 nPos = _nCachedElements; nPos--;) + { + _pBlock[nPos].pPred = _pBlock.get() + nPos - 1; + _pBlock[nPos].pSucc = _pBlock.get() + nPos + 1; + } +} + +template< class t_Key, class t_Val, class t_KeyHash > +inline void LRU_Cache< t_Key, t_Val, t_KeyHash >::toFront( CacheEntry * pEntry ) const +{ + if (pEntry != _pHead) + { + // cut out element + if (pEntry == _pTail) + { + _pTail = pEntry->pPred; + } + else + { + pEntry->pSucc->pPred = pEntry->pPred; + pEntry->pPred->pSucc = pEntry->pSucc; + } + // push to front + _pHead->pPred = pEntry; + pEntry->pSucc = _pHead; + _pHead = pEntry; + } +} + +template< class t_Key, class t_Val, class t_KeyHash > +inline t_Val LRU_Cache< t_Key, t_Val, t_KeyHash >::getValue( const t_Key & rKey ) const +{ + std::scoped_lock aGuard( _aCacheMutex ); + const typename t_Key2Element::const_iterator iFind( _aKey2Element.find( rKey ) ); + if (iFind != _aKey2Element.end()) + { + CacheEntry * pEntry = (*iFind).second; + toFront( pEntry ); +#ifdef __CACHE_DIAGNOSE + SAL_INFO("stoc.corerefl", "> retrieved element \"" ); + SAL_INFO("stoc.corerefl", "" << pEntry->aKey); + SAL_INFO("stoc.corerefl", "\" from cache <" ); +#endif + return pEntry->aVal; + } + return t_Val(); +} + +template< class t_Key, class t_Val, class t_KeyHash > +inline void LRU_Cache< t_Key, t_Val, t_KeyHash >::setValue( + const t_Key & rKey, const t_Val & rValue ) +{ + std::scoped_lock aGuard( _aCacheMutex ); + if (_nCachedElements > 0) + { + const typename t_Key2Element::const_iterator iFind( _aKey2Element.find( rKey ) ); + + CacheEntry * pEntry; + if (iFind == _aKey2Element.end()) + { + pEntry = _pTail; // erase last element +#ifdef __CACHE_DIAGNOSE + if (pEntry->aKey.getLength()) + { + SAL_INFO("stoc.corerefl", "> kicking element \"" ); + SAL_INFO("stoc.corerefl", "" << pEntry->aKey); + SAL_INFO("stoc.corerefl", "\" from cache <" ); + } +#endif + _aKey2Element.erase( pEntry->aKey ); + pEntry->aKey = rKey; + _aKey2Element[ rKey ] = pEntry; + } + else + { + pEntry = (*iFind).second; +#ifdef __CACHE_DIAGNOSE + SAL_INFO("stoc.corerefl", "> replacing element \"" ); + SAL_INFO("stoc.corerefl", "" << pEntry->aKey); + SAL_INFO("stoc.corerefl", "\" in cache <" ); +#endif + } + pEntry->aVal = rValue; + toFront( pEntry ); + } +} + +template< class t_Key, class t_Val, class t_KeyHash > +inline void LRU_Cache< t_Key, t_Val, t_KeyHash >::clear() +{ + std::scoped_lock aGuard( _aCacheMutex ); + _aKey2Element.clear(); + for ( sal_Int32 nPos = _nCachedElements; nPos--; ) + { + _pBlock[nPos].aKey = t_Key(); + _pBlock[nPos].aVal = t_Val(); + } + _nCachedElements = 0; +#ifdef __CACHE_DIAGNOSE + SAL_INFO("stoc.corerefl", "> cleared cache <" ); +#endif +} + + +/** Template instance for OUString keys, Any values.<br> +*/ +typedef LRU_Cache< OUString, css::uno::Any, OUStringHash > + LRU_CacheAnyByOUString; + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/stoc/source/corereflection/reflection.component b/stoc/source/corereflection/reflection.component new file mode 100644 index 000000000..70ccb68e0 --- /dev/null +++ b/stoc/source/corereflection/reflection.component @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.stoc.CoreReflection" + constructor="com_sun_star_comp_stoc_CoreReflection_get_implementation" + single-instance="true"> + <service name="com.sun.star.reflection.CoreReflection"/> + <singleton name="com.sun.star.reflection.theCoreReflection"/> + </implementation> +</component> |