/home/andreas/src/svn/mapnik/include/mapnik/attribute.hpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * 
00003  * This file is part of Mapnik (c++ mapping toolkit)
00004  *
00005  * Copyright (C) 2006 Artem Pavlenko
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020  *
00021  *****************************************************************************/
00022 
00023 //$Id: attribute.hpp 41 2005-04-13 20:21:56Z pavlenko $
00024 
00025 #ifndef ATTRIBUTE_HPP
00026 #define ATTRIBUTE_HPP
00027 
00028 // stl
00029 #include <typeinfo>
00030 #include <sstream>
00031 #include <map>
00032 // boost
00033 #include <boost/any.hpp>
00034 
00035 namespace mapnik {
00036     template <typename T>
00037     struct attribute_traits
00038     {
00039         static std::string to_string(const T& value)
00040         {
00041             std::stringstream ss;
00042             ss << value;
00043             return ss.str();
00044         }
00045     };
00046 
00047     template <>
00048     struct attribute_traits<std::string>
00049     {
00050         static std::string to_string(const std::string& value)
00051         {
00052             return value;
00053         }
00054     };
00055     
00056     class MAPNIK_DECL attribute
00057     {   
00058     public:
00059         attribute()
00060             : base_(0) {}
00061 
00062         template <typename T>
00063         attribute(const T& value)
00064             : base_(new attribute_impl<T>(value)) 
00065         {}
00066 
00067         attribute(const attribute& rhs)
00068             : base_(rhs.base_ ? rhs.base_->clone() : 0)
00069         {}
00070 
00071         ~attribute() 
00072         {
00073             delete base_;
00074         }
00075 
00076         template<typename T>
00077         attribute& operator=(const T& rhs)
00078         {
00079             attribute(rhs).swap(*this);
00080             return *this;
00081         }
00082 
00083         attribute& operator=(const attribute& rhs)
00084         {
00085             attribute(rhs).swap(*this);
00086             return *this;
00087         }
00088 
00089         bool empty() const
00090         {
00091             return !base_;
00092         }
00093 
00094         const std::type_info & type() const
00095         {
00096             return base_ ? base_->type() : typeid(void);
00097         }
00098 
00099         const std::string to_string() const
00100         {
00101             return base_ ? base_->to_string() : "";
00102         }
00103     private:
00104         attribute& swap(attribute& rhs)
00105         {
00106             std::swap(base_,rhs.base_);
00107             return *this;
00108         }
00109         
00110         class attribute_base
00111         {
00112         public:
00113             virtual ~attribute_base() {}
00114             virtual attribute_base* clone() const=0;
00115             virtual std::string to_string() const=0;
00116             virtual const std::type_info& type()  const=0;
00117         };
00118 
00119         template <typename T,typename ATraits=attribute_traits<T> >
00120         class attribute_impl : public attribute_base
00121         {           
00122         public:
00123             typedef T value_type;
00124             attribute_impl(const value_type& value)
00125                 : value_(value) {}
00126             
00127             virtual std::string to_string() const
00128             {
00129                 return  ATraits::to_string(value_);
00130             }
00131             
00132             virtual attribute_base* clone() const
00133             {
00134                 return new attribute_impl(value_);
00135             }
00136             virtual const std::type_info& type() const 
00137             {
00138                 return typeid(value_);
00139             }
00140             value_type value_;
00141         };
00142     private:
00143         template<typename value_type>
00144         friend value_type* attribute_cast(attribute*);
00145         attribute_base* base_;
00146     };
00147     
00148     
00149     template<typename T>
00150     struct bad_attribute_cast : public std::bad_cast
00151     {
00152         virtual const char* what() const throw()
00153         {
00154             return "attribute::failed conversion";
00155         }
00156     };
00157     
00158     template <typename T> 
00159     bool is_type(const attribute& attr)
00160     {
00161         return attr.type()==typeid(T);
00162     }
00163     
00164     template <typename T>
00165     T* attribute_cast(attribute* attr)
00166     {
00167         return attr && attr->type() == typeid(T)
00168             ? &static_cast<attribute::attribute_impl<T>*>(attr->base_)->value_
00169             : 0;
00170     }
00171 
00172     template <typename T>
00173     const T* attribute_cast(const attribute* attr)
00174     {
00175         return attribute_cast<T>(const_cast<attribute*>(attr));
00176     }
00177     
00178     template <typename T>
00179     T attribute_cast(const attribute& attr)
00180     {
00181         using namespace boost;
00182         typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
00183         const nonref * result=attribute_cast<nonref>(&attr);
00184         if (!result)
00185         {
00186             throw bad_attribute_cast<T>();
00187         }
00188         return *result;
00189     }
00190     
00191     template <typename T>
00192     T attribute_cast(attribute& attr)
00193     {
00194         using namespace boost;
00195         typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
00196         nonref * result=attribute_cast<nonref>(&attr);
00197         if (!result)
00198             throw bad_attribute_cast<T>();
00199         return *result;
00200     }
00201     
00202        
00203     template <typename T>
00204     attribute attribute_from_string(const std::string& val)
00205     {
00206         std::istringstream is(val);
00207         T t;
00208         is >> t;
00209         return attribute(t);
00210     }
00211 
00212     template <typename charT, typename traits>
00213     inline std::basic_ostream<charT,traits>& 
00214     operator << (std::basic_ostream<charT,traits>& out,
00215                  const attribute& attr)
00216     {
00217         out << attr.to_string();
00218         return out; 
00219     }
00220 }
00221 
00222 #endif //ATTRIBUTE_HPP

Generated on Thu Jul 19 17:59:25 2007 for Mapnik by  doxygen 1.4.7