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

Generated by: LCOV version 1.10