/src/kdegraphics-mobipocket/lib/pdb.cpp
Line | Count | Source |
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 | 0 | : device(dev) |
23 | 0 | { |
24 | 0 | const auto pdbHead = device->read(0x4e); |
25 | 0 | if (pdbHead.size() < 0x4e) |
26 | 0 | return; |
27 | | |
28 | 0 | fileType = pdbHead.mid(0x3c, 8); |
29 | |
|
30 | 0 | const auto nrecords = qFromBigEndian<quint16>(pdbHead.constData() + 0x4c); |
31 | 0 | const auto recordData = device->read(8 * nrecords); |
32 | 0 | if (recordData.size() < 8 * nrecords) |
33 | 0 | return; |
34 | | |
35 | 0 | quint32 lastOffset = 0x4d + 8 * nrecords; |
36 | 0 | for (int i = 0; i < nrecords; i++) { |
37 | 0 | const quint32 offset = qFromBigEndian<quint32>(recordData.constData() + 8 * i); |
38 | 0 | if (offset < lastOffset) { |
39 | 0 | return; |
40 | 0 | } |
41 | 0 | if (offset > dev->size()) { |
42 | 0 | break; |
43 | 0 | } |
44 | 0 | recordOffsets.append(offset); |
45 | 0 | lastOffset = offset; |
46 | 0 | } |
47 | 0 | valid = true; |
48 | 0 | } |
49 | | |
50 | 0 | PDB::~PDB() = default; |
51 | | |
52 | | PDB::PDB(QIODevice *device) |
53 | 0 | : d(new PDBPrivate(device)) |
54 | 0 | { |
55 | 0 | } |
56 | | |
57 | | QByteArray PDB::getRecord(quint16 i) const |
58 | 0 | { |
59 | 0 | if (i >= d->recordOffsets.size()) { |
60 | 0 | return QByteArray(); |
61 | 0 | } |
62 | | |
63 | 0 | quint32 offset = d->recordOffsets[i]; |
64 | 0 | quint32 end = (i + 1 < d->recordOffsets.size()) ? d->recordOffsets[i + 1] : d->device->size(); |
65 | |
|
66 | 0 | if (!d->device->seek(offset)) |
67 | 0 | return QByteArray(); |
68 | | |
69 | 0 | return d->device->read(end - offset); |
70 | 0 | } |
71 | | |
72 | | QByteArray PDB::fileType() const |
73 | 0 | { |
74 | 0 | return d->fileType; |
75 | 0 | } |
76 | | |
77 | | bool PDB::isValid() const |
78 | 0 | { |
79 | 0 | return d->valid; |
80 | 0 | } |
81 | | |
82 | | quint16 PDB::recordCount() const |
83 | 0 | { |
84 | | // Range guaranteed by constructor/PDB field size |
85 | 0 | return d->recordOffsets.size(); |
86 | 0 | } |
87 | | |
88 | | } |