1 /*
2  * This is an open source non-commercial project. Dear PVS-Studio, please check it.
3  * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
4  *
5  * Copyright (C) 2014-2015  Ivan Romanov <drizt72@zoho.eu>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #pragma once
23 
24 #include "abstracttreenode.h"
25 
26 #include <QVariant>
27 #include <QMap>
28 #include <QList>
29 
30 class Bencode : public AbstractTreeNode<Bencode>
31 {
32 public:
33     enum Type {
34         Invalid,
35         // Not limited, can be signed. I use qlonglong
36         Integer,
37         // It is not correct. By fact can contains byte arrays.
38         // I use QByteArray. When converting to json all non
39         // printable symbols and '%' will be replaced with %HH (hex code)
40         String,
41         List,
42         Dictionary
43     };
44 
45     Bencode(Type type = Type::Invalid, const QByteArray &key = QByteArray());
46     Bencode(qlonglong integer, const QByteArray &key = QByteArray());
47     Bencode(const QByteArray &string, const QByteArray &key = QByteArray());
48 
49     void setType(Type type);
type()50     inline Type type() const { return _type; }
51 
setInteger(qlonglong integer)52     inline void setInteger(qlonglong integer) { _integer = integer; }
integer()53     inline qlonglong integer() const { return _integer; }
54 
setString(const QByteArray & string)55     inline void setString(const QByteArray &string) { _string = string; }
string()56     inline QByteArray string() const { return _string; }
57 
setKey(const QByteArray & key)58     inline void setKey(const QByteArray &key) { _key = key; }
key()59     inline QByteArray key() const { return _key; }
60 
setHex(bool hex)61     inline void setHex(bool hex) { _hex = hex; }
hex()62     inline bool hex() const { return _hex; }
63 
64     Bencode *checkAndCreate(Type type, int index);
65     Bencode *checkAndCreate(Type type, const QByteArray &key);
66 
67     void appendMapItem(Bencode *item);
68 
69     // Avoid compilation error due the next not overriden child function
child(int index)70     inline Bencode *child(int index) const
71     {
72         return AbstractTreeNode<Bencode>::child(index);
73     }
74 
75     Bencode *child(const QByteArray &key) const;
76 
isValid()77     inline bool isValid() const { return _type != Invalid; }
isInteger()78     inline bool isInteger() const { return _type == Integer; }
isString()79     inline bool isString() const { return _type == String; }
isList()80     inline bool isList() const { return _type == List; }
isDictionary()81     inline bool isDictionary() const { return _type == Dictionary; }
82 
83     QByteArray toRaw() const;
84     QVariant toJson() const;
85 
86     static Bencode *fromRaw(const QByteArray &raw);
87     static Bencode *fromJson(const QVariant &json);
88     static QString typeToStr(Type type);
89 
90     bool compare(const Bencode *other) const;
91 
92     // reimplemented
93     Bencode *clone() const override;
94     QString toString() const override;
95 
96 private:
97     static Bencode *parseItem(const QByteArray &raw, int &pos);
98 
99     static Bencode *parseInteger(const QByteArray &raw, int &pos);
100     static Bencode *parseString(const QByteArray &raw, int &pos);
101     static Bencode *parseList(const QByteArray &raw, int &pos);
102     static Bencode *parseDictionary(const QByteArray &raw, int &pos);
103 
104     static QString fromRawString(const QByteArray &raw);
105     static QByteArray toRawString(const QString &string);
106 
107     static QByteArray toRaw(const Bencode *bencode);
108     static QVariant toJson(const Bencode *bencode);
109 
110     Type _type;
111 
112     qlonglong _integer;
113     QByteArray _string;
114     QByteArray _key;
115     bool _hex;
116 };
117