00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef ATTRIBUTE_HPP
00026 #define ATTRIBUTE_HPP
00027
00028
00029 #include <boost/any.hpp>
00030
00031 #include <typeinfo>
00032 #include <sstream>
00033 #include <map>
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