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

Generated by: LCOV version 1.10