Basic reading and writing of quick notes to and from zionworx playlists
[kworship.git] / kworship / filters / zionworx / KwPascalStream.cpp
blob368f52afb02a28373bc7132ccfba65a647a55da7
1 /***************************************************************************
2 * This file is part of KWorship. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
4 * *
5 * KWorship is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * KWorship 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 *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with KWorship. If not, write to the Free Software Foundation, *
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
20 /**
21 * @file KwPascalStream.cpp
22 * @brief Provides Pascal serialization of binary data.
23 * @author James Hogan <james@albanarts.com>
26 #include "KwPascalStream.h"
28 #include <QtEndian>
29 #include <QBuffer>
30 #include <QVariant>
31 #include <QStringList>
34 * Constructors + destructor
37 /// Use a byte array as a buffer.
38 KwPascalStream::KwPascalStream(QByteArray* a, QIODevice::OpenMode mode)
39 : m_d(new QBuffer(a))
41 m_d->open(mode);
44 /// Use a constant byte array as a buffer.
45 KwPascalStream::KwPascalStream(const QByteArray* a)
46 : m_d(new QBuffer((QByteArray*)a))
48 m_d->open(QIODevice::ReadOnly);
51 /// Destructor.
52 KwPascalStream::~KwPascalStream()
54 delete m_d;
58 * Reading interface
61 /// Find whether we're at the end of the file.
62 bool KwPascalStream::atEnd() const
64 return m_d->atEnd();
67 /// Read a single byte.
68 uint8_t KwPascalStream::read8()
70 uint8_t result;
71 m_d->read((char*)&result, 1);
72 return result;
75 /// Read 2 bytes.
76 uint16_t KwPascalStream::read16()
78 uint16_t result;
79 m_d->read((char*)&result, 2);
80 return qFromLittleEndian(result);
83 /// Read 4 bytes.
84 uint32_t KwPascalStream::read32()
86 uint32_t result;
87 m_d->read((char*)&result, 4);
88 return qFromLittleEndian(result);
91 /// Read short string.
92 QByteArray KwPascalStream::readString()
94 uint8_t len = read8();
95 return m_d->read(len);
98 /// Read long string.
99 QByteArray KwPascalStream::readLString()
101 uint32_t len = read32();
102 return m_d->read(len);
105 /// Read wide string.
106 QString KwPascalStream::readWString()
108 uint32_t len = read32();
109 QByteArray data = m_d->read(len>>1);
110 return QString::fromUtf8(data, data.size());
113 /// Read UTF8 string.
114 QString KwPascalStream::readUtf8String()
116 return QString::fromUtf8(readLString());
120 * Writing interface
123 /// Write a single byte.
124 void KwPascalStream::write8(uint8_t byte)
126 m_d->write((char*)&byte,1);
129 /// Write 2 bytes.
130 void KwPascalStream::write16(uint16_t word)
132 word = qToLittleEndian(word);
133 m_d->write((char*)&word, 2);
136 /// Write 4 bytes.
137 void KwPascalStream::write32(uint32_t dword)
139 dword = qToLittleEndian(dword);
140 m_d->write((char*)&dword, 4);
143 /// Write short string (length < 2^8).
144 void KwPascalStream::writeString(const QByteArray& str)
146 int len = str.size();
147 if (len > 0xff)
149 len = 0xff;
151 write8(len);
152 m_d->write(str, len);
155 /// Write long string.
156 void KwPascalStream::writeLString(const QByteArray& str)
158 unsigned int len = str.size();
159 write32(len);
160 m_d->write(str, len);
163 /// Write UTF8 string.
164 void KwPascalStream::writeUtf8String(const QString& str)
166 writeLString(str.toUtf8());
170 * Property interface
173 /// Write a property.
174 void KwPascalStream::writeProperty(const QByteArray& name, const QVariant& value)
176 writeString(name);
177 *this << value;
180 /// Read a property.
181 void KwPascalStream::readProperty(QByteArray& name, QVariant& value)
183 name = readString();
184 *this >> value;
187 /// Start a list.
188 void KwPascalStream::writeStartList()
190 write8(vaList);
193 /// End a list.
194 void KwPascalStream::writeEndList()
196 write8(vaNull);
199 /// Write a string in an appropriate format.
200 KwPascalStream& KwPascalStream::operator << (const QString& str)
202 if (str.size() == str.toUtf8().size())
204 if (str.size() < 0x100)
206 write8(vaString);
207 writeString(str.toLatin1());
209 else
211 write8(vaLString);
212 writeLString(str.toLatin1());
215 else
217 write8(vaUTF8String);
218 writeUtf8String(str);
220 return *this;
223 /// Write a variant.
224 KwPascalStream& KwPascalStream::operator << (const QVariant& var)
226 switch (var.type())
228 case QVariant::List:
229 *this << var.toList();
230 break;
231 case QVariant::StringList:
232 *this << var.toStringList();
233 break;
234 case QVariant::String:
235 *this << var.toString();
236 break;
237 default:
238 Q_ASSERT(!"Unimplemented variant type");
239 break;
241 return *this;
244 /// Read a variant.
245 KwPascalStream& KwPascalStream::operator >> (QVariant& var)
247 // Read the type byte
248 int8_t type = read8();
249 switch (type)
251 case vaNull:
252 var = QVariant();
253 break;
254 case vaList:
256 QVariantList list;
257 QVariant item;
258 while (true)
260 *this >> item;
261 if (!item.isValid())
263 break;
265 list += item;
267 var = list;
269 break;
270 case vaInt8:
271 var = (int8_t)read8();
272 break;
273 case vaInt16:
274 var = (int16_t)read16();
275 break;
276 case vaInt32:
277 var = (int32_t)read32();
278 break;
279 case vaExtended:
280 /// @todo Implement missing readers
281 var = 0;
282 break;
283 case vaString:
284 var = QString::fromLatin1(readString());
285 break;
286 case vaIdent:
287 /// @todo Implement missing readers
288 var = 0;
289 break;
290 case vaFalse:
291 var = false;
292 break;
293 case vaTrue:
294 var = true;
295 break;
296 case vaBinary:
297 case vaSet:
298 /// @todo Implement missing readers
299 var = 0;
300 break;
301 case vaLString:
302 var = QString::fromLatin1(readLString());
303 break;
304 case vaNil:
305 case vaCollection:
306 case vaSingle:
307 case vaCurrency:
308 case vaDate:
309 /// @todo Implement missing readers
310 var = 0;
311 break;
312 case vaWString:
313 var = readWString();
314 break;
315 case vaInt64:
316 /// @todo Implement missing readers
317 var = 0;
318 break;
319 case vaUTF8String:
320 var = readUtf8String();
321 break;
322 default:
323 var = 0;
324 break;
326 return *this;