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 | |
9 | namespace Mobipocket |
10 | { |
11 | |
12 | struct PDBPrivate { |
13 | PDBPrivate(QIODevice *dev); |
14 | |
15 | QIODevice *device; |
16 | QByteArray fileType; |
17 | QList<quint32> recordOffsets; |
18 | bool valid = false; |
19 | }; |
20 | |
21 | PDBPrivate::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 | |
50 | PDB::~PDB() = default; |
51 | |
52 | PDB::PDB(QIODevice *device) |
53 | : d(new PDBPrivate(device)) |
54 | { |
55 | } |
56 | |
57 | QByteArray 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 | |
72 | QByteArray PDB::fileType() const |
73 | { |
74 | return d->fileType; |
75 | } |
76 | |
77 | bool PDB::isValid() const |
78 | { |
79 | return d->valid; |
80 | } |
81 | |
82 | quint16 PDB::recordCount() const |
83 | { |
84 | // Range guaranteed by constructor/PDB field size |
85 | return d->recordOffsets.size(); |
86 | } |
87 | |
88 | } |
89 |