~ubuntu-branches/ubuntu/trusty/miro/trusty

« back to all changes in this revision

Viewing changes to portable/libtorrent/include/libtorrent/entry.hpp

  • Committer: Daniel Hahler
  • Date: 2010-04-13 18:51:35 UTC
  • mfrom: (1.2.10 upstream)
  • Revision ID: ubuntu-launchpad@thequod.de-20100413185135-xi24v1diqg8w406x
Merging shared upstream rev into target branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 
3
 
Copyright (c) 2003, Arvid Norberg
4
 
All rights reserved.
5
 
 
6
 
Redistribution and use in source and binary forms, with or without
7
 
modification, are permitted provided that the following conditions
8
 
are met:
9
 
 
10
 
    * Redistributions of source code must retain the above copyright
11
 
      notice, this list of conditions and the following disclaimer.
12
 
    * Redistributions in binary form must reproduce the above copyright
13
 
      notice, this list of conditions and the following disclaimer in
14
 
      the documentation and/or other materials provided with the distribution.
15
 
    * Neither the name of the author nor the names of its
16
 
      contributors may be used to endorse or promote products derived
17
 
      from this software without specific prior written permission.
18
 
 
19
 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
 
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
 
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
 
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
 
POSSIBILITY OF SUCH DAMAGE.
30
 
 
31
 
*/
32
 
 
33
 
#ifndef TORRENT_ENTRY_HPP_INCLUDED
34
 
#define TORRENT_ENTRY_HPP_INCLUDED
35
 
 
36
 
/*
37
 
 *
38
 
 * This file declares the entry class. It is a
39
 
 * variant-type that can be an integer, list,
40
 
 * dictionary (map) or a string. This type is
41
 
 * used to hold bdecoded data (which is the
42
 
 * encoding BitTorrent messages uses).
43
 
 *
44
 
 * it has 4 accessors to access the actual
45
 
 * type of the object. They are:
46
 
 * integer()
47
 
 * string()
48
 
 * list()
49
 
 * dict()
50
 
 * The actual type has to match the type you
51
 
 * are asking for, otherwise you will get an
52
 
 * assertion failure.
53
 
 * When you default construct an entry, it is
54
 
 * uninitialized. You can initialize it through the
55
 
 * assignment operator, copy-constructor or
56
 
 * the constructor that takes a data_type enum.
57
 
 *
58
 
 *
59
 
 */
60
 
 
61
 
 
62
 
#include <iosfwd>
63
 
#include <map>
64
 
#include <list>
65
 
#include <string>
66
 
#include <stdexcept>
67
 
 
68
 
#include "libtorrent/size_type.hpp"
69
 
#include "libtorrent/config.hpp"
70
 
#include "libtorrent/assert.hpp"
71
 
 
72
 
namespace libtorrent
73
 
