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