1 /*
2 * HLLib
3 * Copyright (C) 2006-2010 Ryan Gregg
4
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later
9 * version.
10 */
11
12 #include "HLLib.h"
13 #include "MappingStream.h"
14
15 using namespace HLLib;
16 using namespace HLLib::Streams;
17
CMappingStream(Mapping::CMapping & Mapping,hlULongLong uiMappingOffset,hlULongLong uiMappingSize,hlULongLong uiViewSize)18 CMappingStream::CMappingStream(Mapping::CMapping &Mapping, hlULongLong uiMappingOffset, hlULongLong uiMappingSize, hlULongLong uiViewSize) : bOpened(hlFalse), uiMode(HL_MODE_INVALID), Mapping(Mapping), uiMappingOffset(uiMappingOffset), uiMappingSize(uiMappingSize), uiViewSize(uiViewSize), pView(0), uiPointer(0), uiLength(0)
19 {
20 if(this->uiViewSize == 0)
21 {
22 switch(this->Mapping.GetType())
23 {
24 case HL_MAPPING_FILE:
25 if(this->Mapping.GetMode() & HL_MODE_QUICK_FILEMAPPING)
26 {
27 case HL_MAPPING_MEMORY:
28 this->uiViewSize = this->uiMappingSize;
29 break;
30 }
31 default:
32 this->uiViewSize = HL_DEFAULT_VIEW_SIZE;
33 break;
34 }
35 }
36 }
37
~CMappingStream()38 CMappingStream::~CMappingStream()
39 {
40 this->Close();
41 }
42
GetType() const43 HLStreamType CMappingStream::GetType() const
44 {
45 return HL_STREAM_MAPPING;
46 }
47
GetMapping() const48 const Mapping::CMapping &CMappingStream::GetMapping() const
49 {
50 return this->Mapping;
51 }
52
GetFileName() const53 const hlChar *CMappingStream::GetFileName() const
54 {
55 return "";
56 }
57
GetOpened() const58 hlBool CMappingStream::GetOpened() const
59 {
60 return this->bOpened;
61 }
62
GetMode() const63 hlUInt CMappingStream::GetMode() const
64 {
65 return this->uiMode;
66 }
67
Open(hlUInt uiMode)68 hlBool CMappingStream::Open(hlUInt uiMode)
69 {
70 this->Close();
71
72 if((uiMode & (HL_MODE_READ | HL_MODE_WRITE)) == 0)
73 {
74 LastError.SetErrorMessageFormated("Invalid open mode (%#.8x).", uiMode);
75 return hlFalse;
76 }
77
78 if((uiMode & HL_MODE_READ) != 0 && (this->Mapping.GetMode() & HL_MODE_READ) == 0)
79 {
80 LastError.SetErrorMessage("Mapping does not have read permissions.");
81 return hlFalse;
82 }
83
84 if((uiMode & HL_MODE_WRITE) != 0 && (this->Mapping.GetMode() & HL_MODE_WRITE) == 0)
85 {
86 LastError.SetErrorMessage("Mapping does not have write permissions.");
87 return hlFalse;
88 }
89
90 this->uiPointer = 0;
91 this->uiLength = (uiMode & HL_MODE_READ) ? this->uiMappingSize : 0;
92
93 this->bOpened = hlTrue;
94 this->uiMode = uiMode;
95
96 return hlTrue;
97 }
98
Close()99 hlVoid CMappingStream::Close()
100 {
101 this->bOpened = hlFalse;
102 this->uiMode = HL_MODE_INVALID;
103
104 this->Mapping.Unmap(this->pView);
105
106 this->uiPointer = 0;
107 this->uiLength = 0;
108 }
109
GetStreamSize() const110 hlULongLong CMappingStream::GetStreamSize() const
111 {
112 return this->uiLength;
113 }
114
GetStreamPointer() const115 hlULongLong CMappingStream::GetStreamPointer() const
116 {
117 return this->uiPointer;
118 }
119
Seek(hlLongLong iOffset,HLSeekMode eSeekMode)120 hlULongLong CMappingStream::Seek(hlLongLong iOffset, HLSeekMode eSeekMode)
121 {
122 if(!this->bOpened)
123 {
124 return 0;
125 }
126
127 switch(eSeekMode)
128 {
129 case HL_SEEK_BEGINNING:
130 this->uiPointer = 0;
131 break;
132 case HL_SEEK_CURRENT:
133
134 break;
135 case HL_SEEK_END:
136 this->uiPointer = this->uiLength;
137 break;
138 }
139
140 hlLongLong iPointer = static_cast<hlLongLong>(this->uiPointer) + iOffset;
141
142 if(iPointer < 0)
143 {
144 iPointer = 0;
145 }
146 else if(iPointer > static_cast<hlLongLong>(this->uiLength))
147 {
148 iPointer = static_cast<hlLongLong>(this->uiLength);
149 }
150
151 this->uiPointer = static_cast<hlULongLong>(iPointer);
152
153 return this->uiPointer;
154 }
155
Read(hlChar & cChar)156 hlBool CMappingStream::Read(hlChar &cChar)
157 {
158 if(!this->bOpened)
159 {
160 return 0;
161 }
162
163 if((this->uiMode & HL_MODE_READ) == 0)
164 {
165 LastError.SetErrorMessage("Stream not in read mode.");
166 return 0;
167 }
168
169 if(this->uiPointer < this->uiLength)
170 {
171 if(!this->Map(this->uiPointer))
172 {
173 return 0;
174 }
175
176 hlULongLong uiViewPointer = this->uiPointer - (this->pView->GetAllocationOffset() + this->pView->GetOffset() - this->uiMappingOffset);
177 hlULongLong uiViewBytes = this->pView->GetLength() - uiViewPointer;
178
179 if(uiViewBytes >= 1)
180 {
181 cChar = *(static_cast<const hlChar *>(this->pView->GetView()) + uiViewPointer);
182 this->uiPointer++;
183 return 1;
184 }
185 }
186
187 return 0;
188 }
189
Read(hlVoid * lpData,hlUInt uiBytes)190 hlUInt CMappingStream::Read(hlVoid *lpData, hlUInt uiBytes)
191 {
192 if(!this->bOpened)
193 {
194 return 0;
195 }
196
197 if((this->uiMode & HL_MODE_READ) == 0)
198 {
199 LastError.SetErrorMessage("Stream not in read mode.");
200 return 0;
201 }
202
203 if(this->uiPointer == this->uiLength)
204 {
205 return 0;
206 }
207 else
208 {
209 hlULongLong uiOffset = 0;
210 while(uiBytes && this->uiPointer < this->uiLength)
211 {
212 if(!this->Map(this->uiPointer))
213 {
214 break;
215 }
216
217 hlULongLong uiViewPointer = this->uiPointer - (this->pView->GetAllocationOffset() + this->pView->GetOffset() - this->uiMappingOffset);
218 hlULongLong uiViewBytes = this->pView->GetLength() - uiViewPointer;
219
220 if(uiViewBytes >= uiBytes)
221 {
222 memcpy(static_cast<hlByte *>(lpData) + uiOffset, static_cast<const hlByte *>(this->pView->GetView()) + uiViewPointer, uiBytes);
223 this->uiPointer += static_cast<hlULongLong>(uiBytes);
224 uiOffset += uiBytes;
225 break;
226 }
227 else
228 {
229 memcpy(static_cast<hlByte *>(lpData) + uiOffset, static_cast<const hlByte *>(this->pView->GetView()) + uiViewPointer, static_cast<size_t>(uiViewBytes));
230 this->uiPointer += uiViewBytes;
231 uiOffset += uiViewBytes;
232 uiBytes -= static_cast<hlUInt>(uiViewBytes);
233 }
234 }
235
236 return static_cast<hlUInt>(uiOffset);
237 }
238 }
239
Write(hlChar cChar)240 hlBool CMappingStream::Write(hlChar cChar)
241 {
242 if(!this->bOpened)
243 {
244 return 0;
245 }
246
247 if((this->uiMode & HL_MODE_WRITE) == 0)
248 {
249 LastError.SetErrorMessage("Stream not in write mode.");
250 return 0;
251 }
252
253 if(this->uiPointer < this->uiMappingSize)
254 {
255 if(!this->Map(this->uiPointer))
256 {
257 return 0;
258 }
259
260 hlULongLong uiViewPointer = this->uiPointer - (this->pView->GetAllocationOffset() + this->pView->GetOffset() - this->uiMappingOffset);
261 hlULongLong uiViewBytes = this->pView->GetLength() - uiViewPointer;
262
263 if(uiViewBytes >= 1)
264 {
265 *(static_cast<hlChar *>(const_cast<hlVoid *>(this->pView->GetView())) + uiViewPointer) = cChar;
266 this->uiPointer++;
267
268 if(this->uiPointer > this->uiLength)
269 {
270 this->uiLength = this->uiPointer;
271 }
272
273 return 1;
274 }
275 }
276
277 return 0;
278 }
279
Write(const hlVoid * lpData,hlUInt uiBytes)280 hlUInt CMappingStream::Write(const hlVoid *lpData, hlUInt uiBytes)
281 {
282 if(!this->bOpened)
283 {
284 return 0;
285 }
286
287 if((this->uiMode & HL_MODE_WRITE) == 0)
288 {
289 LastError.SetErrorMessage("Stream not in write mode.");
290 return 0;
291 }
292
293 if(this->uiPointer == this->uiMappingSize)
294 {
295 return 0;
296 }
297 else
298 {
299 hlULongLong uiOffset = 0;
300 while(uiBytes && this->uiPointer < this->uiMappingSize)
301 {
302 if(!this->Map(this->uiPointer))
303 {
304 break;
305 }
306
307 hlULongLong uiViewPointer = this->uiPointer - (this->pView->GetAllocationOffset() + this->pView->GetOffset() - this->uiMappingOffset);
308 hlULongLong uiViewBytes = this->pView->GetLength() - uiViewPointer;
309
310 if(uiViewBytes >= uiBytes)
311 {
312 memcpy(static_cast<hlByte *>(const_cast<hlVoid *>(this->pView->GetView())) + uiViewPointer, static_cast<const hlByte *>(lpData) + uiOffset, uiBytes);
313 this->uiPointer += static_cast<hlULongLong>(uiBytes);
314 uiOffset += uiBytes;
315 break;
316 }
317 else
318 {
319 memcpy(static_cast<hlByte *>(const_cast<hlVoid *>(this->pView->GetView())) + uiViewPointer, static_cast<const hlByte *>(lpData) + uiOffset, static_cast<size_t>(uiViewBytes));
320 this->uiPointer += uiViewBytes;
321 uiOffset += uiViewBytes;
322 uiBytes -= static_cast<hlUInt>(uiViewBytes);
323 }
324 }
325
326 if(this->uiPointer > this->uiLength)
327 {
328 this->uiLength = this->uiPointer;
329 }
330
331 return static_cast<hlUInt>(uiOffset);
332 }
333 }
334
Map(hlULongLong uiPointer)335 hlBool CMappingStream::Map(hlULongLong uiPointer)
336 {
337 uiPointer = (uiPointer / this->uiViewSize) * this->uiViewSize;
338
339 if(this->pView)
340 {
341 if(this->pView->GetAllocationOffset() - this->uiMappingOffset == uiPointer)
342 {
343 return hlTrue;
344 }
345 }
346
347 hlULongLong uiLength = uiPointer + this->uiViewSize > this->uiMappingSize ? this->uiMappingSize - uiPointer : this->uiViewSize;
348
349 return this->Mapping.Map(this->pView, this->uiMappingOffset + uiPointer, uiLength);
350 }
351