1 /***************************************************************************
3 * Copyright (C) 2006 David Brodsky *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License as *
7 * published by the Free Software Foundation and appearing *
8 * in the file LICENSE.GPL included in the packaging of this file. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
13 * General Public License for more details. *
15 ***************************************************************************/
19 #include <tairon/crypto/sha1.h>
29 /* {{{ BEncode::BEncode() */
30 BEncode::BEncode() : type(BEncode::NONE
)
35 /* {{{ BEncode::BEncode(const int64_t v) */
36 BEncode::BEncode(const int64_t v
) : type(BEncode::VALUE
), value(v
)
41 /* {{{ BEncode::BEncode(const String &s) */
42 BEncode::BEncode(const String
&s
) : type(BEncode::STRING
), string(new String(s
))
47 /* {{{ BEncode::BEncode(const BEncode &b) */
48 BEncode::BEncode(const BEncode
&b
) : type(b
.type
)
55 string
= new String(*(b
.string
));
58 list
= new BEncode::List(*(b
.list
));
61 map
= new BEncode::Map(*(b
.map
));
69 /* {{{ BEncode::BEncode(BEncode::Type t) */
70 BEncode::BEncode(BEncode::Type t
) : type(t
)
77 string
= new String();
91 /* {{{ BEncode::~BEncode() */
98 /* {{{ BEncode::asList() */
99 BEncode::List
&BEncode::asList()
102 throw BEncodeException("BEncode is not type list");
108 /* {{{ BEncode::asList() const */
109 const BEncode::List
&BEncode::asList() const
112 throw BEncodeException("BEncode is not type list");
118 /* {{{ BEncode::asMap() */
119 BEncode::Map
&BEncode::asMap()
122 throw BEncodeException("BEncode is not type map");
128 /* {{{ BEncode::asMap() const */
129 const BEncode::Map
&BEncode::asMap() const
132 throw BEncodeException("BEncode is not type map");
138 /* {{{ BEncode::asString() */
139 String
&BEncode::asString()
142 throw BEncodeException("BEncode is not type string");
148 /* {{{ BEncode::asString() const */
149 const String
&BEncode::asString() const
152 throw BEncodeException("BEncode is not type string");
158 /* {{{ BEncode::asValue() */
159 int64_t &BEncode::asValue()
162 throw BEncodeException("BEncode is not type value");
168 /* {{{ BEncode::asValue() const */
169 const int64_t &BEncode::asValue() const
172 throw BEncodeException("BEncode is not type value");
178 /* {{{ BEncode::clear */
179 void BEncode::clear()
182 case BEncode::STRING
:
195 type
= BEncode::NONE
;
199 /* {{{ BEncode::computeSHA1() const */
200 String
BEncode::computeSHA1() const
202 std::stringstream stream
;
206 throw BEncodeException("Cannot write BEncode to stream");
208 return Tairon::Crypto::SHA1::hash(stream
.str());
212 /* {{{ BEncode::isList() const */
213 bool BEncode::isList() const
215 return (type
== BEncode::LIST
);
219 /* {{{ BEncode::isMap() const */
220 bool BEncode::isMap() const
222 return (type
== BEncode::MAP
);
226 /* {{{ BEncode::isString() const */
227 bool BEncode::isString() const
229 return (type
== BEncode::STRING
);
233 /* {{{ BEncode::isValue() const */
234 bool BEncode::isValue() const
236 return (type
== BEncode::VALUE
);
240 /* {{{ BEncode::getType() const */
241 BEncode::Type
BEncode::getType() const
247 /* {{{ BEncode::operator=(const BEncode &b) */
248 BEncode
&BEncode::operator=(const BEncode
&b
)
257 case BEncode::STRING
:
258 string
= new String(*(b
.string
));
261 list
= new BEncode::List(*(b
.list
));
264 map
= new BEncode::Map(*(b
.map
));
274 /* {{{ BEncode::operator[](const String &key) */
275 BEncode
&BEncode::operator[](const String
&key
)
277 if (type
!= BEncode::MAP
)
278 throw BEncodeException("Wrong type for BEncode operator [" + key
+ "]");
280 BEncode::Map::iterator it
= map
->find(key
);
282 if (it
== map
->end())
283 throw BEncodeException("BEncode operator [] could not find element " + key
);
289 /* {{{ BEncode::operator[](const String &key) const */
290 const BEncode
&BEncode::operator[](const String
&key
) const
292 if (type
!= BEncode::MAP
)
293 throw BEncodeException("Wrong type for BEncode operator [" + key
+ "]");
295 BEncode::Map::const_iterator it
= map
->find(key
);
297 if (it
== map
->end())
298 throw BEncodeException("BEncode operator [] could not find element " + key
);
304 /* {{{ BEncode::readString(std::istream &s, String &str) */
305 bool BEncode::readString(std::istream
&s
, String
&str
)
310 if (s
.fail() || s
.get() != ':')
315 size_t len
= str
.length();
316 for (size_t i
= 0; i
< len
&& s
.good(); ++i
)
323 /* {{{ operator>>(std::istream &s, BEncode &b) */
324 std::istream
&operator>>(std::istream
&s
, BEncode
&b
)
329 s
.setstate(std::istream::failbit
);
335 const char *reason
= 0;
337 switch (c
= s
.peek()) {
342 if (s
.fail() || s
.get() != 'e') {
343 reason
= "Failed to load integer";
347 b
.type
= BEncode::VALUE
;
354 b
.list
= new BEncode::List
;
355 b
.type
= BEncode::LIST
;
358 if (s
.peek() == 'e') {
363 BEncode::List::iterator it
= b
.list
->insert(b
.list
->end(), BEncode());
368 reason
= "Failed to load list";
375 b
.map
= new BEncode::Map
;
376 b
.type
= BEncode::MAP
;
379 if (s
.peek() == 'e') {
386 if (!BEncode::readString(s
, str
))
392 reason
= "Failed to load dictionary";
397 if (c
>= '0' && c
<= '9') {
398 b
.string
= new String();
399 b
.type
= BEncode::STRING
;
401 if (b
.readString(s
, *b
.string
))
405 reason
= "Failed to load string";
410 std::stringstream stream
;
411 stream
<< reason
<< " at position " << s
.tellg();
413 s
.setstate(std::istream::failbit
);
416 throw BEncodeException(stream
.str());
422 /* {{{ operator<<(std::ostream &s, const BEncode &b) */
423 std::ostream
&operator<<(std::ostream
&s
, const BEncode
&b
)
427 return s
<< 'i' << b
.value
<< 'e';
428 case BEncode::STRING
:
429 return s
<< b
.string
->size() << ':' << *(b
.string
);
433 for (BEncode::List::const_iterator it
= b
.list
->begin(); it
!= b
.list
->end(); ++it
)
440 for (BEncode::Map::const_iterator it
= b
.map
->begin(); it
!= b
.map
->end(); ++it
)
441 s
<< it
->first
.size() << ':' << it
->first
<< it
->second
;
454 }; // namespace Tairent
456 // vim: ai sw=4 ts=4 noet fdm=marker