LCOV - code coverage report
Current view: top level - lunchbox - any.h (source / functions) Hit Total Coverage
Test: Lunchbox Lines: 42 43 97.7 %
Date: 2015-07-07 14:54:45 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             : 
      35             : // Don't reorder below!
      36             : #include <boost/serialization/singleton.hpp>
      37             : #include <boost/serialization/extended_type_info.hpp>
      38             : #include <boost/serialization/access.hpp>
      39             : #include <boost/serialization/assume_abstract.hpp>
      40             : #include <boost/serialization/base_object.hpp>
      41             : #include <boost/serialization/type_info_implementation.hpp>
      42             : #include <boost/serialization/shared_ptr.hpp>
      43             : 
      44             : // See boost/python/type_id.hpp
      45             : // TODO: add BOOST_TYPEID_COMPARE_BY_NAME to config.hpp
      46             : # if (defined(__GNUC__) && __GNUC__ >= 3) \
      47             :  || defined(_AIX) \
      48             :  || (   defined(__sgi) && defined(__host_mips)) \
      49             :  || (defined(__hpux) && defined(__HP_aCC)) \
      50             :  || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
      51             : #  define BOOST_AUX_ANY_TYPE_ID_NAME
      52             : #  include <cstring>
      53             : # endif
      54             : 
      55             : 
      56             : namespace lunchbox
      57             : {
      58             : 
      59             : /**
      60             :  * A class which can hold instances of any type.
      61             :  *
      62             :  * This class is based on boost.any with the extension to support serialization
      63             :  * if the ValueType supports boost.serialization.
      64             :  *
      65             :  * Example: @include tests/any.cpp
      66             :  */
      67             : class Any
      68             : {
      69             : public:
      70             :     /** @name Construction/Destruction */
      71             :     //@{
      72             :     /** Construct a new, empty Any. @version 1.5.0 */
      73             :     LUNCHBOX_API Any();
      74             : 
      75             :     /** Construct a new Any with the given value. @version 1.5.0 */
      76             :     template< typename ValueType >
      77          18 :     Any( const ValueType& value )
      78          18 :       : content( new holder< ValueType >( value ))
      79             :     {
      80          18 :     }
      81             : 
      82             :     /** Copy-construct a new Any with copying content of other. @version 1.5.0*/
      83             :     LUNCHBOX_API Any( const Any& other );
      84             : 
      85             :     /** Destruct this Any. @version 1.5.0 */
      86             :     LUNCHBOX_API ~Any();
      87             :     //@}
      88             : 
      89             :     /** @name Modifiers */
      90             :     //@{
      91             :     /** Exchange the content of this and rhs. @version 1.5.0 */
      92             :     LUNCHBOX_API Any& swap( Any& rhs );
      93             : 
      94             :     /** Assign a new value to this Any. @version 1.5.0 */
      95             :     template< typename ValueType >
      96           4 :     Any& operator=( const ValueType& rhs )
      97             :     {
      98           4 :         Any( rhs ).swap( *this );
      99           4 :         return *this;
     100             :     }
     101             : 
     102             :     /** Exchange the content of this and rhs. @version 1.5.0 */
     103             :     LUNCHBOX_API Any& operator=( Any rhs );
     104             :     //@}
     105             : 
     106             :     /** @name Queries */
     107             :     //@{
     108             :     /** @return true if this Any is not holding a value. @version 1.5.0 */
     109             :     LUNCHBOX_API bool empty() const;
     110             : 
     111             :     /**
     112             :      * @return the typeid of the contained value if non-empty, otherwise
     113             :      * typeid(void).
     114             :      * @version 1.5.0
     115             :      */
     116             :     LUNCHBOX_API const std::type_info& type() const;
     117             : 
     118             :     /**
     119             :      * @return true if this and rhs are empty or if their values are equal.
     120             :      * @version 1.5.0
     121             :      */
     122             :     LUNCHBOX_API bool operator == ( const Any& rhs ) const;
     123             : 
     124             :     /**
     125             :      * @return true if the value from this and rhs are not equal.
     126             :      * @version 1.5.0
     127             :      */
     128           1 :     bool operator != ( const Any& rhs ) const { return !(*this == rhs); }
     129             :     //@}
     130             : 
     131             : 
     132             :     /** @cond IGNORE */
     133          61 :     class placeholder
     134             :     {
     135             :     public:
     136          61 :         virtual ~placeholder() {}
     137             : 
     138             :         virtual bool operator == ( const placeholder& rhs ) const = 0;
     139             : 
     140             :         bool operator != ( const placeholder& rhs ) const
     141             :             { return !(*this == rhs); }
     142             : 
     143             :         virtual const std::type_info& type() const = 0;
     144             : 
     145             :         virtual placeholder* clone() const = 0;
     146             : 
     147             :     private:
     148             :         friend class boost::serialization::access;
     149             :         template< class Archive >
     150          56 :         void serialize( Archive&, const unsigned int ) {}
     151             :     };
     152             : 
     153             :     BOOST_SERIALIZATION_ASSUME_ABSTRACT(placeholder)
     154             : 
     155             :     template< typename ValueType >
     156         122 :     class holder : public placeholder
     157             :     {
     158             :     public:
     159          28 :         holder()
     160          28 :             : held()
     161             :         {
     162          28 :         }
     163             : 
     164          33 :         explicit holder( const ValueType& value )
     165          33 :           : held( value )
     166             :         {
     167          33 :         }
     168             : 
     169          69 :         virtual const std::type_info& type() const
     170             :         {
     171          69 :             return typeid(ValueType);
     172             :         }
     173             : 
     174          30 :         virtual bool operator == ( const placeholder& rhs ) const
     175             :         {
     176          30 :             return held == static_cast< const holder& >( rhs ).held;
     177             :         }
     178             : 
     179          15 :         virtual placeholder* clone() const
     180             :         {
     181          15 :             return new holder( held );
     182             :         }
     183             : 
     184             :         ValueType held;
     185             : 
     186             :     private:
     187             :         holder& operator=( const holder& );
     188             : 
     189             :         friend class boost::serialization::access;
     190             :         template< class Archive >
     191          56 :         void serialize( Archive & ar, const unsigned int /*version*/ )
     192             :         {
     193             :             // serialize base class information
     194          56 :             ar & boost::serialization::base_object< placeholder >( *this );
     195          56 :             ar & held;
     196          56 :         }
     197             :     };
     198             :     /** @endcond */
     199             : 
     200             : private:
     201             :     template< typename ValueType >
     202             :     friend ValueType* any_cast( Any* );
     203             : 
     204             :     template< typename ValueType >
     205             :     friend ValueType* unsafe_any_cast( Any* );
     206             : 
     207             :     friend class boost::serialization::access;
     208             :     template< class Archive >
     209          56 :     void serialize( Archive & ar, const unsigned int /*version*/ )
     210             :     {
     211          56 :         ar & content;
     212          56 :     }
     213             : 
     214             :     boost::shared_ptr< placeholder > content;
     215             : };
     216             : 
     217             : /** A specialization for exceptions thrown by an unsuccessful any_cast. */
     218           5 : class bad_any_cast : public std::bad_cast
     219             : {
     220             : public:
     221             :     LUNCHBOX_API bad_any_cast( const std::string& from, const std::string& to );
     222             : 
     223           0 :     virtual const char* what() const throw() { return data; }
     224             : 
     225             : private:
     226             :     char data[256];
     227             : };
     228             : 
     229             : /**
     230             :  * Retrieve the value stored in an Any including type checking.
     231             :  *
     232             :  * @return the value stored in the given Any, 0 if types are not matching
     233             :  * @version 1.5.0
     234             :  */
     235             : template< typename ValueType >
     236           4 : ValueType* any_cast( Any* operand )
     237             : {
     238             :     return operand &&
     239             : #ifdef BOOST_AUX_ANY_TYPE_ID_NAME
     240           4 :         std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0
     241             : #else
     242             :         operand->type() == typeid(ValueType)
     243             : #endif
     244           3 :         ? &static_cast<Any::holder<ValueType> *>(operand->content.get())->held
     245          11 :         : 0;
     246             : }
     247             : 
     248             : /**
     249             :  * Retrieve the value stored in an Any including type checking.
     250             :  *
     251             :  * @return the value stored in the given Any, 0 if types are not matching
     252             :  * @version 1.5.0
     253             :  */
     254             : template< typename ValueType >
     255             : inline const ValueType* any_cast( const Any* operand )
     256             : {
     257             :     return any_cast<ValueType>(const_cast<Any *>(operand));
     258             : }
     259             : 
     260             : /**
     261             :  * Retrieve the value stored in an Any including type checking.
     262             :  *
     263             :  * @return the value stored in the given Any
     264             :  * @throw bad_any_cast if types are not matching
     265             :  * @version 1.5.0
     266             :  */
     267             : template< typename ValueType >
     268           4 : ValueType any_cast( Any& operand )
     269             : {
     270             :     typedef typename boost::remove_reference< ValueType >::type nonref;
     271             : 
     272           4 :     nonref* result = any_cast< nonref >( &operand );
     273           4 :     if( !result )
     274           1 :         boost::throw_exception(
     275           1 :                       bad_any_cast( demangleTypeID( operand.type().name( )),
     276           3 :                                     demangleTypeID( typeid( nonref ).name( ))));
     277           3 :     return *result;
     278             : }
     279             : 
     280             : /**
     281             :  * Retrieve the value stored in an Any including type checking.
     282             :  *
     283             :  * @return the value stored in the given Any
     284             :  * @throw bad_any_cast if types are not matching
     285             :  * @version 1.5.0
     286             :  */
     287             : template< typename ValueType >
     288             : inline ValueType any_cast( const Any& operand )
     289             : {
     290             :     typedef typename boost::remove_reference< ValueType >::type nonref;
     291             : 
     292             :     return any_cast< const nonref& >( const_cast< Any& >( operand ));
     293             : }
     294             : 
     295             : /**
     296             :  * Retrieve the value stored in an Any without type checking.
     297             :  *
     298             :  * @return the value stored in the given Any
     299             :  * @version 1.5.0
     300             :  */
     301             : template< typename ValueType >
     302             : inline ValueType* unsafe_any_cast( Any* operand )
     303             : {
     304             :     return &static_cast< Any::holder< ValueType >* >(
     305             :                              operand->content.get( ))->held;
     306             : }
     307             : 
     308             : /**
     309             :  * Retrieve the value stored in an Any without type checking.
     310             :  *
     311             :  * @return the value stored in the given Any
     312             :  * @version 1.5.0
     313             :  */
     314             : template< typename ValueType >
     315             : inline const ValueType* unsafe_any_cast( const Any* operand )
     316             : {
     317             :     return unsafe_any_cast< ValueType >( const_cast< Any* > ( operand ));
     318             : }
     319             : 
     320             : /**
     321             :  * Retrieve the value stored in an Any without type checking.
     322             :  *
     323             :  * @return the value stored in the given Any
     324             :  * @version 1.5.0
     325             :  */
     326             : template< typename ValueType >
     327             : ValueType unsafe_any_cast( Any& operand )
     328             : {
     329             :     typedef typename boost::remove_reference< ValueType >::type nonref;
     330             :     return *unsafe_any_cast< nonref >( &operand );
     331             : }
     332             : 
     333             : /**
     334             :  * Retrieve the value stored in an Any without type checking.
     335             :  *
     336             :  * @return the value stored in the given Any
     337             :  * @version 1.5.0
     338             :  */
     339             : template< typename ValueType >
     340             : ValueType unsafe_any_cast( const Any& operand )
     341             : {
     342             :    typedef typename boost::remove_reference< ValueType >::type nonref;
     343             :    return unsafe_any_cast< const nonref& >( const_cast< Any& >( operand ));
     344             : }
     345             : 
     346             : }
     347             : 
     348             : #endif

Generated by: LCOV version 1.11