{
74
 
 
75
 
        struct TORRENT_EXPORT type_error: std::runtime_error
76
 
        {
77
 
                type_error(const char* error): std::runtime_error(error) {}
78
 
        };
79
 
 
80
 
        namespace detail
81
 
        {
82
 
                template<int v1, int v2>
83
 
                struct max2 { enum { value = v1>v2?v1:v2 }; };
84
 
 
85
 
                template<int v1, int v2, int v3>
86
 
                struct max3
87
 
                {
88
 
                        enum
89
 
                        {
90
 
                                temp = max2<v1,v2>::value,
91
 
                                value = temp>v3?temp:v3
92
 
                        };
93
 
                };
94
 
 
95
 
                template<int v1, int v2, int v3, int v4>
96
 
                struct max4
97
 
                {
98
 
                        enum
99
 
                        {
100
 
                                temp = max3<v1,v2, v3>::value,
101
 
                                value = temp>v4?temp:v4
102
 
                        };
103
 
                };
104
 
        }
105
 
 
106
 
        class entry;
107
 
 
108
 
        class TORRENT_EXPORT entry
109
 
        {
110
 
        public:
111
 
 
112
 
                // the key is always a string. If a generic entry would be allowed
113
 
                // as a key, sorting would become a problem (e.g. to compare a string
114
 
                // to a list). The definition doesn't mention such a limit though.
115
 
                typedef std::map<std::string, entry> dictionary_type;
116
 
                typedef std::string string_type;
117
 
                typedef std::list<entry> list_type;
118
 
                typedef size_type integer_type;
119
 
 
120
 
                enum data_type
121
 
                {
122
 
                        int_t,
123
 
                        string_t,
124
 
                        list_t,
125
 
                        dictionary_t,
126
 
                        undefined_t
127
 
                };
128
 
 
129
 
                data_type type() const;
130
 
 
131
 
                entry(dictionary_type const&);
132
 
                entry(string_type const&);
133
 
                entry(list_type const&);
134
 
                entry(integer_type const&);
135
 
 
136
 
                entry();
137
 
                entry(data_type t);
138
 
                entry(entry const& e);
139
 
                ~entry();
140
 
 
141
 
                bool operator==(entry const& e) const;
142
 
                
143
 
                void operator=(entry const&);
144
 
                void operator=(dictionary_type const&);
145
 
                void operator=(string_type const&);
146
 
                void operator=(list_type const&);
147
 
                void operator=(integer_type const&);
148
 
 
149
 
                integer_type& integer();
150
 
                const integer_type& integer() const;
151
 
                string_type& string();
152
 
                const string_type& string() const;
153
 
                list_type& list();
154
 
                const list_type& list() const;
155
 
                dictionary_type& dict();
156
 
                const dictionary_type& dict() const;
157
 
 
158
 
                void swap(entry& e);
159
 
 
160
 
                // these functions requires that the entry
161
 
                // is a dictionary, otherwise they will throw   
162
 
                entry& operator[](char const* key);
163
 
                entry& operator[](std::string const& key);
164
 
#ifndef BOOST_NO_EXCEPTIONS
165
 
                const entry& operator[](char const* key) const;
166
 
                const entry& operator[](std::string const& key) const;
167
 
#endif
168
 
                entry* find_key(char const* key);
169
 
                entry const* find_key(char const* key) const;
170
 
                entry* find_key(std::string const& key);
171
 
                entry const* find_key(std::string const& key) const;
172
 
                
173
 
                void print(std::ostream& os, int indent = 0) const;
174
 
 
175
 
        protected:
176
 
 
177
 
                void construct(data_type t);
178
 
                void copy(const entry& e);
179
 
                void destruct();
180
 
 
181
 
        private:
182
 
 
183
 
                data_type m_type;
184
 
 
185
 
#if defined(_MSC_VER) && _MSC_VER < 1310
186
 
                // workaround for msvc-bug.
187
 
                // assumes sizeof(map<string, char>) == sizeof(map<string, entry>)
188
 
                // and sizeof(list<char>) == sizeof(list<entry>)
189
 
                union
190
 
                {
191
 
                        char data[
192
 
                                detail::max4<sizeof(std::list<char>)
193
 
                                , sizeof(std::map<std::string, char>)
194
 
                                , sizeof(string_type)
195
 
                                , sizeof(integer_type)>::value];
196
 
                        integer_type dummy_aligner;
197
 
                };
198
 
#else
199
 
                union
200
 
                {
201
 
                        char data[detail::max4<sizeof(list_type)
202
 
                                , sizeof(dictionary_type)
203
 
                                , sizeof(string_type)
204
 
                                , sizeof(integer_type)>::value];
205
 
                        integer_type dummy_aligner;
206
 
                };
207
 
#endif
208
 
 
209
 
#ifdef TORRENT_DEBUG
210
 
        public:
211
 
                // in debug mode this is set to false by bdecode
212
 
                // to indicate that the program has not yet queried
213
 
                // the type of this entry, and sould not assume
214
 
                // that it has a certain type. This is asserted in
215
 
                // the accessor functions. This does not apply if
216
 
                // exceptions are used.
217
 
                mutable bool m_type_queried;
218
 
#endif
219
 
        };
220
 
 
221
 
        inline std::ostream& operator<<(std::ostream& os, const entry& e)
222
 
        {
223
 
                e.print(os, 0);
224
 
                return os;
225
 
        }
226
 
 
227
 
        inline entry::data_type entry::type() const
228
 
        {
229
 
#ifdef TORRENT_DEBUG
230
 
                m_type_queried = true;
231
 
#endif
232
 
                return m_type;
233
 
        }
234
 
 
235
 
        inline entry::~entry() { destruct(); }
236
 
 
237
 
        inline void entry::operator=(const entry& e)
238
 
        {
239
 
                destruct();
240
 
                copy(e);
241
 
        }
242
 
 
243
 
        inline entry::integer_type& entry::integer()
244
 
        {
245
 
                if (m_type == undefined_t) construct(int_t);
246
 
#ifndef BOOST_NO_EXCEPTIONS
247
 
                if (m_type != int_t) throw type_error("invalid type requested from entry");
248
 
#elif defined TORRENT_DEBUG
249
 
                TORRENT_ASSERT(m_type_queried);
250
 
#endif
251
 
                TORRENT_ASSERT(m_type == int_t);
252
 
                return *reinterpret_cast<integer_type*>(data);
253
 
        }
254
 
 
255
 
        inline entry::integer_type const& entry::integer() const
256
 
        {
257
 
#ifndef BOOST_NO_EXCEPTIONS
258
 
                if (m_type != int_t) throw type_error("invalid type requested from entry");
259
 
#elif defined TORRENT_DEBUG
260
 
                TORRENT_ASSERT(m_type_queried);
261
 
#endif
262
 
                TORRENT_ASSERT(m_type == int_t);
263
 
                return *reinterpret_cast<const integer_type*>(data);
264
 
        }
265
 
 
266
 
        inline entry::string_type& entry::string()
267
 
        {
268
 
                if (m_type == undefined_t) construct(string_t);
269
 
#ifndef BOOST_NO_EXCEPTIONS
270
 
                if (m_type != string_t) throw type_error("invalid type requested from entry");
271
 
#elif defined TORRENT_DEBUG
272
 
                TORRENT_ASSERT(m_type_queried);
273
 
#endif
274
 
                TORRENT_ASSERT(m_type == string_t);
275
 
                return *reinterpret_cast<string_type*>(data);
276
 
        }
277
 
 
278
 
        inline entry::string_type const& entry::string() const
279
 
        {
280
 
#ifndef BOOST_NO_EXCEPTIONS
281
 
                if (m_type != string_t) throw type_error("invalid type requested from entry");
282
 
#elif defined TORRENT_DEBUG
283
 
                TORRENT_ASSERT(m_type_queried);
284
 
#endif
285
 
                TORRENT_ASSERT(m_type == string_t);
286
 
                return *reinterpret_cast<const string_type*>(data);
287
 
        }
288
 
 
289
 
        inline entry::list_type& entry::list()
290
 
        {
291
 
                if (m_type == undefined_t) construct(list_t);
292
 
#ifndef BOOST_NO_EXCEPTIONS
293
 
                if (m_type != list_t) throw type_error("invalid type requested from entry");
294
 
#elif defined TORRENT_DEBUG
295
 
                TORRENT_ASSERT(m_type_queried);
296
 
#endif
297
 
                TORRENT_ASSERT(m_type == list_t);
298
 
                return *reinterpret_cast<list_type*>(data);
299
 
        }
300
 
 
301
 
        inline entry::list_type const& entry::list() const
302
 
        {
303
 
#ifndef BOOST_NO_EXCEPTIONS
304
 
                if (m_type != list_t) throw type_error("invalid type requested from entry");
305
 
#elif defined TORRENT_DEBUG
306
 
                TORRENT_ASSERT(m_type_queried);
307
 
#endif
308
 
                TORRENT_ASSERT(m_type == list_t);
309
 
                return *reinterpret_cast<const list_type*>(data);
310
 
        }
311
 
 
312
 
        inline entry::dictionary_type& entry::dict()
313
 
        {
314
 
                if (m_type == undefined_t) construct(dictionary_t);
315
 
#ifndef BOOST_NO_EXCEPTIONS
316
 
                if (m_type != dictionary_t) throw type_error("invalid type requested from entry");
317
 
#elif defined TORRENT_DEBUG
318
 
                TORRENT_ASSERT(m_type_queried);
319
 
#endif
320
 
                TORRENT_ASSERT(m_type == dictionary_t);
321
 
                return *reinterpret_cast<dictionary_type*>(data);
322
 
        }
323
 
 
324
 
        inline entry::dictionary_type const& entry::dict() const
325
 
        {
326
 
#ifndef BOOST_NO_EXCEPTIONS
327
 
                if (m_type != dictionary_t) throw type_error("invalid type requested from entry");
328
 
#elif defined TORRENT_DEBUG
329
 
                TORRENT_ASSERT(m_type_queried);
330
 
#endif
331
 
                TORRENT_ASSERT(m_type == dictionary_t);
332
 
                return *reinterpret_cast<const dictionary_type*>(data);
333
 
        }
334
 
 
335
 
}
336
 
 
337
 
#endif // TORRENT_ENTRY_HPP_INCLUDED
338