Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* libcdr
3 : * Version: MPL 1.1 / GPLv2+ / LGPLv2+
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License or as specified alternatively below. You may obtain a copy of
8 : * the License at http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * Major Contributor(s):
16 : * Copyright (C) 2012 Fridrich Strba <fridrich.strba@bluewin.ch>
17 : * Copyright (C) 2011 Eilidh McAdam <tibbylickle@gmail.com>
18 : *
19 : *
20 : * All Rights Reserved.
21 : *
22 : * For minor contributions see the git repository.
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
26 : * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
27 : * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
28 : * instead of those above.
29 : */
30 :
31 :
32 : #include <zlib.h>
33 : #include "CDRInternalStream.h"
34 : #include "libcdr_utils.h"
35 : #include <string.h> // for memcpy
36 :
37 :
38 : #define CHUNK 16384
39 :
40 0 : libcdr::CDRInternalStream::CDRInternalStream(const std::vector<unsigned char> &buffer) :
41 : WPXInputStream(),
42 : m_offset(0),
43 0 : m_buffer(buffer)
44 : {
45 0 : }
46 :
47 0 : libcdr::CDRInternalStream::CDRInternalStream(WPXInputStream *input, unsigned long size, bool compressed) :
48 : WPXInputStream(),
49 : m_offset(0),
50 0 : m_buffer()
51 : {
52 0 : if (!size)
53 0 : return;
54 :
55 0 : if (!compressed)
56 : {
57 0 : unsigned long tmpNumBytesRead = 0;
58 0 : const unsigned char *tmpBuffer = input->read(size, tmpNumBytesRead);
59 :
60 0 : if (size != tmpNumBytesRead)
61 : return;
62 :
63 0 : m_buffer = std::vector<unsigned char>(size);
64 0 : memcpy(&m_buffer[0], tmpBuffer, size);
65 : }
66 : else
67 : {
68 : int ret;
69 : unsigned have;
70 : z_stream strm;
71 : unsigned char out[CHUNK];
72 :
73 : /* allocate inflate state */
74 0 : strm.zalloc = Z_NULL;
75 0 : strm.zfree = Z_NULL;
76 0 : strm.opaque = Z_NULL;
77 0 : strm.avail_in = 0;
78 0 : strm.next_in = Z_NULL;
79 0 : ret = inflateInit(&strm);
80 0 : if (ret != Z_OK)
81 : return;
82 :
83 0 : unsigned long tmpNumBytesRead = 0;
84 0 : const unsigned char *tmpBuffer = input->read(size, tmpNumBytesRead);
85 :
86 0 : if (size != tmpNumBytesRead)
87 : return;
88 :
89 0 : strm.avail_in = tmpNumBytesRead;
90 0 : strm.next_in = (Bytef *)tmpBuffer;
91 :
92 0 : do
93 : {
94 0 : strm.avail_out = CHUNK;
95 0 : strm.next_out = out;
96 0 : ret = inflate(&strm, Z_NO_FLUSH);
97 0 : switch (ret)
98 : {
99 : case Z_NEED_DICT:
100 : case Z_DATA_ERROR:
101 : case Z_MEM_ERROR:
102 0 : (void)inflateEnd(&strm);
103 0 : m_buffer.clear();
104 : return;
105 : }
106 :
107 0 : have = CHUNK - strm.avail_out;
108 :
109 0 : for (unsigned long i=0; i<have; i++)
110 0 : m_buffer.push_back(out[i]);
111 :
112 : }
113 : while (strm.avail_out == 0);
114 0 : (void)inflateEnd(&strm);
115 : }
116 : }
117 :
118 0 : const unsigned char *libcdr::CDRInternalStream::read(unsigned long numBytes, unsigned long &numBytesRead)
119 : {
120 0 : numBytesRead = 0;
121 :
122 0 : if (numBytes == 0)
123 0 : return 0;
124 :
125 : int numBytesToRead;
126 :
127 0 : if ((m_offset+numBytes) < m_buffer.size())
128 0 : numBytesToRead = numBytes;
129 : else
130 0 : numBytesToRead = m_buffer.size() - m_offset;
131 :
132 0 : numBytesRead = numBytesToRead; // about as paranoid as we can be..
133 :
134 0 : if (numBytesToRead == 0)
135 0 : return 0;
136 :
137 0 : long oldOffset = m_offset;
138 0 : m_offset += numBytesToRead;
139 :
140 0 : return &m_buffer[oldOffset];
141 : }
142 :
143 0 : int libcdr::CDRInternalStream::seek(long offset, WPX_SEEK_TYPE seekType)
144 : {
145 0 : if (seekType == WPX_SEEK_CUR)
146 0 : m_offset += offset;
147 0 : else if (seekType == WPX_SEEK_SET)
148 0 : m_offset = offset;
149 :
150 0 : if (m_offset < 0)
151 : {
152 0 : m_offset = 0;
153 0 : return 1;
154 : }
155 0 : if ((long)m_offset > (long)m_buffer.size())
156 : {
157 0 : m_offset = m_buffer.size();
158 0 : return 1;
159 : }
160 :
161 0 : return 0;
162 : }
163 :
164 0 : long libcdr::CDRInternalStream::tell()
165 : {
166 0 : return m_offset;
167 : }
168 :
169 0 : bool libcdr::CDRInternalStream::atEOS()
170 : {
171 0 : if ((long)m_offset >= (long)m_buffer.size())
172 0 : return true;
173 :
174 0 : return false;
175 : }
176 : /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
|