Home | History | Annotate | Download | only in crt
      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"
     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 }
     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 }
     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 }
     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 }
     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 }
     75 CFX_StreamImp::CFX_StreamImp() : CFX_ThreadLock(), m_dwAccess(0) {}
     76 CFX_FileStreamImp::CFX_FileStreamImp()
     77     : CFX_StreamImp(), m_hFile(NULL), m_iLength(0) {}
     78 CFX_FileStreamImp::~CFX_FileStreamImp() {
     79   if (m_hFile != NULL) {
     80     FXSYS_fclose(m_hFile);
     81   }
     82 }
     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 }
    178 int32_t CFX_FileStreamImp::GetLength() const {
    179   FXSYS_assert(m_hFile != NULL);
    180   return m_iLength;
    181 }
    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 }
    187 int32_t CFX_FileStreamImp::GetPosition() {
    188   FXSYS_assert(m_hFile != NULL);
    189   return FXSYS_ftell(m_hFile);
    190 }
    191 FX_BOOL CFX_FileStreamImp::IsEOF() const {
    192   FXSYS_assert(m_hFile != NULL);
    193   return FXSYS_ftell(m_hFile) >= m_iLength;
    194 }
    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 }
    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 }
    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 }
    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 }
    250 void CFX_FileStreamImp::Flush() {
    251   FXSYS_assert(m_hFile != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
    252   FXSYS_fflush(m_hFile);
    253 }
    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 }
    260 CFX_FileReadStreamImp::CFX_FileReadStreamImp()
    261     : m_pFileRead(NULL), m_iPosition(0), m_iLength(0) {}
    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 }
    272 int32_t CFX_FileReadStreamImp::GetLength() const {
    273   return m_iLength;
    274 }
    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 }
    294 FX_BOOL CFX_FileReadStreamImp::IsEOF() const {
    295   return m_iPosition >= m_iLength;
    296 }
    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 }
    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 }
    325 CFX_BufferReadStreamImp::CFX_BufferReadStreamImp()
    326     : m_pBufferRead(NULL),
    327       m_bReleaseBufferRead(FALSE),
    328       m_iPosition(0),
    329       m_iBufferSize(0) {}
    330 CFX_BufferReadStreamImp::~CFX_BufferReadStreamImp() {
    331   if (m_bReleaseBufferRead && m_pBufferRead != NULL) {
    332     m_pBufferRead->Release();
    333   }
    334 }
    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 }
    359 int32_t CFX_BufferReadStreamImp::GetLength() const {
    360   return m_iBufferSize;
    361 }
    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 }
    382 FX_BOOL CFX_BufferReadStreamImp::IsEOF() const {
    383   return m_pBufferRead ? m_pBufferRead->IsEOF() : TRUE;
    384 }
    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 }
    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 }
    455 CFX_FileWriteStreamImp::CFX_FileWriteStreamImp()
    456     : m_pFileWrite(NULL), m_iPosition(0) {}
    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 }
    469 int32_t CFX_FileWriteStreamImp::GetLength() const {
    470   if (!m_pFileWrite) {
    471     return 0;
    472   }
    473   return (int32_t)m_pFileWrite->GetSize();
    474 }
    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 }
    495 FX_BOOL CFX_FileWriteStreamImp::IsEOF() const {
    496   return m_iPosition >= GetLength();
    497 }
    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 }
    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 }
    512 void CFX_FileWriteStreamImp::Flush() {
    513   if (m_pFileWrite) {
    514     m_pFileWrite->Flush();
    515   }
    516 }
    517 CFX_BufferStreamImp::CFX_BufferStreamImp()
    518     : CFX_StreamImp(),
    519       m_pData(NULL),
    520       m_iTotalSize(0),
    521       m_iPosition(0),
    522       m_iLength(0) {}
    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 }
    535 int32_t CFX_BufferStreamImp::GetLength() const {
    536   FXSYS_assert(m_pData != NULL);
    537   return m_iLength;
    538 }
    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 }
    556 int32_t CFX_BufferStreamImp::GetPosition() {
    557   FXSYS_assert(m_pData != NULL);
    558   return m_iPosition;
    559 }
    560 FX_BOOL CFX_BufferStreamImp::IsEOF() const {
    561   FXSYS_assert(m_pData != NULL);
    562   return m_iPosition >= m_iLength;
    563 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    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 }
    695 void CFX_TextStream::Release() {
    696   if (--m_iRefCount < 1) {
    697     delete this;
    698   }
    699 }
    700 IFX_Stream* CFX_TextStream::Retain() {
    701   m_iRefCount++;
    702   return this;
    703 }
    704 FX_DWORD CFX_TextStream::GetAccessModes() const {
    705   return m_pStreamImp->GetAccessModes() | FX_STREAMACCESS_Text;
    706 }
    707 int32_t CFX_TextStream::GetLength() const {
    708   return m_pStreamImp->GetLength();
    709 }
    710 int32_t CFX_TextStream::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
    711   return m_pStreamImp->Seek(eSeek, iOffset);
    712 }
    713 int32_t CFX_TextStream::GetPosition() {
    714   return m_pStreamImp->GetPosition();
    715 }
    716 FX_BOOL CFX_TextStream::IsEOF() const {
    717   return m_pStreamImp->IsEOF();
    718 }
    719 int32_t CFX_TextStream::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
    720   return m_pStreamImp->ReadData(pBuffer, iBufferSize);
    721 }
    722 int32_t CFX_TextStream::WriteData(const uint8_t* pBuffer, int32_t iBufferSize) {
    723   return m_pStreamImp->WriteData(pBuffer, iBufferSize);
    724 }
    725 void CFX_TextStream::Flush() {
    726   m_pStreamImp->Flush();
    727 }
    728 FX_BOOL CFX_TextStream::SetLength(int32_t iLength) {
    729   return m_pStreamImp->SetLength(iLength);
    730 }
    731 FX_WORD CFX_TextStream::GetCodePage() const {
    732   return m_wCodePage;
    733 }
    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 }
    747 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 }
    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 }
    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 }
    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 }
    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) {}
    847 CFX_Stream::~CFX_Stream() {
    848   if (m_eStreamType != FX_STREAMTYPE_Stream && m_pStreamImp != NULL) {
    849     m_pStreamImp->Release();
    850   }
    851 }
    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 }
    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 }
    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 }
    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 }
    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 }
    960 void CFX_Stream::Release() {
    961   if (--m_iRefCount < 1) {
    962     delete this;
    963   }
    964 }
    965 IFX_Stream* CFX_Stream::Retain() {
    966   m_iRefCount++;
    967   return this;
    968 }
    969 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 }
    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 }
   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 }
   1014 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 }
   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 }
   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 }
   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 }
   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 }
   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 }
   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 }
   1145 int32_t CFX_Stream::GetBOM(uint8_t bom[4]) const {
   1146   if (m_pStreamImp == NULL) {
   1147     return -1;
   1148   }
   1149   return 0;
   1150 }
   1151 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 }
   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 }
   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 }
   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 }
   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 }
   1211 CFGAS_FileRead::~CFGAS_FileRead() {
   1212   if (m_bReleaseStream) {
   1213     m_pStream->Release();
   1214   }
   1215 }
   1216 FX_FILESIZE CFGAS_FileRead::GetSize() {
   1217   return (FX_FILESIZE)m_pStream->GetLength();
   1218 }
   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 
   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 }
   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 }
   1245 CFX_BufferAccImp::~CFX_BufferAccImp() {
   1246   if (m_bReleaseStream && m_pBufferRead) {
   1247     m_pBufferRead->Release();
   1248   }
   1249 }
   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 }
   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 
   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 
   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 }
   1333 CFGAS_FileWrite::~CFGAS_FileWrite() {
   1334   if (m_bReleaseStream) {
   1335     m_pStream->Release();
   1336   }
   1337 }
   1338 FX_FILESIZE CFGAS_FileWrite::GetSize() {
   1339   return m_pStream->GetLength();
   1340 }
   1341 FX_BOOL CFGAS_FileWrite::Flush() {
   1342   m_pStream->Flush();
   1343   return TRUE;
   1344 }
   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 }
   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