1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include <algorithm>
8
9 #include "xfa/src/fgas/src/fgas_base.h"
10 #include "fx_stream.h"
CreateStream(IFX_BufferRead * pBufferRead,FX_DWORD dwAccess,int32_t iFileSize,FX_BOOL bReleaseBufferRead)11 IFX_Stream* IFX_Stream::CreateStream(IFX_BufferRead* pBufferRead,
12 FX_DWORD dwAccess,
13 int32_t iFileSize,
14 FX_BOOL bReleaseBufferRead) {
15 CFX_Stream* pSR = new CFX_Stream;
16 if (!pSR->LoadBufferRead(pBufferRead, iFileSize, dwAccess,
17 bReleaseBufferRead)) {
18 pSR->Release();
19 return NULL;
20 }
21 if (dwAccess & FX_STREAMACCESS_Text) {
22 return new CFX_TextStream(pSR, TRUE);
23 }
24 return pSR;
25 }
CreateStream(IFX_FileRead * pFileRead,FX_DWORD dwAccess)26 IFX_Stream* IFX_Stream::CreateStream(IFX_FileRead* pFileRead,
27 FX_DWORD dwAccess) {
28 CFX_Stream* pSR = new CFX_Stream;
29 if (!pSR->LoadFileRead(pFileRead, dwAccess)) {
30 pSR->Release();
31 return NULL;
32 }
33 if (dwAccess & FX_STREAMACCESS_Text) {
34 return new CFX_TextStream(pSR, TRUE);
35 }
36 return pSR;
37 }
CreateStream(IFX_FileWrite * pFileWrite,FX_DWORD dwAccess)38 IFX_Stream* IFX_Stream::CreateStream(IFX_FileWrite* pFileWrite,
39 FX_DWORD dwAccess) {
40 CFX_Stream* pSR = new CFX_Stream;
41 if (!pSR->LoadFileWrite(pFileWrite, dwAccess)) {
42 pSR->Release();
43 return NULL;
44 }
45 if (dwAccess & FX_STREAMACCESS_Text) {
46 return new CFX_TextStream(pSR, TRUE);
47 }
48 return pSR;
49 }
CreateStream(const FX_WCHAR * pszFileName,FX_DWORD dwAccess)50 IFX_Stream* IFX_Stream::CreateStream(const FX_WCHAR* pszFileName,
51 FX_DWORD dwAccess) {
52 CFX_Stream* pSR = new CFX_Stream;
53 if (!pSR->LoadFile(pszFileName, dwAccess)) {
54 pSR->Release();
55 return NULL;
56 }
57 if (dwAccess & FX_STREAMACCESS_Text) {
58 return new CFX_TextStream(pSR, TRUE);
59 }
60 return pSR;
61 }
CreateStream(uint8_t * pData,int32_t length,FX_DWORD dwAccess)62 IFX_Stream* IFX_Stream::CreateStream(uint8_t* pData,
63 int32_t length,
64 FX_DWORD dwAccess) {
65 CFX_Stream* pSR = new CFX_Stream;
66 if (!pSR->LoadBuffer(pData, length, dwAccess)) {
67 pSR->Release();
68 return NULL;
69 }
70 if (dwAccess & FX_STREAMACCESS_Text) {
71 return new CFX_TextStream(pSR, TRUE);
72 }
73 return pSR;
74 }
CFX_StreamImp()75 CFX_StreamImp::CFX_StreamImp() : CFX_ThreadLock(), m_dwAccess(0) {}
CFX_FileStreamImp()76 CFX_FileStreamImp::CFX_FileStreamImp()
77 : CFX_StreamImp(), m_hFile(NULL), m_iLength(0) {}
~CFX_FileStreamImp()78 CFX_FileStreamImp::~CFX_FileStreamImp() {
79 if (m_hFile != NULL) {
80 FXSYS_fclose(m_hFile);
81 }
82 }
LoadFile(const FX_WCHAR * pszSrcFileName,FX_DWORD dwAccess)83 FX_BOOL CFX_FileStreamImp::LoadFile(const FX_WCHAR* pszSrcFileName,
84 FX_DWORD dwAccess) {
85 FXSYS_assert(m_hFile == NULL);
86 FXSYS_assert(pszSrcFileName != NULL && FXSYS_wcslen(pszSrcFileName) > 0);
87 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || \
88 _FX_OS_ == _FX_WIN64_
89 CFX_WideString wsMode;
90 if (dwAccess & FX_STREAMACCESS_Write) {
91 if (dwAccess & FX_STREAMACCESS_Append) {
92 wsMode = L"a+b";
93 } else if (dwAccess & FX_STREAMACCESS_Truncate) {
94 wsMode = L"w+b";
95 } else {
96 wsMode = L"r+b";
97 }
98 } else {
99 wsMode = L"rb";
100 }
101 #ifdef _FX_WINAPI_PARTITION_APP_
102 CFX_WideString wsSrcFileName(pszSrcFileName);
103 _wfopen_s(&m_hFile, wsSrcFileName, wsMode);
104 #else
105 m_hFile = FXSYS_wfopen(pszSrcFileName, wsMode);
106 #endif
107 if (m_hFile == NULL) {
108 if (dwAccess & FX_STREAMACCESS_Write) {
109 if (dwAccess & FX_STREAMACCESS_Create) {
110 #ifdef _FX_WINAPI_PARTITION_APP_
111 CFX_WideString wsSrcFileName(pszSrcFileName);
112 _wfopen_s(&m_hFile, wsSrcFileName, L"w+b");
113 #else
114 m_hFile = FXSYS_wfopen(pszSrcFileName, L"w+b");
115 #endif
116 }
117 if (m_hFile == NULL) {
118 #ifdef _FX_WINAPI_PARTITION_APP_
119 CFX_WideString wsSrcFileName(pszSrcFileName);
120 _wfopen_s(&m_hFile, wsSrcFileName, L"r+b");
121 #else
122 m_hFile = FXSYS_wfopen(pszSrcFileName, L"r+b");
123 #endif
124 if (m_hFile == NULL) {
125 return FALSE;
126 }
127 if (dwAccess & FX_STREAMACCESS_Truncate) {
128 FX_fsetsize(m_hFile, 0);
129 }
130 }
131 } else {
132 return FALSE;
133 }
134 }
135 #else
136 CFX_ByteString wsMode;
137 if (dwAccess & FX_STREAMACCESS_Write) {
138 if (dwAccess & FX_STREAMACCESS_Append) {
139 wsMode = "a+b";
140 } else if (dwAccess & FX_STREAMACCESS_Truncate) {
141 wsMode = "w+b";
142 } else {
143 wsMode = "r+b";
144 }
145 } else {
146 wsMode = "rb";
147 }
148 CFX_ByteString szFileName = CFX_ByteString::FromUnicode(pszSrcFileName);
149 m_hFile = FXSYS_fopen(szFileName, wsMode);
150 if (m_hFile == NULL) {
151 if (dwAccess & FX_STREAMACCESS_Write) {
152 if (dwAccess & FX_STREAMACCESS_Create) {
153 m_hFile = FXSYS_fopen(szFileName, "w+b");
154 }
155 if (m_hFile == NULL) {
156 m_hFile = FXSYS_fopen(szFileName, "r+b");
157 if (m_hFile == NULL) {
158 return FALSE;
159 }
160 if (dwAccess & FX_STREAMACCESS_Truncate) {
161 FX_fsetsize(m_hFile, 0);
162 }
163 }
164 } else {
165 return FALSE;
166 }
167 }
168 #endif
169 m_dwAccess = dwAccess;
170 if ((dwAccess & (FX_STREAMACCESS_Write | FX_STREAMACCESS_Truncate)) ==
171 (FX_STREAMACCESS_Write | FX_STREAMACCESS_Truncate)) {
172 m_iLength = 0;
173 } else {
174 m_iLength = FX_filelength(m_hFile);
175 }
176 return TRUE;
177 }
GetLength() const178 int32_t CFX_FileStreamImp::GetLength() const {
179 FXSYS_assert(m_hFile != NULL);
180 return m_iLength;
181 }
Seek(FX_STREAMSEEK eSeek,int32_t iOffset)182 int32_t CFX_FileStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
183 FXSYS_assert(m_hFile != NULL);
184 FXSYS_fseek(m_hFile, iOffset, eSeek);
185 return FXSYS_ftell(m_hFile);
186 }
GetPosition()187 int32_t CFX_FileStreamImp::GetPosition() {
188 FXSYS_assert(m_hFile != NULL);
189 return FXSYS_ftell(m_hFile);
190 }
IsEOF() const191 FX_BOOL CFX_FileStreamImp::IsEOF() const {
192 FXSYS_assert(m_hFile != NULL);
193 return FXSYS_ftell(m_hFile) >= m_iLength;
194 }
ReadData(uint8_t * pBuffer,int32_t iBufferSize)195 int32_t CFX_FileStreamImp::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
196 FXSYS_assert(m_hFile != NULL);
197 FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
198 return FXSYS_fread(pBuffer, 1, iBufferSize, m_hFile);
199 }
ReadString(FX_WCHAR * pStr,int32_t iMaxLength,FX_BOOL & bEOS)200 int32_t CFX_FileStreamImp::ReadString(FX_WCHAR* pStr,
201 int32_t iMaxLength,
202 FX_BOOL& bEOS) {
203 FXSYS_assert(m_hFile != NULL);
204 FXSYS_assert(pStr != NULL && iMaxLength > 0);
205 if (m_iLength <= 0) {
206 return 0;
207 }
208 int32_t iPosition = FXSYS_ftell(m_hFile);
209 int32_t iLen = std::min((m_iLength - iPosition) / 2, iMaxLength);
210 if (iLen <= 0) {
211 return 0;
212 }
213 iLen = FXSYS_fread(pStr, 2, iLen, m_hFile);
214 int32_t iCount = 0;
215 while (*pStr != L'\0' && iCount < iLen) {
216 pStr++, iCount++;
217 }
218 iPosition += iCount * 2;
219 if (FXSYS_ftell(m_hFile) != iPosition) {
220 FXSYS_fseek(m_hFile, iPosition, 0);
221 }
222 bEOS = (iPosition >= m_iLength);
223 return iCount;
224 }
WriteData(const uint8_t * pBuffer,int32_t iBufferSize)225 int32_t CFX_FileStreamImp::WriteData(const uint8_t* pBuffer,
226 int32_t iBufferSize) {
227 FXSYS_assert(m_hFile != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
228 FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
229 int32_t iRet = FXSYS_fwrite(pBuffer, 1, iBufferSize, m_hFile);
230 if (iRet != 0) {
231 int32_t iPos = FXSYS_ftell(m_hFile);
232 if (iPos > m_iLength) {
233 m_iLength = iPos;
234 }
235 }
236 return iRet;
237 }
WriteString(const FX_WCHAR * pStr,int32_t iLength)238 int32_t CFX_FileStreamImp::WriteString(const FX_WCHAR* pStr, int32_t iLength) {
239 FXSYS_assert(m_hFile != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
240 FXSYS_assert(pStr != NULL && iLength > 0);
241 int32_t iRet = FXSYS_fwrite(pStr, 2, iLength, m_hFile);
242 if (iRet != 0) {
243 int32_t iPos = FXSYS_ftell(m_hFile);
244 if (iPos > m_iLength) {
245 m_iLength = iPos;
246 }
247 }
248 return iRet;
249 }
Flush()250 void CFX_FileStreamImp::Flush() {
251 FXSYS_assert(m_hFile != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
252 FXSYS_fflush(m_hFile);
253 }
SetLength(int32_t iLength)254 FX_BOOL CFX_FileStreamImp::SetLength(int32_t iLength) {
255 FXSYS_assert(m_hFile != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
256 FX_BOOL bRet = FX_fsetsize(m_hFile, iLength);
257 m_iLength = FX_filelength(m_hFile);
258 return bRet;
259 }
CFX_FileReadStreamImp()260 CFX_FileReadStreamImp::CFX_FileReadStreamImp()
261 : m_pFileRead(NULL), m_iPosition(0), m_iLength(0) {}
LoadFileRead(IFX_FileRead * pFileRead,FX_DWORD dwAccess)262 FX_BOOL CFX_FileReadStreamImp::LoadFileRead(IFX_FileRead* pFileRead,
263 FX_DWORD dwAccess) {
264 FXSYS_assert(m_pFileRead == NULL && pFileRead != NULL);
265 if (dwAccess & FX_STREAMACCESS_Write) {
266 return FALSE;
267 }
268 m_pFileRead = pFileRead;
269 m_iLength = m_pFileRead->GetSize();
270 return TRUE;
271 }
GetLength() const272 int32_t CFX_FileReadStreamImp::GetLength() const {
273 return m_iLength;
274 }
Seek(FX_STREAMSEEK eSeek,int32_t iOffset)275 int32_t CFX_FileReadStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
276 switch (eSeek) {
277 case FX_STREAMSEEK_Begin:
278 m_iPosition = iOffset;
279 break;
280 case FX_STREAMSEEK_Current:
281 m_iPosition += iOffset;
282 break;
283 case FX_STREAMSEEK_End:
284 m_iPosition = m_iLength + iOffset;
285 break;
286 }
287 if (m_iPosition < 0) {
288 m_iPosition = 0;
289 } else if (m_iPosition >= m_iLength) {
290 m_iPosition = m_iLength;
291 }
292 return m_iPosition;
293 }
IsEOF() const294 FX_BOOL CFX_FileReadStreamImp::IsEOF() const {
295 return m_iPosition >= m_iLength;
296 }
ReadData(uint8_t * pBuffer,int32_t iBufferSize)297 int32_t CFX_FileReadStreamImp::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
298 FXSYS_assert(m_pFileRead != NULL);
299 FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
300 if (iBufferSize > m_iLength - m_iPosition) {
301 iBufferSize = m_iLength - m_iPosition;
302 }
303 if (m_pFileRead->ReadBlock(pBuffer, m_iPosition, iBufferSize)) {
304 m_iPosition += iBufferSize;
305 return iBufferSize;
306 }
307 return 0;
308 }
ReadString(FX_WCHAR * pStr,int32_t iMaxLength,FX_BOOL & bEOS)309 int32_t CFX_FileReadStreamImp::ReadString(FX_WCHAR* pStr,
310 int32_t iMaxLength,
311 FX_BOOL& bEOS) {
312 FXSYS_assert(m_pFileRead != NULL);
313 FXSYS_assert(pStr != NULL && iMaxLength > 0);
314 iMaxLength = ReadData((uint8_t*)pStr, iMaxLength * 2) / 2;
315 if (iMaxLength <= 0) {
316 return 0;
317 }
318 int32_t i = 0;
319 while (i < iMaxLength && pStr[i] != L'\0') {
320 ++i;
321 }
322 bEOS = (m_iPosition >= m_iLength) || pStr[i] == L'\0';
323 return i;
324 }
CFX_BufferReadStreamImp()325 CFX_BufferReadStreamImp::CFX_BufferReadStreamImp()
326 : m_pBufferRead(NULL),
327 m_bReleaseBufferRead(FALSE),
328 m_iPosition(0),
329 m_iBufferSize(0) {}
~CFX_BufferReadStreamImp()330 CFX_BufferReadStreamImp::~CFX_BufferReadStreamImp() {
331 if (m_bReleaseBufferRead && m_pBufferRead != NULL) {
332 m_pBufferRead->Release();
333 }
334 }
LoadBufferRead(IFX_BufferRead * pBufferRead,int32_t iFileSize,FX_DWORD dwAccess,FX_BOOL bReleaseBufferRead)335 FX_BOOL CFX_BufferReadStreamImp::LoadBufferRead(IFX_BufferRead* pBufferRead,
336 int32_t iFileSize,
337 FX_DWORD dwAccess,
338 FX_BOOL bReleaseBufferRead) {
339 FXSYS_assert(m_pBufferRead == NULL && pBufferRead != NULL);
340 if (dwAccess & FX_STREAMACCESS_Write) {
341 return FALSE;
342 }
343 m_bReleaseBufferRead = bReleaseBufferRead;
344 m_pBufferRead = pBufferRead;
345 m_iBufferSize = iFileSize;
346 if (m_iBufferSize >= 0) {
347 return TRUE;
348 }
349 if (!m_pBufferRead->ReadNextBlock(TRUE)) {
350 return FALSE;
351 }
352 m_iBufferSize = m_pBufferRead->GetBlockSize();
353 while (!m_pBufferRead->IsEOF()) {
354 m_pBufferRead->ReadNextBlock(FALSE);
355 m_iBufferSize += m_pBufferRead->GetBlockSize();
356 }
357 return TRUE;
358 }
GetLength() const359 int32_t CFX_BufferReadStreamImp::GetLength() const {
360 return m_iBufferSize;
361 }
Seek(FX_STREAMSEEK eSeek,int32_t iOffset)362 int32_t CFX_BufferReadStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
363 int32_t iLength = GetLength();
364 switch (eSeek) {
365 case FX_STREAMSEEK_Begin:
366 m_iPosition = iOffset;
367 break;
368 case FX_STREAMSEEK_Current:
369 m_iPosition += iOffset;
370 break;
371 case FX_STREAMSEEK_End:
372 m_iPosition = iLength + iOffset;
373 break;
374 }
375 if (m_iPosition < 0) {
376 m_iPosition = 0;
377 } else if (m_iPosition >= iLength) {
378 m_iPosition = iLength;
379 }
380 return m_iPosition;
381 }
IsEOF() const382 FX_BOOL CFX_BufferReadStreamImp::IsEOF() const {
383 return m_pBufferRead ? m_pBufferRead->IsEOF() : TRUE;
384 }
ReadData(uint8_t * pBuffer,int32_t iBufferSize)385 int32_t CFX_BufferReadStreamImp::ReadData(uint8_t* pBuffer,
386 int32_t iBufferSize) {
387 FXSYS_assert(m_pBufferRead != NULL);
388 FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
389 int32_t iLength = GetLength();
390 if (m_iPosition >= iLength) {
391 return 0;
392 }
393 if (iBufferSize > iLength - m_iPosition) {
394 iBufferSize = iLength - m_iPosition;
395 }
396 FX_DWORD dwBlockOffset = m_pBufferRead->GetBlockOffset();
397 FX_DWORD dwBlockSize = m_pBufferRead->GetBlockSize();
398 if (m_iPosition < (int32_t)dwBlockOffset) {
399 if (!m_pBufferRead->ReadNextBlock(TRUE)) {
400 return 0;
401 }
402 dwBlockOffset = m_pBufferRead->GetBlockOffset();
403 dwBlockSize = m_pBufferRead->GetBlockSize();
404 }
405 while (m_iPosition < (int32_t)dwBlockOffset ||
406 m_iPosition >= (int32_t)(dwBlockOffset + dwBlockSize)) {
407 if (m_pBufferRead->IsEOF() || !m_pBufferRead->ReadNextBlock(FALSE)) {
408 break;
409 }
410 dwBlockOffset = m_pBufferRead->GetBlockOffset();
411 dwBlockSize = m_pBufferRead->GetBlockSize();
412 }
413 if (m_iPosition < (int32_t)dwBlockOffset ||
414 m_iPosition >= (int32_t)(dwBlockOffset + dwBlockSize)) {
415 return 0;
416 }
417 const uint8_t* pBufferTmp = m_pBufferRead->GetBlockBuffer();
418 FX_DWORD dwOffsetTmp = m_iPosition - dwBlockOffset;
419 FX_DWORD dwCopySize =
420 std::min(iBufferSize, (int32_t)(dwBlockSize - dwOffsetTmp));
421 FXSYS_memcpy(pBuffer, pBufferTmp + dwOffsetTmp, dwCopySize);
422 dwOffsetTmp = dwCopySize;
423 iBufferSize -= dwCopySize;
424 while (iBufferSize > 0) {
425 if (!m_pBufferRead->ReadNextBlock(FALSE)) {
426 break;
427 }
428 dwBlockOffset = m_pBufferRead->GetBlockOffset();
429 dwBlockSize = m_pBufferRead->GetBlockSize();
430 pBufferTmp = m_pBufferRead->GetBlockBuffer();
431 dwCopySize = std::min((FX_DWORD)iBufferSize, dwBlockSize);
432 FXSYS_memcpy(pBuffer + dwOffsetTmp, pBufferTmp, dwCopySize);
433 dwOffsetTmp += dwCopySize;
434 iBufferSize -= dwCopySize;
435 }
436 m_iPosition += dwOffsetTmp;
437 return dwOffsetTmp;
438 }
ReadString(FX_WCHAR * pStr,int32_t iMaxLength,FX_BOOL & bEOS)439 int32_t CFX_BufferReadStreamImp::ReadString(FX_WCHAR* pStr,
440 int32_t iMaxLength,
441 FX_BOOL& bEOS) {
442 FXSYS_assert(m_pBufferRead != NULL);
443 FXSYS_assert(pStr != NULL && iMaxLength > 0);
444 iMaxLength = ReadData((uint8_t*)pStr, iMaxLength * 2) / 2;
445 if (iMaxLength <= 0) {
446 return 0;
447 }
448 int32_t i = 0;
449 while (i < iMaxLength && pStr[i] != L'\0') {
450 ++i;
451 }
452 bEOS = (m_iPosition >= GetLength()) || pStr[i] == L'\0';
453 return i;
454 }
CFX_FileWriteStreamImp()455 CFX_FileWriteStreamImp::CFX_FileWriteStreamImp()
456 : m_pFileWrite(NULL), m_iPosition(0) {}
LoadFileWrite(IFX_FileWrite * pFileWrite,FX_DWORD dwAccess)457 FX_BOOL CFX_FileWriteStreamImp::LoadFileWrite(IFX_FileWrite* pFileWrite,
458 FX_DWORD dwAccess) {
459 FXSYS_assert(m_pFileWrite == NULL && pFileWrite != NULL);
460 if (dwAccess & FX_STREAMACCESS_Read) {
461 return FALSE;
462 }
463 if (dwAccess & FX_STREAMACCESS_Append) {
464 m_iPosition = pFileWrite->GetSize();
465 }
466 m_pFileWrite = pFileWrite;
467 return TRUE;
468 }
GetLength() const469 int32_t CFX_FileWriteStreamImp::GetLength() const {
470 if (!m_pFileWrite) {
471 return 0;
472 }
473 return (int32_t)m_pFileWrite->GetSize();
474 }
Seek(FX_STREAMSEEK eSeek,int32_t iOffset)475 int32_t CFX_FileWriteStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
476 int32_t iLength = GetLength();
477 switch (eSeek) {
478 case FX_STREAMSEEK_Begin:
479 m_iPosition = iOffset;
480 break;
481 case FX_STREAMSEEK_Current:
482 m_iPosition += iOffset;
483 break;
484 case FX_STREAMSEEK_End:
485 m_iPosition = iLength + iOffset;
486 break;
487 }
488 if (m_iPosition < 0) {
489 m_iPosition = 0;
490 } else if (m_iPosition >= iLength) {
491 m_iPosition = iLength;
492 }
493 return m_iPosition;
494 }
IsEOF() const495 FX_BOOL CFX_FileWriteStreamImp::IsEOF() const {
496 return m_iPosition >= GetLength();
497 }
WriteData(const uint8_t * pBuffer,int32_t iBufferSize)498 int32_t CFX_FileWriteStreamImp::WriteData(const uint8_t* pBuffer,
499 int32_t iBufferSize) {
500 if (!m_pFileWrite) {
501 return 0;
502 }
503 if (m_pFileWrite->WriteBlock(pBuffer, m_iPosition, iBufferSize)) {
504 m_iPosition += iBufferSize;
505 }
506 return iBufferSize;
507 }
WriteString(const FX_WCHAR * pStr,int32_t iLength)508 int32_t CFX_FileWriteStreamImp::WriteString(const FX_WCHAR* pStr,
509 int32_t iLength) {
510 return WriteData((const uint8_t*)pStr, iLength * sizeof(FX_WCHAR));
511 }
Flush()512 void CFX_FileWriteStreamImp::Flush() {
513 if (m_pFileWrite) {
514 m_pFileWrite->Flush();
515 }
516 }
CFX_BufferStreamImp()517 CFX_BufferStreamImp::CFX_BufferStreamImp()
518 : CFX_StreamImp(),
519 m_pData(NULL),
520 m_iTotalSize(0),
521 m_iPosition(0),
522 m_iLength(0) {}
LoadBuffer(uint8_t * pData,int32_t iTotalSize,FX_DWORD dwAccess)523 FX_BOOL CFX_BufferStreamImp::LoadBuffer(uint8_t* pData,
524 int32_t iTotalSize,
525 FX_DWORD dwAccess) {
526 FXSYS_assert(m_pData == NULL);
527 FXSYS_assert(pData != NULL && iTotalSize > 0);
528 m_dwAccess = dwAccess;
529 m_pData = pData;
530 m_iTotalSize = iTotalSize;
531 m_iPosition = 0;
532 m_iLength = (dwAccess & FX_STREAMACCESS_Write) != 0 ? 0 : iTotalSize;
533 return TRUE;
534 }
GetLength() const535 int32_t CFX_BufferStreamImp::GetLength() const {
536 FXSYS_assert(m_pData != NULL);
537 return m_iLength;
538 }
Seek(FX_STREAMSEEK eSeek,int32_t iOffset)539 int32_t CFX_BufferStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
540 FXSYS_assert(m_pData != NULL);
541 if (eSeek == FX_STREAMSEEK_Begin) {
542 m_iPosition = iOffset;
543 } else if (eSeek == FX_STREAMSEEK_Current) {
544 m_iPosition += iOffset;
545 } else if (eSeek == FX_STREAMSEEK_End) {
546 m_iPosition = m_iLength + iOffset;
547 }
548 if (m_iPosition > m_iLength) {
549 m_iPosition = m_iLength;
550 }
551 if (m_iPosition < 0) {
552 m_iPosition = 0;
553 }
554 return m_iPosition;
555 }
GetPosition()556 int32_t CFX_BufferStreamImp::GetPosition() {
557 FXSYS_assert(m_pData != NULL);
558 return m_iPosition;
559 }
IsEOF() const560 FX_BOOL CFX_BufferStreamImp::IsEOF() const {
561 FXSYS_assert(m_pData != NULL);
562 return m_iPosition >= m_iLength;
563 }
ReadData(uint8_t * pBuffer,int32_t iBufferSize)564 int32_t CFX_BufferStreamImp::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
565 FXSYS_assert(m_pData != NULL);
566 FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
567 int32_t iLen = std::min(m_iLength - m_iPosition, iBufferSize);
568 if (iLen <= 0) {
569 return 0;
570 }
571 FXSYS_memcpy(pBuffer, m_pData + m_iPosition, iLen);
572 m_iPosition += iLen;
573 return iLen;
574 }
ReadString(FX_WCHAR * pStr,int32_t iMaxLength,FX_BOOL & bEOS)575 int32_t CFX_BufferStreamImp::ReadString(FX_WCHAR* pStr,
576 int32_t iMaxLength,
577 FX_BOOL& bEOS) {
578 FXSYS_assert(m_pData != NULL);
579 FXSYS_assert(pStr != NULL && iMaxLength > 0);
580 int32_t iLen = std::min((m_iLength - m_iPosition) / 2, iMaxLength);
581 if (iLen <= 0) {
582 return 0;
583 }
584 const FX_WCHAR* pSrc = (const FX_WCHAR*)(FX_CHAR*)(m_pData + m_iPosition);
585 int32_t iCount = 0;
586 while (*pSrc != L'\0' && iCount < iLen) {
587 *pStr++ = *pSrc++, iCount++;
588 }
589 m_iPosition += iCount * 2;
590 bEOS = (*pSrc == L'\0') || (m_iPosition >= m_iLength);
591 return iCount;
592 }
WriteData(const uint8_t * pBuffer,int32_t iBufferSize)593 int32_t CFX_BufferStreamImp::WriteData(const uint8_t* pBuffer,
594 int32_t iBufferSize) {
595 FXSYS_assert(m_pData != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
596 FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
597 int32_t iLen = std::min(m_iTotalSize - m_iPosition, iBufferSize);
598 if (iLen <= 0) {
599 return 0;
600 }
601 FXSYS_memcpy(m_pData + m_iPosition, pBuffer, iLen);
602 m_iPosition += iLen;
603 if (m_iPosition > m_iLength) {
604 m_iLength = m_iPosition;
605 }
606 return iLen;
607 }
WriteString(const FX_WCHAR * pStr,int32_t iLength)608 int32_t CFX_BufferStreamImp::WriteString(const FX_WCHAR* pStr,
609 int32_t iLength) {
610 FXSYS_assert(m_pData != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
611 FXSYS_assert(pStr != NULL && iLength > 0);
612 int32_t iLen = std::min((m_iTotalSize - m_iPosition) / 2, iLength);
613 if (iLen <= 0) {
614 return 0;
615 }
616 FXSYS_memcpy(m_pData + m_iPosition, pStr, iLen * 2);
617 m_iPosition += iLen * 2;
618 if (m_iPosition > m_iLength) {
619 m_iLength = m_iPosition;
620 }
621 return iLen;
622 }
CreateTextStream(IFX_Stream * pBaseStream,FX_BOOL bDeleteOnRelease)623 IFX_Stream* IFX_Stream::CreateTextStream(IFX_Stream* pBaseStream,
624 FX_BOOL bDeleteOnRelease) {
625 FXSYS_assert(pBaseStream != NULL);
626 return new CFX_TextStream(pBaseStream, bDeleteOnRelease);
627 }
CFX_TextStream(IFX_Stream * pStream,FX_BOOL bDelStream)628 CFX_TextStream::CFX_TextStream(IFX_Stream* pStream, FX_BOOL bDelStream)
629 : m_wCodePage(FX_CODEPAGE_DefANSI),
630 m_wBOMLength(0),
631 m_dwBOM(0),
632 m_pBuf(NULL),
633 m_iBufSize(0),
634 m_bDelStream(bDelStream),
635 m_pStreamImp(pStream),
636 m_iRefCount(1) {
637 FXSYS_assert(m_pStreamImp != NULL);
638 m_pStreamImp->Retain();
639 InitStream();
640 }
~CFX_TextStream()641 CFX_TextStream::~CFX_TextStream() {
642 m_pStreamImp->Release();
643 if (m_bDelStream) {
644 m_pStreamImp->Release();
645 }
646 if (m_pBuf != NULL) {
647 FX_Free(m_pBuf);
648 }
649 }
InitStream()650 void CFX_TextStream::InitStream() {
651 int32_t iPosition = m_pStreamImp->GetPosition();
652 m_pStreamImp->Seek(FX_STREAMSEEK_Begin, 0);
653 m_pStreamImp->ReadData((uint8_t*)&m_dwBOM, 3);
654 #if _FX_ENDIAN_ == _FX_LITTLE_ENDIAN_
655 m_dwBOM &= 0x00FFFFFF;
656 if (m_dwBOM == 0x00BFBBEF) {
657 m_wBOMLength = 3;
658 m_wCodePage = FX_CODEPAGE_UTF8;
659 } else {
660 m_dwBOM &= 0x0000FFFF;
661 if (m_dwBOM == 0x0000FFFE) {
662 m_wBOMLength = 2;
663 m_wCodePage = FX_CODEPAGE_UTF16BE;
664 } else if (m_dwBOM == 0x0000FEFF) {
665 m_wBOMLength = 2;
666 m_wCodePage = FX_CODEPAGE_UTF16LE;
667 } else {
668 m_wBOMLength = 0;
669 m_dwBOM = 0;
670 m_wCodePage = FXSYS_GetACP();
671 }
672 }
673 #else
674 m_dwBOM &= 0xFFFFFF00;
675 if (m_dwBOM == 0xEFBBBF00) {
676 m_wBOMLength = 3;
677 m_wCodePage = FX_CODEPAGE_UTF8;
678 } else {
679 m_dwBOM &= 0xFFFF0000;
680 if (m_dwBOM == 0xFEFF0000) {
681 m_wBOMLength = 2;
682 m_wCodePage = FX_CODEPAGE_UTF16BE;
683 } else if (m_dwBOM == 0xFFFE0000) {
684 m_wBOMLength = 2;
685 m_wCodePage = FX_CODEPAGE_UTF16LE;
686 } else {
687 m_wBOMLength = 0;
688 m_dwBOM = 0;
689 m_wCodePage = FXSYS_GetACP();
690 }
691 }
692 #endif
693 m_pStreamImp->Seek(FX_STREAMSEEK_Begin, std::max(m_wBOMLength, iPosition));
694 }
Release()695 void CFX_TextStream::Release() {
696 if (--m_iRefCount < 1) {
697 delete this;
698 }
699 }
Retain()700 IFX_Stream* CFX_TextStream::Retain() {
701 m_iRefCount++;
702 return this;
703 }
GetAccessModes() const704 FX_DWORD CFX_TextStream::GetAccessModes() const {
705 return m_pStreamImp->GetAccessModes() | FX_STREAMACCESS_Text;
706 }
GetLength() const707 int32_t CFX_TextStream::GetLength() const {
708 return m_pStreamImp->GetLength();
709 }
Seek(FX_STREAMSEEK eSeek,int32_t iOffset)710 int32_t CFX_TextStream::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
711 return m_pStreamImp->Seek(eSeek, iOffset);
712 }
GetPosition()713 int32_t CFX_TextStream::GetPosition() {
714 return m_pStreamImp->GetPosition();
715 }
IsEOF() const716 FX_BOOL CFX_TextStream::IsEOF() const {
717 return m_pStreamImp->IsEOF();
718 }
ReadData(uint8_t * pBuffer,int32_t iBufferSize)719 int32_t CFX_TextStream::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
720 return m_pStreamImp->ReadData(pBuffer, iBufferSize);
721 }
WriteData(const uint8_t * pBuffer,int32_t iBufferSize)722 int32_t CFX_TextStream::WriteData(const uint8_t* pBuffer, int32_t iBufferSize) {
723 return m_pStreamImp->WriteData(pBuffer, iBufferSize);
724 }
Flush()725 void CFX_TextStream::Flush() {
726 m_pStreamImp->Flush();
727 }
SetLength(int32_t iLength)728 FX_BOOL CFX_TextStream::SetLength(int32_t iLength) {
729 return m_pStreamImp->SetLength(iLength);
730 }
GetCodePage() const731 FX_WORD CFX_TextStream::GetCodePage() const {
732 return m_wCodePage;
733 }
CreateSharedStream(FX_DWORD dwAccess,int32_t iOffset,int32_t iLength)734 IFX_Stream* CFX_TextStream::CreateSharedStream(FX_DWORD dwAccess,
735 int32_t iOffset,
736 int32_t iLength) {
737 IFX_Stream* pSR =
738 m_pStreamImp->CreateSharedStream(dwAccess, iOffset, iLength);
739 if (pSR == NULL) {
740 return NULL;
741 }
742 if (dwAccess & FX_STREAMACCESS_Text) {
743 return new CFX_TextStream(pSR, TRUE);
744 }
745 return pSR;
746 }
GetBOM(uint8_t bom[4]) const747 int32_t CFX_TextStream::GetBOM(uint8_t bom[4]) const {
748 if (m_wBOMLength < 1) {
749 return 0;
750 }
751 *(FX_DWORD*)bom = m_dwBOM;
752 return m_wBOMLength;
753 }
SetCodePage(FX_WORD wCodePage)754 FX_WORD CFX_TextStream::SetCodePage(FX_WORD wCodePage) {
755 if (m_wBOMLength > 0) {
756 return m_wCodePage;
757 }
758 FX_WORD v = m_wCodePage;
759 m_wCodePage = wCodePage;
760 return v;
761 }
ReadString(FX_WCHAR * pStr,int32_t iMaxLength,FX_BOOL & bEOS,int32_t const * pByteSize)762 int32_t CFX_TextStream::ReadString(FX_WCHAR* pStr,
763 int32_t iMaxLength,
764 FX_BOOL& bEOS,
765 int32_t const* pByteSize) {
766 FXSYS_assert(pStr != NULL && iMaxLength > 0);
767 if (m_pStreamImp == NULL) {
768 return -1;
769 }
770 int32_t iLen;
771 if (m_wCodePage == FX_CODEPAGE_UTF16LE ||
772 m_wCodePage == FX_CODEPAGE_UTF16BE) {
773 int32_t iBytes = pByteSize == NULL ? iMaxLength * 2 : *pByteSize;
774 m_pStreamImp->Lock();
775 iLen = m_pStreamImp->ReadData((uint8_t*)pStr, iBytes);
776 m_pStreamImp->Unlock();
777 iMaxLength = iLen / 2;
778 if (sizeof(FX_WCHAR) > 2) {
779 FX_UTF16ToWChar(pStr, iMaxLength);
780 }
781 #if _FX_ENDIAN_ == _FX_BIG_ENDIAN_
782 if (m_wCodePage == FX_CODEPAGE_UTF16LE) {
783 FX_SwapByteOrder(pStr, iMaxLength);
784 }
785 #else
786 if (m_wCodePage == FX_CODEPAGE_UTF16BE) {
787 FX_SwapByteOrder(pStr, iMaxLength);
788 }
789 #endif
790 } else {
791 int32_t pos = m_pStreamImp->GetPosition();
792 int32_t iBytes = pByteSize == NULL ? iMaxLength : *pByteSize;
793 iBytes = std::min(iBytes, m_pStreamImp->GetLength() - pos);
794 if (iBytes > 0) {
795 if (m_pBuf == NULL) {
796 m_pBuf = FX_Alloc(uint8_t, iBytes);
797 m_iBufSize = iBytes;
798 } else if (iBytes > m_iBufSize) {
799 m_pBuf = FX_Realloc(uint8_t, m_pBuf, iBytes);
800 m_iBufSize = iBytes;
801 }
802 m_pStreamImp->Lock();
803 iLen = m_pStreamImp->ReadData(m_pBuf, iBytes);
804 int32_t iSrc = iLen;
805 int32_t iDecode = FX_DecodeString(m_wCodePage, (const FX_CHAR*)m_pBuf,
806 &iSrc, pStr, &iMaxLength, TRUE);
807 m_pStreamImp->Seek(FX_STREAMSEEK_Current, iSrc - iLen);
808 m_pStreamImp->Unlock();
809 if (iDecode < 1) {
810 return -1;
811 }
812 } else {
813 iMaxLength = 0;
814 }
815 }
816 bEOS = m_pStreamImp->IsEOF();
817 return iMaxLength;
818 }
WriteString(const FX_WCHAR * pStr,int32_t iLength)819 int32_t CFX_TextStream::WriteString(const FX_WCHAR* pStr, int32_t iLength) {
820 FXSYS_assert(pStr != NULL && iLength > 0);
821 if ((m_pStreamImp->GetAccessModes() & FX_STREAMACCESS_Write) == 0) {
822 return -1;
823 }
824 if (m_wCodePage == FX_CODEPAGE_UTF8) {
825 int32_t len = iLength;
826 CFX_UTF8Encoder encoder;
827 while (len-- > 0) {
828 encoder.Input(*pStr++);
829 }
830 CFX_ByteStringC bsResult = encoder.GetResult();
831 m_pStreamImp->Lock();
832 m_pStreamImp->WriteData((const uint8_t*)bsResult.GetCStr(),
833 bsResult.GetLength());
834 m_pStreamImp->Unlock();
835 }
836 return iLength;
837 }
CFX_Stream()838 CFX_Stream::CFX_Stream()
839 : m_eStreamType(FX_SREAMTYPE_Unknown),
840 m_pStreamImp(NULL),
841 m_dwAccess(0),
842 m_iTotalSize(0),
843 m_iPosition(0),
844 m_iStart(0),
845 m_iLength(0),
846 m_iRefCount(1) {}
~CFX_Stream()847 CFX_Stream::~CFX_Stream() {
848 if (m_eStreamType != FX_STREAMTYPE_Stream && m_pStreamImp != NULL) {
849 m_pStreamImp->Release();
850 }
851 }
LoadFile(const FX_WCHAR * pszSrcFileName,FX_DWORD dwAccess)852 FX_BOOL CFX_Stream::LoadFile(const FX_WCHAR* pszSrcFileName,
853 FX_DWORD dwAccess) {
854 if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
855 return FALSE;
856 }
857 if (pszSrcFileName == NULL || FXSYS_wcslen(pszSrcFileName) < 1) {
858 return FALSE;
859 }
860 m_pStreamImp = new CFX_FileStreamImp();
861 FX_BOOL bRet =
862 ((CFX_FileStreamImp*)m_pStreamImp)->LoadFile(pszSrcFileName, dwAccess);
863 if (!bRet) {
864 m_pStreamImp->Release();
865 m_pStreamImp = NULL;
866 } else {
867 m_eStreamType = FX_STREAMTYPE_File;
868 m_dwAccess = dwAccess;
869 m_iLength = m_pStreamImp->GetLength();
870 }
871 return bRet;
872 }
LoadFileRead(IFX_FileRead * pFileRead,FX_DWORD dwAccess)873 FX_BOOL CFX_Stream::LoadFileRead(IFX_FileRead* pFileRead, FX_DWORD dwAccess) {
874 if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
875 return FALSE;
876 }
877 if (pFileRead == NULL) {
878 return FALSE;
879 }
880 m_pStreamImp = new CFX_FileReadStreamImp();
881 FX_BOOL bRet =
882 ((CFX_FileReadStreamImp*)m_pStreamImp)->LoadFileRead(pFileRead, dwAccess);
883 if (!bRet) {
884 m_pStreamImp->Release();
885 m_pStreamImp = NULL;
886 } else {
887 m_eStreamType = FX_STREAMTYPE_File;
888 m_dwAccess = dwAccess;
889 m_iLength = m_pStreamImp->GetLength();
890 }
891 return bRet;
892 }
LoadFileWrite(IFX_FileWrite * pFileWrite,FX_DWORD dwAccess)893 FX_BOOL CFX_Stream::LoadFileWrite(IFX_FileWrite* pFileWrite,
894 FX_DWORD dwAccess) {
895 if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
896 return FALSE;
897 }
898 if (pFileWrite == NULL) {
899 return FALSE;
900 }
901 m_pStreamImp = new CFX_FileWriteStreamImp();
902 FX_BOOL bRet = ((CFX_FileWriteStreamImp*)m_pStreamImp)
903 ->LoadFileWrite(pFileWrite, dwAccess);
904 if (!bRet) {
905 m_pStreamImp->Release();
906 m_pStreamImp = NULL;
907 } else {
908 m_eStreamType = FX_STREAMTYPE_File;
909 m_dwAccess = dwAccess;
910 m_iLength = m_pStreamImp->GetLength();
911 }
912 return bRet;
913 }
LoadBuffer(uint8_t * pData,int32_t iTotalSize,FX_DWORD dwAccess)914 FX_BOOL CFX_Stream::LoadBuffer(uint8_t* pData,
915 int32_t iTotalSize,
916 FX_DWORD dwAccess) {
917 if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
918 return FALSE;
919 }
920 if (pData == NULL || iTotalSize < 1) {
921 return FALSE;
922 }
923 m_pStreamImp = new CFX_BufferStreamImp();
924 FX_BOOL bRet = ((CFX_BufferStreamImp*)m_pStreamImp)
925 ->LoadBuffer(pData, iTotalSize, dwAccess);
926 if (!bRet) {
927 m_pStreamImp->Release();
928 m_pStreamImp = NULL;
929 } else {
930 m_eStreamType = FX_STREAMTYPE_Buffer;
931 m_dwAccess = dwAccess;
932 m_iLength = m_pStreamImp->GetLength();
933 }
934 return bRet;
935 }
LoadBufferRead(IFX_BufferRead * pBufferRead,int32_t iFileSize,FX_DWORD dwAccess,FX_BOOL bReleaseBufferRead)936 FX_BOOL CFX_Stream::LoadBufferRead(IFX_BufferRead* pBufferRead,
937 int32_t iFileSize,
938 FX_DWORD dwAccess,
939 FX_BOOL bReleaseBufferRead) {
940 if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
941 return FALSE;
942 }
943 if (!pBufferRead) {
944 return FALSE;
945 }
946 m_pStreamImp = new CFX_BufferReadStreamImp;
947 FX_BOOL bRet = ((CFX_BufferReadStreamImp*)m_pStreamImp)
948 ->LoadBufferRead(pBufferRead, iFileSize, dwAccess,
949 bReleaseBufferRead);
950 if (!bRet) {
951 m_pStreamImp->Release();
952 m_pStreamImp = NULL;
953 } else {
954 m_eStreamType = FX_STREAMTYPE_BufferRead;
955 m_dwAccess = dwAccess;
956 m_iLength = m_pStreamImp->GetLength();
957 }
958 return bRet;
959 }
Release()960 void CFX_Stream::Release() {
961 if (--m_iRefCount < 1) {
962 delete this;
963 }
964 }
Retain()965 IFX_Stream* CFX_Stream::Retain() {
966 m_iRefCount++;
967 return this;
968 }
GetLength() const969 int32_t CFX_Stream::GetLength() const {
970 if (m_pStreamImp == NULL) {
971 return -1;
972 }
973 if (m_eStreamType == FX_STREAMTYPE_File ||
974 m_eStreamType == FX_STREAMTYPE_Buffer) {
975 return m_pStreamImp->GetLength();
976 }
977 return m_iLength;
978 }
Seek(FX_STREAMSEEK eSeek,int32_t iOffset)979 int32_t CFX_Stream::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
980 if (m_pStreamImp == NULL) {
981 return -1;
982 }
983 if (m_eStreamType == FX_STREAMTYPE_File ||
984 m_eStreamType == FX_STREAMTYPE_Buffer) {
985 return m_iPosition = m_pStreamImp->Seek(eSeek, iOffset);
986 }
987 int32_t iEnd = m_iStart + m_iLength;
988 int32_t iPosition = m_iStart + iOffset;
989 if (eSeek == FX_STREAMSEEK_Begin) {
990 m_iPosition = iPosition;
991 } else if (eSeek == FX_STREAMSEEK_Current) {
992 m_iPosition += iOffset;
993 } else if (eSeek == FX_STREAMSEEK_End) {
994 m_iPosition = iEnd + iOffset;
995 }
996 if (m_iPosition > iEnd) {
997 m_iPosition = iEnd;
998 }
999 if (m_iPosition < m_iStart) {
1000 m_iPosition = m_iStart;
1001 }
1002 return m_iPosition - m_iStart;
1003 }
GetPosition()1004 int32_t CFX_Stream::GetPosition() {
1005 if (m_pStreamImp == NULL) {
1006 return -1;
1007 }
1008 if (m_eStreamType == FX_STREAMTYPE_File ||
1009 m_eStreamType == FX_STREAMTYPE_Buffer) {
1010 return m_iPosition = m_pStreamImp->GetPosition();
1011 }
1012 return m_iPosition - m_iStart;
1013 }
IsEOF() const1014 FX_BOOL CFX_Stream::IsEOF() const {
1015 if (m_pStreamImp == NULL) {
1016 return TRUE;
1017 }
1018 if (m_eStreamType == FX_STREAMTYPE_File ||
1019 m_eStreamType == FX_STREAMTYPE_Buffer) {
1020 return m_pStreamImp->IsEOF();
1021 }
1022 return m_iPosition >= m_iStart + m_iLength;
1023 }
ReadData(uint8_t * pBuffer,int32_t iBufferSize)1024 int32_t CFX_Stream::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
1025 FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
1026 if (m_pStreamImp == NULL) {
1027 return -1;
1028 }
1029 int32_t iLen = std::min(m_iStart + m_iLength - m_iPosition, iBufferSize);
1030 if (iLen <= 0) {
1031 return 0;
1032 }
1033 m_pStreamImp->Lock();
1034 if (m_pStreamImp->GetPosition() != m_iPosition) {
1035 m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
1036 }
1037 iLen = m_pStreamImp->ReadData(pBuffer, iLen);
1038 m_iPosition = m_pStreamImp->GetPosition();
1039 m_pStreamImp->Unlock();
1040 return iLen;
1041 }
ReadString(FX_WCHAR * pStr,int32_t iMaxLength,FX_BOOL & bEOS,int32_t const * pByteSize)1042 int32_t CFX_Stream::ReadString(FX_WCHAR* pStr,
1043 int32_t iMaxLength,
1044 FX_BOOL& bEOS,
1045 int32_t const* pByteSize) {
1046 FXSYS_assert(pStr != NULL && iMaxLength > 0);
1047 if (m_pStreamImp == NULL) {
1048 return -1;
1049 }
1050 int32_t iEnd = m_iStart + m_iLength;
1051 int32_t iLen = iEnd - m_iPosition;
1052 if (pByteSize != NULL) {
1053 iLen = std::min(iLen, *pByteSize);
1054 }
1055 iLen = std::min(iEnd / 2, iMaxLength);
1056 if (iLen <= 0) {
1057 return 0;
1058 }
1059 m_pStreamImp->Lock();
1060 if (m_pStreamImp->GetPosition() != m_iPosition) {
1061 m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
1062 }
1063 iLen = m_pStreamImp->ReadString(pStr, iLen, bEOS);
1064 m_iPosition = m_pStreamImp->GetPosition();
1065 if (iLen > 0 && m_iPosition >= iEnd) {
1066 bEOS = TRUE;
1067 }
1068 m_pStreamImp->Unlock();
1069 return iLen;
1070 }
WriteData(const uint8_t * pBuffer,int32_t iBufferSize)1071 int32_t CFX_Stream::WriteData(const uint8_t* pBuffer, int32_t iBufferSize) {
1072 FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
1073 if (m_pStreamImp == NULL) {
1074 return -1;
1075 }
1076 if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
1077 return -1;
1078 }
1079 int32_t iLen = iBufferSize;
1080 if (m_eStreamType == FX_STREAMTYPE_Stream) {
1081 iLen = std::min(m_iStart + m_iTotalSize - m_iPosition, iBufferSize);
1082 if (iLen <= 0) {
1083 return 0;
1084 }
1085 }
1086 m_pStreamImp->Lock();
1087 int32_t iEnd = m_iStart + m_iLength;
1088 if (m_pStreamImp->GetPosition() != m_iPosition) {
1089 m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
1090 }
1091 iLen = m_pStreamImp->WriteData(pBuffer, iLen);
1092 m_iPosition = m_pStreamImp->GetPosition();
1093 if (m_iPosition > iEnd) {
1094 m_iLength = m_iPosition - m_iStart;
1095 }
1096 m_pStreamImp->Unlock();
1097 return iLen;
1098 }
WriteString(const FX_WCHAR * pStr,int32_t iLength)1099 int32_t CFX_Stream::WriteString(const FX_WCHAR* pStr, int32_t iLength) {
1100 FXSYS_assert(pStr != NULL && iLength > 0);
1101 if (m_pStreamImp == NULL) {
1102 return -1;
1103 }
1104 if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
1105 return -1;
1106 }
1107 int32_t iLen = iLength;
1108 if (m_eStreamType == FX_STREAMTYPE_Stream) {
1109 iLen = std::min((m_iStart + m_iTotalSize - m_iPosition) / 2, iLength);
1110 if (iLen <= 0) {
1111 return 0;
1112 }
1113 }
1114 m_pStreamImp->Lock();
1115 int32_t iEnd = m_iStart + m_iLength;
1116 if (m_pStreamImp->GetPosition() != m_iPosition) {
1117 m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
1118 }
1119 iLen = m_pStreamImp->WriteString(pStr, iLen);
1120 m_iPosition = m_pStreamImp->GetPosition();
1121 if (m_iPosition > iEnd) {
1122 m_iLength = m_iPosition - m_iStart;
1123 }
1124 m_pStreamImp->Unlock();
1125 return iLen;
1126 }
Flush()1127 void CFX_Stream::Flush() {
1128 if (m_pStreamImp == NULL) {
1129 return;
1130 }
1131 if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
1132 return;
1133 }
1134 m_pStreamImp->Flush();
1135 }
SetLength(int32_t iLength)1136 FX_BOOL CFX_Stream::SetLength(int32_t iLength) {
1137 if (m_pStreamImp == NULL) {
1138 return FALSE;
1139 }
1140 if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
1141 return FALSE;
1142 }
1143 return m_pStreamImp->SetLength(iLength);
1144 }
GetBOM(uint8_t bom[4]) const1145 int32_t CFX_Stream::GetBOM(uint8_t bom[4]) const {
1146 if (m_pStreamImp == NULL) {
1147 return -1;
1148 }
1149 return 0;
1150 }
GetCodePage() const1151 FX_WORD CFX_Stream::GetCodePage() const {
1152 #if _FX_ENDIAN_ == _FX_LITTLE_ENDIAN_
1153 return FX_CODEPAGE_UTF16LE;
1154 #else
1155 return FX_CODEPAGE_UTF16BE;
1156 #endif
1157 }
SetCodePage(FX_WORD wCodePage)1158 FX_WORD CFX_Stream::SetCodePage(FX_WORD wCodePage) {
1159 #if _FX_ENDIAN_ == _FX_LITTLE_ENDIAN_
1160 return FX_CODEPAGE_UTF16LE;
1161 #else
1162 return FX_CODEPAGE_UTF16BE;
1163 #endif
1164 }
CreateSharedStream(FX_DWORD dwAccess,int32_t iOffset,int32_t iLength)1165 IFX_Stream* CFX_Stream::CreateSharedStream(FX_DWORD dwAccess,
1166 int32_t iOffset,
1167 int32_t iLength) {
1168 FXSYS_assert(iLength > 0);
1169 if (m_pStreamImp == NULL) {
1170 return NULL;
1171 }
1172 if ((m_dwAccess & FX_STREAMACCESS_Text) != 0 &&
1173 (dwAccess & FX_STREAMACCESS_Text) == 0) {
1174 return NULL;
1175 }
1176 if ((m_dwAccess & FX_STREAMACCESS_Write) == 0 &&
1177 (dwAccess & FX_STREAMACCESS_Write) != 0) {
1178 return NULL;
1179 }
1180 int32_t iStart = m_iStart + iOffset;
1181 int32_t iTotal = m_iStart + m_iLength;
1182 if (iStart < m_iStart || iStart >= iTotal) {
1183 return NULL;
1184 }
1185 int32_t iEnd = iStart + iLength;
1186 if (iEnd < iStart || iEnd > iTotal) {
1187 return NULL;
1188 }
1189 CFX_Stream* pShared = new CFX_Stream;
1190 pShared->m_eStreamType = FX_STREAMTYPE_Stream;
1191 pShared->m_pStreamImp = m_pStreamImp;
1192 pShared->m_dwAccess = dwAccess;
1193 pShared->m_iTotalSize = iLength;
1194 pShared->m_iPosition = iStart;
1195 pShared->m_iStart = iStart;
1196 pShared->m_iLength = (dwAccess & FX_STREAMACCESS_Write) != 0 ? 0 : iLength;
1197 if (dwAccess & FX_STREAMACCESS_Text) {
1198 return IFX_Stream::CreateTextStream(pShared, TRUE);
1199 }
1200 return pShared;
1201 }
FX_CreateFileRead(IFX_Stream * pBaseStream,FX_BOOL bReleaseStream)1202 IFX_FileRead* FX_CreateFileRead(IFX_Stream* pBaseStream,
1203 FX_BOOL bReleaseStream) {
1204 FXSYS_assert(pBaseStream != NULL);
1205 return new CFGAS_FileRead(pBaseStream, bReleaseStream);
1206 }
CFGAS_FileRead(IFX_Stream * pStream,FX_BOOL bReleaseStream)1207 CFGAS_FileRead::CFGAS_FileRead(IFX_Stream* pStream, FX_BOOL bReleaseStream)
1208 : m_bReleaseStream(bReleaseStream), m_pStream(pStream) {
1209 FXSYS_assert(m_pStream != NULL);
1210 }
~CFGAS_FileRead()1211 CFGAS_FileRead::~CFGAS_FileRead() {
1212 if (m_bReleaseStream) {
1213 m_pStream->Release();
1214 }
1215 }
GetSize()1216 FX_FILESIZE CFGAS_FileRead::GetSize() {
1217 return (FX_FILESIZE)m_pStream->GetLength();
1218 }
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)1219 FX_BOOL CFGAS_FileRead::ReadBlock(void* buffer,
1220 FX_FILESIZE offset,
1221 size_t size) {
1222 m_pStream->Lock();
1223 m_pStream->Seek(FX_STREAMSEEK_Begin, (int32_t)offset);
1224 int32_t iLen = m_pStream->ReadData((uint8_t*)buffer, (int32_t)size);
1225 m_pStream->Unlock();
1226 return iLen == (int32_t)size;
1227 }
1228
FX_CreateFileRead(IFX_BufferRead * pBufferRead,FX_FILESIZE iFileSize,FX_BOOL bReleaseStream)1229 IFX_FileRead* FX_CreateFileRead(IFX_BufferRead* pBufferRead,
1230 FX_FILESIZE iFileSize,
1231 FX_BOOL bReleaseStream) {
1232 if (!pBufferRead) {
1233 return NULL;
1234 }
1235 return new CFX_BufferAccImp(pBufferRead, iFileSize, bReleaseStream);
1236 }
CFX_BufferAccImp(IFX_BufferRead * pBufferRead,FX_FILESIZE iFileSize,FX_BOOL bReleaseStream)1237 CFX_BufferAccImp::CFX_BufferAccImp(IFX_BufferRead* pBufferRead,
1238 FX_FILESIZE iFileSize,
1239 FX_BOOL bReleaseStream)
1240 : m_pBufferRead(pBufferRead),
1241 m_bReleaseStream(bReleaseStream),
1242 m_iBufSize(iFileSize) {
1243 FXSYS_assert(m_pBufferRead);
1244 }
~CFX_BufferAccImp()1245 CFX_BufferAccImp::~CFX_BufferAccImp() {
1246 if (m_bReleaseStream && m_pBufferRead) {
1247 m_pBufferRead->Release();
1248 }
1249 }
GetSize()1250 FX_FILESIZE CFX_BufferAccImp::GetSize() {
1251 if (!m_pBufferRead) {
1252 return 0;
1253 }
1254 if (m_iBufSize >= 0) {
1255 return m_iBufSize;
1256 }
1257 if (!m_pBufferRead->ReadNextBlock(TRUE)) {
1258 return 0;
1259 }
1260 m_iBufSize = (FX_FILESIZE)m_pBufferRead->GetBlockSize();
1261 while (!m_pBufferRead->IsEOF()) {
1262 m_pBufferRead->ReadNextBlock(FALSE);
1263 m_iBufSize += (FX_FILESIZE)m_pBufferRead->GetBlockSize();
1264 }
1265 return m_iBufSize;
1266 }
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)1267 FX_BOOL CFX_BufferAccImp::ReadBlock(void* buffer,
1268 FX_FILESIZE offset,
1269 size_t size) {
1270 if (!m_pBufferRead) {
1271 return FALSE;
1272 }
1273 if (!buffer || !size) {
1274 return TRUE;
1275 }
1276 FX_FILESIZE dwBufSize = GetSize();
1277 if (offset >= dwBufSize) {
1278 return FALSE;
1279 }
1280 size_t dwBlockSize = m_pBufferRead->GetBlockSize();
1281 FX_FILESIZE dwBlockOffset = m_pBufferRead->GetBlockOffset();
1282 if (offset < dwBlockOffset) {
1283 if (!m_pBufferRead->ReadNextBlock(TRUE)) {
1284 return FALSE;
1285 }
1286 dwBlockSize = m_pBufferRead->GetBlockSize();
1287 dwBlockOffset = m_pBufferRead->GetBlockOffset();
1288 }
1289 while (offset < dwBlockOffset ||
1290 offset >= (FX_FILESIZE)(dwBlockOffset + dwBlockSize)) {
1291 if (m_pBufferRead->IsEOF() || !m_pBufferRead->ReadNextBlock(FALSE)) {
1292 break;
1293 }
1294 dwBlockSize = m_pBufferRead->GetBlockSize();
1295 dwBlockOffset = m_pBufferRead->GetBlockOffset();
1296 }
1297 if (offset < dwBlockOffset ||
1298 offset >= (FX_FILESIZE)(dwBlockOffset + dwBlockSize)) {
1299 return FALSE;
1300 }
1301 const uint8_t* pBuffer = m_pBufferRead->GetBlockBuffer();
1302 const FX_FILESIZE dwOffset = offset - dwBlockOffset;
1303 size_t dwCopySize =
1304 std::min(size, static_cast<size_t>(dwBlockSize - dwOffset));
1305 FXSYS_memcpy(buffer, pBuffer + dwOffset, dwCopySize);
1306 offset = dwCopySize;
1307 size -= dwCopySize;
1308 while (size) {
1309 if (!m_pBufferRead->ReadNextBlock(FALSE)) {
1310 break;
1311 }
1312 dwBlockOffset = m_pBufferRead->GetBlockOffset();
1313 dwBlockSize = m_pBufferRead->GetBlockSize();
1314 pBuffer = m_pBufferRead->GetBlockBuffer();
1315 dwCopySize = std::min(size, dwBlockSize);
1316 FXSYS_memcpy(((uint8_t*)buffer) + offset, pBuffer, dwCopySize);
1317 offset += dwCopySize;
1318 size -= dwCopySize;
1319 }
1320 return TRUE;
1321 }
1322
FX_CreateFileWrite(IFX_Stream * pBaseStream,FX_BOOL bReleaseStream)1323 IFX_FileWrite* FX_CreateFileWrite(IFX_Stream* pBaseStream,
1324 FX_BOOL bReleaseStream) {
1325 FXSYS_assert(pBaseStream != NULL);
1326 return new CFGAS_FileWrite(pBaseStream, bReleaseStream);
1327 }
1328
CFGAS_FileWrite(IFX_Stream * pStream,FX_BOOL bReleaseStream)1329 CFGAS_FileWrite::CFGAS_FileWrite(IFX_Stream* pStream, FX_BOOL bReleaseStream)
1330 : m_pStream(pStream), m_bReleaseStream(bReleaseStream) {
1331 FXSYS_assert(m_pStream != NULL);
1332 }
~CFGAS_FileWrite()1333 CFGAS_FileWrite::~CFGAS_FileWrite() {
1334 if (m_bReleaseStream) {
1335 m_pStream->Release();
1336 }
1337 }
GetSize()1338 FX_FILESIZE CFGAS_FileWrite::GetSize() {
1339 return m_pStream->GetLength();
1340 }
Flush()1341 FX_BOOL CFGAS_FileWrite::Flush() {
1342 m_pStream->Flush();
1343 return TRUE;
1344 }
WriteBlock(const void * pData,size_t size)1345 FX_BOOL CFGAS_FileWrite::WriteBlock(const void* pData, size_t size) {
1346 return m_pStream->WriteData((const uint8_t*)pData, (int32_t)size) ==
1347 (int32_t)size;
1348 }
WriteBlock(const void * pData,FX_FILESIZE offset,size_t size)1349 FX_BOOL CFGAS_FileWrite::WriteBlock(const void* pData,
1350 FX_FILESIZE offset,
1351 size_t size) {
1352 m_pStream->Lock();
1353 m_pStream->Seek(FX_STREAMSEEK_Begin, offset);
1354 int32_t iLen = m_pStream->WriteData((uint8_t*)pData, (int32_t)size);
1355 m_pStream->Unlock();
1356 return iLen == (int32_t)size;
1357 }
1358