/src/libvisio/src/lib/VSDInternalStream.cpp
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* |
3 | | * This file is part of the libvisio 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 "VSDInternalStream.h" |
11 | | |
12 | | #include <string.h> |
13 | | |
14 | | VSDInternalStream::VSDInternalStream(librevenge::RVNGInputStream *input, unsigned long size, bool compressed) : |
15 | 9.39M | librevenge::RVNGInputStream(), |
16 | 9.39M | m_offset(0), |
17 | 9.39M | m_buffer() |
18 | 9.39M | { |
19 | 9.39M | unsigned long tmpNumBytesRead = 0; |
20 | | |
21 | 9.39M | const unsigned char *tmpBuffer = input->read(size, tmpNumBytesRead); |
22 | | |
23 | 9.39M | if (tmpNumBytesRead < 2) |
24 | 7.85M | return; |
25 | | |
26 | 1.54M | if (!compressed) |
27 | 1.17M | { |
28 | 1.17M | m_buffer.assign(tmpBuffer, tmpBuffer + tmpNumBytesRead); |
29 | 1.17M | } |
30 | 372k | else |
31 | 372k | { |
32 | 372k | unsigned char buffer[4096] = { 0 }; |
33 | 372k | unsigned pos = 0; |
34 | 372k | unsigned offset = 0; |
35 | | |
36 | 161M | while (offset < tmpNumBytesRead) |
37 | 161M | { |
38 | 161M | unsigned flag = tmpBuffer[offset++]; |
39 | 161M | if (offset > tmpNumBytesRead-1) |
40 | 103k | break; |
41 | | |
42 | 161M | unsigned mask = 1; |
43 | 1.45G | for (unsigned bit = 0; bit < 8 && offset < tmpNumBytesRead; ++bit) |
44 | 1.28G | { |
45 | 1.28G | if (flag & mask) |
46 | 511M | { |
47 | 511M | buffer[pos&4095] = tmpBuffer[offset++]; |
48 | 511M | m_buffer.push_back(buffer[pos&4095]); |
49 | 511M | pos++; |
50 | 511M | } |
51 | 778M | else |
52 | 778M | { |
53 | 778M | if (offset > tmpNumBytesRead-2) |
54 | 85.3k | break; |
55 | 778M | unsigned char addr1 = tmpBuffer[offset++]; |
56 | 778M | unsigned char addr2 = tmpBuffer[offset++]; |
57 | | |
58 | 778M | unsigned length = (addr2&15) + 3; |
59 | 778M | unsigned pointer = (((unsigned)addr2 & 0xF0) << 4) | addr1; |
60 | 778M | if (pointer > 4078) |
61 | 10.1M | pointer -= 4078; |
62 | 767M | else |
63 | 767M | pointer += 18; |
64 | | |
65 | 8.24G | for (unsigned j = 0; j < length; ++j) |
66 | 7.46G | { |
67 | 7.46G | buffer[(pos+j) & 4095] = buffer[(pointer+j) & 4095]; |
68 | 7.46G | m_buffer.push_back(buffer[(pointer+j) & 4095]); |
69 | 7.46G | } |
70 | 778M | pos += length; |
71 | 778M | } |
72 | 1.28G | mask = mask << 1; |
73 | 1.28G | } |
74 | 161M | } |
75 | 372k | } |
76 | 1.54M | } |
77 | | |
78 | | const unsigned char *VSDInternalStream::read(unsigned long numBytes, unsigned long &numBytesRead) |
79 | 1.51G | { |
80 | 1.51G | numBytesRead = 0; |
81 | | |
82 | 1.51G | if (numBytes == 0) |
83 | 149k | return nullptr; |
84 | | |
85 | 1.51G | int numBytesToRead; |
86 | | |
87 | 1.51G | if (numBytes < m_buffer.size() - m_offset) |
88 | 1.50G | numBytesToRead = numBytes; |
89 | 1.13M | else |
90 | 1.13M | numBytesToRead = m_buffer.size() - m_offset; |
91 | | |
92 | 1.51G | numBytesRead = numBytesToRead; // about as paranoid as we can be.. |
93 | | |
94 | 1.51G | if (numBytesToRead == 0) |
95 | 6.57k | return nullptr; |
96 | | |
97 | 1.51G | long oldOffset = m_offset; |
98 | 1.51G | m_offset += numBytesToRead; |
99 | | |
100 | 1.51G | return &m_buffer[oldOffset]; |
101 | 1.51G | } |
102 | | |
103 | | int VSDInternalStream::seek(long offset, librevenge::RVNG_SEEK_TYPE seekType) |
104 | 75.6M | { |
105 | 75.6M | if (seekType == librevenge::RVNG_SEEK_CUR) |
106 | 64.9M | m_offset += offset; |
107 | 10.6M | else if (seekType == librevenge::RVNG_SEEK_SET) |
108 | 10.4M | m_offset = offset; |
109 | 255k | else if (seekType == librevenge::RVNG_SEEK_END) |
110 | 255k | m_offset = long(static_cast<unsigned long>(m_buffer.size())) + offset; |
111 | | |
112 | 75.6M | if (m_offset < 0) |
113 | 46.0k | { |
114 | 46.0k | m_offset = 0; |
115 | 46.0k | return 1; |
116 | 46.0k | } |
117 | 75.5M | if ((long)m_offset > (long)m_buffer.size()) |
118 | 1.45M | { |
119 | 1.45M | m_offset = m_buffer.size(); |
120 | 1.45M | return 1; |
121 | 1.45M | } |
122 | | |
123 | 74.1M | return 0; |
124 | 75.5M | } |
125 | | |
126 | | long VSDInternalStream::tell() |
127 | 514M | { |
128 | 514M | return m_offset; |
129 | 514M | } |
130 | | |
131 | | bool VSDInternalStream::isEnd() |
132 | 2.11G | { |
133 | 2.11G | if ((long)m_offset >= (long)m_buffer.size()) |
134 | 3.66M | return true; |
135 | | |
136 | 2.11G | return false; |
137 | 2.11G | } |
138 | | /* vim:set shiftwidth=2 softtabstop=2 expandtab: */ |