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
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef TORRENT_ENTRY_HPP_INCLUDED
00034 #define TORRENT_ENTRY_HPP_INCLUDED
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 #include <iostream>
00063 #include <map>
00064 #include <list>
00065 #include <string>
00066 #include <stdexcept>
00067 #include <cassert>
00068
00069 #include "libtorrent/size_type.hpp"
00070 #include "libtorrent/config.hpp"
00071
00072 namespace libtorrent
00073 {
00074
00075 struct TORRENT_EXPORT type_error: std::runtime_error
00076 {
00077 type_error(const char* error): std::runtime_error(error) {}
00078 };
00079
00080 namespace detail
00081 {
00082 template<int v1, int v2>
00083 struct max2 { enum { value = v1>v2?v1:v2 }; };
00084
00085 template<int v1, int v2, int v3>
00086 struct max3
00087 {
00088 enum
00089 {
00090 temp = max2<v1,v2>::value,
00091 value = temp>v3?temp:v3
00092 };
00093 };
00094
00095 template<int v1, int v2, int v3, int v4>
00096 struct max4
00097 {
00098 enum
00099 {
00100 temp = max3<v1,v2, v3>::value,
00101 value = temp>v4?temp:v4
00102 };
00103 };
00104 }
00105
00106 class entry;
00107
00108 class TORRENT_EXPORT entry
00109 {
00110 public:
00111
00112
00113
00114
00115 typedef std::map<std::string, entry> dictionary_type;
00116 typedef std::string string_type;
00117 typedef std::list<entry> list_type;
00118 typedef size_type integer_type;
00119
00120 enum data_type
00121 {
00122 int_t,
00123 string_t,
00124 list_t,
00125 dictionary_t,
00126 undefined_t
00127 };
00128
00129 data_type type() const;
00130
00131 entry(dictionary_type const&);
00132 entry(string_type const&);
00133 entry(list_type const&);
00134 entry(integer_type const&);
00135
00136 entry();
00137 entry(data_type t);
00138 entry(entry const& e);
00139 ~entry();
00140
00141 bool operator==(entry const& e) const;
00142
00143 void operator=(entry const&);
00144 void operator=(dictionary_type const&);
00145 void operator=(string_type const&);
00146 void operator=(list_type const&);
00147 void operator=(integer_type const&);
00148
00149 integer_type& integer();
00150 const integer_type& integer() const;
00151 string_type& string();
00152 const string_type& string() const;
00153 list_type& list();
00154 const list_type& list() const;
00155 dictionary_type& dict();
00156 const dictionary_type& dict() const;
00157
00158
00159
00160 entry& operator[](char const* key);
00161 entry& operator[](std::string const& key);
00162 const entry& operator[](char const* key) const;
00163 const entry& operator[](std::string const& key) const;
00164 entry* find_key(char const* key);
00165 entry const* find_key(char const* key) const;
00166
00167 void print(std::ostream& os, int indent = 0) const;
00168
00169 private:
00170
00171 void construct(data_type t);
00172 void copy(const entry& e);
00173 void destruct();
00174
00175 data_type m_type;
00176
00177 #if defined(_MSC_VER) && _MSC_VER < 1310
00178
00179
00180
00181 union
00182 {
00183 char data[
00184 detail::max4<sizeof(std::list<char>)
00185 , sizeof(std::map<std::string, char>)
00186 , sizeof(string_type)
00187 , sizeof(integer_type)>::value];
00188 integer_type dummy_aligner;
00189 };
00190 #else
00191 union
00192 {
00193 char data[detail::max4<sizeof(list_type)
00194 , sizeof(dictionary_type)
00195 , sizeof(string_type)
00196 , sizeof(integer_type)>::value];
00197 integer_type dummy_aligner;
00198 };
00199 #endif
00200
00201 };
00202
00203 inline std::ostream& operator<<(std::ostream& os, const entry& e)
00204 {
00205 e.print(os, 0);
00206 return os;
00207 }
00208
00209 inline entry::data_type entry::type() const { return m_type; }
00210
00211 inline entry::entry(): m_type(undefined_t) {}
00212 inline entry::entry(data_type t): m_type(t) { construct(t); }
00213 inline entry::entry(const entry& e) { copy(e); }
00214 inline entry::~entry() { destruct(); }
00215
00216 inline void entry::operator=(const entry& e)
00217 {
00218 destruct();
00219 copy(e);
00220 }
00221
00222 inline entry::integer_type& entry::integer()
00223 {
00224 if (m_type == undefined_t) construct(int_t);
00225 if (m_type != int_t) throw type_error("invalid type requested from entry");
00226 return *reinterpret_cast<integer_type*>(data);
00227 }
00228
00229 inline entry::integer_type const& entry::integer() const
00230 {
00231 if (m_type != int_t) throw type_error("invalid type requested from entry");
00232 return *reinterpret_cast<const integer_type*>(data);
00233 }
00234
00235 inline entry::string_type& entry::string()
00236 {
00237 if (m_type == undefined_t) construct(string_t);
00238 if (m_type != string_t) throw type_error("invalid type requested from entry");
00239 return *reinterpret_cast<string_type*>(data);
00240 }
00241
00242 inline entry::string_type const& entry::string() const
00243 {
00244 if (m_type != string_t) throw type_error("invalid type requested from entry");
00245 return *reinterpret_cast<const string_type*>(data);
00246 }
00247
00248 inline entry::list_type& entry::list()
00249 {
00250 if (m_type == undefined_t) construct(list_t);
00251 if (m_type != list_t) throw type_error("invalid type requested from entry");
00252 return *reinterpret_cast<list_type*>(data);
00253 }
00254
00255 inline entry::list_type const& entry::list() const
00256 {
00257 if (m_type != list_t) throw type_error("invalid type requested from entry");
00258 return *reinterpret_cast<const list_type*>(data);
00259 }
00260
00261 inline entry::dictionary_type& entry::dict()
00262 {
00263 if (m_type == undefined_t) construct(dictionary_t);
00264 if (m_type != dictionary_t) throw type_error("invalid type requested from entry");
00265 return *reinterpret_cast<dictionary_type*>(data);
00266 }
00267
00268 inline entry::dictionary_type const& entry::dict() const
00269 {
00270 if (m_type != dictionary_t) throw type_error("invalid type requested from entry");
00271 return *reinterpret_cast<const dictionary_type*>(data);
00272 }
00273
00274 }
00275
00276 #endif // TORRENT_ENTRY_HPP_INCLUDED