LCOV - code coverage report
Current view: top level - lunchbox - any.h (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 42 43 97.7 %
Date: 2014-08-05 Functions: 187 190 98.4 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2012, Daniel Nachbaur <daniel.nachbaur@gmail.com>
       3             :  *
       4             :  * This library is free software; you can redistribute it and/or modify it under
       5             :  * the terms of the GNU Lesser General Public License version 3.0 as published
       6             :  * by the Free Software Foundation.
       7             :  *
       8             :  * This library is distributed in the hope that it will be useful, but WITHOUT
       9             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      10             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      11             :  * details.
      12             :  *
      13             :  * You should have received a copy of the GNU Lesser General Public License
      14             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      15             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      16             :  */
      17             : 
      18             : // Based on boost/any.hpp
      19             : // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
      20             : //
      21             : // Distributed under the Boost Software License, Version 1.0. (See
      22             : // accompanying file LICENSE_1_0.txt or copy at
      23             : // http://www.boost.org/LICENSE_1_0.txt)
      24             : 
      25             : 
      26             : #ifndef LUNCHBOX_ANY_H
      27             : #define LUNCHBOX_ANY_H
      28             : 
      29             : #include <lunchbox/api.h>
      30             : #include <lunchbox/debug.h>
      31             : 
      32             : #include <boost/type_traits/remove_reference.hpp>
      33             : #include <boost/shared_ptr.hpp>
      34             : #include <boost/serialization/access.hpp>
      35             : #include <boost/serialization/assume_abstract.hpp>
      36             : #include <boost/serialization/base_object.hpp>
      37             : #include <boost/serialization/shared_ptr.hpp>
      38             : 
      39             : // See boost/python/type_id.hpp
      40             : // TODO: add BOOST_TYPEID_COMPARE_BY_NAME to config.hpp
      41             : # if (defined(__GNUC__) && __GNUC__ >= 3) \
      42             :  || defined(_AIX) \
      43             :  || (   defined(__sgi) && defined(__host_mips)) \
      44             :  || (defined(__hpux) && defined(__HP_aCC)) \
      45             :  || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
      46             : #  define BOOST_AUX_ANY_TYPE_ID_NAME
      47             : #  include <cstring>
      48             : # endif
      49             : 
      50             : 
      51             : namespace lunchbox
      52             : {
      53             : 
      54             : /**
      55             :  * A class which can hold instances of any type.
      56             :  *
      57             :  * This class is based on boost.any with the extension to support serialization
      58             :  * if the ValueType supports boost.serialization.
      59             :  *
      60             :  * Example: @include tests/any.cpp
      61             :  */
      62             : class Any
      63             : {
      64             : public:
      65             :     /** @name Construction/Destruction */
      66             :     //@{
      67             :     /** Construct a new, empty Any. @version 1.5.0 */
      68             :     LUNCHBOX_API Any();
      69             : 
      70             :     /** Construct a new Any with the given value. @version 1.5.0 */
      71             :     template< typename ValueType >
      72          18 :     Any( const ValueType& value )
      73          18 :       : content( new holder< ValueType >( value ))
      74             :     {
      75          18 :     }
      76             : 
      77             :     /** Copy-construct a new Any with copying content of other. @version 1.5.0*/
      78             :     LUNCHBOX_API Any( const Any& other );
      79             : 
      80             :     /** Destruct this Any. @version 1.5.0 */
      81             :     LUNCHBOX_API ~Any();
      82             :     //@}
      83             : 
      84             :     /** @name Modifiers */
      85             :     //@{
      86             :     /** Exchange the content of this and rhs. @version 1.5.0 */
      87             :     LUNCHBOX_API Any& swap( Any& rhs );
      88             : 
      89             :     /** Assign a new value to this Any. @version 1.5.0 */
      90             :     template< typename ValueType >
      91           4 :     Any& operator=( const ValueType& rhs )
      92             :     {
      93           4 :         Any( rhs ).swap( *this );
      94           4 :         return *this;
      95             :     }
      96             : 
      97             :     /** Exchange the content of this and rhs. @version 1.5.0 */
      98             :     LUNCHBOX_API Any& operator=( Any rhs );
      99             :     //@}
     100             : 
     101             :     /** @name Queries */
     102             :     //@{
     103             :     /** @return true if this Any is not holding a value. @version 1.5.0 */
     104             :     LUNCHBOX_API bool empty() const;
     105             : 
     106             :     /**
     107             :      * @return the typeid of the contained value if non-empty, otherwise
     108             :      * typeid(void).
     109             :      * @version 1.5.0
     110             :      */
     111             :     LUNCHBOX_API const std::type_info& type() const;
     112             : 
     113             :     /**
     114             :      * @return true if this and rhs are empty or if their values are equal.
     115             :      * @version 1.5.0
     116             :      */
     117             :     LUNCHBOX_API bool operator == ( const Any& rhs ) const;
     118             : 
     119             :     /**
     120             :      * @return true if the value from this and rhs are not equal.
     121             :      * @version 1.5.0
     122             :      */
     123           1 :     bool operator != ( const Any& rhs ) const { return !(*this == rhs); }
     124             :     //@}
     125             : 
     126             : 
     127             :     /** @cond IGNORE */
     128          61 :     class placeholder
     129             :     {
     130             :     public:
     131          61 :         virtual ~placeholder() {}
     132             : 
     133             :         virtual bool operator == ( const placeholder& rhs ) const = 0;
     134             : 
     135             :         bool operator != ( const placeholder& rhs ) const
     136             :             { return !(*this == rhs); }
     137             : 
     138             :         virtual const std::type_info& type() const = 0;
     139             : 
     140             :         virtual placeholder* clone() const = 0;
     141             : 
     142             :     private:
     143             :         friend class boost::serialization::access;
     144             :         template< class Archive >
     145          56 :         void serialize( Archive&, const unsigned int ) {}
     146             :     };
     147             : 
     148             :     BOOST_SERIALIZATION_ASSUME_ABSTRACT(placeholder)
     149             : 
     150             :     template< typename ValueType >
     151         122 :     class holder : public placeholder
     152             :     {
     153             :     public:
     154          28 :         holder()
     155          28 :             : held()
     156             :         {
     157          28 :         }
     158             : 
     159          33 :         explicit holder( const ValueType& value )
     160          33 :           : held( value )
     161             :         {
     162          33 :         }
     163             : 
     164          69 :         virtual const std::type_info& type() const
     165             :         {
     166          69 :             return typeid(ValueType);
     167             :         }
     168             : 
     169          30 :         virtual bool operator == ( const placeholder& rhs ) const
     170             :         {
     171          30 :             return held == static_cast< const holder& >( rhs ).held;
     172             :         }
     173             : 
     174          15 :         virtual placeholder* clone() const
     175             :         {
     176          15 :             return new holder( held );
     177             :         }
     178             : 
     179             :         ValueType held;
     180             : 
     181             :     private:
     182             :         holder& operator=( const holder& );
     183             : 
     184             :         friend class boost::serialization::access;
     185             :         template< class Archive >
     186          56 :         void serialize( Archive & ar, const unsigned int /*version*/ )
     187             :         {
     188             :             // serialize base class information
     189          56 :             ar & boost::serialization::base_object< placeholder >( *this );
     190          56 :             ar & held;
     191          56 :         }
     192             :     };
     193             :     /** @endcond */
     194             : 
     195             : private:
     196             :     template< typename ValueType >
     197             :     friend ValueType* any_cast( Any* );
     198             : 
     199             :     template< typename ValueType >
     200             :     friend ValueType* unsafe_any_cast( Any* );
     201             : 
     202             :     friend class boost::serialization::access;
     203             :     template< class Archive >
     204          56 :     void serialize( Archive & ar, const unsigned int /*version*/ )
     205             :     {
     206          56 :         ar & content;
     207          56 :     }
     208             : 
     209             :     boost::shared_ptr< placeholder > content;
     210             : };
     211             : 
     212             : /** A specialization for exceptions thrown by an unsuccessful any_cast. */
     213           5 : class bad_any_cast : public std::bad_cast
     214             : {
     215             : public:
     216             :     LUNCHBOX_API bad_any_cast( const std::string& from, const std::string& to );
     217             : 
     218           0 :     virtual const char* what() const throw() { return data; }
     219             : 
     220             : private:
     221             :     char data[256];
     222             : };
     223             : 
     224             : /**
     225             :  * Retrieve the value stored in an Any including type checking.
     226             :  *
     227             :  * @return the value stored in the given Any, 0 if types are not matching
     228             :  * @version 1.5.0
     229             :  */
     230             : template< typename ValueType >
     231           4 : ValueType* any_cast( Any* operand )
     232             : {
     233             :     return operand &&
     234             : #ifdef BOOST_AUX_ANY_TYPE_ID_NAME
     235           4 :         std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0
     236             : #else
     237             :         operand->type() == typeid(ValueType)
     238             : #endif
     239           3 :         ? &static_cast<Any::holder<ValueType> *>(operand->content.get())->held
     240          11 :         : 0;
     241             : }
     242             : 
     243             : /**
     244             :  * Retrieve the value stored in an Any including type checking.
     245             :  *
     246             :  * @return the value stored in the given Any, 0 if types are not matching
     247             :  * @version 1.5.0
     248             :  */
     249             : template< typename ValueType >
     250             : inline const ValueType* any_cast( const Any* operand )
     251             : {
     252             :     return any_cast<ValueType>(const_cast<Any *>(operand));
     253             : }
     254             : 
     255             : /**
     256             :  * Retrieve the value stored in an Any including type checking.
     257             :  *
     258             :  * @return the value stored in the given Any
     259             :  * @throw bad_any_cast if types are not matching
     260             :  * @version 1.5.0
     261             :  */
     262             : template< typename ValueType >
     263           4 : ValueType any_cast( Any& operand )
     264             : {
     265             :     typedef typename boost::remove_reference< ValueType >::type nonref;
     266             : 
     267           4 :     nonref* result = any_cast< nonref >( &operand );
     268           4 :     if( !result )
     269           1 :         boost::throw_exception(
     270           1 :                       bad_any_cast( demangleTypeID( operand.type().name( )),
     271           3 :                                     demangleTypeID( typeid( nonref ).name( ))));
     272           3 :     return *result;
     273             : }
     274             : 
     275             : /**
     276             :  * Retrieve the value stored in an Any including type checking.
     277             :  *
     278             :  * @return the value stored in the given Any
     279             :  * @throw bad_any_cast if types are not matching
     280             :  * @version 1.5.0
     281             :  */
     282             : template< typename ValueType >
     283             : inline ValueType any_cast( const Any& operand )
     284             : {
     285             :     typedef typename boost::remove_reference< ValueType >::type nonref;
     286             : 
     287             :     return any_cast< const nonref& >( const_cast< Any& >( operand ));
     288             : }
     289             : 
     290             : /**
     291             :  * Retrieve the value stored in an Any without type checking.
     292             :  *
     293             :  * @return the value stored in the given Any
     294             :  * @version 1.5.0
     295             :  */
     296             : template< typename ValueType >
     297             : inline ValueType* unsafe_any_cast( Any* operand )
     298             : {
     299             :     return &static_cast< Any::holder< ValueType >* >(
     300             :                              operand->content.get( ))->held;
     301             : }
     302             : 
     303             : /**
     304             :  * Retrieve the value stored in an Any without type checking.
     305             :  *
     306             :  * @return the value stored in the given Any
     307             :  * @version 1.5.0
     308             :  */
     309             : template< typename ValueType >
     310             : inline const ValueType* unsafe_any_cast( const Any* operand )
     311             : {
     312             :     return unsafe_any_cast< ValueType >( const_cast< Any* > ( operand ));
     313             : }
     314             : 
     315             : /**
     316             :  * Retrieve the value stored in an Any without type checking.
     317             :  *
     318             :  * @return the value stored in the given Any
     319             :  * @version 1.5.0
     320             :  */
     321             : template< typename ValueType >
     322             : ValueType unsafe_any_cast( Any& operand )
     323             : {
     324             :     typedef typename boost::remove_reference< ValueType >::type nonref;
     325             :     return *unsafe_any_cast< nonref >( &operand );
     326             : }
     327             : 
     328             : /**
     329             :  * Retrieve the value stored in an Any without type checking.
     330             :  *
     331             :  * @return the value stored in the given Any
     332             :  * @version 1.5.0
     333             :  */
     334             : template< typename ValueType >
     335             : ValueType unsafe_any_cast( const Any& operand )
     336             : {
     337             :    typedef typename boost::remove_reference< ValueType >::type nonref;
     338             :    return unsafe_any_cast< const nonref& >( const_cast< Any& >( operand ));
     339             : }
     340             : 
     341             : }
     342             : 
     343             : #endif

Generated by: LCOV version 1.10