/src/libcdr/src/lib/CDRInternalStream.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 libcdr 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 "CDRInternalStream.h" |
11 | | |
12 | | #include <zlib.h> |
13 | | #include <string.h> // for memcpy |
14 | | |
15 | | |
16 | 5.76k | #define CHUNK 16384 |
17 | | |
18 | | libcdr::CDRInternalStream::CDRInternalStream(const std::vector<unsigned char> &buffer) : |
19 | 3.57k | librevenge::RVNGInputStream(), |
20 | 3.57k | m_offset(0), |
21 | 3.57k | m_buffer(buffer) |
22 | 3.57k | { |
23 | 3.57k | } |
24 | | |
25 | | libcdr::CDRInternalStream::CDRInternalStream(librevenge::RVNGInputStream *input, unsigned long size, bool compressed) : |
26 | 22.9k | librevenge::RVNGInputStream(), |
27 | 22.9k | m_offset(0), |
28 | 22.9k | m_buffer() |
29 | 22.9k | { |
30 | 22.9k | if (!size) |
31 | 199 | return; |
32 | | |
33 | 22.7k | if (!compressed) |
34 | 22.4k | { |
35 | 22.4k | unsigned long tmpNumBytesRead = 0; |
36 | 22.4k | const unsigned char *tmpBuffer = input->read(size, tmpNumBytesRead); |
37 | | |
38 | 22.4k | if (size != tmpNumBytesRead) |
39 | 3.28k | return; |
40 | | |
41 | 19.1k | m_buffer = std::vector<unsigned char>(size); |
42 | 19.1k | memcpy(&m_buffer[0], tmpBuffer, size); |
43 | 19.1k | } |
44 | 300 | else |
45 | 300 | { |
46 | 300 | int ret; |
47 | 300 | z_stream strm; |
48 | 300 | unsigned char out[CHUNK]; |
49 | | |
50 | | /* allocate inflate state */ |
51 | 300 | strm.zalloc = Z_NULL; |
52 | 300 | strm.zfree = Z_NULL; |
53 | 300 | strm.opaque = Z_NULL; |
54 | 300 | strm.avail_in = 0; |
55 | 300 | strm.next_in = Z_NULL; |
56 | 300 | ret = inflateInit(&strm); |
57 | 300 | if (ret != Z_OK) |
58 | 0 | return; |
59 | | |
60 | 300 | unsigned long tmpNumBytesRead = 0; |
61 | 300 | const unsigned char *tmpBuffer = input->read(size, tmpNumBytesRead); |
62 | | |
63 | 300 | if (size != tmpNumBytesRead) |
64 | 0 | { |
65 | 0 | (void)inflateEnd(&strm); |
66 | 0 | return; |
67 | 0 | } |
68 | | |
69 | 300 | strm.avail_in = (uInt)tmpNumBytesRead; |
70 | 300 | strm.next_in = const_cast<Bytef *>(tmpBuffer); |
71 | | |
72 | 300 | do |
73 | 2.93k | { |
74 | 2.93k | strm.avail_out = CHUNK; |
75 | 2.93k | strm.next_out = out; |
76 | 2.93k | ret = inflate(&strm, Z_NO_FLUSH); |
77 | 2.93k | switch (ret) |
78 | 2.93k | { |
79 | 0 | case Z_NEED_DICT: |
80 | 108 | case Z_DATA_ERROR: |
81 | 108 | case Z_MEM_ERROR: |
82 | 108 | (void)inflateEnd(&strm); |
83 | 108 | m_buffer.clear(); |
84 | 108 | return; |
85 | 2.82k | default: |
86 | 2.82k | break; |
87 | 2.93k | } |
88 | | |
89 | 2.82k | unsigned have = CHUNK - strm.avail_out; |
90 | | |
91 | 43.3M | for (unsigned long i=0; i<have; i++) |
92 | 43.3M | m_buffer.push_back(out[i]); |
93 | | |
94 | 2.82k | } |
95 | 2.82k | while (strm.avail_out == 0); |
96 | 192 | (void)inflateEnd(&strm); |
97 | 192 | } |
98 | 22.7k | } |
99 | | |
100 | | const unsigned char *libcdr::CDRInternalStream::read(unsigned long numBytes, unsigned long &numBytesRead) |
101 | 1.57M | { |
102 | 1.57M | numBytesRead = 0; |
103 | | |
104 | 1.57M | if (numBytes == 0) |
105 | 0 | return nullptr; |
106 | | |
107 | 1.57M | unsigned long numBytesToRead; |
108 | | |
109 | 1.57M | if ((m_offset+numBytes) < m_buffer.size()) |
110 | 1.56M | numBytesToRead = numBytes; |
111 | 4.54k | else |
112 | 4.54k | numBytesToRead = m_buffer.size() - m_offset; |
113 | | |
114 | 1.57M | numBytesRead = numBytesToRead; // about as paranoid as we can be.. |
115 | | |
116 | 1.57M | if (numBytesToRead == 0) |
117 | 0 | return nullptr; |
118 | | |
119 | 1.57M | long oldOffset = m_offset; |
120 | 1.57M | m_offset += numBytesToRead; |
121 | | |
122 | 1.57M | return &m_buffer[oldOffset]; |
123 | 1.57M | } |
124 | | |
125 | | int libcdr::CDRInternalStream::seek(long offset, librevenge::RVNG_SEEK_TYPE seekType) |
126 | 330k | { |
127 | 330k | if (seekType == librevenge::RVNG_SEEK_CUR) |
128 | 135k | m_offset += offset; |
129 | 194k | else if (seekType == librevenge::RVNG_SEEK_SET) |
130 | 156k | m_offset = offset; |
131 | 37.4k | else if (seekType == librevenge::RVNG_SEEK_END) |
132 | 37.4k | m_offset = long(static_cast<unsigned long>(m_buffer.size())) + offset; |
133 | | |
134 | 330k | if (m_offset < 0) |
135 | 0 | { |
136 | 0 | m_offset = 0; |
137 | 0 | return 1; |
138 | 0 | } |
139 | 330k | if ((long)m_offset > (long)m_buffer.size()) |
140 | 54.8k | { |
141 | 54.8k | m_offset = m_buffer.size(); |
142 | 54.8k | return 1; |
143 | 54.8k | } |
144 | | |
145 | 275k | return 0; |
146 | 330k | } |
147 | | |
148 | | long libcdr::CDRInternalStream::tell() |
149 | 213k | { |
150 | 213k | return m_offset; |
151 | 213k | } |
152 | | |
153 | | bool libcdr::CDRInternalStream::isEnd() |
154 | 2.78M | { |
155 | 2.78M | if ((long)m_offset >= (long)m_buffer.size()) |
156 | 27.6k | return true; |
157 | | |
158 | 2.75M | return false; |
159 | 2.78M | } |
160 | | /* vim:set shiftwidth=2 softtabstop=2 expandtab: */ |