1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3 * This file is part of the libqxp project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10 #include "QXPBlockParser.h"
11
12 #include <librevenge-stream/librevenge-stream.h>
13 #include <algorithm>
14 #include <memory>
15 #include <vector>
16 #include <cstdlib>
17
18 #include "QXPHeader.h"
19
20 namespace libqxp
21 {
22
23 using librevenge::RVNGInputStream;
24 using librevenge::RVNGStringStream;
25 using std::make_shared;
26 using std::vector;
27
QXPBlockParser(const std::shared_ptr<RVNGInputStream> & input,const std::shared_ptr<QXPHeader> & header)28 QXPBlockParser::QXPBlockParser(const std::shared_ptr<RVNGInputStream> &input, const std::shared_ptr<QXPHeader> &header)
29 : m_input(input)
30 , m_header(header)
31 , be(header->isBigEndian())
32 , m_blockLength(256)
33 {
34 }
35
getBlock(const uint32_t index)36 std::shared_ptr<RVNGInputStream> QXPBlockParser::getBlock(const uint32_t index)
37 {
38 seek(m_input, (index - 1) * m_blockLength);
39 auto block = readNBytes(m_input, m_blockLength);
40 return make_shared<RVNGStringStream>(block, m_blockLength);
41 }
42
getChain(const uint32_t index)43 std::shared_ptr<RVNGInputStream> QXPBlockParser::getChain(const uint32_t index)
44 {
45 bool bigIdx = m_header->version() >= QXPVersion::QXP_31_MAC;
46
47 vector<unsigned char> chain;
48 bool isBig = false;
49 uint32_t next = index;
50 while (next > 0)
51 {
52 seek(m_input, (next - 1) * m_blockLength);
53 const uint16_t count = isBig ? readU16(m_input, be) : 1;
54
55 uint32_t len = (next - 1 + count) * m_blockLength - (bigIdx ? 4 : 2) - m_input->tell();
56 auto block = readNBytes(m_input, len);
57 std::copy(block, block + len, std::back_inserter(chain));
58
59 const int32_t nextVal = bigIdx ? readS32(m_input, be) : readS16(m_input, be);
60 isBig = nextVal < 0;
61 next = abs(nextVal);
62 }
63 return make_shared<RVNGStringStream>(chain.data(), chain.size());
64 }
65
66 }
67
68 /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
69