LCOV - code coverage report
Current view: top level - comphelper/source/container - enumerablemap.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 211 266 79.3 %
Date: 2014-11-03 Functions: 44 50 88.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include "comphelper_module.hxx"
      22             : #include "comphelper_services.hxx"
      23             : #include <comphelper/anytostring.hxx>
      24             : #include <comphelper/anycompare.hxx>
      25             : #include <comphelper/componentbase.hxx>
      26             : #include <comphelper/extract.hxx>
      27             : 
      28             : #include <com/sun/star/container/XEnumerableMap.hpp>
      29             : #include <com/sun/star/lang/XInitialization.hpp>
      30             : #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
      31             : #include <com/sun/star/beans/Pair.hpp>
      32             : #include <com/sun/star/lang/XServiceInfo.hpp>
      33             : 
      34             : #include <cppuhelper/compbase3.hxx>
      35             : #include <cppuhelper/implbase1.hxx>
      36             : #include <cppuhelper/supportsservice.hxx>
      37             : #include <rtl/math.hxx>
      38             : #include <rtl/ustrbuf.hxx>
      39             : #include <typelib/typedescription.hxx>
      40             : 
      41             : #include <map>
      42             : #include <memory>
      43             : #include <utility>
      44             : 
      45             : #include <boost/noncopyable.hpp>
      46             : 
      47             : namespace comphelper
      48             : {
      49             : 
      50             : 
      51             :     using ::com::sun::star::uno::Reference;
      52             :     using ::com::sun::star::uno::XInterface;
      53             :     using ::com::sun::star::uno::UNO_QUERY;
      54             :     using ::com::sun::star::uno::UNO_QUERY_THROW;
      55             :     using ::com::sun::star::uno::UNO_SET_THROW;
      56             :     using ::com::sun::star::uno::Exception;
      57             :     using ::com::sun::star::uno::RuntimeException;
      58             :     using ::com::sun::star::uno::Any;
      59             :     using ::com::sun::star::uno::makeAny;
      60             :     using ::com::sun::star::uno::Sequence;
      61             :     using ::com::sun::star::uno::Type;
      62             :     using ::com::sun::star::container::XEnumerableMap;
      63             :     using ::com::sun::star::lang::NoSupportException;
      64             :     using ::com::sun::star::beans::IllegalTypeException;
      65             :     using ::com::sun::star::container::NoSuchElementException;
      66             :     using ::com::sun::star::lang::IllegalArgumentException;
      67             :     using ::com::sun::star::lang::XInitialization;
      68             :     using ::com::sun::star::ucb::AlreadyInitializedException;
      69             :     using ::com::sun::star::beans::Pair;
      70             :     using ::com::sun::star::uno::TypeClass;
      71             :     using ::com::sun::star::uno::TypeClass_VOID;
      72             :     using ::com::sun::star::uno::TypeClass_UNKNOWN;
      73             :     using ::com::sun::star::uno::TypeClass_ANY;
      74             :     using ::com::sun::star::uno::TypeClass_EXCEPTION;
      75             :     using ::com::sun::star::uno::TypeClass_STRUCT;
      76             :     using ::com::sun::star::uno::TypeClass_FLOAT;
      77             :     using ::com::sun::star::uno::TypeClass_DOUBLE;
      78             :     using ::com::sun::star::uno::TypeClass_INTERFACE;
      79             :     using ::com::sun::star::lang::XServiceInfo;
      80             :     using ::com::sun::star::uno::XComponentContext;
      81             :     using ::com::sun::star::container::XEnumeration;
      82             :     using ::com::sun::star::uno::TypeDescription;
      83             :     using ::com::sun::star::lang::WrappedTargetException;
      84             :     using ::com::sun::star::lang::DisposedException;
      85             : 
      86             : 
      87             :     //= MapData
      88             : 
      89             :     class IMapModificationListener;
      90             :     typedef ::std::vector< IMapModificationListener* > MapListeners;
      91             : 
      92             :     typedef ::std::map< Any, Any, LessPredicateAdapter > KeyedValues;
      93          74 :     struct MapData
      94             :     {
      95             :         Type                                        m_aKeyType;
      96             :         Type                                        m_aValueType;
      97             :         ::std::unique_ptr< KeyedValues >            m_pValues;
      98             :         ::std::shared_ptr< IKeyPredicateLess >      m_pKeyCompare;
      99             :         bool                                        m_bMutable;
     100             :         MapListeners                                m_aModListeners;
     101             : 
     102          68 :         MapData()
     103          68 :             :m_bMutable( true )
     104             :         {
     105          68 :         }
     106             : 
     107           6 :         MapData( const MapData& _source )
     108             :             :m_aKeyType( _source.m_aKeyType )
     109             :             ,m_aValueType( _source.m_aValueType )
     110          12 :             ,m_pValues( new KeyedValues( *_source.m_pValues ) )
     111             :             ,m_pKeyCompare( _source.m_pKeyCompare )
     112             :             ,m_bMutable( false )
     113          18 :             ,m_aModListeners()
     114             :         {
     115           6 :         }
     116             :     private:
     117             :         MapData& operator=( const MapData& _source ) SAL_DELETED_FUNCTION;
     118             :     };
     119             : 
     120             : 
     121             :     //= IMapModificationListener
     122             : 
     123             :     /** implemented by components who want to be notified of modifications in the MapData they work with
     124             :     */
     125          12 :     class SAL_NO_VTABLE IMapModificationListener
     126             :     {
     127             :     public:
     128             :         /// called when the map was modified
     129             :         virtual void mapModified() = 0;
     130          12 :         virtual ~IMapModificationListener()
     131          12 :         {
     132          12 :         }
     133             :     };
     134             : 
     135             : 
     136             :     //= MapData helpers
     137             : 
     138             : 
     139          12 :     static void lcl_registerMapModificationListener( MapData& _mapData, IMapModificationListener& _listener )
     140             :     {
     141             :     #if OSL_DEBUG_LEVEL > 0
     142             :         for (   MapListeners::const_iterator lookup = _mapData.m_aModListeners.begin();
     143             :                 lookup != _mapData.m_aModListeners.end();
     144             :                 ++lookup
     145             :              )
     146             :         {
     147             :             OSL_ENSURE( *lookup != &_listener, "lcl_registerMapModificationListener: this listener is already registered!" );
     148             :         }
     149             :     #endif
     150          12 :         _mapData.m_aModListeners.push_back( &_listener );
     151          12 :     }
     152             : 
     153             : 
     154           6 :     static void lcl_revokeMapModificationListener( MapData& _mapData, IMapModificationListener& _listener )
     155             :     {
     156          18 :         for (   MapListeners::iterator lookup = _mapData.m_aModListeners.begin();
     157          12 :                 lookup != _mapData.m_aModListeners.end();
     158             :                 ++lookup
     159             :              )
     160             :         {
     161           6 :             if ( *lookup == &_listener )
     162             :             {
     163           6 :                 _mapData.m_aModListeners.erase( lookup );
     164          12 :                 return;
     165             :             }
     166             :         }
     167             :         OSL_FAIL( "lcl_revokeMapModificationListener: the listener is not registered!" );
     168             :     }
     169             : 
     170             : 
     171         292 :     static void lcl_notifyMapDataListeners_nothrow( const MapData& _mapData )
     172             :     {
     173         930 :         for (   MapListeners::const_iterator loop = _mapData.m_aModListeners.begin();
     174         620 :                 loop != _mapData.m_aModListeners.end();
     175             :                 ++loop
     176             :             )
     177             :         {
     178          18 :             (*loop)->mapModified();
     179             :         }
     180         292 :     }
     181             : 
     182             : 
     183             :     //= EnumerableMap
     184             : 
     185             :     typedef ::cppu::WeakAggComponentImplHelper3 <   XInitialization
     186             :                                                 ,   XEnumerableMap
     187             :                                                 ,   XServiceInfo
     188             :                                                 > Map_IFace;
     189             : 
     190             :     class COMPHELPER_DLLPRIVATE EnumerableMap :public Map_IFace
     191             :                                     ,public ComponentBase
     192             :     {
     193             :     protected:
     194             :         EnumerableMap();
     195             :         virtual ~EnumerableMap();
     196             : 
     197             :         // XInitialization
     198             :         virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException, std::exception) SAL_OVERRIDE;
     199             : 
     200             :         // XEnumerableMap
     201             :         virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createKeyEnumeration( sal_Bool _Isolated ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     202             :         virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createValueEnumeration( sal_Bool _Isolated ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     203             :         virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createElementEnumeration( sal_Bool _Isolated ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     204             : 
     205             :         // XMap
     206             :         virtual Type SAL_CALL getKeyType() throw (RuntimeException, std::exception) SAL_OVERRIDE;
     207             :         virtual Type SAL_CALL getValueType() throw (RuntimeException, std::exception) SAL_OVERRIDE;
     208             :         virtual void SAL_CALL clear(  ) throw (NoSupportException, RuntimeException, std::exception) SAL_OVERRIDE;
     209             :         virtual sal_Bool SAL_CALL containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception) SAL_OVERRIDE;
     210             :         virtual sal_Bool SAL_CALL containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception) SAL_OVERRIDE;
     211             :         virtual Any SAL_CALL get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception) SAL_OVERRIDE;
     212             :         virtual Any SAL_CALL put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception) SAL_OVERRIDE;
     213             :         virtual Any SAL_CALL remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception) SAL_OVERRIDE;
     214             : 
     215             :         // XElementAccess (base of XMap)
     216             :         virtual Type SAL_CALL getElementType() throw (RuntimeException, std::exception) SAL_OVERRIDE;
     217             :         virtual sal_Bool SAL_CALL hasElements() throw (RuntimeException, std::exception) SAL_OVERRIDE;
     218             : 
     219             :         // XServiceInfo
     220             :         virtual OUString SAL_CALL getImplementationName(  ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
     221             :         virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
     222             :         virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
     223             : 
     224             :     public:
     225             :         // XServiceInfo, static version (used for component registration)
     226             :         static OUString SAL_CALL getImplementationName_static(  );
     227             :         static Sequence< OUString > SAL_CALL getSupportedServiceNames_static(  );
     228             :         static Reference< XInterface > SAL_CALL Create( const Reference< XComponentContext >& );
     229             : 
     230             :     private:
     231             :         void    impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues );
     232             : 
     233             :         /// throws a IllegalTypeException if the given value is not compatible with our ValueType
     234             :         void    impl_checkValue_throw( const Any& _value ) const;
     235             :         void    impl_checkKey_throw( const Any& _key ) const;
     236             :         void    impl_checkNaN_throw( const Any& _keyOrValue, const Type& _keyOrValueType ) const;
     237             :         void    impl_checkMutable_throw() const;
     238             : 
     239             :     private:
     240             :         ::osl::Mutex        m_aMutex;
     241             :         MapData             m_aData;
     242             : 
     243             :         ::std::vector< ::com::sun::star::uno::WeakReference< XInterface > >
     244             :                             m_aDependentComponents;
     245             :     };
     246             : 
     247             : 
     248             :     //= EnumerationType
     249             : 
     250             :     enum EnumerationType
     251             :     {
     252             :         eKeys, eValues, eBoth
     253             :     };
     254             : 
     255             : 
     256             :     //= MapEnumerator
     257             : 
     258             :     class MapEnumerator:
     259             :         public IMapModificationListener, private boost::noncopyable
     260             :     {
     261             :     public:
     262          12 :         MapEnumerator( ::cppu::OWeakObject& _rParent, MapData& _mapData, const EnumerationType _type )
     263             :             :m_rParent( _rParent )
     264             :             ,m_rMapData( _mapData )
     265             :             ,m_eType( _type )
     266          12 :             ,m_mapPos( _mapData.m_pValues->begin() )
     267          24 :             ,m_disposed( false )
     268             :         {
     269          12 :             lcl_registerMapModificationListener( m_rMapData, *this );
     270          12 :         }
     271             : 
     272          12 :         virtual ~MapEnumerator()
     273          24 :         {
     274          12 :             dispose();
     275          12 :         }
     276             : 
     277          24 :         void dispose()
     278             :         {
     279          24 :             if ( !m_disposed )
     280             :             {
     281           6 :                 lcl_revokeMapModificationListener( m_rMapData, *this );
     282           6 :                 m_disposed = true;
     283             :             }
     284          24 :         }
     285             : 
     286             :         // XEnumeration equivalents
     287             :         bool hasMoreElements();
     288             :         Any nextElement();
     289             : 
     290             :         // IMapModificationListener
     291             :         virtual void mapModified() SAL_OVERRIDE;
     292             : 
     293             :     private:
     294             :         ::cppu::OWeakObject&        m_rParent;
     295             :         MapData&                    m_rMapData;
     296             :         const EnumerationType       m_eType;
     297             :         KeyedValues::const_iterator m_mapPos;
     298             :         bool                        m_disposed;
     299             :     };
     300             : 
     301             : 
     302             :     //= MapEnumeration
     303             : 
     304             :     typedef ::cppu::WeakImplHelper1 <   XEnumeration
     305             :                                     >   MapEnumeration_Base;
     306             :     class MapEnumeration :public ComponentBase
     307             :                          ,public MapEnumeration_Base
     308             :     {
     309             :     public:
     310          12 :         MapEnumeration( ::cppu::OWeakObject& _parentMap, MapData& _mapData, ::cppu::OBroadcastHelper& _rBHelper,
     311             :                         const EnumerationType _type, const bool _isolated )
     312             :             :ComponentBase( _rBHelper, ComponentBase::NoInitializationNeeded() )
     313             :             ,m_xKeepMapAlive( _parentMap )
     314           6 :             ,m_pMapDataCopy( _isolated ? new MapData( _mapData ) : NULL )
     315          18 :             ,m_aEnumerator( *this, _isolated ? *m_pMapDataCopy : _mapData, _type )
     316             :         {
     317          12 :         }
     318             : 
     319             :         // XEnumeration
     320             :         virtual sal_Bool SAL_CALL hasMoreElements(  ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
     321             :         virtual Any SAL_CALL nextElement(  ) throw (NoSuchElementException, WrappedTargetException, RuntimeException, std::exception) SAL_OVERRIDE;
     322             : 
     323             :     protected:
     324          24 :         virtual ~MapEnumeration()
     325          24 :         {
     326          12 :             acquire();
     327             :             {
     328          12 :                 ::osl::MutexGuard aGuard( getMutex() );
     329          12 :                 m_aEnumerator.dispose();
     330          12 :                 m_pMapDataCopy.reset();
     331             :             }
     332          24 :         }
     333             : 
     334             :     private:
     335             :         // since we share our mutex with the main map, we need to keep it alive as long as we live
     336             :         Reference< XInterface >     m_xKeepMapAlive;
     337             :         ::std::unique_ptr< MapData > m_pMapDataCopy;
     338             :         MapEnumerator               m_aEnumerator;
     339             :     };
     340             : 
     341             : 
     342             :     //= EnumerableMap
     343             : 
     344             : 
     345          68 :     EnumerableMap::EnumerableMap()
     346             :         :Map_IFace( m_aMutex )
     347          68 :         ,ComponentBase( Map_IFace::rBHelper )
     348             :     {
     349          68 :     }
     350             : 
     351             : 
     352         204 :     EnumerableMap::~EnumerableMap()
     353             :     {
     354          68 :         if ( !impl_isDisposed() )
     355             :         {
     356           0 :             acquire();
     357           0 :             dispose();
     358             :         }
     359         136 :     }
     360             : 
     361             : 
     362          68 :     void SAL_CALL EnumerableMap::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException, std::exception)
     363             :     {
     364          68 :         ComponentMethodGuard aGuard( *this, ComponentMethodGuard::WithoutInit );
     365          68 :         if ( impl_isInitialized_nothrow() )
     366           0 :             throw AlreadyInitializedException();
     367             : 
     368          68 :         sal_Int32 nArgumentCount = _arguments.getLength();
     369          68 :         if ( ( nArgumentCount != 2 ) && ( nArgumentCount != 3 ) )
     370           0 :             throw IllegalArgumentException();
     371             : 
     372         136 :         Type aKeyType, aValueType;
     373          68 :         if ( !( _arguments[0] >>= aKeyType ) )
     374           0 :             throw IllegalArgumentException("com.sun.star.uno.Type expected.", *this, 1 );
     375          68 :         if ( !( _arguments[1] >>= aValueType ) )
     376           0 :             throw IllegalArgumentException("com.sun.star.uno.Type expected.", *this, 2 );
     377             : 
     378         136 :         Sequence< Pair< Any, Any > > aInitialValues;
     379          68 :         bool bMutable = true;
     380          68 :         if ( nArgumentCount == 3 )
     381             :         {
     382          18 :             if ( !( _arguments[2] >>= aInitialValues ) )
     383           0 :                 throw IllegalArgumentException("[]com.sun.star.beans.Pair<any,any> expected.", *this, 2 );
     384          18 :             bMutable = false;
     385             :         }
     386             : 
     387             :         // for the value, anything is allowed, except VOID
     388          68 :         if ( ( aValueType.getTypeClass() == TypeClass_VOID ) || ( aValueType.getTypeClass() == TypeClass_UNKNOWN ) )
     389           0 :             throw IllegalTypeException("Unsupported value type.", *this );
     390             : 
     391             :         // create the comparator for the KeyType, and throw if the type is not supported
     392         136 :         ::std::unique_ptr< IKeyPredicateLess > pComparator( getStandardLessPredicate( aKeyType, NULL ) );
     393          68 :         if ( !pComparator.get() )
     394           0 :             throw IllegalTypeException("Unsupported key type.", *this );
     395             : 
     396             :         // init members
     397          68 :         m_aData.m_aKeyType = aKeyType;
     398          68 :         m_aData.m_aValueType = aValueType;
     399          68 :         m_aData.m_pKeyCompare = std::move(pComparator);
     400          68 :         m_aData.m_pValues.reset( new KeyedValues( *m_aData.m_pKeyCompare ) );
     401          68 :         m_aData.m_bMutable = bMutable;
     402             : 
     403          68 :         if ( aInitialValues.getLength() )
     404          18 :             impl_initValues_throw( aInitialValues );
     405             : 
     406         136 :         setInitialized();
     407          68 :     }
     408             : 
     409             : 
     410          18 :     void EnumerableMap::impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues )
     411             :     {
     412             :         OSL_PRECOND( m_aData.m_pValues.get() && m_aData.m_pValues->empty(), "EnumerableMap::impl_initValues_throw: illegal call!" );
     413          18 :         if ( !m_aData.m_pValues.get() || !m_aData.m_pValues->empty() )
     414           0 :             throw RuntimeException();
     415             : 
     416          18 :         const Pair< Any, Any >* mapping = _initialValues.getConstArray();
     417          18 :         const Pair< Any, Any >* mappingEnd = mapping + _initialValues.getLength();
     418         102 :         for ( ; mapping != mappingEnd; ++mapping )
     419             :         {
     420          84 :             impl_checkValue_throw( mapping->Second );
     421          84 :             (*m_aData.m_pValues)[ mapping->First ] = mapping->Second;
     422             :         }
     423          18 :     }
     424             : 
     425             : 
     426         446 :     void EnumerableMap::impl_checkValue_throw( const Any& _value ) const
     427             :     {
     428         446 :         if ( !_value.hasValue() )
     429             :             // nothing to do, NULL values are always allowed, regardless of the ValueType
     430         446 :             return;
     431             : 
     432         446 :         TypeClass eAllowedTypeClass = m_aData.m_aValueType.getTypeClass();
     433         446 :         bool bValid = false;
     434             : 
     435         446 :         switch ( eAllowedTypeClass )
     436             :         {
     437             :         default:
     438         446 :             bValid = ( _value.getValueTypeClass() == eAllowedTypeClass );
     439         446 :             break;
     440             :         case TypeClass_ANY:
     441           0 :             bValid = true;
     442           0 :             break;
     443             :         case TypeClass_INTERFACE:
     444             :         {
     445             :             // special treatment: _value might contain the proper type, but the interface
     446             :             // might actually be NULL. Which is still valid ...
     447           0 :             if ( m_aData.m_aValueType.isAssignableFrom( _value.getValueType() ) )
     448             :                 // this also catches the special case where XFoo is our value type,
     449             :                 // and _value contains a NULL-reference to XFoo, or a derived type
     450           0 :                 bValid = true;
     451             :             else
     452             :             {
     453           0 :                 Reference< XInterface > xValue( _value, UNO_QUERY );
     454           0 :                 if ( xValue.is() )
     455             :                     // XInterface is not-NULL, but is X(ValueType) not-NULL, too?
     456           0 :                     xValue.set( xValue->queryInterface( m_aData.m_aValueType ), UNO_QUERY );
     457           0 :                 bValid = xValue.is();
     458             :             }
     459             :         }
     460           0 :         break;
     461             :         case TypeClass_EXCEPTION:
     462             :         case TypeClass_STRUCT:
     463             :         {
     464             :             // values are accepted if and only if their type equals, or is derived from, our value type
     465             : 
     466           0 :             if ( _value.getValueTypeClass() != eAllowedTypeClass )
     467           0 :                 bValid = false;
     468             :             else
     469             :             {
     470           0 :                 const TypeDescription aValueTypeDesc( _value.getValueType() );
     471           0 :                 const TypeDescription aRequiredTypeDesc( m_aData.m_aValueType );
     472             : 
     473             :                 const _typelib_CompoundTypeDescription* pValueCompoundTypeDesc =
     474           0 :                     reinterpret_cast< const _typelib_CompoundTypeDescription* >( aValueTypeDesc.get() );
     475             : 
     476           0 :                 while ( pValueCompoundTypeDesc )
     477             :                 {
     478           0 :                     if ( typelib_typedescription_equals( &pValueCompoundTypeDesc->aBase, aRequiredTypeDesc.get() ) )
     479           0 :                         break;
     480           0 :                     pValueCompoundTypeDesc = pValueCompoundTypeDesc->pBaseTypeDescription;
     481             :                 }
     482           0 :                 bValid = ( pValueCompoundTypeDesc != NULL );
     483             :             }
     484             :         }
     485           0 :         break;
     486             :         }
     487             : 
     488         446 :         if ( !bValid )
     489             :         {
     490           0 :             OUStringBuffer aMessage;
     491           0 :             aMessage.appendAscii( "Incompatible value type. Found '" );
     492           0 :             aMessage.append( _value.getValueTypeName() );
     493           0 :             aMessage.appendAscii( "', where '" );
     494           0 :             aMessage.append( m_aData.m_aValueType.getTypeName() );
     495           0 :             aMessage.appendAscii( "' (or compatible type) is expected." );
     496           0 :             throw IllegalTypeException( aMessage.makeStringAndClear(), *const_cast< EnumerableMap* >( this ) );
     497             :         }
     498             : 
     499         446 :         impl_checkNaN_throw( _value, m_aData.m_aValueType );
     500             :     }
     501             : 
     502             : 
     503        1062 :     void EnumerableMap::impl_checkNaN_throw( const Any& _keyOrValue, const Type& _keyOrValueType ) const
     504             :     {
     505        2124 :         if  (   ( _keyOrValueType.getTypeClass() == TypeClass_DOUBLE )
     506        1062 :             ||  ( _keyOrValueType.getTypeClass() == TypeClass_FLOAT )
     507             :             )
     508             :         {
     509         264 :             double nValue(0);
     510         264 :             if ( _keyOrValue >>= nValue )
     511         264 :                 if ( ::rtl::math::isNan( nValue ) )
     512             :                     throw IllegalArgumentException(
     513             :                         "NaN (not-a-number) not supported by this implementation.",
     514           0 :                         *const_cast< EnumerableMap* >( this ), 0 );
     515             :             // (note that the case of _key not containing a float/double value is handled in the
     516             :             // respective IKeyPredicateLess implementation, so there's no need to handle this here.)
     517             :         }
     518        1062 :     }
     519             : 
     520             : 
     521         616 :     void EnumerableMap::impl_checkKey_throw( const Any& _key ) const
     522             :     {
     523         616 :         if ( !_key.hasValue() )
     524             :             throw IllegalArgumentException(
     525             :                 "NULL keys not supported by this implementation.",
     526           0 :                 *const_cast< EnumerableMap* >( this ), 0 );
     527             : 
     528         616 :         impl_checkNaN_throw( _key, m_aData.m_aKeyType );
     529         616 :     }
     530             : 
     531             : 
     532         292 :     void EnumerableMap::impl_checkMutable_throw() const
     533             :     {
     534         292 :         if ( !m_aData.m_bMutable )
     535             :             throw NoSupportException(
     536             :                     "The map is immutable.",
     537           0 :                     *const_cast< EnumerableMap* >( this ) );
     538         292 :     }
     539             : 
     540             : 
     541           4 :     Reference< XEnumeration > SAL_CALL EnumerableMap::createKeyEnumeration( sal_Bool _Isolated ) throw (NoSupportException, RuntimeException, std::exception)
     542             :     {
     543           4 :         ComponentMethodGuard aGuard( *this );
     544           4 :         return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eKeys, _Isolated );
     545             :     }
     546             : 
     547             : 
     548           4 :     Reference< XEnumeration > SAL_CALL EnumerableMap::createValueEnumeration( sal_Bool _Isolated ) throw (NoSupportException, RuntimeException, std::exception)
     549             :     {
     550           4 :         ComponentMethodGuard aGuard( *this );
     551           4 :         return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eValues, _Isolated );
     552             :     }
     553             : 
     554             : 
     555           4 :     Reference< XEnumeration > SAL_CALL EnumerableMap::createElementEnumeration( sal_Bool _Isolated ) throw (NoSupportException, RuntimeException, std::exception)
     556             :     {
     557           4 :         ComponentMethodGuard aGuard( *this );
     558           4 :         return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eBoth, _Isolated );
     559             :     }
     560             : 
     561             : 
     562          18 :     Type SAL_CALL EnumerableMap::getKeyType() throw (RuntimeException, std::exception)
     563             :     {
     564          18 :         ComponentMethodGuard aGuard( *this );
     565          18 :         return m_aData.m_aKeyType;
     566             :     }
     567             : 
     568             : 
     569          18 :     Type SAL_CALL EnumerableMap::getValueType() throw (RuntimeException, std::exception)
     570             :     {
     571          18 :         ComponentMethodGuard aGuard( *this );
     572          18 :         return m_aData.m_aValueType;
     573             :     }
     574             : 
     575             : 
     576          18 :     void SAL_CALL EnumerableMap::clear(  ) throw (NoSupportException, RuntimeException, std::exception)
     577             :     {
     578          18 :         ComponentMethodGuard aGuard( *this );
     579          18 :         impl_checkMutable_throw();
     580             : 
     581          18 :         m_aData.m_pValues->clear();
     582             : 
     583          18 :         lcl_notifyMapDataListeners_nothrow( m_aData );
     584          18 :     }
     585             : 
     586             : 
     587         174 :     sal_Bool SAL_CALL EnumerableMap::containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception)
     588             :     {
     589         174 :         ComponentMethodGuard aGuard( *this );
     590         174 :         impl_checkKey_throw( _key );
     591             : 
     592         174 :         KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key );
     593         174 :         return ( pos != m_aData.m_pValues->end() );
     594             :     }
     595             : 
     596             : 
     597         174 :     sal_Bool SAL_CALL EnumerableMap::containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception)
     598             :     {
     599         174 :         ComponentMethodGuard aGuard( *this );
     600         174 :         impl_checkValue_throw( _value );
     601             : 
     602        1656 :         for (   KeyedValues::const_iterator mapping = m_aData.m_pValues->begin();
     603        1104 :                 mapping != m_aData.m_pValues->end();
     604             :                 ++mapping
     605             :             )
     606             :         {
     607         552 :             if ( mapping->second == _value )
     608         174 :                 return sal_True;
     609             :         }
     610           0 :         return sal_False;
     611             :     }
     612             : 
     613             : 
     614         168 :     Any SAL_CALL EnumerableMap::get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception)
     615             :     {
     616         168 :         ComponentMethodGuard aGuard( *this );
     617         168 :         impl_checkKey_throw( _key );
     618             : 
     619         168 :         KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key );
     620         168 :         if ( pos == m_aData.m_pValues->end() )
     621           0 :             throw NoSuchElementException( anyToString( _key ), *this );
     622             : 
     623         168 :         return pos->second;
     624             :     }
     625             : 
     626             : 
     627         188 :     Any SAL_CALL EnumerableMap::put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception)
     628             :     {
     629         188 :         ComponentMethodGuard aGuard( *this );
     630         188 :         impl_checkMutable_throw();
     631         188 :         impl_checkKey_throw( _key );
     632         188 :         impl_checkValue_throw( _value );
     633             : 
     634         188 :         Any previousValue;
     635             : 
     636         188 :         KeyedValues::iterator pos = m_aData.m_pValues->find( _key );
     637         188 :         if ( pos != m_aData.m_pValues->end() )
     638             :         {
     639           0 :             previousValue = pos->second;
     640           0 :             pos->second = _value;
     641             :         }
     642             :         else
     643             :         {
     644         188 :             (*m_aData.m_pValues)[ _key ] = _value;
     645             :         }
     646             : 
     647         188 :         lcl_notifyMapDataListeners_nothrow( m_aData );
     648             : 
     649         188 :         return previousValue;
     650             :     }
     651             : 
     652             : 
     653          86 :     Any SAL_CALL EnumerableMap::remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception)
     654             :     {
     655          86 :         ComponentMethodGuard aGuard( *this );
     656          86 :         impl_checkMutable_throw();
     657          86 :         impl_checkKey_throw( _key );
     658             : 
     659          86 :         Any previousValue;
     660             : 
     661          86 :         KeyedValues::iterator pos = m_aData.m_pValues->find( _key );
     662          86 :         if ( pos != m_aData.m_pValues->end() )
     663             :         {
     664          86 :             previousValue = pos->second;
     665          86 :             m_aData.m_pValues->erase( pos );
     666             :         }
     667             : 
     668          86 :         lcl_notifyMapDataListeners_nothrow( m_aData );
     669             : 
     670          86 :         return previousValue;
     671             :     }
     672             : 
     673             : 
     674           0 :     Type SAL_CALL EnumerableMap::getElementType() throw (RuntimeException, std::exception)
     675             :     {
     676           0 :         return ::cppu::UnoType< Pair< Any, Any > >::get();
     677             :     }
     678             : 
     679             : 
     680          72 :     sal_Bool SAL_CALL EnumerableMap::hasElements() throw (RuntimeException, std::exception)
     681             :     {
     682          72 :         ComponentMethodGuard aGuard( *this );
     683          72 :         return m_aData.m_pValues->empty();
     684             :     }
     685             : 
     686             : 
     687           0 :     OUString SAL_CALL EnumerableMap::getImplementationName(  ) throw (RuntimeException, std::exception)
     688             :     {
     689           0 :         return getImplementationName_static();
     690             :     }
     691             : 
     692           0 :     sal_Bool SAL_CALL EnumerableMap::supportsService( const OUString& _serviceName ) throw (RuntimeException, std::exception)
     693             :     {
     694           0 :         return cppu::supportsService(this, _serviceName);
     695             :     }
     696             : 
     697             : 
     698           0 :     Sequence< OUString > SAL_CALL EnumerableMap::getSupportedServiceNames(  ) throw (RuntimeException, std::exception)
     699             :     {
     700           0 :         return getSupportedServiceNames_static();
     701             :     }
     702             : 
     703             : 
     704         284 :     OUString SAL_CALL EnumerableMap::getImplementationName_static(  )
     705             :     {
     706         284 :         return OUString( "org.openoffice.comp.comphelper.EnumerableMap" );
     707             :     }
     708             : 
     709             : 
     710         284 :     Sequence< OUString > SAL_CALL EnumerableMap::getSupportedServiceNames_static(  )
     711             :     {
     712         284 :         Sequence< OUString > aServiceNames(1);
     713         284 :         aServiceNames[0] = "com.sun.star.container.EnumerableMap";
     714         284 :         return aServiceNames;
     715             :     }
     716             : 
     717             : 
     718          68 :     Reference< XInterface > SAL_CALL EnumerableMap::Create( SAL_UNUSED_PARAMETER const Reference< XComponentContext >& )
     719             :     {
     720          68 :         return *new EnumerableMap;
     721             :     }
     722             : 
     723             : 
     724             :     //= MapEnumerator
     725             : 
     726             : 
     727          60 :     bool MapEnumerator::hasMoreElements()
     728             :     {
     729          60 :         if ( m_disposed )
     730           0 :             throw DisposedException( OUString(), m_rParent );
     731          60 :         return m_mapPos != m_rMapData.m_pValues->end();
     732             :     }
     733             : 
     734             : 
     735          60 :     Any MapEnumerator::nextElement()
     736             :     {
     737          60 :         if ( m_disposed )
     738           0 :             throw DisposedException( OUString(), m_rParent );
     739          60 :         if ( m_mapPos == m_rMapData.m_pValues->end() )
     740           0 :             throw NoSuchElementException("No more elements.", m_rParent );
     741             : 
     742          60 :         Any aNextElement;
     743          60 :         switch ( m_eType )
     744             :         {
     745          20 :         case eKeys:     aNextElement = m_mapPos->first; break;
     746          20 :         case eValues:   aNextElement = m_mapPos->second; break;
     747          20 :         case eBoth:     aNextElement <<= Pair< Any, Any >( m_mapPos->first, m_mapPos->second ); break;
     748             :         }
     749          60 :         ++m_mapPos;
     750          60 :         return aNextElement;
     751             :     }
     752             : 
     753             : 
     754          18 :     void MapEnumerator::mapModified()
     755             :     {
     756          18 :         m_disposed = true;
     757          18 :     }
     758             : 
     759             : 
     760             :     //= MapEnumeration - implementation
     761             : 
     762             : 
     763          60 :     sal_Bool SAL_CALL MapEnumeration::hasMoreElements(  ) throw (RuntimeException, std::exception)
     764             :     {
     765          60 :         ComponentMethodGuard aGuard( *this );
     766          60 :         return m_aEnumerator.hasMoreElements();
     767             :     }
     768             : 
     769             : 
     770          60 :     Any SAL_CALL MapEnumeration::nextElement(  ) throw (NoSuchElementException, WrappedTargetException, RuntimeException, std::exception)
     771             :     {
     772          60 :         ComponentMethodGuard aGuard( *this );
     773          60 :         return m_aEnumerator.nextElement();
     774             :     }
     775             : 
     776             : 
     777             : } // namespace comphelper
     778             : 
     779             : 
     780         284 : void createRegistryInfo_Map()
     781             : {
     782         284 :     ::comphelper::module::OAutoRegistration< ::comphelper::EnumerableMap > aAutoRegistration;
     783         284 : }
     784             : 
     785             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10