/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 | 33.0k | #define CHUNK 16384 |
17 | | |
18 | | libcdr::CDRInternalStream::CDRInternalStream(const std::vector<unsigned char> &buffer) : |
19 | 22.3k | librevenge::RVNGInputStream(), |
20 | 22.3k | m_offset(0), |
21 | 22.3k | m_buffer(buffer) |
22 | 22.3k | { |
23 | 22.3k | } |
24 | | |
25 | | libcdr::CDRInternalStream::CDRInternalStream(librevenge::RVNGInputStream *input, unsigned long size, bool compressed) : |
26 | 226k | librevenge::RVNGInputStream(), |
27 | 226k | m_offset(0), |
28 | 226k | m_buffer() |
29 | 226k | { |
30 | 226k | if (!size) |
31 | 3.37k | return; |
32 | | |
33 | 223k | if (!compressed) |
34 | 213k | { |
35 | 213k | unsigned long tmpNumBytesRead = 0; |
36 | 213k | const unsigned char *tmpBuffer = input->read(size, tmpNumBytesRead); |
37 | | |
38 | 213k | if (size != tmpNumBytesRead) |
39 | 26.5k | return; |
40 | | |
41 | 187k | m_buffer = std::vector<unsigned char>(size); |
42 | 187k | memcpy(&m_buffer[0], tmpBuffer, size); |
43 | 187k | } |
44 | 9.57k | else |
45 | 9.57k | { |
46 | 9.57k | int ret; |
47 | 9.57k | z_stream strm; |
48 | 9.57k | unsigned char out[CHUNK]; |
49 | | |
50 | | /* allocate inflate state */ |
51 | 9.57k | strm.zalloc = Z_NULL; |
52 | 9.57k | strm.zfree = Z_NULL; |
53 | 9.57k | strm.opaque = Z_NULL; |
54 | 9.57k | strm.avail_in = 0; |
55 | 9.57k | strm.next_in = Z_NULL; |
56 | 9.57k | ret = inflateInit(&strm); |
57 | 9.57k | if (ret != Z_OK) |
58 | 0 | return; |
59 | | |
60 | 9.57k | unsigned long tmpNumBytesRead = 0; |
61 | 9.57k | const unsigned char *tmpBuffer = input->read(size, tmpNumBytesRead); |
62 | | |
63 | 9.57k | if (size != tmpNumBytesRead) |
64 | 360 | { |
65 | 360 | (void)inflateEnd(&strm); |
66 | 360 | return; |
67 | 360 | } |
68 | | |
69 | 9.21k | strm.avail_in = (uInt)tmpNumBytesRead; |
70 | 9.21k | strm.next_in = const_cast<Bytef *>(tmpBuffer); |
71 | | |
72 | 9.21k | do |
73 | 18.9k | { |
74 | 18.9k | strm.avail_out = CHUNK; |
75 | 18.9k | strm.next_out = out; |
76 | 18.9k | ret = inflate(&strm, Z_NO_FLUSH); |
77 | 18.9k | switch (ret) |
78 | 18.9k | { |
79 | 5 | case Z_NEED_DICT: |
80 | 4.78k | case Z_DATA_ERROR: |
81 | 4.78k | case Z_MEM_ERROR: |
82 | 4.78k | (void)inflateEnd(&strm); |
83 | 4.78k | m_buffer.clear(); |
84 | 4.78k | return; |
85 | 14.1k | default: |
86 | 14.1k | break; |
87 | 18.9k | } |
88 | | |
89 | 14.1k | unsigned have = CHUNK - strm.avail_out; |
90 | | |
91 | 163M | for (unsigned long i=0; i<have; i++) |
92 | 163M | m_buffer.push_back(out[i]); |
93 | | |
94 | 14.1k | } |
95 | 14.1k | while (strm.avail_out == 0); |
96 | 4.43k | (void)inflateEnd(&strm); |
97 | 4.43k | } |
98 | 223k | } |
99 | | |
100 | | const unsigned char *libcdr::CDRInternalStream::read(unsigned long numBytes, unsigned long &numBytesRead) |
101 | 6.28M | { |
102 | 6.28M | numBytesRead = 0; |
103 | | |
104 | 6.28M | if (numBytes == 0) |
105 | 486 | return nullptr; |
106 | | |
107 | 6.28M | if (m_offset < 0) |
108 | 0 | return nullptr; |
109 | | |
110 | 6.28M | const unsigned long bufSize = m_buffer.size(); |
111 | 6.28M | const unsigned long pos = static_cast<unsigned long>(m_offset); |
112 | 6.28M | const unsigned long remaining = pos < bufSize ? bufSize - pos : 0; |
113 | 6.28M | const unsigned long numBytesToRead = numBytes < remaining ? numBytes : remaining; |
114 | | |
115 | 6.28M | numBytesRead = numBytesToRead; // about as paranoid as we can be.. |
116 | | |
117 | 6.28M | if (numBytesToRead == 0) |
118 | 127 | return nullptr; |
119 | | |
120 | 6.28M | long oldOffset = m_offset; |
121 | 6.28M | m_offset += numBytesToRead; |
122 | | |
123 | 6.28M | return &m_buffer[oldOffset]; |
124 | 6.28M | } |
125 | | |
126 | | int libcdr::CDRInternalStream::seek(long offset, librevenge::RVNG_SEEK_TYPE seekType) |
127 | 2.35M | { |
128 | 2.35M | if (seekType == librevenge::RVNG_SEEK_CUR) |
129 | 993k | m_offset += offset; |
130 | 1.35M | else if (seekType == librevenge::RVNG_SEEK_SET) |
131 | 1.09M | m_offset = offset; |
132 | 263k | else if (seekType == librevenge::RVNG_SEEK_END) |
133 | 263k | m_offset = long(static_cast<unsigned long>(m_buffer.size())) + offset; |
134 | | |
135 | 2.35M | if (m_offset < 0) |
136 | 0 | { |
137 | 0 | m_offset = 0; |
138 | 0 | return 1; |
139 | 0 | } |
140 | 2.35M | if ((long)m_offset > (long)m_buffer.size()) |
141 | 447k | { |
142 | 447k | m_offset = m_buffer.size(); |
143 | 447k | return 1; |
144 | 447k | } |
145 | | |
146 | 1.90M | return 0; |
147 | 2.35M | } |
148 | | |
149 | | long libcdr::CDRInternalStream::tell() |
150 | 1.52M | { |
151 | 1.52M | return m_offset; |
152 | 1.52M | } |
153 | | |
154 | | bool libcdr::CDRInternalStream::isEnd() |
155 | 9.97M | { |
156 | 9.97M | if ((long)m_offset >= (long)m_buffer.size()) |
157 | 248k | return true; |
158 | | |
159 | 9.72M | return false; |
160 | 9.97M | } |
161 | | /* vim:set shiftwidth=2 softtabstop=2 expandtab: */ |