diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /stoc/source/corereflection | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'stoc/source/corereflection')
-rw-r--r-- | stoc/source/corereflection/base.hxx | 406 | ||||
-rw-r--r-- | stoc/source/corereflection/crarray.cxx | 166 | ||||
-rw-r--r-- | stoc/source/corereflection/crbase.cxx | 250 | ||||
-rw-r--r-- | stoc/source/corereflection/crcomp.cxx | 310 | ||||
-rw-r--r-- | stoc/source/corereflection/crefl.cxx | 333 | ||||
-rw-r--r-- | stoc/source/corereflection/crenum.cxx | 158 | ||||
-rw-r--r-- | stoc/source/corereflection/criface.cxx | 830 | ||||
-rw-r--r-- | stoc/source/corereflection/dump.cxx | 358 | ||||
-rw-r--r-- | stoc/source/corereflection/lrucache.hxx | 209 | ||||
-rw-r--r-- | stoc/source/corereflection/reflection.component | 33 |
10 files changed, 3053 insertions, 0 deletions
diff --git a/stoc/source/corereflection/base.hxx b/stoc/source/corereflection/base.hxx new file mode 100644 index 0000000000..03d844de3c --- /dev/null +++ b/stoc/source/corereflection/base.hxx @@ -0,0 +1,406 @@ +/* -*- 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/compbase.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::WeakComponentImplHelper< + css::reflection::XIdlReflection, + css::container::XHierarchicalNameAccess, + 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; + + // WeakComponentImplHelper + virtual void SAL_CALL disposing() 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; + + // 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, + OUString aName, 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; +}; + + +typedef cppu::ImplInheritanceHelper<IdlClassImpl, css::reflection::XIdlArray> ArrayIdlClassImpl_Base; +class ArrayIdlClassImpl : public ArrayIdlClassImpl_Base +{ +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 ) + : ArrayIdlClassImpl_Base( pReflection, rName, eTypeClass, pTypeDescr ) + {} + + // 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, OUString aName, + 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 0000000000..67be31e1ac --- /dev/null +++ b/stoc/source/corereflection/crarray.cxx @@ -0,0 +1,166 @@ +/* -*- 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 +{ + +// 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(), + getXWeak(), 0 ); + } + if (nLen < 0) + { + throw IllegalArgumentException( + "negative length given!", + getXWeak(), 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(), + getXWeak(), 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(), + getXWeak(), 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), + getXWeak() ); + } + + 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(), + getXWeak(), 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), + getXWeak() ); + } + + 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!", + getXWeak(), 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 0000000000..439ee5b222 --- /dev/null +++ b/stoc/source/corereflection/crbase.cxx @@ -0,0 +1,250 @@ +/* -*- 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 <utility> + +#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, + OUString aName, typelib_TypeClass eTypeClass, + typelib_TypeDescription * pTypeDescr ) + : m_xReflection( pReflection ) + , _aName(std::move( aName )) + , _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, OUString aName, + typelib_TypeDescription * pTypeDescr, + typelib_TypeDescription * pDeclTypeDescr ) + : m_xReflection( pReflection ) + , _aName(std::move( aName )) + , _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 0000000000..b1143e158b --- /dev/null +++ b/stoc/source/corereflection/crcomp.cxx @@ -0,0 +1,310 @@ +/* -*- 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 { + +typedef cppu::ImplInheritanceHelper<IdlMemberImpl, XIdlField, XIdlField2> IdlCompFieldImpl_Base; +class IdlCompFieldImpl : public IdlCompFieldImpl_Base +{ + sal_Int32 _nOffset; + +public: + IdlCompFieldImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr, + sal_Int32 nOffset ) + : IdlCompFieldImpl_Base( pReflection, rName, pTypeDescr, pDeclTypeDescr ) + , _nOffset( nOffset ) + {} + + // 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; +}; + +} + +// 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(), + getXWeak(), 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", + getXWeak(), 1 ); + } + return; + } + TYPELIB_DANGER_RELEASE( pObjTD ); + } + throw IllegalArgumentException( + "expected struct or exception, got " + rObj.getValueType().getTypeName(), + getXWeak(), 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", + getXWeak(), 1 ); + } + return; + } + TYPELIB_DANGER_RELEASE( pObjTD ); + } + throw IllegalArgumentException( + "expected struct or exception, got " + rObj.getValueType().getTypeName(), + getXWeak(), 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 0000000000..1f4562181a --- /dev/null +++ b/stoc/source/corereflection/crefl.cxx @@ -0,0 +1,333 @@ +/* -*- 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> +#include "base.hxx" + +using namespace css; +using namespace css::uno; +using namespace css::lang; +using namespace css::reflection; +using namespace cppu; +using namespace osl; + +namespace stoc_corefl +{ + +IdlReflectionServiceImpl::IdlReflectionServiceImpl( + const Reference< XComponentContext > & xContext ) + : WeakComponentImplHelper( _aComponentMutex ) +{ + xContext->getValueByName( + "/singletons/com.sun.star.reflection.theTypeDescriptionManager" ) >>= _xTDMgr; + OSL_ENSURE( _xTDMgr.is(), "### cannot get singleton \"TypeDescriptionManager\" from context!" ); +} + +IdlReflectionServiceImpl::~IdlReflectionServiceImpl() {} + +// XComponent + +void IdlReflectionServiceImpl::disposing() +{ + 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!", + getXWeak() ); +} + + +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!", + getXWeak() ); + } + } + } + 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!", + getXWeak() ); + } + } + } + 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!", + getXWeak() ); +} + +} + + +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 0000000000..2cb07c9b5e --- /dev/null +++ b/stoc/source/corereflection/crenum.cxx @@ -0,0 +1,158 @@ +/* -*- 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 { + +typedef cppu::ImplInheritanceHelper<IdlMemberImpl, XIdlField, XIdlField2> IdlEnumFieldImpl_Base; +class IdlEnumFieldImpl : public IdlEnumFieldImpl_Base +{ + sal_Int32 _nValue; + +public: + IdlEnumFieldImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, sal_Int32 nValue ) + : IdlEnumFieldImpl_Base( pReflection, rName, pTypeDescr, pTypeDescr ) + , _nValue( nValue ) + {} + + // 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; +}; + +} + +// 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", + getXWeak() ); +} + +void IdlEnumFieldImpl::set( Any &, const Any & ) +{ + throw IllegalAccessException( + "cannot set enum field, it is constant", + getXWeak() ); +} + + +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 0000000000..23d3d9bae2 --- /dev/null +++ b/stoc/source/corereflection/criface.cxx @@ -0,0 +1,830 @@ +/* -*- 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 { + +typedef cppu::ImplInheritanceHelper<IdlMemberImpl, XIdlField, XIdlField2> IdlAttributeFieldImpl_Base; +class IdlAttributeFieldImpl : public IdlAttributeFieldImpl_Base +{ +public: + typelib_InterfaceAttributeTypeDescription * getAttributeTypeDescr() const + { return reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>(getTypeDescr()); } + + IdlAttributeFieldImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr ) + : IdlAttributeFieldImpl_Base( pReflection, rName, pTypeDescr, pDeclTypeDescr ) + {} + + // 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; +}; + +} + +// 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!", + getXWeak(), 0 ); +} + +void IdlAttributeFieldImpl::set( Any & rObj, const Any & rValue ) +{ + if (getAttributeTypeDescr()->bReadOnly) + { + throw IllegalAccessException( + "cannot set readonly attribute!", + getXWeak() ); + } + + 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!", + getXWeak(), 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 { + +typedef cppu::ImplInheritanceHelper<IdlMemberImpl, XIdlMethod> IdlInterfaceMethodImpl_Base; +class IdlInterfaceMethodImpl : public IdlInterfaceMethodImpl_Base +{ + 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 ) + : IdlInterfaceMethodImpl_Base( pReflection, rName, pTypeDescr, pDeclTypeDescr ) + {} + + // XTypeProvider + 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; +}; + +} + +// XTypeProvider + +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 ); + + uno_any_destruct(&aRet, + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_type_copyAndConvertData(&aRet, pUnoExc, cppu::UnoType<Any>::get().getTypeLibType(), + getReflection()->getUno2Cpp().get() ); + uno_any_destruct( pUnoExc, nullptr ); + throw InvocationTargetException("exception occurred during invocation!", + *o3tl::doAccess<Reference<XInterface>>(rObj), aRet); + } + 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!", + getXWeak(), 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/dump.cxx b/stoc/source/corereflection/dump.cxx new file mode 100644 index 0000000000..0905393db9 --- /dev/null +++ b/stoc/source/corereflection/dump.cxx @@ -0,0 +1,358 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include <sal/config.h> + +#include <bitset> + +#include <com/sun/star/container/NoSuchElementException.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/reflection/XConstantTypeDescription.hpp> +#include <com/sun/star/reflection/XConstantsTypeDescription.hpp> +#include <com/sun/star/reflection/XDump.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/DeploymentException.hpp> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Type.hxx> +#include <com/sun/star/uno/TypeClass.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <config_typesizes.h> +#include <cppu/unotype.hxx> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <o3tl/unreachable.hxx> +#include <osl/mutex.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/ustring.hxx> +#include <sal/log.hxx> +#include <sal/types.h> +#include <typelib/typedescription.h> +#include <typelib/typedescription.hxx> +#include <uno/sequence2.h> + +namespace com::sun::star::uno +{ +class XInterface; +} + +namespace +{ +template <typename T> OUString hex(T value, sal_Int32 width) +{ + OUStringBuffer buf(OUString::number(value, 16)); + while (buf.getLength() < width) + { + buf.insert(0, '0'); + } + return buf.makeStringAndClear(); +} + +css::uno::TypeDescription getTypeDescription(css::uno::Type const& type) +{ + typelib_TypeDescription* d = nullptr; + type.getDescription(&d); + return css::uno::TypeDescription(d); +} + +OUString +getIdentifier(css::uno::Reference<css::reflection::XConstantTypeDescription> const& constant) +{ + auto const n = constant->getName(); + auto const i = n.lastIndexOf('.'); + if (i == -1 || i == n.getLength() - 1) + { + throw css::uno::DeploymentException("bad constant name " + n); + } + return n.copy(i + 1); +} + +OUString +dumpBitset(css::uno::Sequence<css::uno::Reference<css::reflection::XConstantTypeDescription>> const& + constants, + sal_uInt64 value) +{ + OUStringBuffer buf; + auto a = value; + for (auto const& i : constants) + { + sal_uInt64 c; + if ((i->getConstantValue() >>= c) && std::bitset<64>{ c }.count() == 1 && (a & c) != 0) + { + if (!buf.isEmpty()) + { + buf.append('+'); + } + buf.append(getIdentifier(i)); + a &= ~c; + } + } + return a == 0 && !buf.isEmpty() ? buf.makeStringAndClear() : OUString::number(value); +} + +class Dump : public cppu::BaseMutex, public cppu::WeakComponentImplHelper<css::reflection::XDump> +{ +public: + explicit Dump(css::uno::Reference<css::uno::XComponentContext> const& context) + : WeakComponentImplHelper(m_aMutex) + , manager_(context->getValueByName( + "/singletons/com.sun.star.reflection.theTypeDescriptionManager"), + css::uno::UNO_QUERY_THROW) + { + } + + void SAL_CALL disposing() override + { + osl::MutexGuard g(m_aMutex); + manager_.clear(); + } + + OUString SAL_CALL dumpValue(css::uno::Any const& value) override + { + switch (value.getValueTypeClass()) + { + case css::uno::TypeClass_VOID: + return "void"; + case css::uno::TypeClass_BOOLEAN: + return OUString::boolean(value.get<bool>()); + case css::uno::TypeClass_BYTE: + return OUString::number(value.get<sal_Int8>()); + case css::uno::TypeClass_SHORT: + return OUString::number(value.get<sal_Int16>()); + case css::uno::TypeClass_UNSIGNED_SHORT: + return OUString::number(value.get<sal_uInt16>()); + case css::uno::TypeClass_LONG: + return OUString::number(value.get<sal_Int32>()); + case css::uno::TypeClass_UNSIGNED_LONG: + return OUString::number(value.get<sal_uInt32>()); + case css::uno::TypeClass_HYPER: + return OUString::number(value.get<sal_Int64>()); + case css::uno::TypeClass_UNSIGNED_HYPER: + return OUString::number(value.get<sal_uInt64>()); + case css::uno::TypeClass_FLOAT: + return OUString::number(value.get<float>()); + case css::uno::TypeClass_DOUBLE: + return OUString::number(value.get<double>()); + case css::uno::TypeClass_CHAR: + return "U+" + hex(value.get<sal_Unicode>(), 16); + case css::uno::TypeClass_STRING: + { + auto const s = value.get<OUString>(); + OUStringBuffer buf; + for (sal_Int32 i = 0; i != s.getLength();) + { + auto const c = s.iterateCodePoints(&i); + if (c >= u8' ' && c <= u8'~') + { + if (c == u8'\"' || c == u8'\\') + { + buf.append('\\'); + } + buf.append(char(c)); + } + else if (c <= 0xFFFF) + { + buf.append("\\u" + hex(c, 4)); + } + else + { + buf.append("\\U" + hex(c, 8)); + } + } + return "\"" + buf + "\""; + } + case css::uno::TypeClass_TYPE: + return value.get<css::uno::Type>().getTypeName(); + case css::uno::TypeClass_SEQUENCE: + { + css::uno::Type const t(reinterpret_cast<typelib_IndirectTypeDescription const*>( + getTypeDescription(value.getValueType()).get()) + ->pType); + auto const n = getTypeDescription(t).get()->nSize; + auto const s = *static_cast<uno_Sequence* const*>(value.getValue()); + OUStringBuffer buf; + for (sal_Int32 i = 0; i != s->nElements; ++i) + { + if (i != 0) + { + buf.append(", "); + } + css::uno::Any const e(s->elements + i * n, t); + buf.append(t == cppu::UnoType<css::uno::Any>::get() ? dumpAny(e) + : dumpValue(e)); + } + return "[" + buf + "]"; + } + case css::uno::TypeClass_ENUM: + { + auto const d = getTypeDescription(value.getValueType()); + auto const ed = reinterpret_cast<typelib_EnumTypeDescription const*>(d.get()); + auto const e = *static_cast<sal_Int32 const*>(value.getValue()); + for (sal_Int32 i = 0; i != ed->nEnumValues; ++i) + { + if (ed->pEnumValues[i] == e) + { + return OUString(ed->ppEnumNames[i]); + } + } + return OUString::number(e); + } + case css::uno::TypeClass_STRUCT: + case css::uno::TypeClass_EXCEPTION: + { + auto const d = getTypeDescription(value.getValueType()); + OUStringBuffer buf; + dumpCompoundType(reinterpret_cast<typelib_CompoundTypeDescription const*>(d.get()), + value.getValue(), &buf); + return "[" + buf + "]"; + } + case css::uno::TypeClass_INTERFACE: + { + auto const p = *static_cast<void* const*>(value.getValue()); + return p == nullptr ? OUString("null") + : OUString("0x" + + hex(reinterpret_cast<sal_uIntPtr>(p), + SAL_TYPES_SIZEOFPOINTER * 2)); + } + default: + O3TL_UNREACHABLE; + } + } + + OUString SAL_CALL dumpAny(css::uno::Any const& value) override + { + return "[" + value.getValueType().getTypeName() + ": " + dumpValue(value) + "]"; + } + + OUString SAL_CALL dumpConstant(OUString const& constantsGroup, + css::uno::Any const& value) override + { + css::uno::Reference<css::container::XHierarchicalNameAccess> manager; + { + osl::MutexGuard g(m_aMutex); + if (rBHelper.bDisposed) + { + throw css::lang::DisposedException("css.reflection.Dumper"); + } + manager = manager_; + } + css::uno::Reference<css::reflection::XConstantsTypeDescription> g; + try + { + manager_->getByHierarchicalName(constantsGroup) >>= g; + } + catch (css::container::NoSuchElementException) + { + } + if (!g.is()) + { + throw css::lang::IllegalArgumentException("not a constants group: " + constantsGroup, + {}, 0); + } + auto const s = g->getConstants(); + switch (value.getValueTypeClass()) + { + case css::uno::TypeClass_BOOLEAN: + for (auto const& i : s) + { + if (i->getConstantValue() == value) + { + return getIdentifier(i); + } + } + return OUString::boolean(value.get<bool>()); + case css::uno::TypeClass_BYTE: + case css::uno::TypeClass_SHORT: + case css::uno::TypeClass_LONG: + case css::uno::TypeClass_HYPER: + { + auto const v = value.get<sal_Int64>(); + for (auto const& i : s) + { + sal_Int64 c; + if ((i->getConstantValue() >>= c) && c == v) + { + return getIdentifier(i); + } + } + return v >= 0 ? dumpBitset(s, v) : OUString::number(v); + } + case css::uno::TypeClass_UNSIGNED_SHORT: + case css::uno::TypeClass_UNSIGNED_LONG: + case css::uno::TypeClass_UNSIGNED_HYPER: + { + auto const v = value.get<sal_uInt64>(); + for (auto const& i : s) + { + sal_uInt64 c; + if ((i->getConstantValue() >>= c) && c == v) + { + return getIdentifier(i); + } + } + return dumpBitset(s, v); + } + case css::uno::TypeClass_FLOAT: + case css::uno::TypeClass_DOUBLE: + { + auto const v = value.get<double>(); + for (auto const& i : s) + { + double c; + if ((i->getConstantValue() >>= c) && c == v) + { + return getIdentifier(i); + } + } + return OUString::number(v); + } + default: + throw css::lang::IllegalArgumentException( + "not a numeric type: " + value.getValueTypeName(), {}, 1); + } + } + +private: + css::uno::Reference<css::container::XHierarchicalNameAccess> manager_; + + void dumpCompoundType(typelib_CompoundTypeDescription const* description, void const* data, + OUStringBuffer* buffer) + { + if (auto base = description->pBaseTypeDescription) + { + dumpCompoundType(base, data, buffer); + } + for (sal_Int32 i = 0; i != description->nMembers; ++i) + { + if (!buffer->isEmpty()) + { + buffer->append(", "); + } + buffer->append(OUString::unacquired(description->ppMemberNames + i) + ": "); + css::uno::Type t(description->ppTypeRefs[i]); + css::uno::Any const m(static_cast<char const*>(data) + description->pMemberOffsets[i], + t); + buffer->append(t == cppu::UnoType<css::uno::Any>::get() ? dumpAny(m) : dumpValue(m)); + } + } +}; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_stoc_Dump_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 Dump(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/stoc/source/corereflection/lrucache.hxx b/stoc/source/corereflection/lrucache.hxx new file mode 100644 index 0000000000..d5eebe804f --- /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 0000000000..0210c80904 --- /dev/null +++ b/stoc/source/corereflection/reflection.component @@ -0,0 +1,33 @@ +<?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> + <implementation name="com.sun.star.comp.stoc.Dump" + constructor="com_sun_star_comp_stoc_Dump_get_implementation" + single-instance="true"> + <singleton name="com.sun.star.reflection.Dump"/> + </implementation> +</component> |