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

Generated by: LCOV version 1.11