source: trunk/examples/network/torrent/bencodeparser.cpp@ 5

Last change on this file since 5 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 5.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "bencodeparser.h"
43
44#include <QList>
45#include <QMetaType>
46
47BencodeParser::BencodeParser()
48{
49}
50
51bool BencodeParser::parse(const QByteArray &content)
52{
53 if (content.isEmpty()) {
54 errString = QString("No content");
55 return false;
56 }
57
58 this->content = content;
59 index = 0;
60 infoStart = 0;
61 infoLength = 0;
62 return getDictionary(&dictionaryValue);
63}
64
65QString BencodeParser::errorString() const
66{
67 return errString;
68}
69
70QMap<QByteArray, QVariant> BencodeParser::dictionary() const
71{
72 return dictionaryValue;
73}
74
75QByteArray BencodeParser::infoSection() const
76{
77 return content.mid(infoStart, infoLength);
78}
79
80bool BencodeParser::getByteString(QByteArray *byteString)
81{
82 const int contentSize = content.size();
83 int size = -1;
84 do {
85 char c = content.at(index);
86 if (c < '0' || c > '9') {
87 if (size == -1)
88 return false;
89 if (c != ':') {
90 errString = QString("Unexpected character at pos %1: %2")
91 .arg(index).arg(c);
92 return false;
93 }
94 ++index;
95 break;
96 }
97 if (size == -1)
98 size = 0;
99 size *= 10;
100 size += c - '0';
101 } while (++index < contentSize);
102
103 if (byteString)
104 *byteString = content.mid(index, size);
105 index += size;
106 return true;
107}
108
109bool BencodeParser::getInteger(qint64 *integer)
110{
111 const int contentSize = content.size();
112 if (content.at(index) != 'i')
113 return false;
114
115 ++index;
116 qint64 num = -1;
117 bool negative = false;
118
119 do {
120 char c = content.at(index);
121 if (c < '0' || c > '9') {
122 if (num == -1) {
123 if (c != '-' || negative)
124 return false;
125 negative = true;
126 continue;
127 } else {
128 if (c != 'e') {
129 errString = QString("Unexpected character at pos %1: %2")
130 .arg(index).arg(c);
131 return false;
132 }
133 ++index;
134 break;
135 }
136 }
137 if (num == -1)
138 num = 0;
139 num *= 10;
140 num += c - '0';
141 } while (++index < contentSize);
142
143 if (integer)
144 *integer = negative ? -num : num;
145 return true;
146}
147
148bool BencodeParser::getList(QList<QVariant> *list)
149{
150 const int contentSize = content.size();
151 if (content.at(index) != 'l')
152 return false;
153
154 QList<QVariant> tmp;
155 ++index;
156
157 do {
158 if (content.at(index) == 'e') {
159 ++index;
160 break;
161 }
162
163 qint64 number;
164 QByteArray byteString;
165 QList<QVariant> tmpList;
166 QMap<QByteArray, QVariant> dictionary;
167
168 if (getInteger(&number))
169 tmp << number;
170 else if (getByteString(&byteString))
171 tmp << byteString;
172 else if (getList(&tmpList))
173 tmp << tmpList;
174 else if (getDictionary(&dictionary))
175 tmp << qVariantFromValue<QMap<QByteArray, QVariant> >(dictionary);
176 else {
177 errString = QString("error at index %1").arg(index);
178 return false;
179 }
180 } while (index < contentSize);
181
182 if (list)
183 *list = tmp;
184 return true;
185}
186
187bool BencodeParser::getDictionary(QMap<QByteArray, QVariant> *dictionary)
188{
189 const int contentSize = content.size();
190 if (content.at(index) != 'd')
191 return false;
192
193 QMap<QByteArray, QVariant> tmp;
194 ++index;
195