00001
00002
00003
00004
00005
00006
00007
00008 #include <algorithm>
00009 #include <iomanip>
00010 #include "libtorrent/entry.hpp"
00011 #include "libtorrent/config.hpp"
00012
00013 #if defined(_MSC_VER)
00014 namespace std
00015 {
00016 using ::isprint;
00017 }
00018 #define for if (false) {} else for
00019 #endif
00020
00021 namespace
00022 {
00023 template <class T>
00024 void call_destructor(T* o)
00025 {
00026 assert(o);
00027 o->~T();
00028 }
00029
00030 struct compare_string
00031 {
00032 compare_string(char const* s): m_str(s) {}
00033
00034 bool operator()(
00035 std::pair<std::string
00036 , libtorrent::entry> const& e) const
00037 {
00038 return m_str && e.first == m_str;
00039 }
00040 char const* m_str;
00041 };
00042 }
00043
00044 namespace libtorrent
00045 {
00046 namespace detail
00047 {
00048 TORRENT_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val)
00049 {
00050 int sign = 0;
00051 if (val < 0)
00052 {
00053 sign = 1;
00054 val = -val;
00055 }
00056 buf[--size] = '\0';
00057 if (val == 0) buf[--size] = '0';
00058 for (; size > sign && val != 0;)
00059 {
00060 buf[--size] = '0' + char(val % 10);
00061 val /= 10;
00062 }
00063 if (sign) buf[--size] = '-';
00064 return buf + size;
00065 }
00066 }
00067
00068 entry& entry::operator[](char const* key)
00069 {
00070 dictionary_type::iterator i = dict().find(key);
00071 if (i != dict().end()) return i->second;
00072 dictionary_type::iterator ret = dict().insert(
00073 dict().begin()
00074 , std::make_pair(std::string(key), entry()));
00075 return ret->second;
00076 }
00077
00078 entry& entry::operator[](std::string const& key)
00079 {
00080 return (*this)[key.c_str()];
00081 }
00082
00083 entry* entry::find_key(char const* key)
00084 {
00085 dictionary_type::iterator i = std::find_if(
00086 dict().begin()
00087 , dict().end()
00088 , compare_string(key));
00089 if (i == dict().end()) return 0;
00090 return &i->second;
00091
00092 }
00093
00094 entry const* entry::find_key(char const* key) const
00095 {
00096 dictionary_type::const_iterator i = dict().find(key);
00097 if (i == dict().end()) return 0;
00098 return &i->second;
00099 }
00100
00101 const entry& entry::operator[](char const* key) const
00102 {
00103 dictionary_type::const_iterator i = dict().find(key);
00104 if (i == dict().end()) throw type_error(
00105 (std::string("key not found: ") + key).c_str());
00106 return i->second;
00107 }
00108
00109 const entry& entry::operator[](std::string const& key) const
00110 {
00111 return (*this)[key.c_str()];
00112 }
00113
00114 entry::entry(dictionary_type const& v)
00115 {
00116 new(data) dictionary_type(v);
00117 m_type = dictionary_t;
00118 }
00119
00120 entry::entry(string_type const& v)
00121 {
00122 new(data) string_type(v);
00123 m_type = string_t;
00124 }
00125
00126 entry::entry(list_type const& v)
00127 {
00128 new(data) list_type(v);
00129 m_type = list_t;
00130 }
00131
00132 entry::entry(integer_type const& v)
00133 {
00134 new(data) integer_type(v);
00135 m_type = int_t;
00136 }
00137
00138 void entry::operator=(dictionary_type const& v)
00139 {
00140 destruct();
00141 new(data) dictionary_type(v);
00142 m_type = dictionary_t;
00143 }
00144
00145 void entry::operator=(string_type const& v)
00146 {
00147 destruct();
00148 new(data) string_type(v);
00149 m_type = string_t;
00150 }
00151
00152 void entry::operator=(list_type const& v)
00153 {
00154 destruct();
00155 new(data) list_type(v);
00156 m_type = list_t;
00157 }
00158
00159 void entry::operator=(integer_type const& v)
00160 {
00161 destruct();
00162 new(data) integer_type(v);
00163 m_type = int_t;
00164 }
00165
00166 bool entry::operator==(entry const& e) const
00167 {
00168 if (m_type != e.m_type) return false;
00169
00170 switch(m_type)
00171 {
00172 case int_t:
00173 return integer() == e.integer();
00174 case string_t:
00175 return string() == e.string();
00176 case list_t:
00177 return list() == e.list();
00178 case dictionary_t:
00179 return dict() == e.dict();
00180 default:
00181 assert(m_type == undefined_t);
00182 return true;
00183 }
00184 }
00185
00186 void entry::construct(data_type t)
00187 {
00188 m_type = t;
00189 switch(m_type)
00190 {
00191 case int_t:
00192 new(data) integer_type;
00193 break;
00194 case string_t:
00195 new(data) string_type;
00196 break;
00197 case list_t:
00198 new(data) list_type;
00199 break;
00200 case dictionary_t:
00201 new (data) dictionary_type;
00202 break;
00203 default:
00204 assert(m_type == undefined_t);
00205 m_type = undefined_t;
00206 }
00207 }
00208
00209 void entry::copy(entry const& e)
00210 {
00211 m_type = e.m_type;
00212 switch(m_type)
00213 {
00214 case int_t:
00215 new(data) integer_type(e.integer());
00216 break;
00217 case string_t:
00218 new(data) string_type(e.string());
00219 break;
00220 case list_t:
00221 new(data) list_type(e.list());
00222 break;
00223 case dictionary_t:
00224 new (data) dictionary_type(e.dict());
00225 break;
00226 default:
00227 m_type = undefined_t;
00228 }
00229 }
00230
00231 void entry::destruct()
00232 {
00233 switch(m_type)
00234 {
00235 case int_t:
00236 call_destructor(reinterpret_cast<integer_type*>(data));
00237 break;
00238 case string_t:
00239 call_destructor(reinterpret_cast<string_type*>(data));
00240 break;
00241 case list_t:
00242 call_destructor(reinterpret_cast<list_type*>(data));
00243 break;
00244 case dictionary_t:
00245 call_destructor(reinterpret_cast<dictionary_type*>(data));
00246 break;
00247 default:
00248 assert(m_type == undefined_t);
00249 break;
00250 }
00251 }
00252
00253 void entry::print(std::ostream& os, int indent) const
00254 {
00255 assert(indent >= 0);
00256 for (int i = 0; i < indent; ++i) os << " ";
00257 switch (m_type)
00258 {
00259 case int_t:
00260 os << integer() << "\n";
00261 break;
00262 case string_t:
00263 {
00264 bool binary_string = false;
00265 for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
00266 {
00267 if (!std::isprint(static_cast<unsigned char>(*i)))
00268 {
00269 binary_string = true;
00270 break;
00271 }
00272 }
00273 if (binary_string)
00274 {
00275 os.unsetf(std::ios_base::dec);
00276 os.setf(std::ios_base::hex);
00277 for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
00278 os << std::setfill('0') << std::setw(2)
00279 << static_cast<unsigned int>((unsigned char)*i);
00280 os.unsetf(std::ios_base::hex);
00281 os.setf(std::ios_base::dec);
00282 os << "\n";
00283 }
00284 else
00285 {
00286 os << string() << "\n";
00287 }
00288 } break;
00289 case list_t:
00290 {
00291 os << "list\n";
00292 for (list_type::const_iterator i = list().begin(); i != list().end(); ++i)
00293 {
00294 i->print(os, indent+1);
00295 }
00296 } break;
00297 case dictionary_t:
00298 {
00299 os << "dictionary\n";
00300 for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i)
00301 {
00302 for (int j = 0; j < indent+1; ++j) os << " ";
00303 os << "[" << i->first << "]";
00304 if (i->second.type() != entry::string_t
00305 && i->second.type() != entry::int_t)
00306 os << "\n";
00307 else os << " ";
00308 i->second.print(os, indent+2);
00309 }
00310 } break;
00311 default:
00312 os << "<uninitialized>\n";
00313 }
00314 }
00315 }
00316