kget
bdecoder.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "bdecoder.h"
00021 #include <util/log.h>
00022 #include <util/error.h>
00023 #include <klocale.h>
00024 #include "bnode.h"
00025
00026 namespace bt
00027 {
00028
00029 BDecoder::BDecoder(const QByteArray & data,bool verbose,Uint32 off)
00030 : data(data),pos(off),verbose(verbose)
00031 {
00032 }
00033
00034
00035 BDecoder::~BDecoder()
00036 {}
00037
00038 BNode* BDecoder::decode()
00039 {
00040 if (pos >= (Uint32)data.size())
00041 return 0;
00042
00043 if (data[pos] == 'd')
00044 {
00045 return parseDict();
00046 }
00047 else if (data[pos] == 'l')
00048 {
00049 return parseList();
00050 }
00051 else if (data[pos] == 'i')
00052 {
00053 return parseInt();
00054 }
00055 else if (data[pos] >= '0' && data[pos] <= '9')
00056 {
00057 return parseString();
00058 }
00059 else
00060 {
00061 throw Error(i18n("Illegal token: %1",data[pos]));
00062 }
00063 }
00064
00065 BDictNode* BDecoder::parseDict()
00066 {
00067 Uint32 off = pos;
00068
00069 BDictNode* curr = new BDictNode(off);
00070 pos++;
00071 if (verbose) Out(SYS_GEN|LOG_DEBUG) << "DICT" << endl;
00072 try
00073 {
00074 while (pos < (Uint32)data.size() && data[pos] != 'e')
00075 {
00076 if (verbose) Out(SYS_GEN|LOG_DEBUG) << "Key : " << endl;
00077 BNode* kn = decode();
00078 BValueNode* k = dynamic_cast<BValueNode*>(kn);
00079 if (!k || k->data().getType() != Value::STRING)
00080 {
00081 delete kn;
00082 throw Error(i18n("Decode error"));
00083 }
00084
00085 QByteArray key = k->data().toByteArray();
00086 delete kn;
00087
00088 BNode* data = decode();
00089 curr->insert(key,data);
00090 }
00091 pos++;
00092 }
00093 catch (...)
00094 {
00095 delete curr;
00096 throw;
00097 }
00098 if (verbose) Out(SYS_GEN|LOG_DEBUG) << "END" << endl;
00099 curr->setLength(pos - off);
00100 return curr;
00101 }
00102
00103 BListNode* BDecoder::parseList()
00104 {
00105 Uint32 off = pos;
00106 if (verbose) Out(SYS_GEN|LOG_DEBUG) << "LIST" << endl;
00107 BListNode* curr = new BListNode(off);
00108 pos++;
00109 try
00110 {
00111 while (pos < (Uint32)data.size() && data[pos] != 'e')
00112 {
00113 BNode* n = decode();
00114 curr->append(n);
00115 }
00116 pos++;
00117 }
00118 catch (...)
00119 {
00120 delete curr;
00121 throw;
00122 }
00123 if (verbose) Out(SYS_GEN|LOG_DEBUG) << "END" << endl;
00124 curr->setLength(pos - off);
00125 return curr;
00126 }
00127
00128 BValueNode* BDecoder::parseInt()
00129 {
00130 Uint32 off = pos;
00131 pos++;
00132 QString n;
00133
00134 while (pos < (Uint32)data.size() && data[pos] != 'e')
00135 {
00136 n += data[pos];
00137 pos++;
00138 }
00139
00140
00141 if (pos >= (Uint32)data.size())
00142 {
00143 throw Error(i18n("Unexpected end of input"));
00144 }
00145
00146
00147 bool ok = true;
00148 int val = 0;
00149 val = n.toInt(&ok);
00150 if (ok)
00151 {
00152 pos++;
00153 if (verbose) Out(SYS_GEN|LOG_DEBUG) << "INT = " << val << endl;
00154 BValueNode* vn = new BValueNode(Value(val),off);
00155 vn->setLength(pos - off);
00156 return vn;
00157 }
00158 else
00159 {
00160 Int64 bi = 0LL;
00161 bi = n.toLongLong(&ok);
00162 if (!ok)
00163 throw Error(i18n("Cannot convert %1 to an int",n));
00164
00165 pos++;
00166 if (verbose) Out(SYS_GEN|LOG_DEBUG) << "INT64 = " << n << endl;
00167 BValueNode* vn = new BValueNode(Value(bi),off);
00168 vn->setLength(pos - off);
00169 return vn;
00170 }
00171 }
00172
00173 BValueNode* BDecoder::parseString()
00174 {
00175 Uint32 off = pos;
00176
00177
00178
00179 QString n;
00180 while (pos < (Uint32)data.size() && data[pos] != ':')
00181 {
00182 n += data[pos];
00183 pos++;
00184 }
00185
00186 if (pos >= (Uint32)data.size())
00187 {
00188 throw Error(i18n("Unexpected end of input"));
00189 }
00190
00191
00192 bool ok = true;
00193 int len = 0;
00194 len = n.toInt(&ok);
00195 if (!ok)
00196 {
00197 throw Error(i18n("Cannot convert %1 to an int",n));
00198 }
00199
00200 pos++;
00201 if (pos + len > (Uint32)data.size())
00202 throw Error(i18n("Torrent is incomplete!"));
00203
00204 QByteArray arr(data.constData() + pos,len);
00205 pos += len;
00206
00207
00208
00209 BValueNode* vn = new BValueNode(Value(arr),off);
00210 vn->setLength(pos - off);
00211 if (verbose)
00212 {
00213 if (arr.size() < 200)
00214 Out(SYS_GEN|LOG_DEBUG) << "STRING " << QString(arr) << endl;
00215 else
00216 Out(SYS_GEN|LOG_DEBUG) << "STRING " << "really long string" << endl;
00217 }
00218 return vn;
00219 }
00220 }
00221