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