1 /*
2  * The Progressive Graphics File; http://www.libpgf.org
3  *
4  * $Date: 2007-01-19 11:51:24 +0100 (Fr, 19 Jan 2007) $
5  * $Revision: 268 $
6  *
7  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  */
23 
24 //////////////////////////////////////////////////////////////////////
25 /// @file PGFstream.cpp
26 /// @brief PGF stream class implementation
27 /// @author C. Stamm
28 
29 #include "PGFstream.h"
30 
31 #ifdef WIN32
32 #include <malloc.h>
33 #endif
34 
35 //////////////////////////////////////////////////////////////////////
36 // CPGFFileStream
37 //////////////////////////////////////////////////////////////////////
Write(int * count,void * buffPtr)38 void CPGFFileStream::Write(int *count, void *buffPtr) {
39 	ASSERT(count);
40 	ASSERT(buffPtr);
41 	ASSERT(IsValid());
42 	OSError err;
43 	if ((err = FileWrite(m_hFile, count, buffPtr)) != NoError) ReturnWithError(err);
44 
45 }
46 
47 //////////////////////////////////////////////////////////////////////
Read(int * count,void * buffPtr)48 void CPGFFileStream::Read(int *count, void *buffPtr) {
49 	ASSERT(count);
50 	ASSERT(buffPtr);
51 	ASSERT(IsValid());
52 	OSError err;
53 	if ((err = FileRead(m_hFile, count, buffPtr)) != NoError) ReturnWithError(err);
54 }
55 
56 //////////////////////////////////////////////////////////////////////
SetPos(short posMode,INT64 posOff)57 void CPGFFileStream::SetPos(short posMode, INT64 posOff) {
58 	ASSERT(IsValid());
59 	OSError err;
60 	if ((err = SetFPos(m_hFile, posMode, posOff)) != NoError) ReturnWithError(err);
61 }
62 
63 //////////////////////////////////////////////////////////////////////
GetPos() const64 UINT64 CPGFFileStream::GetPos() const {
65 	ASSERT(IsValid());
66 	OSError err;
67 	UINT64 pos = 0;
68 	if ((err = GetFPos(m_hFile, &pos)) != NoError) ReturnWithError2(err, pos);
69 	return pos;
70 }
71 
72 
73 //////////////////////////////////////////////////////////////////////
74 // CPGFMemoryStream
75 //////////////////////////////////////////////////////////////////////
76 /// Allocate memory block of given size
77 /// @param size Memory size
CPGFMemoryStream(size_t size)78 CPGFMemoryStream::CPGFMemoryStream(size_t size)
79 : m_size(size)
80 , m_allocated(true) {
81 	m_buffer = m_pos = m_eos = new(std::nothrow) UINT8[m_size];
82 	if (!m_buffer) ReturnWithError(InsufficientMemory);
83 }
84 
85 //////////////////////////////////////////////////////////////////////
86 /// Use already allocated memory of given size
87 /// @param pBuffer Memory location
88 /// @param size Memory size
CPGFMemoryStream(UINT8 * pBuffer,size_t size)89 CPGFMemoryStream::CPGFMemoryStream(UINT8 *pBuffer, size_t size)
90 : m_buffer(pBuffer)
91 , m_pos(pBuffer)
92 , m_eos(pBuffer + size)
93 , m_size(size)
94 , m_allocated(false) {
95 	ASSERT(IsValid());
96 }
97 
98 //////////////////////////////////////////////////////////////////////
99 /// Use already allocated memory of given size
100 /// @param pBuffer Memory location
101 /// @param size Memory size
Reinitialize(UINT8 * pBuffer,size_t size)102 void CPGFMemoryStream::Reinitialize(UINT8 *pBuffer, size_t size) {
103 	if (!m_allocated) {
104 		m_buffer = m_pos = pBuffer;
105 		m_size = size;
106 		m_eos = m_buffer + size;
107 	}
108 }
109 
110 //////////////////////////////////////////////////////////////////////
Write(int * count,void * buffPtr)111 void CPGFMemoryStream::Write(int *count, void *buffPtr) {
112 	ASSERT(count);
113 	ASSERT(buffPtr);
114 	ASSERT(IsValid());
115 	const size_t deltaSize = 0x4000 + *count;
116 
117 	if (m_pos + *count <= m_buffer + m_size) {
118 		memcpy(m_pos, buffPtr, *count);
119 		m_pos += *count;
120 		if (m_pos > m_eos) m_eos = m_pos;
121 	} else if (m_allocated) {
122 		// memory block is too small -> reallocate a deltaSize larger block
123 		size_t offset = m_pos - m_buffer;
124 		UINT8 *buf_tmp = (UINT8 *)realloc(m_buffer, m_size + deltaSize);
125 		if (!buf_tmp) {
126 			delete[] m_buffer;
127 			m_buffer = 0;
128 			ReturnWithError(InsufficientMemory);
129 		} else {
130 			m_buffer = buf_tmp;
131 		}
132 		m_size += deltaSize;
133 
134 		// reposition m_pos
135 		m_pos = m_buffer + offset;
136 
137 		// write block
138 		memcpy(m_pos, buffPtr, *count);
139 		m_pos += *count;
140 		if (m_pos > m_eos) m_eos = m_pos;
141 	} else {
142 		ReturnWithError(InsufficientMemory);
143 	}
144 	ASSERT(m_pos <= m_eos);
145 }
146 
147 //////////////////////////////////////////////////////////////////////
Read(int * count,void * buffPtr)148 void CPGFMemoryStream::Read(int *count, void *buffPtr) {
149 	ASSERT(IsValid());
150 	ASSERT(count);
151 	ASSERT(buffPtr);
152 	ASSERT(m_buffer + m_size >= m_eos);
153 	ASSERT(m_pos <= m_eos);
154 
155 	if (m_pos + *count <= m_eos) {
156 		memcpy(buffPtr, m_pos, *count);
157 		m_pos += *count;
158 	} else {
159 		// end of memory block reached -> read only until end
160 		*count = (int)__max(0, m_eos - m_pos);
161 		memcpy(buffPtr, m_pos, *count);
162 		m_pos += *count;
163 	}
164 	ASSERT(m_pos <= m_eos);
165 }
166 
167 //////////////////////////////////////////////////////////////////////
SetPos(short posMode,INT64 posOff)168 void CPGFMemoryStream::SetPos(short posMode, INT64 posOff) {
169 	ASSERT(IsValid());
170 	switch(posMode) {
171 	case FSFromStart:
172 		m_pos = m_buffer + posOff;
173 		break;
174 	case FSFromCurrent:
175 		m_pos += posOff;
176 		break;
177 	case FSFromEnd:
178 		m_pos = m_eos + posOff;
179 		break;
180 	default:
181 		ASSERT(false);
182 	}
183 	if (m_pos > m_eos)
184 		ReturnWithError(InvalidStreamPos);
185 }
186 
187 
188 //////////////////////////////////////////////////////////////////////
189 // CPGFMemFileStream
190 #ifdef _MFC_VER
191 //////////////////////////////////////////////////////////////////////
Write(int * count,void * buffPtr)192 void CPGFMemFileStream::Write(int *count, void *buffPtr) {
193 	ASSERT(count);
194 	ASSERT(buffPtr);
195 	ASSERT(IsValid());
196 	m_memFile->Write(buffPtr, *count);
197 }
198 
199 //////////////////////////////////////////////////////////////////////
Read(int * count,void * buffPtr)200 void CPGFMemFileStream::Read(int *count, void *buffPtr) {
201 	ASSERT(count);
202 	ASSERT(buffPtr);
203 	ASSERT(IsValid());
204 	m_memFile->Read(buffPtr, *count);
205 }
206 
207 //////////////////////////////////////////////////////////////////////
SetPos(short posMode,INT64 posOff)208 void CPGFMemFileStream::SetPos(short posMode, INT64 posOff) {
209 	ASSERT(IsValid());
210 	m_memFile->Seek(posOff, posMode);
211 }
212 
213 //////////////////////////////////////////////////////////////////////
GetPos() const214 UINT64 CPGFMemFileStream::GetPos() const {
215 	return (UINT64)m_memFile->GetPosition();
216 }
217 #endif // _MFC_VER
218 
219 //////////////////////////////////////////////////////////////////////
220 // CPGFIStream
221 #if defined(WIN32) || defined(WINCE)
222 //////////////////////////////////////////////////////////////////////
Write(int * count,void * buffPtr)223 void CPGFIStream::Write(int *count, void *buffPtr) {
224 	ASSERT(count);
225 	ASSERT(buffPtr);
226 	ASSERT(IsValid());
227 
228 	HRESULT hr = m_stream->Write(buffPtr, *count, (ULONG *)count);
229 	if (FAILED(hr)) {
230 		ReturnWithError(hr);
231 	}
232 }
233 
234 //////////////////////////////////////////////////////////////////////
Read(int * count,void * buffPtr)235 void CPGFIStream::Read(int *count, void *buffPtr) {
236 	ASSERT(count);
237 	ASSERT(buffPtr);
238 	ASSERT(IsValid());
239 
240 	HRESULT hr = m_stream->Read(buffPtr, *count, (ULONG *)count);
241 	if (FAILED(hr)) {
242 		ReturnWithError(hr);
243 	}
244 }
245 
246 //////////////////////////////////////////////////////////////////////
SetPos(short posMode,INT64 posOff)247 void CPGFIStream::SetPos(short posMode, INT64 posOff) {
248 	ASSERT(IsValid());
249 
250 	LARGE_INTEGER li;
251 	li.QuadPart = posOff;
252 
253 	HRESULT hr = m_stream->Seek(li, posMode, nullptr);
254 	if (FAILED(hr)) {
255 		ReturnWithError(hr);
256 	}
257 }
258 
259 //////////////////////////////////////////////////////////////////////
GetPos() const260 UINT64 CPGFIStream::GetPos() const {
261 	ASSERT(IsValid());
262 
263 	LARGE_INTEGER n;
264 	ULARGE_INTEGER pos;
265 	n.QuadPart = 0;
266 
267 	HRESULT hr = m_stream->Seek(n, FSFromCurrent, &pos);
268 	if (SUCCEEDED(hr)) {
269 		return pos.QuadPart;
270 	} else {
271 		ReturnWithError2(hr, pos.QuadPart);
272 	}
273 }
274 #endif // WIN32 || WINCE
275