1// SPDX-FileCopyrightText: 2008 by Jakub Stachowski <qbast@go2.pl>
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "pdb_p.h"
5
6#include <QIODevice>
7#include <QtEndian>
8
9namespace Mobipocket
10{
11
12struct PDBPrivate {
13 PDBPrivate(QIODevice *dev);
14
15 QIODevice *device;
16 QByteArray fileType;
17 QList<quint32> recordOffsets;
18 bool valid = false;
19};
20
21PDBPrivate::PDBPrivate(QIODevice *dev)
22 : device(dev)
23{
24 const auto pdbHead = device->read(maxlen: 0x4e);
25 if (pdbHead.size() < 0x4e)
26 return;
27
28 fileType = pdbHead.mid(index: 0x3c, len: 8);
29
30 const auto nrecords = qFromBigEndian<quint16>(src: pdbHead.constData() + 0x4c);
31 const auto recordData = device->read(maxlen: 8 * nrecords);
32 if (recordData.size() < 8 * nrecords)
33 return;
34
35 quint32 lastOffset = 0x4d + 8 * nrecords;
36 for (int i = 0; i < nrecords; i++) {
37 const quint32 offset = qFromBigEndian<quint32>(src: recordData.constData() + 8 * i);
38 if (offset < lastOffset) {
39 return;
40 }
41 if (offset > dev->size()) {
42 break;
43 }
44 recordOffsets.append(t: offset);
45 lastOffset = offset;
46 }
47 valid = true;
48}
49
50PDB::~PDB() = default;
51
52PDB::PDB(QIODevice *device)
53 : d(new PDBPrivate(device))
54{
55}
56
57QByteArray PDB::getRecord(quint16 i) const
58{
59 if (i >= d->recordOffsets.size()) {
60 return QByteArray();
61 }
62
63 quint32 offset = d->recordOffsets[i];
64 quint32 end = (i + 1 < d->recordOffsets.size()) ? d->recordOffsets[i + 1] : d->device->size();
65
66 if (!d->device->seek(pos: offset))
67 return QByteArray();
68
69 return d->device->read(maxlen: end - offset);
70}
71
72QByteArray PDB::fileType() const
73{
74 return d->fileType;
75}
76
77bool PDB::isValid() const
78{
79 return d->valid;
80}
81
82quint16 PDB::recordCount() const
83{
84 // Range guaranteed by constructor/PDB field size
85 return d->recordOffsets.size();
86}
87
88}
89

source code of kdegraphics-mobipocket/lib/pdb.cpp