BinaryWriter.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2006-2007 by Peter Dimov.
00004 
00005 This file is part of Calitko (http://www.calitko.org).
00006 
00007 Calitko is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 Calitko is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Calitko; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021 */
00022 
00023 #include "Qt.h"
00024 #include "BinaryWriter.h"
00025 #include "Imports.cpp"
00026 
00028 BinaryWriter::BinaryWriter (QByteArray *buffer, bool autoGrow)
00029     : BinaryWriterBase (buffer, LittleEndian, autoGrow)
00030 {
00031 }
00032 
00034 BinaryWriter::BinaryWriter (bool autoGrow)
00035        : BinaryWriterBase (LittleEndian, autoGrow)
00036 {
00037 }
00038 
00040 
00047 void BinaryWriter::writeUuid (const QUuid &uuid)
00048 {
00049     setByteOrder (BigEndian);
00050     writeUInt32 (uuid.data1);
00051     writeUInt16 (uuid.data2);
00052     writeUInt16 (uuid.data3);
00053     writeByte (uuid.data4[0]);
00054     writeByte (uuid.data4[1]);
00055     writeByte (uuid.data4[2]);
00056     writeByte (uuid.data4[3]);
00057     writeByte (uuid.data4[4]);
00058     writeByte (uuid.data4[5]);
00059     writeByte (uuid.data4[6]);
00060     writeByte (uuid.data4[7]);
00061     setByteOrder (LittleEndian);
00062 }
00063 
00065 
00070 void BinaryWriter::writeIPv4Address (const QHostAddress &address)
00071 {
00072     Q_ASSERT (address.protocol() == QAbstractSocket::IPv4Protocol
00073              || address.isNull());
00074     setByteOrder (BigEndian);
00075     writeUInt32 (address.toIPv4Address());
00076     setByteOrder (LittleEndian);
00077 }
00078 
00080 
00087 void BinaryWriter::writeGgepBlock (const GgepBlock &block)
00088 {
00089     using Extensions::Ggep;
00090     if (block.extensions().count() == 0)
00091         return;
00092 
00093     writeByte (GgepBlock::MagicByte);
00094     const Ggep *lastExtension = block.extensions().last();
00095     foreach (const Ggep* extension, block.extensions()) {
00096         writeGgepBlockExtensionHeader (extension, lastExtension);
00097 
00098         QByteArray rawData (extension->rawData());
00099         writeGgepBlockDataLength (rawData.length());
00100 
00101         writeBytes (rawData);
00102     }
00103 }
00104 
00106 
00109 void BinaryWriter::writeGgepBlockExtensionHeader (const Ggep *extension,
00110                                                   const Ggep *lastExtension)
00111 {
00112     uchar flags = 0x00;
00113     if (extension->isFlagSet (Ggep::Compression))
00114         flags |= Ggep::Compression;
00115     if (extension->isFlagSet (Ggep::Encoding))
00116         flags |= Ggep::Encoding;
00117     if (extension == lastExtension)
00118         flags |= Ggep::LastExtension;
00119     flags |= extension->id().size();
00120 
00121     writeByte (static_cast <uchar> (flags));        // flags
00122     writeBytes (extension->id());                   // ID
00123 }
00124 
00126 
00130 void BinaryWriter::writeGgepBlockDataLength (int length)
00131 {
00132     do {
00133         uchar byte = length & 0x3F;
00134         length >>= 6;
00135         byte |= (length > 0) ? 0x80 : 0x40;
00136         writeByte (byte);                           // length byte
00137     } while (length > 0);
00138 }
00139 
00141 
00144 void BinaryWriter::writeQueryData (const QueryData &data)
00145 {
00146     writeHugeGemBlock (data);
00147 }
00148 
00150 
00154 void BinaryWriter::writeMinSpeed (const MinSpeed &speed)
00155 {
00156     uchar flags = 0x80;
00157 
00158     if(speed.isFirewalled)
00159         flags |= 0x40;
00160     if(speed.wantXmlMetadata)
00161         flags |= 0x20;
00162     if(speed.isLeafGuidedDynamicQuery)
00163         flags |= 0x10;
00164     if(speed.isAllowedGgepH)
00165         flags |= 0x08;
00166     if(speed.isOutOfBoundQuery)
00167         flags |= 0x04;
00168 
00169     writeByte (flags);
00170     writeByte (speed.maxQueryHits);
00171 }
00172 
00174 
00177 void BinaryWriter::writeVendorCode (const VendorCode &code)
00178 {
00179     writeBytes (code.toBytes());
00180 }
00181 
00183 
00190 void BinaryWriter::writeHugeGemBlock (const HugeGemBlock &block)
00191 {
00192     QList <QByteArray> extensions;
00193 
00194     extensions += block.urnList;
00195     extensions += block.unknownList;
00196     extensions += block.xmlList;
00197 
00198     if(block.ggepBlock.extensions().size() > 0) {
00199         BinaryWriter writer;
00200         writer.writeGgepBlock (block.ggepBlock);
00201         extensions += writer.buffer();
00202     }
00203 
00204     // Write the first extension and remove it from the list:
00205     if (!extensions.isEmpty())
00206         writeBytes (extensions.takeFirst());
00207     // Write further extensions, if any:
00208     foreach (const QByteArray extension, extensions) {
00209         writeByte ('\x1c');
00210         writeBytes (extension);
00211     }
00212 }
00213 
00215 
00218 void BinaryWriter::writeQueryHitsData (const QueryHitsData &hitsData)
00219 {
00220     writeVendorCode (hitsData.vendorCode);
00221 
00222     if(hitsData.xmlData.size() > 0)
00223         writeByte ('\x04');
00224     else
00225         writeByte ('\x02');
00226 
00227     // Prepare the OpenAreaFlags:
00228     uchar flags1 = 0x3C; // Enable all known flags (except push): 00111100
00229     uchar flags2 = 0x01; // Enable the push flag here: 00000001
00230     // Set the corresponfing the bits if the field is set:
00231     if(hitsData.ggepBlock.extensions().count() > 0)     flags2 |= 0x20;
00232     if(hitsData.flagUploadSpeed)                        flags2 |= 0x10;
00233     if(hitsData.flagHaveUploaded)                       flags2 |= 0x08;
00234     if(hitsData.flagBusy)                               flags2 |= 0x04;
00235     if(hitsData.flagPush)                               flags1 |= 0x01;
00236     // Write the flags:
00237     writeByte (flags1);
00238     writeByte (flags2);
00239 
00240     // Write the xmlData length + 1 (for the ending zero byte):
00241     if(hitsData.xmlData.size() > 0)
00242         writeUInt16 (static_cast <quint16> (hitsData.xmlData.size() + 1));
00243 
00244     // Write any aditional private data:
00245     writeBytes (hitsData.privateVendor);
00246 
00247     // Write the GGEP block:
00248     writeGgepBlock (hitsData.ggepBlock);
00249 
00250     // Write the xmlData itself followed by a zero byte:
00251     if(hitsData.xmlData.size() > 0) {
00252         writeBytes (hitsData.xmlData);
00253         writeByte('\0');
00254     }
00255 
00256     // Finally write the serventId:
00257     writeUuid (hitsData.serventId);
00258 }
00259 
00261 
00264 void BinaryWriter::writeQueryHitsResultSet (const ResultSet &resultSet)
00265 {
00266     foreach(const Result result, resultSet) {
00267         writeUInt32 (result.fileIndex);
00268         writeUInt32 (result.fileSize);
00269         writeString (result.fullFileName.toUtf8());
00270         writeHugeGemBlock (result.resultData);
00271         writeByte ('\0');
00272     }
00273 }