summaryrefslogtreecommitdiff
path: root/xfa/src/fgas/crt
diff options
context:
space:
mode:
authorDan Sinclair <dsinclair@chromium.org>2016-03-09 13:49:00 -0500
committerDan Sinclair <dsinclair@chromium.org>2016-03-09 13:49:00 -0500
commit9332e0c2fced598a632e3bbe905b6f63b1f5b06b (patch)
treea8957a09cb34ecd28afcd6ebbed309d9c60e4644 /xfa/src/fgas/crt
parent8388037a5c58d60043b11c03a8efe78c54c65a4b (diff)
downloadpdfium-9332e0c2fced598a632e3bbe905b6f63b1f5b06b.tar.xz
Cleanup the xfa/src/fgas directory.
This CL moves the code from xfa/src/fgas/src up one level. It then takes the headers in xfa/src/fgas/include and moves them to their correct folder. The src/ and include/ directories are then removed. In some cases, when moving from include/ there was another header with the same name. Those headers were either folded together, or the content of the conflicting folder moved to an anonymous namespace in the cpp file as they were not used anywhere else. Files with duplicate names as core/src/crt were renamed to be fgas_ instead of fx_. (e.g. fgas_system.h, fgas_memory.h, fgas_stream.h) R=tsepez@chromium.org Review URL: https://codereview.chromium.org/1776303002 .
Diffstat (limited to 'xfa/src/fgas/crt')
-rw-r--r--xfa/src/fgas/crt/fgas_algorithm.cpp306
-rw-r--r--xfa/src/fgas/crt/fgas_algorithm.h54
-rw-r--r--xfa/src/fgas/crt/fgas_codepage.cpp343
-rw-r--r--xfa/src/fgas/crt/fgas_codepage.h179
-rw-r--r--xfa/src/fgas/crt/fgas_encode.cpp193
-rw-r--r--xfa/src/fgas/crt/fgas_language.h269
-rw-r--r--xfa/src/fgas/crt/fgas_memory.cpp446
-rw-r--r--xfa/src/fgas/crt/fgas_memory.h59
-rw-r--r--xfa/src/fgas/crt/fgas_stream.cpp1626
-rw-r--r--xfa/src/fgas/crt/fgas_stream.h78
-rw-r--r--xfa/src/fgas/crt/fgas_system.cpp117
-rw-r--r--xfa/src/fgas/crt/fgas_system.h23
-rw-r--r--xfa/src/fgas/crt/fgas_utils.cpp434
-rw-r--r--xfa/src/fgas/crt/fgas_utils.h737
14 files changed, 4864 insertions, 0 deletions
diff --git a/xfa/src/fgas/crt/fgas_algorithm.cpp b/xfa/src/fgas/crt/fgas_algorithm.cpp
new file mode 100644
index 0000000000..60b43ac886
--- /dev/null
+++ b/xfa/src/fgas/crt/fgas_algorithm.cpp
@@ -0,0 +1,306 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/src/fgas/crt/fgas_algorithm.h"
+
+#include "core/include/fxcrt/fx_basic.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static const FX_CHAR g_FXBase64EncoderMap[64] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
+};
+
+struct FX_BASE64DATA {
+ FX_DWORD data1 : 2;
+ FX_DWORD data2 : 6;
+ FX_DWORD data3 : 4;
+ FX_DWORD data4 : 4;
+ FX_DWORD data5 : 6;
+ FX_DWORD data6 : 2;
+ FX_DWORD data7 : 8;
+};
+
+static void FX_Base64EncodePiece(const FX_BASE64DATA& src,
+ int32_t iBytes,
+ FX_CHAR dst[4]) {
+ dst[0] = g_FXBase64EncoderMap[src.data2];
+ FX_DWORD b = src.data1 << 4;
+ if (iBytes > 1) {
+ b |= src.data4;
+ }
+ dst[1] = g_FXBase64EncoderMap[b];
+ if (iBytes > 1) {
+ b = src.data3 << 2;
+ if (iBytes > 2) {
+ b |= src.data6;
+ }
+ dst[2] = g_FXBase64EncoderMap[b];
+ if (iBytes > 2) {
+ dst[3] = g_FXBase64EncoderMap[src.data5];
+ } else {
+ dst[3] = '=';
+ }
+ } else {
+ dst[2] = dst[3] = '=';
+ }
+}
+int32_t FX_Base64EncodeA(const uint8_t* pSrc, int32_t iSrcLen, FX_CHAR* pDst) {
+ FXSYS_assert(pSrc != NULL);
+ if (iSrcLen < 1) {
+ return 0;
+ }
+ if (pDst == NULL) {
+ int32_t iDstLen = iSrcLen / 3 * 4;
+ if ((iSrcLen % 3) != 0) {
+ iDstLen += 4;
+ }
+ return iDstLen;
+ }
+ FX_BASE64DATA srcData;
+ int32_t iBytes = 3;
+ FX_CHAR* pDstEnd = pDst;
+ while (iSrcLen > 0) {
+ if (iSrcLen > 2) {
+ ((uint8_t*)&srcData)[0] = *pSrc++;
+ ((uint8_t*)&srcData)[1] = *pSrc++;
+ ((uint8_t*)&srcData)[2] = *pSrc++;
+ iSrcLen -= 3;
+ } else {
+ *((FX_DWORD*)&srcData) = 0;
+ ((uint8_t*)&srcData)[0] = *pSrc++;
+ if (iSrcLen > 1) {
+ ((uint8_t*)&srcData)[1] = *pSrc++;
+ }
+ iBytes = iSrcLen;
+ iSrcLen = 0;
+ }
+ FX_Base64EncodePiece(srcData, iBytes, pDstEnd);
+ pDstEnd += 4;
+ }
+ return pDstEnd - pDst;
+}
+
+static const uint8_t g_FXBase64DecoderMap[256] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
+ 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
+ 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
+ 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+};
+static void FX_Base64DecodePiece(const FX_CHAR src[4],
+ int32_t iChars,
+ FX_BASE64DATA& dst,
+ int32_t& iBytes) {
+ FXSYS_assert(iChars > 0 && iChars < 5);
+ iBytes = 1;
+ dst.data2 = g_FXBase64DecoderMap[(uint8_t)src[0]];
+ if (iChars > 1) {
+ uint8_t b = g_FXBase64DecoderMap[(uint8_t)src[1]];
+ dst.data1 = b >> 4;
+ dst.data4 = b;
+ if (iChars > 2) {
+ iBytes = 2;
+ b = g_FXBase64DecoderMap[(uint8_t)src[2]];
+ dst.data3 = b >> 2;
+ dst.data6 = b;
+ if (iChars > 3) {
+ iBytes = 3;
+ dst.data5 = g_FXBase64DecoderMap[(uint8_t)src[3]];
+ } else {
+ dst.data5 = 0;
+ }
+ } else {
+ dst.data3 = 0;
+ }
+ } else {
+ dst.data1 = 0;
+ }
+}
+int32_t FX_Base64DecodeA(const FX_CHAR* pSrc, int32_t iSrcLen, uint8_t* pDst) {
+ FXSYS_assert(pSrc != NULL);
+ if (iSrcLen < 1) {
+ return 0;
+ }
+ while (iSrcLen > 0 && pSrc[iSrcLen - 1] == '=') {
+ iSrcLen--;
+ }
+ if (iSrcLen < 1) {
+ return 0;
+ }
+ if (pDst == NULL) {
+ int32_t iDstLen = iSrcLen / 4 * 3;
+ iSrcLen %= 4;
+ if (iSrcLen == 1) {
+ iDstLen += 1;
+ } else if (iSrcLen == 2) {
+ iDstLen += 1;
+ } else if (iSrcLen == 3) {
+ iDstLen += 2;
+ }
+ return iDstLen;
+ }
+ FX_CHAR srcData[4];
+ FX_BASE64DATA dstData;
+ int32_t iChars = 4, iBytes;
+ uint8_t* pDstEnd = pDst;
+ while (iSrcLen > 0) {
+ if (iSrcLen > 3) {
+ *((FX_DWORD*)srcData) = *((FX_DWORD*)pSrc);
+ pSrc += 4;
+ iSrcLen -= 4;
+ } else {
+ *((FX_DWORD*)&dstData) = 0;
+ *((FX_DWORD*)srcData) = 0;
+ srcData[0] = *pSrc++;
+ if (iSrcLen > 1) {
+ srcData[1] = *pSrc++;
+ }
+ if (iSrcLen > 2) {
+ srcData[2] = *pSrc++;
+ }
+ iChars = iSrcLen;
+ iSrcLen = 0;
+ }
+ FX_Base64DecodePiece(srcData, iChars, dstData, iBytes);
+ *pDstEnd++ = ((uint8_t*)&dstData)[0];
+ if (iBytes > 1) {
+ *pDstEnd++ = ((uint8_t*)&dstData)[1];
+ }
+ if (iBytes > 2) {
+ *pDstEnd++ = ((uint8_t*)&dstData)[2];
+ }
+ }
+ return pDstEnd - pDst;
+}
+int32_t FX_Base64DecodeW(const FX_WCHAR* pSrc, int32_t iSrcLen, uint8_t* pDst) {
+ FXSYS_assert(pSrc != NULL);
+ if (iSrcLen < 1) {
+ return 0;
+ }
+ while (iSrcLen > 0 && pSrc[iSrcLen - 1] == '=') {
+ iSrcLen--;
+ }
+ if (iSrcLen < 1) {
+ return 0;
+ }
+ if (pDst == NULL) {
+ int32_t iDstLen = iSrcLen / 4 * 3;
+ iSrcLen %= 4;
+ if (iSrcLen == 1) {
+ iDstLen += 1;
+ } else if (iSrcLen == 2) {
+ iDstLen += 1;
+ } else if (iSrcLen == 3) {
+ iDstLen += 2;
+ }
+ return iDstLen;
+ }
+ FX_CHAR srcData[4];
+ FX_BASE64DATA dstData;
+ int32_t iChars = 4, iBytes;
+ uint8_t* pDstEnd = pDst;
+ while (iSrcLen > 0) {
+ if (iSrcLen > 3) {
+ srcData[0] = (FX_CHAR)*pSrc++;
+ srcData[1] = (FX_CHAR)*pSrc++;
+ srcData[2] = (FX_CHAR)*pSrc++;
+ srcData[3] = (FX_CHAR)*pSrc++;
+ iSrcLen -= 4;
+ } else {
+ *((FX_DWORD*)&dstData) = 0;
+ *((FX_DWORD*)srcData) = 0;
+ srcData[0] = (FX_CHAR)*pSrc++;
+ if (iSrcLen > 1) {
+ srcData[1] = (FX_CHAR)*pSrc++;
+ }
+ if (iSrcLen > 2) {
+ srcData[2] = (FX_CHAR)*pSrc++;
+ }
+ iChars = iSrcLen;
+ iSrcLen = 0;
+ }
+ FX_Base64DecodePiece(srcData, iChars, dstData, iBytes);
+ *pDstEnd++ = ((uint8_t*)&dstData)[0];
+ if (iBytes > 1) {
+ *pDstEnd++ = ((uint8_t*)&dstData)[1];
+ }
+ if (iBytes > 2) {
+ *pDstEnd++ = ((uint8_t*)&dstData)[2];
+ }
+ }
+ return pDstEnd - pDst;
+}
+
+static const uint8_t g_FXHex2DecMap[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0,
+ 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12,
+ 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+uint8_t FX_Hex2Dec(uint8_t hexHigh, uint8_t hexLow) {
+ return (g_FXHex2DecMap[hexHigh] << 4) + g_FXHex2DecMap[hexLow];
+}
+int32_t FX_SeparateStringW(const FX_WCHAR* pStr,
+ int32_t iStrLen,
+ FX_WCHAR delimiter,
+ CFX_WideStringArray& pieces) {
+ if (pStr == NULL) {
+ return 0;
+ }
+ if (iStrLen < 0) {
+ iStrLen = FXSYS_wcslen(pStr);
+ }
+ const FX_WCHAR* pToken = pStr;
+ const FX_WCHAR* pEnd = pStr + iStrLen;
+ while (TRUE) {
+ if (pStr >= pEnd || delimiter == *pStr) {
+ CFX_WideString sub(pToken, pStr - pToken);
+ pieces.Add(sub);
+ pToken = pStr + 1;
+ if (pStr >= pEnd) {
+ break;
+ }
+ }
+ pStr++;
+ }
+ return pieces.GetSize();
+}
+#ifdef __cplusplus
+}
+#endif
diff --git a/xfa/src/fgas/crt/fgas_algorithm.h b/xfa/src/fgas/crt/fgas_algorithm.h
new file mode 100644
index 0000000000..f819716820
--- /dev/null
+++ b/xfa/src/fgas/crt/fgas_algorithm.h
@@ -0,0 +1,54 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_CRT_FGAS_ALGORITHM_H_
+#define XFA_SRC_FGAS_CRT_FGAS_ALGORITHM_H_
+
+#include <cstdint>
+
+#include "core/include/fxcrt/fx_basic.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int32_t FX_Base64EncodeA(const uint8_t* pSrc, int32_t iSrcLen, FX_CHAR* pDst);
+int32_t FX_Base64DecodeA(const FX_CHAR* pSrc, int32_t iSrcLen, uint8_t* pDst);
+int32_t FX_Base64DecodeW(const FX_WCHAR* pSrc, int32_t iSrcLen, uint8_t* pDst);
+uint8_t FX_Hex2Dec(uint8_t hexHigh, uint8_t hexLow);
+int32_t FX_SeparateStringW(const FX_WCHAR* pStr,
+ int32_t iStrLen,
+ FX_WCHAR delimiter,
+ CFX_WideStringArray& pieces);
+#ifdef __cplusplus
+};
+#endif
+
+template <class baseType>
+class CFX_DSPATemplate {
+ public:
+ int32_t Lookup(const baseType& find, const baseType* pArray, int32_t iCount) {
+ FXSYS_assert(pArray != NULL);
+ if (iCount < 1) {
+ return -1;
+ }
+ int32_t iStart = 0, iEnd = iCount - 1, iMid;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ const baseType& v = pArray[iMid];
+ if (find == v) {
+ return iMid;
+ } else if (find < v) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ } while (iStart <= iEnd);
+ return -1;
+ }
+};
+
+#endif // XFA_SRC_FGAS_CRT_FGAS_ALGORITHM_H_
diff --git a/xfa/src/fgas/crt/fgas_codepage.cpp b/xfa/src/fgas/crt/fgas_codepage.cpp
new file mode 100644
index 0000000000..622c4174bc
--- /dev/null
+++ b/xfa/src/fgas/crt/fgas_codepage.cpp
@@ -0,0 +1,343 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/include/fxcrt/fx_ext.h"
+#include "xfa/src/fgas/crt/fgas_codepage.h"
+#include "xfa/src/fgas/crt/fgas_language.h"
+
+static const FX_CHARSET_MAP g_FXCharset2CodePageTable[] = {
+ {0, 1252}, {1, 0}, {2, 42}, {77, 10000}, {78, 10001},
+ {79, 10003}, {80, 10008}, {81, 10002}, {83, 10005}, {84, 10004},
+ {85, 10006}, {86, 10081}, {87, 10021}, {88, 10029}, {89, 10007},
+ {128, 932}, {129, 949}, {130, 1361}, {134, 936}, {136, 950},
+ {161, 1253}, {162, 1254}, {163, 1258}, {177, 1255}, {178, 1256},
+ {186, 1257}, {204, 1251}, {222, 874}, {238, 1250}, {254, 437},
+ {255, 850},
+};
+FX_WORD FX_GetCodePageFromCharset(uint8_t charset) {
+ int32_t iEnd = sizeof(g_FXCharset2CodePageTable) / sizeof(FX_CHARSET_MAP) - 1;
+ FXSYS_assert(iEnd >= 0);
+ int32_t iStart = 0, iMid;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ const FX_CHARSET_MAP& cp = g_FXCharset2CodePageTable[iMid];
+ if (charset == cp.charset) {
+ return cp.codepage;
+ } else if (charset < cp.charset) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ } while (iStart <= iEnd);
+ return 0xFFFF;
+}
+static const FX_CHARSET_MAP g_FXCodepage2CharsetTable[] = {
+ {1, 0}, {2, 42}, {254, 437}, {255, 850}, {222, 874},
+ {128, 932}, {134, 936}, {129, 949}, {136, 950}, {238, 1250},
+ {204, 1251}, {0, 1252}, {161, 1253}, {162, 1254}, {177, 1255},
+ {178, 1256}, {186, 1257}, {163, 1258}, {130, 1361}, {77, 10000},
+ {78, 10001}, {79, 10003}, {80, 10008}, {81, 10002}, {83, 10005},
+ {84, 10004}, {85, 10006}, {86, 10081}, {87, 10021}, {88, 10029},
+ {89, 10007},
+};
+FX_WORD FX_GetCharsetFromCodePage(FX_WORD codepage) {
+ int32_t iEnd = sizeof(g_FXCodepage2CharsetTable) / sizeof(FX_CHARSET_MAP) - 1;
+ FXSYS_assert(iEnd >= 0);
+ int32_t iStart = 0, iMid;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ const FX_CHARSET_MAP& cp = g_FXCodepage2CharsetTable[iMid];
+ if (codepage == cp.codepage) {
+ return cp.charset;
+ } else if (codepage < cp.codepage) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ } while (iStart <= iEnd);
+ return 0xFFFF;
+}
+const FX_LANG2CPMAP g_FXLang2CodepageTable[] = {
+ {FX_LANG_Arabic_SaudiArabia, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_Bulgarian_Bulgaria, FX_CODEPAGE_MSWin_Cyrillic},
+ {FX_LANG_Catalan_Catalan, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Chinese_Taiwan, FX_CODEPAGE_ChineseTraditional},
+ {FX_LANG_CzechRepublic, FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Danish_Denmark, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_German_Germany, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Greek_Greece, FX_CODEPAGE_MSWin_Greek},
+ {FX_LANG_English_UnitedStates, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_TraditionalSort, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Finnish_Finland, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_French_France, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Hebrew_Israel, FX_CODEPAGE_MSWin_Hebrew},
+ {FX_LANG_Hungarian_Hungary, FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Icelandic_Iceland, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Italian_Italy, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Japanese_Japan, FX_CODEPAGE_ShiftJIS},
+ {FX_LANG_Korean_Korea, FX_CODEPAGE_Korean},
+ {FX_LANG_Dutch_Netherlands, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Norwegian_Bokmal, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Polish_Poland, FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Portuguese_Brazil, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Romanian_Romania, FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Russian_Russia, FX_CODEPAGE_MSWin_Cyrillic},
+ {FX_LANG_Croatian_Croatia, FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Slovak_Slovakia, FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Albanian_Albania, FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Swedish_Sweden, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Thai_Thailand, FX_CODEPAGE_MSDOS_Thai},
+ {FX_LANG_Turkish_Turkey, FX_CODEPAGE_MSWin_Turkish},
+ {FX_LANG_Urdu_Pakistan, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_Indonesian_Indonesia, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Ukrainian_Ukraine, FX_CODEPAGE_MSWin_Cyrillic},
+ {FX_LANG_Belarusian_Belarus, FX_CODEPAGE_MSWin_Cyrillic},
+ {FX_LANG_Slovenian_Slovenia, FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Estonian_Estonia, FX_CODEPAGE_MSWin_Baltic},
+ {FX_LANG_Latvian_Latvia, FX_CODEPAGE_MSWin_Baltic},
+ {FX_LANG_Lithuanian_Lithuania, FX_CODEPAGE_MSWin_Baltic},
+ {FX_LANG_Persian, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_Vietnamese_Vietnam, FX_CODEPAGE_MSWin_Vietnamese},
+ {FX_LANG_Armenian_Armenia, FX_CODEPAGE_DefANSI},
+ {FX_LANG_Azerbaijan_Latin, FX_CODEPAGE_MSWin_Turkish},
+ {FX_LANG_Basque_Basque, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Macedonian, FX_CODEPAGE_MSWin_Cyrillic},
+ {FX_LANG_Afrikaans_SouthAfrica, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Georgian_Georgia, FX_CODEPAGE_DefANSI},
+ {FX_LANG_Faroese_FaroeIslands, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Hindi_India, FX_CODEPAGE_DefANSI},
+ {FX_LANG_Malay_Malaysia, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Kazakh_Kazakhstan, FX_CODEPAGE_MSWin_Cyrillic},
+ {FX_LANG_Kyrgyz_Kyrgyzstan, FX_CODEPAGE_MSWin_Cyrillic},
+ {FX_LANG_Kiswahili_Kenya, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Uzbek_LatinUzbekistan, FX_CODEPAGE_MSWin_Turkish},
+ {FX_LANG_Tatar_Russia, FX_CODEPAGE_MSWin_Cyrillic},
+ {FX_LANG_Punjabi_India, FX_CODEPAGE_DefANSI},
+ {FX_LANG_Gujarati_India, FX_CODEPAGE_DefANSI},
+ {FX_LANG_Tamil_India, FX_CODEPAGE_DefANSI},
+ {FX_LANG_Telugu_India, FX_CODEPAGE_DefANSI},
+ {FX_LANG_Kannada_India, FX_CODEPAGE_DefANSI},
+ {FX_LANG_Marathi_India, FX_CODEPAGE_DefANSI},
+ {FX_LANG_SanskritIndia, FX_CODEPAGE_DefANSI},
+ {FX_LANG_Mongolian_CyrillicMongolia, FX_CODEPAGE_MSWin_Cyrillic},
+ {FX_LANG_Galician_Galician, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Konkani_India, FX_CODEPAGE_DefANSI},
+ {FX_LANG_Syriac_Syria, FX_CODEPAGE_DefANSI},
+ {FX_LANG_Divehi_Maldives, FX_CODEPAGE_DefANSI},
+ {FX_LANG_Arabic_Iraq, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_Chinese_PRC, FX_CODEPAGE_ChineseSimplified},
+ {FX_LANG_German_Switzerland, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_English_UnitedKingdom, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Mexico, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_French_Belgium, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Italian_Switzerland, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Dutch_Belgium, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Norwegian_Nynorsk, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Portuguese_Portugal, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_SerbianLatin_Serbia, FX_CODEPAGE_MSWin_EasternEuropean},
+ {FX_LANG_Swedish_Finland, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Azerbaijan_Cyrillic, FX_CODEPAGE_MSWin_Cyrillic},
+ {FX_LANG_Malay_BruneiDarussalam, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Uzbek_CyrillicUzbekistan, FX_CODEPAGE_MSWin_Cyrillic},
+ {FX_LANG_Arabic_Egypt, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_Chinese_HongKong, FX_CODEPAGE_ChineseTraditional},
+ {FX_LANG_German_Austria, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_English_Australia, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_InternationalSort, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_French_Canada, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_SerbianCyrillic_Serbia, FX_CODEPAGE_MSWin_Cyrillic},
+ {FX_LANG_Arabic_Libya, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_Chinese_Singapore, FX_CODEPAGE_ChineseSimplified},
+ {FX_LANG_German_Luxembourg, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_English_Canada, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Guatemala, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_French_Switzerland, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Algeria, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_Chinese_Macao, FX_CODEPAGE_ChineseTraditional},
+ {FX_LANG_German_Liechtenstein, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_English_NewZealand, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_CostaRica, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_French_Luxembourg, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Morocco, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_English_Ireland, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Panama, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_French_Monaco, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Tunisia, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_English_SouthAfrica, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_DominicanRepublic, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Oman, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_English_Jamaica, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Venezuela, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Yemen, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_English_Caribbean, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Colombia, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Syria, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_English_Belize, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Peru, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Jordan, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_English_TrinidadTobago, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Argentina, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Lebanon, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_English_Zimbabwe, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Ecuador, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Kuwait, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_English_Philippines, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Chile, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_UAE, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_Spanish_Uruguay, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Bahrain, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_Spanish_Paraguay, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Arabic_Qatar, FX_CODEPAGE_MSWin_Arabic},
+ {FX_LANG_Spanish_Bolivia, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_ElSalvador, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Honduras, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_Nicaragua, FX_CODEPAGE_MSWin_WesternEuropean},
+ {FX_LANG_Spanish_PuertoRico, FX_CODEPAGE_MSWin_WesternEuropean},
+};
+FX_WORD FX_GetDefCodePageByLanguage(FX_WORD wLanguage) {
+ int32_t iEnd = sizeof(g_FXLang2CodepageTable) / sizeof(FX_LANG2CPMAP) - 1;
+ FXSYS_assert(iEnd >= 0);
+ int32_t iStart = 0, iMid;
+ do {
+ iMid = (iStart + iEnd) / 2;
+ const FX_LANG2CPMAP& cp = g_FXLang2CodepageTable[iMid];
+ if (wLanguage == cp.wLanguage) {
+ return cp.wCodepage;
+ } else if (wLanguage < cp.wLanguage) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ } while (iStart <= iEnd);
+ return 0xFFFF;
+}
+static const FX_STR2CPHASH g_FXCPHashTable[] = {
+ {0xd45, 0x6faf}, {0xd46, 0x6fb0}, {0xd47, 0x6fb1},
+ {0xd48, 0x6fb2}, {0xd49, 0x4e6}, {0xd4d, 0x6fbd},
+ {0xe9e, 0x4e4}, {0xc998, 0x1b5}, {0x18ef0, 0x3a8},
+ {0x19f85, 0x5182}, {0x2e2335, 0x3b6}, {0x325153, 0x5182},
+ {0x145bded, 0x2716}, {0x3c9a5f2, 0xc6f3}, {0x4c45f2d, 0x3a4},
+ {0x4c45f4e, 0xc431}, {0x58caf51, 0x4e4}, {0x5a5cd7d, 0x3a8},
+ {0x5a6c6a7, 0x4e4}, {0x5a6ca0b, 0x1b5}, {0x5a6cd68, 0x307},
+ {0x5a6d8d3, 0x4e4}, {0x5a6d948, 0x354}, {0x5a6d96b, 0x362},
+ {0x5a6d984, 0x366}, {0x5a90e35, 0x1b5}, {0x5e0cf00, 0x6fb5},
+ {0x609c324, 0x551}, {0x617d97f, 0x5182}, {0x6a6fd91, 0xfde8},
+ {0x6a6fd92, 0xfde9}, {0x6b102de, 0xcadc}, {0x6b10f48, 0x4e89},
+ {0x1020805f, 0x4e4}, {0x10f0524c, 0x6fb5}, {0x11d558fe, 0x6fb0},
+ {0x13898d19, 0xc42d}, {0x13898d3a, 0xc431}, {0x138a319e, 0x6fb1},
+ {0x14679c09, 0x96c6}, {0x153f0a3d, 0x6fb2}, {0x1576eeb3, 0x4e20},
+ {0x169a0ce6, 0xc6f9}, {0x16f3e2dc, 0x6fb3}, {0x18a8bb7a, 0x6fb4},
+ {0x1a5d9419, 0x6fb5}, {0x1a847b48, 0x3a8}, {0x1b762419, 0xcec8},
+ {0x1b9d7847, 0x475}, {0x1c126cb9, 0x6fb6}, {0x1ccdbc7d, 0x4f42},
+ {0x1d330f5f, 0x2714}, {0x1dc74559, 0x4e6}, {0x1edd80da, 0x4e4},
+ {0x23e4b03d, 0xfde8}, {0x24f28a16, 0x4f3d}, {0x286e7a32, 0x2715},
+ {0x2c7c18ed, 0x3a8}, {0x2e2103b7, 0x2713}, {0x304bf479, 0x6fb4},
+ {0x304bf47d, 0x6fb5}, {0x309bb869, 0xfde8}, {0x309bb86a, 0xfde9},
+ {0x33664357, 0x3b6}, {0x352d6b49, 0x3a4}, {0x36f5661c, 0x1b5},
+ {0x392e8f48, 0xcadc}, {0x3dc7c64c, 0x47c}, {0x3ed2e8e1, 0x4e4},
+ {0x3f0c2fea, 0xcaed}, {0x3f0fef8f, 0xc6f2}, {0x3f5e130f, 0x5182},
+ {0x47174d1f, 0x3a8}, {0x49686b7b, 0x6fb4}, {0x4b80b0d9, 0x3a4},
+ {0x4dcda97a, 0x4e4}, {0x4dcda9b6, 0x4e4}, {0x4e881e6a, 0x5221},
+ {0x4ffdf5a1, 0x36a}, {0x4ffdf5a5, 0x6fbd}, {0x5241ce16, 0x4e8b},
+ {0x546bab9d, 0x4e4}, {0x54a3d64e, 0x6fb6}, {0x562179bd, 0x5161},
+ {0x57c1df15, 0xc6f7}, {0x61ff6e62, 0x4f36}, {0x6359c7d8, 0x4f35},
+ {0x63f3c335, 0x3a8}, {0x645a0f78, 0x477}, {0x691ac2fd, 0x275f},
+ {0x6dc2eab0, 0x2d0}, {0x6dc2eeef, 0x35e}, {0x6dc2ef10, 0x36a},
+ {0x7103138a, 0x47d}, {0x710dfbd0, 0xc6f5}, {0x7319f6cb, 0x36a},
+ {0x745096ad, 0x3a8}, {0x74866229, 0x4e8c}, {0x77185fa5, 0x3a8},
+ {0x7953f002, 0x6faf}, {0x7953f003, 0x6fb0}, {0x7953f004, 0x6fb1},
+ {0x7953f005, 0x6fb2}, {0x7953f006, 0x6fb7}, {0x7953f00a, 0x6fbd},
+ {0x7c577571, 0x2761}, {0x7e8c8ff1, 0x479}, {0x8031f47f, 0x3b5},
+ {0x8031f481, 0x3b5}, {0x80c4a710, 0x5187}, {0x857c7e14, 0xfde8},
+ {0x857c7e15, 0xfde9}, {0x86b59c90, 0x4e4}, {0x86b59c91, 0x6fb0},
+ {0x86b59c92, 0x6fb1}, {0x86b59c93, 0x6fb2}, {0x86b59c94, 0x6fb3},
+ {0x86b59c95, 0x6fb4}, {0x86b59c96, 0x6fb5}, {0x86b59c97, 0x4e7},
+ {0x86b59c98, 0x4e6}, {0x8b4b24ec, 0x5190}, {0x8face362, 0x4e4},
+ {0x8ff9ec2a, 0xfde9}, {0x919d3989, 0xcadc}, {0x9967e5ad, 0x4e22},
+ {0x99f8b933, 0x6fbd}, {0x9bd2a380, 0x4fc7}, {0x9befad23, 0x4f38},
+ {0x9c7ac649, 0x4f3c}, {0xa02468db, 0xdeae}, {0xa02468ec, 0xdeab},
+ {0xa024692a, 0xdeaa}, {0xa0246997, 0xdeb2}, {0xa02469ff, 0xdeb0},
+ {0xa0246a3d, 0xdeb1}, {0xa0246a8c, 0xdeaf}, {0xa0246a9a, 0xdeb3},
+ {0xa0246b16, 0xdeac}, {0xa0246b1a, 0xdead}, {0xa071addc, 0x4b1},
+ {0xa38b62dc, 0x474}, {0xa4c09fed, 0x3a8}, {0xa51e86e5, 0x4e7},
+ {0xa67ab13e, 0x3a4}, {0xa7414244, 0x51a9}, {0xa9ddbead, 0xc6fb},
+ {0xab24ffab, 0x4e8a}, {0xabef8ac4, 0x2710}, {0xabfa20ac, 0x6fb4},
+ {0xad36895e, 0x4e2}, {0xad36895f, 0x4e3}, {0xaf310e90, 0x402},
+ {0xaf31166f, 0x4e8}, {0xaf7277a5, 0x3b6}, {0xafc0d8b3, 0x96c6},
+ {0xb0fd5dba, 0xcae0}, {0xb0fd5e95, 0xcadc}, {0xb1052893, 0x7149},
+ {0xb1e98745, 0x36a}, {0xb277e91c, 0x5166}, {0xb2f7eac5, 0xcae0},
+ {0xb2f7eba0, 0xcadc}, {0xb2f7ebc1, 0x3b5}, {0xb53fa77d, 0x3a8},
+ {0xb6391138, 0x6fb5}, {0xb7358b7f, 0x6fb6}, {0xb8c42b40, 0x4e4},
+ {0xb8c42ea4, 0x1b5}, {0xb8c439e7, 0x2e1}, {0xb8c43a61, 0x307},
+ {0xb8c43d6c, 0x4e4}, {0xb8c43ddf, 0x352}, {0xb8c43de1, 0x354},
+ {0xb8c43de6, 0x359}, {0xb8c43dff, 0x35d}, {0xb8c43e04, 0x362},
+ {0xb8c43e07, 0x365}, {0xbcd29a7f, 0x3a8}, {0xbce34e78, 0x5182},
+ {0xbce34e7b, 0x556a}, {0xbce81504, 0x3b5}, {0xbd8a4c95, 0x272d},
+ {0xbdd89dad, 0x4e4}, {0xbdd89dae, 0x6fb0}, {0xbdd89daf, 0x6fb1},
+ {0xbdd89db0, 0x6fb2}, {0xbdd89db1, 0x4e6}, {0xbdd89db5, 0x6fbd},
+ {0xc1756e9f, 0x36b}, {0xc7482444, 0x47a}, {0xc9281c18, 0x4e4},
+ {0xc9ef95df, 0x47b}, {0xccc9db0d, 0x4e4}, {0xccc9db0e, 0x6fb0},
+ {0xcd73425f, 0x3b6}, {0xce38b40b, 0x4b0}, {0xce99e549, 0x25},
+ {0xcf598740, 0x4e7}, {0xcf6d6f78, 0x4e4}, {0xcf758df6, 0x3a4},
+ {0xd1266e51, 0x6fb5}, {0xd2910213, 0x2718}, {0xd29196bb, 0x2712},
+ {0xd3eb2fc2, 0x476}, {0xd442dc2c, 0x4fc4}, {0xd9da4da4, 0x2711},
+ {0xdbad2f42, 0x4e4}, {0xdbad2f43, 0x6fb0}, {0xdbad2f44, 0x6fb1},
+ {0xdbad2f45, 0x6fb2}, {0xdbad2f46, 0x6fb3}, {0xdbad2f47, 0x6fb4},
+ {0xdbad2f48, 0x6fb5}, {0xdbad2f49, 0x6fb6}, {0xdbad2f4a, 0x4e6},
+ {0xdc438033, 0x4f31}, {0xdccb439b, 0x477}, {0xdccdc626, 0x3b5},
+ {0xdd80a595, 0x4e4}, {0xdd80a596, 0x6fb0}, {0xdd80a59e, 0x6fb1},
+ {0xdd80a5b4, 0x6fb2}, {0xdd80a5d9, 0x6fb5}, {0xdd80a5da, 0x6fb4},
+ {0xdd80a5fa, 0x6fb6}, {0xdd80a615, 0x6fb3}, {0xdd80a619, 0x4e6},
+ {0xdd80a61a, 0x3b5}, {0xdd80c0f8, 0x4e9f}, {0xdf7e46ff, 0x4fc8},
+ {0xdf8680fd, 0x556a}, {0xdfb0bd6e, 0xc42d}, {0xdff05486, 0x2c4},
+ {0xe3323399, 0x3a4}, {0xe60412dd, 0x3b5}, {0xeee47add, 0x4b0},
+ {0xf021a186, 0x4e2}, {0xf021a187, 0x4e3}, {0xf021a188, 0x4e4},
+ {0xf021a189, 0x4e5}, {0xf021a18a, 0x4e6}, {0xf021a18b, 0x4e7},
+ {0xf021a18c, 0x4e8}, {0xf021a18d, 0x4e9}, {0xf021a18e, 0x4ea},
+ {0xf0700456, 0x6fb3}, {0xf274f175, 0x3b5}, {0xf2a9730b, 0x3a8},
+ {0xf3d463c2, 0x3a4}, {0xf52a70a3, 0xc42e}, {0xf5693147, 0x6fb3},
+ {0xf637e157, 0x478}, {0xfc213f3a, 0x2717}, {0xff654d14, 0x3b5},
+};
+FX_WORD FX_GetCodePageFromStringA(const FX_CHAR* pStr, int32_t iLength) {
+ FXSYS_assert(pStr != NULL);
+ if (iLength < 0) {
+ iLength = FXSYS_strlen(pStr);
+ }
+ if (iLength == 0) {
+ return 0xFFFF;
+ }
+ uint32_t uHash = FX_HashCode_String_GetA(pStr, iLength, TRUE);
+ int32_t iStart = 0, iMid;
+ int32_t iEnd = sizeof(g_FXCPHashTable) / sizeof(FX_STR2CPHASH) - 1;
+ FXSYS_assert(iEnd >= 0);
+ do {
+ iMid = (iStart + iEnd) / 2;
+ const FX_STR2CPHASH& cp = g_FXCPHashTable[iMid];
+ if (uHash == cp.uHash) {
+ return (FX_WORD)cp.uCodePage;
+ } else if (uHash < cp.uHash) {
+ iEnd = iMid - 1;
+ } else {
+ iStart = iMid + 1;
+ }
+ } while (iStart <= iEnd);
+ return 0xFFFF;
+}
+FX_WORD FX_GetCodePageFormStringW(const FX_WCHAR* pStr, int32_t iLength) {
+ if (iLength < 0) {
+ iLength = FXSYS_wcslen(pStr);
+ }
+ if (iLength == 0) {
+ return 0xFFFF;
+ }
+ CFX_ByteString csStr;
+ FX_CHAR* pBuf = csStr.GetBuffer(iLength + 1);
+ for (int32_t i = 0; i < iLength; ++i) {
+ *pBuf++ = (FX_CHAR)*pStr++;
+ }
+ csStr.ReleaseBuffer(iLength);
+ return FX_GetCodePageFromStringA(csStr, iLength);
+}
diff --git a/xfa/src/fgas/crt/fgas_codepage.h b/xfa/src/fgas/crt/fgas_codepage.h
new file mode 100644
index 0000000000..e9111d1ec4
--- /dev/null
+++ b/xfa/src/fgas/crt/fgas_codepage.h
@@ -0,0 +1,179 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_CRT_FGAS_CODEPAGE_H_
+#define XFA_SRC_FGAS_CRT_FGAS_CODEPAGE_H_
+
+#include "core/include/fxcrt/fx_basic.h"
+
+#define FX_CODEPAGE_DefANSI 0
+#define FX_CODEPAGE_DefOEM 1
+#define FX_CODEPAGE_DefMAC 2
+#define FX_CODEPAGE_Thread 3
+#define FX_CODEPAGE_Symbol 42
+#define FX_CODEPAGE_MSDOS_US 437
+#define FX_CODEPAGE_Arabic_ASMO708 708
+#define FX_CODEPAGE_Arabic_ASMO449Plus 709
+#define FX_CODEPAGE_Arabic_Transparent 710
+#define FX_CODEPAGE_Arabic_NafithaEnhanced 711
+#define FX_CODEPAGE_Arabic_TransparentASMO 720
+#define FX_CODEPAGE_MSDOS_Greek1 737
+#define FX_CODEPAGE_MSDOS_Baltic 775
+#define FX_CODEPAGE_MSWin31_WesternEuropean 819
+#define FX_CODEPAGE_MSDOS_WesternEuropean 850
+#define FX_CODEPAGE_MSDOS_EasternEuropean 852
+#define FX_CODEPAGE_MSDOS_Latin3 853
+#define FX_CODEPAGE_MSDOS_Cyrillic 855
+#define FX_CODEPAGE_MSDOS_Turkish 857
+#define FX_CODEPAGE_MSDOS_Latin1Euro 858
+#define FX_CODEPAGE_MSDOS_Portuguese 860
+#define FX_CODEPAGE_MSDOS_Icelandic 861
+#define FX_CODEPAGE_MSDOS_Hebrew 862
+#define FX_CODEPAGE_MSDOS_FrenchCanadian 863
+#define FX_CODEPAGE_MSDOS_Arabic 864
+#define FX_CODEPAGE_MSDOS_Norwegian 865
+#define FX_CODEPAGE_MSDOS_Russian 866
+#define FX_CODEPAGE_MSDOS_Greek2 869
+#define FX_CODEPAGE_MSDOS_Thai 874
+#define FX_CODEPAGE_MSDOS_KamenickyCS 895
+#define FX_CODEPAGE_ShiftJIS 932
+#define FX_CODEPAGE_ChineseSimplified 936
+#define FX_CODEPAGE_Korean 949
+#define FX_CODEPAGE_ChineseTraditional 950
+#define FX_CODEPAGE_UTF16LE 1200
+#define FX_CODEPAGE_UTF16BE 1201
+#define FX_CODEPAGE_MSWin_EasternEuropean 1250
+#define FX_CODEPAGE_MSWin_Cyrillic 1251
+#define FX_CODEPAGE_MSWin_WesternEuropean 1252
+#define FX_CODEPAGE_MSWin_Greek 1253
+#define FX_CODEPAGE_MSWin_Turkish 1254
+#define FX_CODEPAGE_MSWin_Hebrew 1255
+#define FX_CODEPAGE_MSWin_Arabic 1256
+#define FX_CODEPAGE_MSWin_Baltic 1257
+#define FX_CODEPAGE_MSWin_Vietnamese 1258
+#define FX_CODEPAGE_Johab 1361
+#define FX_CODEPAGE_MAC_Roman 10000
+#define FX_CODEPAGE_MAC_ShiftJIS 10001
+#define FX_CODEPAGE_MAC_ChineseTraditional 10002
+#define FX_CODEPAGE_MAC_Korean 10003
+#define FX_CODEPAGE_MAC_Arabic 10004
+#define FX_CODEPAGE_MAC_Hebrew 10005
+#define FX_CODEPAGE_MAC_Greek 10006
+#define FX_CODEPAGE_MAC_Cyrillic 10007
+#define FX_CODEPAGE_MAC_ChineseSimplified 10008
+#define FX_CODEPAGE_MAC_Thai 10021
+#define FX_CODEPAGE_MAC_EasternEuropean 10029
+#define FX_CODEPAGE_MAC_Turkish 10081
+#define FX_CODEPAGE_UTF32LE 12000
+#define FX_CODEPAGE_UTF32BE 12001
+#define FX_CODEPAGE_ISO8859_1 28591
+#define FX_CODEPAGE_ISO8859_2 28592
+#define FX_CODEPAGE_ISO8859_3 28593
+#define FX_CODEPAGE_ISO8859_4 28594
+#define FX_CODEPAGE_ISO8859_5 28595
+#define FX_CODEPAGE_ISO8859_6 28596
+#define FX_CODEPAGE_ISO8859_7 28597
+#define FX_CODEPAGE_ISO8859_8 28598
+#define FX_CODEPAGE_ISO8859_9 28599
+#define FX_CODEPAGE_ISO8859_10 28600
+#define FX_CODEPAGE_ISO8859_11 28601
+#define FX_CODEPAGE_ISO8859_12 28602
+#define FX_CODEPAGE_ISO8859_13 28603
+#define FX_CODEPAGE_ISO8859_14 28604
+#define FX_CODEPAGE_ISO8859_15 28605
+#define FX_CODEPAGE_ISO8859_16 28606
+#define FX_CODEPAGE_ISCII_Devanagari 57002
+#define FX_CODEPAGE_ISCII_Bengali 57003
+#define FX_CODEPAGE_ISCII_Tamil 57004
+#define FX_CODEPAGE_ISCII_Telugu 57005
+#define FX_CODEPAGE_ISCII_Assamese 57006
+#define FX_CODEPAGE_ISCII_Oriya 57007
+#define FX_CODEPAGE_ISCII_Kannada 57008
+#define FX_CODEPAGE_ISCII_Malayalam 57009
+#define FX_CODEPAGE_ISCII_Gujarati 57010
+#define FX_CODEPAGE_ISCII_Punjabi 57011
+#define FX_CODEPAGE_UTF7 65000
+#define FX_CODEPAGE_UTF8 65001
+#define FX_CHARSET_ANSI 0
+#define FX_CHARSET_Default 1
+#define FX_CHARSET_Symbol 2
+#define FX_CHARSET_MAC_Roman 77
+#define FX_CHARSET_MAC_ShiftJIS 78
+#define FX_CHARSET_MAC_Korean 79
+#define FX_CHARSET_MAC_ChineseSimplified 80
+#define FX_CHARSET_MAC_ChineseTriditional 81
+#define FX_CHARSET_MAC_Johab 82
+#define FX_CHARSET_MAC_Hebrew 83
+#define FX_CHARSET_MAC_Arabic 84
+#define FX_CHARSET_MAC_Greek 85
+#define FX_CHARSET_MAC_Turkish 86
+#define FX_CHARSET_MAC_Thai 87
+#define FX_CHARSET_MAC_EasternEuropean 88
+#define FX_CHARSET_MAC_Cyrillic 89
+#define FX_CHARSET_ShiftJIS 128
+#define FX_CHARSET_Korean 129
+#define FX_CHARSET_Johab 130
+#define FX_CHARSET_ChineseSimplified 134
+#define FX_CHARSET_ChineseTriditional 136
+#define FX_CHARSET_MSWin_Greek 161
+#define FX_CHARSET_MSWin_Turkish 162
+#define FX_CHARSET_MSWin_Vietnamese 163
+#define FX_CHARSET_MSWin_Hebrew 177
+#define FX_CHARSET_MSWin_Arabic 178
+#define FX_CHARSET_ArabicTraditional 179
+#define FX_CHARSET_ArabicUser 180
+#define FX_CHARSET_HebrewUser 181
+#define FX_CHARSET_MSWin_Baltic 186
+#define FX_CHARSET_MSWin_Cyrillic 204
+#define FX_CHARSET_Thai 222
+#define FX_CHARSET_MSWin_EasterEuropean 238
+#define FX_CHARSET_US 254
+#define FX_CHARSET_OEM 255
+
+FX_WORD FX_GetCodePageFromCharset(uint8_t charset);
+FX_WORD FX_GetCharsetFromCodePage(FX_WORD codepage);
+FX_WORD FX_GetCodePageFromStringA(const FX_CHAR* pStr, int32_t iLength);
+FX_WORD FX_GetCodePageFormStringW(const FX_WCHAR* pStr, int32_t iLength);
+FX_WORD FX_GetDefCodePageByLanguage(FX_WORD wLanguage);
+void FX_SwapByteOrder(FX_WCHAR* pStr, int32_t iLength);
+void FX_SwapByteOrderCopy(const FX_WCHAR* pSrc,
+ FX_WCHAR* pDst,
+ int32_t iLength);
+void FX_UTF16ToWChar(void* pBuffer, int32_t iLength);
+void FX_UTF16ToWCharCopy(const FX_WORD* pUTF16,
+ FX_WCHAR* pWChar,
+ int32_t iLength);
+void FX_WCharToUTF16(void* pBuffer, int32_t iLength);
+void FX_WCharToUTF16Copy(const FX_WCHAR* pWChar,
+ FX_WORD* pUTF16,
+ int32_t iLength);
+int32_t FX_DecodeString(FX_WORD wCodePage,
+ const FX_CHAR* pSrc,
+ int32_t* pSrcLen,
+ FX_WCHAR* pDst,
+ int32_t* pDstLen,
+ FX_BOOL bErrBreak = FALSE);
+int32_t FX_UTF8Decode(const FX_CHAR* pSrc,
+ int32_t* pSrcLen,
+ FX_WCHAR* pDst,
+ int32_t* pDstLen);
+
+struct FX_STR2CPHASH {
+ uint32_t uHash;
+ uint32_t uCodePage;
+};
+
+struct FX_CHARSET_MAP {
+ uint16_t charset;
+ uint16_t codepage;
+};
+
+struct FX_LANG2CPMAP {
+ FX_WORD wLanguage;
+ FX_WORD wCodepage;
+};
+
+#endif // XFA_SRC_FGAS_CRT_FGAS_CODEPAGE_H_
diff --git a/xfa/src/fgas/crt/fgas_encode.cpp b/xfa/src/fgas/crt/fgas_encode.cpp
new file mode 100644
index 0000000000..564ccf63c4
--- /dev/null
+++ b/xfa/src/fgas/crt/fgas_encode.cpp
@@ -0,0 +1,193 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/src/fgas/crt/fgas_codepage.h"
+
+void FX_SwapByteOrder(FX_WCHAR* pStr, int32_t iLength) {
+ FXSYS_assert(pStr != NULL);
+ if (iLength < 0) {
+ iLength = FXSYS_wcslen(pStr);
+ }
+ FX_WORD wch;
+ if (sizeof(FX_WCHAR) > 2) {
+ while (iLength-- > 0) {
+ wch = (FX_WORD)*pStr;
+ wch = (wch >> 8) | (wch << 8);
+ wch &= 0x00FF;
+ *pStr++ = wch;
+ }
+ } else {
+ while (iLength-- > 0) {
+ wch = (FX_WORD)*pStr;
+ wch = (wch >> 8) | (wch << 8);
+ *pStr++ = wch;
+ }
+ }
+}
+void FX_SwapByteOrderCopy(const FX_WCHAR* pSrc,
+ FX_WCHAR* pDst,
+ int32_t iLength) {
+ FXSYS_assert(pSrc != NULL && pDst != NULL);
+ if (iLength < 0) {
+ iLength = FXSYS_wcslen(pSrc);
+ }
+ FX_WORD wch;
+ if (sizeof(FX_WCHAR) > 2) {
+ while (iLength-- > 0) {
+ wch = (FX_WORD)*pSrc++;
+ wch = (wch >> 8) | (wch << 8);
+ wch &= 0x00FF;
+ *pDst++ = wch;
+ }
+ } else {
+ while (iLength-- > 0) {
+ wch = (FX_WORD)*pSrc++;
+ wch = (wch >> 8) | (wch << 8);
+ *pDst++ = wch;
+ }
+ }
+}
+void FX_UTF16ToWChar(void* pBuffer, int32_t iLength) {
+ FXSYS_assert(pBuffer != NULL && iLength > 0);
+ if (sizeof(FX_WCHAR) == 2) {
+ return;
+ }
+ FX_WORD* pSrc = (FX_WORD*)pBuffer;
+ FX_WCHAR* pDst = (FX_WCHAR*)pBuffer;
+ while (--iLength >= 0) {
+ pDst[iLength] = (FX_WCHAR)pSrc[iLength];
+ }
+}
+void FX_UTF16ToWCharCopy(const FX_WORD* pUTF16,
+ FX_WCHAR* pWChar,
+ int32_t iLength) {
+ FXSYS_assert(pUTF16 != NULL && pWChar != NULL && iLength > 0);
+ if (sizeof(FX_WCHAR) == 2) {
+ FXSYS_memcpy(pWChar, pUTF16, iLength * sizeof(FX_WCHAR));
+ } else {
+ while (--iLength >= 0) {
+ pWChar[iLength] = (FX_WCHAR)pUTF16[iLength];
+ }
+ }
+}
+void FX_WCharToUTF16(void* pBuffer, int32_t iLength) {
+ FXSYS_assert(pBuffer != NULL && iLength > 0);
+ if (sizeof(FX_WCHAR) == 2) {
+ return;
+ }
+ const FX_WCHAR* pSrc = (const FX_WCHAR*)pBuffer;
+ FX_WORD* pDst = (FX_WORD*)pBuffer;
+ while (--iLength >= 0) {
+ *pDst++ = (FX_WORD)*pSrc++;
+ }
+}
+void FX_WCharToUTF16Copy(const FX_WCHAR* pWChar,
+ FX_WORD* pUTF16,
+ int32_t iLength) {
+ FXSYS_assert(pWChar != NULL && pUTF16 != NULL && iLength > 0);
+ if (sizeof(FX_WCHAR) == 2) {
+ FXSYS_memcpy(pUTF16, pWChar, iLength * sizeof(FX_WCHAR));
+ } else {
+ while (--iLength >= 0) {
+ *pUTF16++ = (FX_WORD)*pWChar++;
+ }
+ }
+}
+inline FX_DWORD FX_DWordFromBytes(const uint8_t* pStr) {
+ return FXBSTR_ID(pStr[3], pStr[2], pStr[1], pStr[0]);
+}
+inline FX_WORD FX_WordFromBytes(const uint8_t* pStr) {
+ return (pStr[1] << 8 | pStr[0]);
+}
+int32_t FX_DecodeString(FX_WORD wCodePage,
+ const FX_CHAR* pSrc,
+ int32_t* pSrcLen,
+ FX_WCHAR* pDst,
+ int32_t* pDstLen,
+ FX_BOOL bErrBreak) {
+ if (wCodePage == FX_CODEPAGE_UTF8) {
+ return FX_UTF8Decode(pSrc, pSrcLen, pDst, pDstLen);
+ }
+ return -1;
+}
+int32_t FX_UTF8Decode(const FX_CHAR* pSrc,
+ int32_t* pSrcLen,
+ FX_WCHAR* pDst,
+ int32_t* pDstLen) {
+ if (pSrcLen == NULL || pDstLen == NULL) {
+ return -1;
+ }
+ int32_t iSrcLen = *pSrcLen;
+ if (iSrcLen < 1) {
+ *pSrcLen = *pDstLen = 0;
+ return 1;
+ }
+ int32_t iDstLen = *pDstLen;
+ FX_BOOL bValidDst = (pDst != NULL && iDstLen > 0);
+ FX_DWORD dwCode = 0;
+ int32_t iPending = 0;
+ int32_t iSrcNum = 0, iDstNum = 0;
+ int32_t k = 0;
+ int32_t iIndex = 0;
+ k = 1;
+ while (iIndex < iSrcLen) {
+ uint8_t byte = (uint8_t) * (pSrc + iIndex);
+ if (byte < 0x80) {
+ iPending = 0;
+ k = 1;
+ iDstNum++;
+ iSrcNum += k;
+ if (bValidDst) {
+ *pDst++ = byte;
+ if (iDstNum >= iDstLen) {
+ break;
+ }
+ }
+ } else if (byte < 0xc0) {
+ if (iPending < 1) {
+ break;
+ }
+ iPending--;
+ dwCode |= (byte & 0x3f) << (iPending * 6);
+ if (iPending == 0) {
+ iDstNum++;
+ iSrcNum += k;
+ if (bValidDst) {
+ *pDst++ = dwCode;
+ if (iDstNum >= iDstLen) {
+ break;
+ }
+ }
+ }
+ } else if (byte < 0xe0) {
+ iPending = 1;
+ k = 2;
+ dwCode = (byte & 0x1f) << 6;
+ } else if (byte < 0xf0) {
+ iPending = 2;
+ k = 3;
+ dwCode = (byte & 0x0f) << 12;
+ } else if (byte < 0xf8) {
+ iPending = 3;
+ k = 4;
+ dwCode = (byte & 0x07) << 18;
+ } else if (byte < 0xfc) {
+ iPending = 4;
+ k = 5;
+ dwCode = (byte & 0x03) << 24;
+ } else if (byte < 0xfe) {
+ iPending = 5;
+ k = 6;
+ dwCode = (byte & 0x01) << 30;
+ } else {
+ break;
+ }
+ iIndex++;
+ }
+ *pSrcLen = iSrcNum;
+ *pDstLen = iDstNum;
+ return 1;
+}
diff --git a/xfa/src/fgas/crt/fgas_language.h b/xfa/src/fgas/crt/fgas_language.h
new file mode 100644
index 0000000000..15f32e1379
--- /dev/null
+++ b/xfa/src/fgas/crt/fgas_language.h
@@ -0,0 +1,269 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_CRT_FGAS_LANGUAGE_H_
+#define XFA_SRC_FGAS_CRT_FGAS_LANGUAGE_H_
+
+#define FX_LANG_Neutral 0x0000
+#define FX_LANG_Invariant 0x007f
+#define FX_LANG_UserDefault 0x0400
+#define FX_LANG_SystemDefault 0x0800
+#define FX_LANG_Afrikaans_SouthAfrica 0x0436
+#define FX_LANG_Albanian_Albania 0x041c
+#define FX_LANG_Alsatian_France 0x0484
+#define FX_LANG_Amharic_Ethiopia 0x045e
+#define FX_LANG_Arabic_Algeria 0x1401
+#define FX_LANG_Arabic_Bahrain 0x3c01
+#define FX_LANG_Arabic_Egypt 0x0c01
+#define FX_LANG_Arabic_Iraq 0x0801
+#define FX_LANG_Arabic_Jordan 0x2c01
+#define FX_LANG_Arabic_Kuwait 0x3401
+#define FX_LANG_Arabic_Lebanon 0x3001
+#define FX_LANG_Arabic_Libya 0x1001
+#define FX_LANG_Arabic_Morocco 0x1801
+#define FX_LANG_Arabic_Oman 0x2001
+#define FX_LANG_Arabic_Qatar 0x4001
+#define FX_LANG_Arabic_SaudiArabia 0x0401
+#define FX_LANG_Arabic_Syria 0x2801
+#define FX_LANG_Arabic_Tunisia 0x1c01
+#define FX_LANG_Arabic_UAE 0x3801
+#define FX_LANG_Arabic_Yemen 0x2401
+#define FX_LANG_Armenian_Armenia 0x042b
+#define FX_LANG_Assamese_India 0x044d
+#define FX_LANG_Azerbaijan_Cyrillic 0x082c
+#define FX_LANG_Azerbaijan_Latin 0x042c
+#define FX_LANG_Bashkir_Russia 0x046d
+#define FX_LANG_Basque_Basque 0x042d
+#define FX_LANG_Belarusian_Belarus 0x0423
+#define FX_LANG_Bengali_Bangladesh 0x0845
+#define FX_LANG_Bengali_India 0x0445
+#define FX_LANG_Bosnia_Herzegovina 0x101a
+#define FX_LANG_Bosnian_Cyrillic 0x201a
+#define FX_LANG_Bosnian_Latin 0x141a
+#define FX_LANG_Breton_France 0x047e
+#define FX_LANG_Bulgarian_Bulgaria 0x0402
+#define FX_LANG_Burmese 0x0455
+#define FX_LANG_Catalan_Catalan 0x0403
+#define FX_LANG_Cherokee 0x045c
+#define FX_LANG_Chinese_HongKong 0x0c04
+#define FX_LANG_Chinese_Macao 0x1404
+#define FX_LANG_Chinese_PRC 0x0804
+#define FX_LANG_Chinese_Singapore 0x1004
+#define FX_LANG_Chinese_Taiwan 0x0404
+#define FX_LANG_Corsican_France 0x0483
+#define FX_LANG_Croatian_Croatia 0x041a
+#define FX_LANG_Croatian_Latin 0x101a
+#define FX_LANG_CustomCurrent 0x0c00
+#define FX_LANG_CzechRepublic 0x0405
+#define FX_LANG_Danish_Denmark 0x0406
+#define FX_LANG_Dari_Afghanistan 0x048c
+#define FX_LANG_Divehi_Maldives 0x0465
+#define FX_LANG_Dutch_Belgium 0x0813
+#define FX_LANG_Dutch_Netherlands 0x0413
+#define FX_LANG_Dutch_Preferred 0x0013
+#define FX_LANG_Dzongkha 0x0851
+#define FX_LANG_Edo 0x0466
+#define FX_LANG_English_Australia 0x0c09
+#define FX_LANG_English_Belize 0x2809
+#define FX_LANG_English_Canada 0x1009
+#define FX_LANG_English_Caribbean 0x2409
+#define FX_LANG_English_HongKong 0x3c09
+#define FX_LANG_English_India 0x4009
+#define FX_LANG_English_Indonesia 0x3809
+#define FX_LANG_English_Ireland 0x1809
+#define FX_LANG_English_Jamaica 0x2009
+#define FX_LANG_English_Malaysia 0x4409
+#define FX_LANG_English_NewZealand 0x1409
+#define FX_LANG_English_Philippines 0x3409
+#define FX_LANG_English_Singapore 0x4809
+#define FX_LANG_English_SouthAfrica 0x1c09
+#define FX_LANG_English_TrinidadTobago 0x2c09
+#define FX_LANG_English_UnitedKingdom 0x0809
+#define FX_LANG_English_UnitedStates 0x0409
+#define FX_LANG_English_Zimbabwe 0x3009
+#define FX_LANG_Estonian_Estonia 0x0425
+#define FX_LANG_Faroese_FaroeIslands 0x0438
+#define FX_LANG_Filipino_Philippines 0x0464
+#define FX_LANG_Finnish_Finland 0x040b
+#define FX_LANG_French_Belgium 0x080c
+#define FX_LANG_French_Cameroon 0x2c0c
+#define FX_LANG_French_Canada 0x0c0c
+#define FX_LANG_French_CongoDRC 0x240c
+#define FX_LANG_French_CotedIvoire 0x300c
+#define FX_LANG_French_France 0x040c
+#define FX_LANG_French_Haiti 0x3c0c
+#define FX_LANG_French_Luxembourg 0x140c
+#define FX_LANG_French_Mali 0x340c
+#define FX_LANG_French_Monaco 0x180c
+#define FX_LANG_French_Morocco 0x380c
+#define FX_LANG_French_Reunion 0x200c
+#define FX_LANG_French_Senegal 0x280c
+#define FX_LANG_French_Switzerland 0x100c
+#define FX_LANG_French_WestIndies 0x1c0c
+#define FX_LANG_Frisian_Netherlands 0x0462
+#define FX_LANG_Fulfulde 0x0467
+#define FX_LANG_Gaelic_Ireland 0x083c
+#define FX_LANG_Gaelic_Scotland 0x043c
+#define FX_LANG_Galician_Galician 0x0456
+#define FX_LANG_Georgian_Georgia 0x0437
+#define FX_LANG_German_Austria 0x0c07
+#define FX_LANG_German_Germany 0x0407
+#define FX_LANG_German_Liechtenstein 0x1407
+#define FX_LANG_German_Luxembourg 0x1007
+#define FX_LANG_German_Switzerland 0x0807
+#define FX_LANG_Greek_Greece 0x0408
+#define FX_LANG_Greenlandic_Greenland 0x046f
+#define FX_LANG_Guarani 0x0474
+#define FX_LANG_Gujarati_India 0x0447
+#define FX_LANG_Hausa_LatinNigeria 0x0468
+#define FX_LANG_Hawaiian 0x0475
+#define FX_LANG_Hebrew_Israel 0x040d
+#define FX_LANG_Hindi_India 0x0439
+#define FX_LANG_Hungarian_Hungary 0x040e
+#define FX_LANG_Ibibio_Nigeria 0x0469
+#define FX_LANG_Icelandic_Iceland 0x040f
+#define FX_LANG_Igbo_Nigeria 0x0470
+#define FX_LANG_Indonesian_Indonesia 0x0421
+#define FX_LANG_Inuktitut_LatinCanada 0x085d
+#define FX_LANG_Inuktitut_SyllabicsCanada 0x045d
+#define FX_LANG_IsiXhosa_SouthAfrica 0x0434
+#define FX_LANG_IsiZulu_SouthAfrica 0x0435
+#define FX_LANG_Italian_Italy 0x0410
+#define FX_LANG_Italian_Switzerland 0x0810
+#define FX_LANG_Japanese_Japan 0x0411
+#define FX_LANG_Kannada_India 0x044b
+#define FX_LANG_Kanuri 0x0471
+#define FX_LANG_Kashmiri 0x0860
+#define FX_LANG_Kashmiri_Arabic 0x0460
+#define FX_LANG_Kazakh_Kazakhstan 0x043f
+#define FX_LANG_Khmer_Cambodia 0x0453
+#define FX_LANG_Kiche_Guatemala 0x0486
+#define FX_LANG_Kinyarwanda_Rwanda 0x0487
+#define FX_LANG_Kiswahili_Kenya 0x0441
+#define FX_LANG_Konkani_India 0x0457
+#define FX_LANG_Korean_Korea 0x0412
+#define FX_LANG_Kyrgyz_Kyrgyzstan 0x0440
+#define FX_LANG_Lao_LaoPDR 0x0454
+#define FX_LANG_Latin 0x0476
+#define FX_LANG_Latvian_Latvia 0x0426
+#define FX_LANG_Lithuanian_Lithuania 0x0427
+#define FX_LANG_LithuanianTrad 0x0827
+#define FX_LANG_Lower Sorbian_Germany 0x082e
+#define FX_LANG_Luxembourgish_Luxembourg 0x046e
+#define FX_LANG_Macedonian 0x042f
+#define FX_LANG_Malay_BruneiDarussalam 0x083e
+#define FX_LANG_Malay_Malaysia 0x043e
+#define FX_LANG_Malayalam_India 0x044c
+#define FX_LANG_Maldivian 0x0465
+#define FX_LANG_Maltese_Malta 0x043a
+#define FX_LANG_Manipuri 0x0458
+#define FX_LANG_Maori_NewZealand 0x0481
+#define FX_LANG_Mapudungun_Chile 0x047a
+#define FX_LANG_Marathi_India 0x044e
+#define FX_LANG_Mohawk_Mohawk 0x047c
+#define FX_LANG_Mongolian_CyrillicMongolia 0x0450
+#define FX_LANG_Mongolian_TraditionalMongolian 0x0850
+#define FX_LANG_Nepali_India 0x0861
+#define FX_LANG_Nepali_Nepal 0x0461
+#define FX_LANG_Norwegian_Bokmal 0x0414
+#define FX_LANG_Norwegian_Nynorsk 0x0814
+#define FX_LANG_Occitan_France 0x0482
+#define FX_LANG_Oriya_India 0x0448
+#define FX_LANG_Oromo 0x0472
+#define FX_LANG_Papiamentu 0x0479
+#define FX_LANG_Pashto_Afghanistan 0x0463
+#define FX_LANG_Persian 0x0429
+#define FX_LANG_Polish_Poland 0x0415
+#define FX_LANG_Portuguese_Brazil 0x0416
+#define FX_LANG_Portuguese_Portugal 0x0816
+#define FX_LANG_Punjabi_India 0x0446
+#define FX_LANG_Punjabi_Pakistan 0x0846
+#define FX_LANG_Quechua_Bolivia 0x046b
+#define FX_LANG_Quechua_Ecuador 0x086b
+#define FX_LANG_Quechua_Peru 0x0c6b
+#define FX_LANG_Romanian_Moldova 0x0818
+#define FX_LANG_Romanian_Romania 0x0418
+#define FX_LANG_Romansh_Switzerland 0x0417
+#define FX_LANG_Russian_Moldova 0x0819
+#define FX_LANG_Russian_Russia 0x0419
+#define FX_LANG_Sami_InariFinland 0x243b
+#define FX_LANG_Sami_LuleNorway 0x103b
+#define FX_LANG_Sami_LuleSweden 0x143b
+#define FX_LANG_Sami_NorthernFinland 0x0c3b
+#define FX_LANG_Sami_NorthernNorway 0x043b
+#define FX_LANG_Sami_NorthernSweden 0x083b
+#define FX_LANG_Sami_SkoltFinland 0x203b
+#define FX_LANG_Sami_SouthernNorway 0x183b
+#define FX_LANG_Sami_SouthernSweden 0x1c3b
+#define FX_LANG_SanskritIndia 0x044f
+#define FX_LANG_SerbianCyrillic_BosniaHerzegovina 0x1c1a
+#define FX_LANG_SerbianCyrillic_Serbia 0x0c1a
+#define FX_LANG_SerbianLatin_BosniaHerzegovina 0x181a
+#define FX_LANG_SerbianLatin_Serbia 0x081a
+#define FX_LANG_SesothoSaLeboa 0x046c
+#define FX_LANG_Setswana_SouthAfrica 0x0432
+#define FX_LANG_Sindhi_Arabic 0x0859
+#define FX_LANG_Sindhi_Devanagari 0x0459
+#define FX_LANG_Sinhala_SriLanka 0x045b
+#define FX_LANG_Slovak_Slovakia 0x041b
+#define FX_LANG_Slovenian_Slovenia 0x0424
+#define FX_LANG_Somali 0x0477
+#define FX_LANG_Spanish_Argentina 0x2c0a
+#define FX_LANG_Spanish_Bolivia 0x400a
+#define FX_LANG_Spanish_Chile 0x340a
+#define FX_LANG_Spanish_Colombia 0x240a
+#define FX_LANG_Spanish_CostaRica 0x140a
+#define FX_LANG_Spanish_DominicanRepublic 0x1c0a
+#define FX_LANG_Spanish_Ecuador 0x300a
+#define FX_LANG_Spanish_ElSalvador 0x440a
+#define FX_LANG_Spanish_Guatemala 0x100a
+#define FX_LANG_Spanish_Honduras 0x480a
+#define FX_LANG_Spanish_Mexico 0x080a
+#define FX_LANG_Spanish_Nicaragua 0x4c0a
+#define FX_LANG_Spanish_Panama 0x180a
+#define FX_LANG_Spanish_Paraguay 0x3c0a
+#define FX_LANG_Spanish_Peru 0x280a
+#define FX_LANG_Spanish_PuertoRico 0x500a
+#define FX_LANG_Spanish_InternationalSort 0x0c0a
+#define FX_LANG_Spanish_TraditionalSort 0x040a
+#define FX_LANG_Spanish_UnitedStates 0x540a
+#define FX_LANG_Spanish_Uruguay 0x380a
+#define FX_LANG_Spanish_Venezuela 0x200a
+#define FX_LANG_Sutu_SouthAfrica 0x0430
+#define FX_LANG_Swedish_Finland 0x081d
+#define FX_LANG_Swedish_Sweden 0x041d
+#define FX_LANG_Syriac_Syria 0x045a
+#define FX_LANG_Tajik_CyrillicTajikistan 0x0428
+#define FX_LANG_Tamazight_ArabicMorocco 0x045f
+#define FX_LANG_Tamazight_LatinAlgeria 0x085f
+#define FX_LANG_Tamil_India 0x0449
+#define FX_LANG_Tatar_Russia 0x0444
+#define FX_LANG_Telugu_India 0x044a
+#define FX_LANG_Thai_Thailand 0x041e
+#define FX_LANG_TibetanPRC 0x0451
+#define FX_LANG_Tigrigna_Eritrea 0x0873
+#define FX_LANG_Tigrigna_Ethiopia 0x0473
+#define FX_LANG_Tsonga 0x0431
+#define FX_LANG_Turkish_Turkey 0x041f
+#define FX_LANG_Turkmen_Turkmenistan 0x0442
+#define FX_LANG_UighurPRC 0x0480
+#define FX_LANG_Ukrainian_Ukraine 0x0422
+#define FX_LANG_UpperSorbian_Germany 0x042e
+#define FX_LANG_Urdu_Pakistan 0x0420
+#define FX_LANG_Urdu_India 0x0820
+#define FX_LANG_Uzbek_CyrillicUzbekistan 0x0843
+#define FX_LANG_Uzbek_LatinUzbekistan 0x0443
+#define FX_LANG_Venda 0x0433
+#define FX_LANG_Vietnamese_Vietnam 0x042a
+#define FX_LANG_Welsh_UnitedKingdom 0x0452
+#define FX_LANG_Wolof_Senegal 0x0488
+#define FX_LANG_Xhosa 0x0434
+#define FX_LANG_Yakut_Russia 0x0485
+#define FX_LANG_YiPRC 0x0478
+#define FX_LANG_Yiddish 0x043d
+#define FX_LANG_Yoruba_Nigeria 0x046a
+
+#endif // XFA_SRC_FGAS_CRT_FGAS_LANGUAGE_H_
diff --git a/xfa/src/fgas/crt/fgas_memory.cpp b/xfa/src/fgas/crt/fgas_memory.cpp
new file mode 100644
index 0000000000..c88c7e3aac
--- /dev/null
+++ b/xfa/src/fgas/crt/fgas_memory.cpp
@@ -0,0 +1,446 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/src/fgas/crt/fgas_memory.h"
+
+#include <algorithm>
+
+namespace {
+
+class CFX_DefStore : public IFX_MEMAllocator, public CFX_Target {
+ public:
+ CFX_DefStore() {}
+ ~CFX_DefStore() {}
+ virtual void Release() { delete this; }
+ virtual void* Alloc(size_t size) { return FX_Alloc(uint8_t, size); }
+ virtual void Free(void* pBlock) { FX_Free(pBlock); }
+ virtual size_t GetBlockSize() const { return 0; }
+ virtual size_t GetDefChunkSize() const { return 0; }
+ virtual size_t SetDefChunkSize(size_t size) { return 0; }
+ virtual size_t GetCurrentDataSize() const { return 0; }
+};
+
+#if _FX_OS_ != _FX_ANDROID_
+#pragma pack(push, 1)
+#endif
+struct FX_STATICSTORECHUNK {
+ FX_STATICSTORECHUNK* pNextChunk;
+ size_t iChunkSize;
+ size_t iFreeSize;
+};
+#if _FX_OS_ != _FX_ANDROID_
+#pragma pack(pop)
+#endif
+
+class CFX_StaticStore : public IFX_MEMAllocator, public CFX_Target {
+ public:
+ CFX_StaticStore(size_t iDefChunkSize = 4096);
+ ~CFX_StaticStore();
+ virtual void Release() { delete this; }
+ virtual void* Alloc(size_t size);
+ virtual void Free(void* pBlock) {}
+ virtual size_t GetBlockSize() const { return 0; }
+ virtual size_t GetDefChunkSize() const { return m_iDefChunkSize; }
+ virtual size_t SetDefChunkSize(size_t size);
+ virtual size_t GetCurrentDataSize() const { return m_iAllocatedSize; }
+
+ protected:
+ size_t m_iAllocatedSize;
+ size_t m_iDefChunkSize;
+ FX_STATICSTORECHUNK* m_pChunk;
+ FX_STATICSTORECHUNK* m_pLastChunk;
+ FX_STATICSTORECHUNK* AllocChunk(size_t size);
+ FX_STATICSTORECHUNK* FindChunk(size_t size);
+};
+
+#if _FX_OS_ != _FX_ANDROID_
+#pragma pack(push, 1)
+#endif
+struct FX_FIXEDSTORECHUNK {
+ uint8_t* FirstFlag() { return reinterpret_cast<uint8_t*>(this + 1); }
+ uint8_t* FirstBlock() { return FirstFlag() + iChunkSize; }
+
+ FX_FIXEDSTORECHUNK* pNextChunk;
+ size_t iChunkSize;
+ size_t iFreeNum;
+};
+#if _FX_OS_ != _FX_ANDROID_
+#pragma pack(pop)
+#endif
+
+class CFX_FixedStore : public IFX_MEMAllocator, public CFX_Target {
+ public:
+ CFX_FixedStore(size_t iBlockSize, size_t iBlockNumsInChunk);
+ virtual ~CFX_FixedStore();
+ virtual void Release() { delete this; }
+ virtual void* Alloc(size_t size);
+ virtual void Free(void* pBlock);
+ virtual size_t GetBlockSize() const { return m_iBlockSize; }
+ virtual size_t GetDefChunkSize() const { return m_iDefChunkSize; }
+ virtual size_t SetDefChunkSize(size_t iChunkSize);
+ virtual size_t GetCurrentDataSize() const { return 0; }
+
+ protected:
+ FX_FIXEDSTORECHUNK* AllocChunk();
+
+ size_t m_iBlockSize;
+ size_t m_iDefChunkSize;
+ FX_FIXEDSTORECHUNK* m_pChunk;
+};
+
+#if _FX_OS_ != _FX_ANDROID_
+#pragma pack(push, 1)
+#endif
+struct FX_DYNAMICSTOREBLOCK {
+ uint8_t* Data() { return reinterpret_cast<uint8_t*>(this + 1); }
+ FX_DYNAMICSTOREBLOCK* NextBlock() {
+ return reinterpret_cast<FX_DYNAMICSTOREBLOCK*>(Data() + iBlockSize);
+ }
+ size_t iBlockSize;
+ FX_BOOL bUsed;
+};
+
+struct FX_DYNAMICSTORECHUNK {
+ FX_DYNAMICSTOREBLOCK* FirstBlock() {
+ return reinterpret_cast<FX_DYNAMICSTOREBLOCK*>(this + 1);
+ }
+ FX_DYNAMICSTORECHUNK* pNextChunk;
+ size_t iChunkSize;
+ size_t iFreeSize;
+};
+#if _FX_OS_ != _FX_ANDROID_
+#pragma pack(pop)
+#endif
+
+class CFX_DynamicStore : public IFX_MEMAllocator, public CFX_Target {
+ public:
+ CFX_DynamicStore(size_t iDefChunkSize = 4096);
+ virtual ~CFX_DynamicStore();
+ virtual void Release() { delete this; }
+ virtual void* Alloc(size_t size);
+ virtual void Free(void* pBlock);
+ virtual size_t GetBlockSize() const { return 0; }
+ virtual size_t GetDefChunkSize() const { return m_iDefChunkSize; }
+ virtual size_t SetDefChunkSize(size_t size);
+ virtual size_t GetCurrentDataSize() const { return 0; }
+
+ protected:
+ FX_DYNAMICSTORECHUNK* AllocChunk(size_t size);
+
+ size_t m_iDefChunkSize;
+ FX_DYNAMICSTORECHUNK* m_pChunk;
+};
+
+} // namespace
+
+#define FX_4BYTEALIGN(size) (((size) + 3) / 4 * 4)
+
+IFX_MEMAllocator* FX_CreateAllocator(FX_ALLOCTYPE eType,
+ size_t chunkSize,
+ size_t blockSize) {
+ switch (eType) {
+ case FX_ALLOCTYPE_Dynamic:
+ return new CFX_DynamicStore(chunkSize);
+ case FX_ALLOCTYPE_Default:
+ return new CFX_DefStore();
+ case FX_ALLOCTYPE_Static:
+ return new CFX_StaticStore(chunkSize);
+ case FX_ALLOCTYPE_Fixed:
+ return new CFX_FixedStore(blockSize, chunkSize);
+ default:
+ return NULL;
+ }
+}
+CFX_StaticStore::CFX_StaticStore(size_t iDefChunkSize)
+ : m_iAllocatedSize(0),
+ m_iDefChunkSize(iDefChunkSize),
+ m_pChunk(NULL),
+ m_pLastChunk(NULL) {
+ FXSYS_assert(m_iDefChunkSize != 0);
+}
+CFX_StaticStore::~CFX_StaticStore() {
+ FX_STATICSTORECHUNK* pChunk = m_pChunk;
+ while (pChunk) {
+ FX_STATICSTORECHUNK* pNext = pChunk->pNextChunk;
+ FX_Free(pChunk);
+ pChunk = pNext;
+ }
+}
+FX_STATICSTORECHUNK* CFX_StaticStore::AllocChunk(size_t size) {
+ FXSYS_assert(size != 0);
+ FX_STATICSTORECHUNK* pChunk = (FX_STATICSTORECHUNK*)FX_Alloc(
+ uint8_t, sizeof(FX_STATICSTORECHUNK) + size);
+ pChunk->iChunkSize = size;
+ pChunk->iFreeSize = size;
+ pChunk->pNextChunk = NULL;
+ if (m_pLastChunk == NULL) {
+ m_pChunk = pChunk;
+ } else {
+ m_pLastChunk->pNextChunk = pChunk;
+ }
+ m_pLastChunk = pChunk;
+ return pChunk;
+}
+FX_STATICSTORECHUNK* CFX_StaticStore::FindChunk(size_t size) {
+ FXSYS_assert(size != 0);
+ if (m_pLastChunk == NULL || m_pLastChunk->iFreeSize < size) {
+ return AllocChunk(std::max(m_iDefChunkSize, size));
+ }
+ return m_pLastChunk;
+}
+void* CFX_StaticStore::Alloc(size_t size) {
+ size = FX_4BYTEALIGN(size);
+ FXSYS_assert(size != 0);
+ FX_STATICSTORECHUNK* pChunk = FindChunk(size);
+ FXSYS_assert(pChunk->iFreeSize >= size);
+ uint8_t* p = (uint8_t*)pChunk;
+ p += sizeof(FX_STATICSTORECHUNK) + pChunk->iChunkSize - pChunk->iFreeSize;
+ pChunk->iFreeSize -= size;
+ m_iAllocatedSize += size;
+ return p;
+}
+size_t CFX_StaticStore::SetDefChunkSize(size_t size) {
+ FXSYS_assert(size != 0);
+ size_t v = m_iDefChunkSize;
+ m_iDefChunkSize = size;
+ return v;
+}
+CFX_FixedStore::CFX_FixedStore(size_t iBlockSize, size_t iBlockNumsInChunk)
+ : m_iBlockSize(FX_4BYTEALIGN(iBlockSize)),
+ m_iDefChunkSize(FX_4BYTEALIGN(iBlockNumsInChunk)),
+ m_pChunk(NULL) {
+ FXSYS_assert(m_iBlockSize != 0 && m_iDefChunkSize != 0);
+}
+CFX_FixedStore::~CFX_FixedStore() {
+ FX_FIXEDSTORECHUNK* pChunk = m_pChunk;
+ while (pChunk) {
+ FX_FIXEDSTORECHUNK* pNext = pChunk->pNextChunk;
+ FX_Free(pChunk);
+ pChunk = pNext;
+ }
+}
+FX_FIXEDSTORECHUNK* CFX_FixedStore::AllocChunk() {
+ int32_t iTotalSize = sizeof(FX_FIXEDSTORECHUNK) + m_iDefChunkSize +
+ m_iBlockSize * m_iDefChunkSize;
+ FX_FIXEDSTORECHUNK* pChunk =
+ (FX_FIXEDSTORECHUNK*)FX_Alloc(uint8_t, iTotalSize);
+ if (pChunk == NULL) {
+ return NULL;
+ }
+ FXSYS_memset(pChunk->FirstFlag(), 0, m_iDefChunkSize);
+ pChunk->pNextChunk = m_pChunk;
+ pChunk->iChunkSize = m_iDefChunkSize;
+ pChunk->iFreeNum = m_iDefChunkSize;
+ m_pChunk = pChunk;
+ return pChunk;
+}
+void* CFX_FixedStore::Alloc(size_t size) {
+ if (size > m_iBlockSize) {
+ return NULL;
+ }
+ FX_FIXEDSTORECHUNK* pChunk = m_pChunk;
+ while (pChunk != NULL) {
+ if (pChunk->iFreeNum > 0) {
+ break;
+ }
+ pChunk = pChunk->pNextChunk;
+ }
+ if (pChunk == NULL) {
+ pChunk = AllocChunk();
+ }
+ FXSYS_assert(pChunk != NULL);
+ uint8_t* pFlags = pChunk->FirstFlag();
+ size_t i = 0;
+ for (; i < pChunk->iChunkSize; i++)
+ if (pFlags[i] == 0) {
+ break;
+ }
+ FXSYS_assert(i < pChunk->iChunkSize);
+ pFlags[i] = 1;
+ pChunk->iFreeNum--;
+ return pChunk->FirstBlock() + i * m_iBlockSize;
+}
+void CFX_FixedStore::Free(void* pBlock) {
+ FXSYS_assert(pBlock != NULL);
+ FX_FIXEDSTORECHUNK* pPrior = NULL;
+ FX_FIXEDSTORECHUNK* pChunk = m_pChunk;
+ uint8_t* pStart = NULL;
+ uint8_t* pEnd;
+ while (pChunk != NULL) {
+ pStart = pChunk->FirstBlock();
+ if (pBlock >= pStart) {
+ pEnd = pStart + m_iBlockSize * pChunk->iChunkSize;
+ if (pBlock < pEnd) {
+ break;
+ }
+ }
+ pPrior = pChunk, pChunk = pChunk->pNextChunk;
+ }
+ FXSYS_assert(pChunk != NULL);
+ size_t iPos = ((uint8_t*)pBlock - pStart) / m_iBlockSize;
+ FXSYS_assert(iPos < pChunk->iChunkSize);
+ uint8_t* pFlags = pChunk->FirstFlag();
+ if (pFlags[iPos] == 0) {
+ return;
+ }
+ pFlags[iPos] = 0;
+ pChunk->iFreeNum++;
+ if (pChunk->iFreeNum == pChunk->iChunkSize) {
+ if (pPrior == NULL) {
+ m_pChunk = pChunk->pNextChunk;
+ } else {
+ pPrior->pNextChunk = pChunk->pNextChunk;
+ }
+ FX_Free(pChunk);
+ }
+}
+size_t CFX_FixedStore::SetDefChunkSize(size_t iChunkSize) {
+ FXSYS_assert(iChunkSize != 0);
+ size_t v = m_iDefChunkSize;
+ m_iDefChunkSize = FX_4BYTEALIGN(iChunkSize);
+ return v;
+}
+CFX_DynamicStore::CFX_DynamicStore(size_t iDefChunkSize)
+ : m_iDefChunkSize(iDefChunkSize), m_pChunk(NULL) {
+ FXSYS_assert(m_iDefChunkSize != 0);
+}
+CFX_DynamicStore::~CFX_DynamicStore() {
+ FX_DYNAMICSTORECHUNK* pChunk = m_pChunk;
+ while (pChunk) {
+ FX_DYNAMICSTORECHUNK* pNext = pChunk->pNextChunk;
+ FX_Free(pChunk);
+ pChunk = pNext;
+ }
+}
+FX_DYNAMICSTORECHUNK* CFX_DynamicStore::AllocChunk(size_t size) {
+ FXSYS_assert(size != 0);
+ FX_DYNAMICSTORECHUNK* pChunk = (FX_DYNAMICSTORECHUNK*)FX_Alloc(
+ uint8_t,
+ sizeof(FX_DYNAMICSTORECHUNK) + sizeof(FX_DYNAMICSTOREBLOCK) * 2 + size);
+ if (pChunk == NULL) {
+ return NULL;
+ }
+ pChunk->iChunkSize = size;
+ pChunk->iFreeSize = size;
+ FX_DYNAMICSTOREBLOCK* pBlock = pChunk->FirstBlock();
+ pBlock->iBlockSize = size;
+ pBlock->bUsed = FALSE;
+ pBlock = pBlock->NextBlock();
+ pBlock->iBlockSize = 0;
+ pBlock->bUsed = TRUE;
+ if (m_pChunk != NULL && size >= m_iDefChunkSize) {
+ FX_DYNAMICSTORECHUNK* pLast = m_pChunk;
+ while (pLast->pNextChunk != NULL) {
+ pLast = pLast->pNextChunk;
+ }
+ pLast->pNextChunk = pChunk;
+ pChunk->pNextChunk = NULL;
+ } else {
+ pChunk->pNextChunk = m_pChunk;
+ m_pChunk = pChunk;
+ }
+ return pChunk;
+}
+void* CFX_DynamicStore::Alloc(size_t size) {
+ size = FX_4BYTEALIGN(size);
+ FXSYS_assert(size != 0);
+ FX_DYNAMICSTORECHUNK* pChunk = m_pChunk;
+ FX_DYNAMICSTOREBLOCK* pBlock = NULL;
+ while (pChunk != NULL) {
+ if (pChunk->iFreeSize >= size) {
+ pBlock = pChunk->FirstBlock();
+ FX_BOOL bFind = FALSE;
+ while (pBlock->iBlockSize != 0) {
+ if (!pBlock->bUsed && pBlock->iBlockSize >= size) {
+ bFind = TRUE;
+ break;
+ }
+ pBlock = pBlock->NextBlock();
+ }
+ if (bFind) {
+ break;
+ }
+ }
+ pChunk = pChunk->pNextChunk;
+ }
+ if (pChunk == NULL) {
+ pChunk = AllocChunk(std::max(m_iDefChunkSize, size));
+ pBlock = pChunk->FirstBlock();
+ }
+ FXSYS_assert(pChunk != NULL && pBlock != NULL);
+ size_t m = size + sizeof(FX_DYNAMICSTOREBLOCK);
+ pBlock->bUsed = TRUE;
+ if (pBlock->iBlockSize > m) {
+ size_t n = pBlock->iBlockSize;
+ pBlock->iBlockSize = size;
+ FX_DYNAMICSTOREBLOCK* pNextBlock = pBlock->NextBlock();
+ pNextBlock->bUsed = FALSE;
+ pNextBlock->iBlockSize = n - size - sizeof(FX_DYNAMICSTOREBLOCK);
+ pChunk->iFreeSize -= size + sizeof(FX_DYNAMICSTOREBLOCK);
+ } else {
+ pChunk->iFreeSize -= pBlock->iBlockSize;
+ }
+ return pBlock->Data();
+}
+void CFX_DynamicStore::Free(void* pBlock) {
+ FXSYS_assert(pBlock != NULL);
+ FX_DYNAMICSTORECHUNK* pPriorChunk = NULL;
+ FX_DYNAMICSTORECHUNK* pChunk = m_pChunk;
+ while (pChunk != NULL) {
+ if (pBlock > pChunk &&
+ pBlock <= ((uint8_t*)pChunk + sizeof(FX_DYNAMICSTORECHUNK) +
+ pChunk->iChunkSize)) {
+ break;
+ }
+ pPriorChunk = pChunk, pChunk = pChunk->pNextChunk;
+ }
+ FXSYS_assert(pChunk != NULL);
+ FX_DYNAMICSTOREBLOCK* pPriorBlock = NULL;
+ FX_DYNAMICSTOREBLOCK* pFindBlock = pChunk->FirstBlock();
+ while (pFindBlock->iBlockSize != 0) {
+ if (pBlock == (void*)pFindBlock->Data()) {
+ break;
+ }
+ pPriorBlock = pFindBlock;
+ pFindBlock = pFindBlock->NextBlock();
+ }
+ FXSYS_assert(pFindBlock->iBlockSize != 0 && pFindBlock->bUsed &&
+ pBlock == (void*)pFindBlock->Data());
+ pFindBlock->bUsed = FALSE;
+ pChunk->iFreeSize += pFindBlock->iBlockSize;
+ if (pPriorBlock == NULL) {
+ pPriorBlock = pChunk->FirstBlock();
+ } else if (pPriorBlock->bUsed) {
+ pPriorBlock = pFindBlock;
+ }
+ pFindBlock = pPriorBlock;
+ size_t sizeFree = 0;
+ size_t sizeBlock = 0;
+ while (pFindBlock->iBlockSize != 0 && !pFindBlock->bUsed) {
+ if (pFindBlock != pPriorBlock) {
+ sizeFree += sizeof(FX_DYNAMICSTOREBLOCK);
+ sizeBlock += sizeof(FX_DYNAMICSTOREBLOCK);
+ }
+ sizeBlock += pFindBlock->iBlockSize;
+ pFindBlock = pFindBlock->NextBlock();
+ }
+ pPriorBlock->iBlockSize = sizeBlock;
+ pChunk->iFreeSize += sizeFree;
+ if (pChunk->iFreeSize == pChunk->iChunkSize) {
+ if (pPriorChunk == NULL) {
+ m_pChunk = pChunk->pNextChunk;
+ } else {
+ pPriorChunk->pNextChunk = pChunk->pNextChunk;
+ }
+ FX_Free(pChunk);
+ }
+}
+size_t CFX_DynamicStore::SetDefChunkSize(size_t size) {
+ FXSYS_assert(size != 0);
+ size_t v = m_iDefChunkSize;
+ m_iDefChunkSize = size;
+ return v;
+}
diff --git a/xfa/src/fgas/crt/fgas_memory.h b/xfa/src/fgas/crt/fgas_memory.h
new file mode 100644
index 0000000000..90a8ddaf9a
--- /dev/null
+++ b/xfa/src/fgas/crt/fgas_memory.h
@@ -0,0 +1,59 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_CRT_FGAS_MEMORY_H_
+#define XFA_SRC_FGAS_CRT_FGAS_MEMORY_H_
+
+#include "core/include/fxcrt/fx_memory.h"
+#include "core/include/fxcrt/fx_system.h"
+
+class IFX_MEMAllocator;
+class CFX_Target;
+enum FX_ALLOCTYPE {
+ FX_ALLOCTYPE_Default = 0,
+ FX_ALLOCTYPE_Static,
+ FX_ALLOCTYPE_Fixed,
+ FX_ALLOCTYPE_Dynamic,
+};
+
+class IFX_MEMAllocator {
+ public:
+ virtual ~IFX_MEMAllocator() {}
+ virtual void Release() = 0;
+ virtual void* Alloc(size_t size) = 0;
+ virtual void Free(void* pBlock) = 0;
+ virtual size_t GetBlockSize() const = 0;
+ virtual size_t GetDefChunkSize() const = 0;
+ virtual size_t SetDefChunkSize(size_t size) = 0;
+ virtual size_t GetCurrentDataSize() const = 0;
+};
+
+IFX_MEMAllocator* FX_CreateAllocator(FX_ALLOCTYPE eType,
+ size_t chunkSize,
+ size_t blockSize);
+class CFX_Target {
+ public:
+ virtual ~CFX_Target() {}
+ void* operator new(size_t size) { return FX_Alloc(uint8_t, size); }
+ void operator delete(void* p) { FX_Free(p); }
+ void* operator new(size_t size, IFX_MEMAllocator* pAllocator) {
+ return pAllocator->Alloc(size);
+ }
+ void operator delete(void* p, IFX_MEMAllocator* pAllocator) {
+ pAllocator->Free(p);
+ }
+ void* operator new(size_t size, void* place) { return place; }
+ void operator delete(void* p, void* place) {}
+};
+
+#define FXTARGET_NewWith(__allocator__) new (__allocator__)
+#define FXTARGET_DeleteWith(__class__, __allocator__, pointer) \
+ { \
+ (pointer)->~__class__(); \
+ (pointer)->operator delete((pointer), (__allocator__)); \
+ }
+
+#endif // XFA_SRC_FGAS_CRT_FGAS_MEMORY_H_
diff --git a/xfa/src/fgas/crt/fgas_stream.cpp b/xfa/src/fgas/crt/fgas_stream.cpp
new file mode 100644
index 0000000000..c515b56662
--- /dev/null
+++ b/xfa/src/fgas/crt/fgas_stream.cpp
@@ -0,0 +1,1626 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/src/fgas/crt/fgas_stream.h"
+
+#include <algorithm>
+
+#include "xfa/src/fgas/crt/fgas_system.h"
+#include "xfa/src/fgas/crt/fgas_codepage.h"
+
+namespace {
+
+class CFX_StreamImp {
+ public:
+ virtual void Release() { delete this; }
+ virtual FX_DWORD GetAccessModes() const { return m_dwAccess; }
+ virtual int32_t GetLength() const = 0;
+ virtual int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) = 0;
+ virtual int32_t GetPosition() = 0;
+ virtual FX_BOOL IsEOF() const = 0;
+ virtual int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) = 0;
+ virtual int32_t ReadString(FX_WCHAR* pStr,
+ int32_t iMaxLength,
+ FX_BOOL& bEOS) = 0;
+ virtual int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) = 0;
+ virtual int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) = 0;
+ virtual void Flush() = 0;
+ virtual FX_BOOL SetLength(int32_t iLength) = 0;
+
+ protected:
+ CFX_StreamImp();
+ virtual ~CFX_StreamImp() {}
+ FX_DWORD m_dwAccess;
+};
+
+class CFX_FileStreamImp : public CFX_StreamImp {
+ public:
+ CFX_FileStreamImp();
+ virtual ~CFX_FileStreamImp();
+ FX_BOOL LoadFile(const FX_WCHAR* pszSrcFileName, FX_DWORD dwAccess);
+ virtual int32_t GetLength() const;
+ virtual int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset);
+ virtual int32_t GetPosition();
+ virtual FX_BOOL IsEOF() const;
+ virtual int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize);
+ virtual int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, FX_BOOL& bEOS);
+ virtual int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize);
+ virtual int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength);
+ virtual void Flush();
+ virtual FX_BOOL SetLength(int32_t iLength);
+
+ protected:
+ FXSYS_FILE* m_hFile;
+ int32_t m_iLength;
+};
+
+class CFX_BufferStreamImp : public CFX_StreamImp {
+ public:
+ CFX_BufferStreamImp();
+ virtual ~CFX_BufferStreamImp() {}
+ FX_BOOL LoadBuffer(uint8_t* pData, int32_t iTotalSize, FX_DWORD dwAccess);
+ virtual int32_t GetLength() const;
+ virtual int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset);
+ virtual int32_t GetPosition();
+ virtual FX_BOOL IsEOF() const;
+ virtual int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize);
+ virtual int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, FX_BOOL& bEOS);
+ virtual int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize);
+ virtual int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength);
+ virtual void Flush() {}
+ virtual FX_BOOL SetLength(int32_t iLength) { return FALSE; }
+
+ protected:
+ uint8_t* m_pData;
+ int32_t m_iTotalSize;
+ int32_t m_iPosition;
+ int32_t m_iLength;
+};
+
+class CFX_FileReadStreamImp : public CFX_StreamImp {
+ public:
+ CFX_FileReadStreamImp();
+ virtual ~CFX_FileReadStreamImp() {}
+ FX_BOOL LoadFileRead(IFX_FileRead* pFileRead, FX_DWORD dwAccess);
+ virtual int32_t GetLength() const;
+ virtual int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset);
+ virtual int32_t GetPosition() { return m_iPosition; }
+ virtual FX_BOOL IsEOF() const;
+
+ virtual int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize);
+ virtual int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, FX_BOOL& bEOS);
+ virtual int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) {
+ return 0;
+ }
+ virtual int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) {
+ return 0;
+ }
+ virtual void Flush() {}
+ virtual FX_BOOL SetLength(int32_t iLength) { return FALSE; }
+
+ protected:
+ IFX_FileRead* m_pFileRead;
+ int32_t m_iPosition;
+ int32_t m_iLength;
+};
+
+class CFX_BufferReadStreamImp : public CFX_StreamImp {
+ public:
+ CFX_BufferReadStreamImp();
+ ~CFX_BufferReadStreamImp();
+ FX_BOOL LoadBufferRead(IFX_BufferRead* pBufferRead,
+ int32_t iFileSize,
+ FX_DWORD dwAccess,
+ FX_BOOL bReleaseBufferRead);
+
+ virtual int32_t GetLength() const;
+ virtual int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset);
+ virtual int32_t GetPosition() { return m_iPosition; }
+ virtual FX_BOOL IsEOF() const;
+
+ virtual int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize);
+ virtual int32_t ReadString(FX_WCHAR* pStr, int32_t iMaxLength, FX_BOOL& bEOS);
+ virtual int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) {
+ return 0;
+ }
+ virtual int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) {
+ return 0;
+ }
+ virtual void Flush() {}
+ virtual FX_BOOL SetLength(int32_t iLength) { return FALSE; }
+
+ private:
+ IFX_BufferRead* m_pBufferRead;
+ FX_BOOL m_bReleaseBufferRead;
+ int32_t m_iPosition;
+ int32_t m_iBufferSize;
+};
+
+class CFX_FileWriteStreamImp : public CFX_StreamImp {
+ public:
+ CFX_FileWriteStreamImp();
+ virtual ~CFX_FileWriteStreamImp() {}
+ FX_BOOL LoadFileWrite(IFX_FileWrite* pFileWrite, FX_DWORD dwAccess);
+ virtual int32_t GetLength() const;
+ virtual int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset);
+ virtual int32_t GetPosition() { return m_iPosition; }
+ virtual FX_BOOL IsEOF() const;
+ virtual int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) { return 0; }
+ virtual int32_t ReadString(FX_WCHAR* pStr,
+ int32_t iMaxLength,
+ FX_BOOL& bEOS) {
+ return 0;
+ }
+ virtual int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize);
+ virtual int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength);
+ virtual void Flush();
+ virtual FX_BOOL SetLength(int32_t iLength) { return FALSE; }
+
+ protected:
+ IFX_FileWrite* m_pFileWrite;
+ int32_t m_iPosition;
+};
+
+enum FX_STREAMTYPE {
+ FX_SREAMTYPE_Unknown = 0,
+ FX_STREAMTYPE_File,
+ FX_STREAMTYPE_Buffer,
+ FX_STREAMTYPE_Stream,
+ FX_STREAMTYPE_BufferRead,
+};
+
+class CFX_Stream : public IFX_Stream {
+ public:
+ CFX_Stream();
+ ~CFX_Stream();
+ FX_BOOL LoadFile(const FX_WCHAR* pszSrcFileName, FX_DWORD dwAccess);
+ FX_BOOL LoadBuffer(uint8_t* pData, int32_t iTotalSize, FX_DWORD dwAccess);
+ FX_BOOL LoadFileRead(IFX_FileRead* pFileRead, FX_DWORD dwAccess);
+ FX_BOOL LoadFileWrite(IFX_FileWrite* pFileWrite, FX_DWORD dwAccess);
+ FX_BOOL LoadBufferRead(IFX_BufferRead* pBufferRead,
+ int32_t iFileSize,
+ FX_DWORD dwAccess,
+ FX_BOOL bReleaseBufferRead);
+ virtual void Release();
+ virtual IFX_Stream* Retain();
+ virtual FX_DWORD GetAccessModes() const { return m_dwAccess; }
+ virtual int32_t GetLength() const;
+ virtual int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset);
+ virtual int32_t GetPosition();
+ virtual FX_BOOL IsEOF() const;
+ virtual int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize);
+ virtual int32_t ReadString(FX_WCHAR* pStr,
+ int32_t iMaxLength,
+ FX_BOOL& bEOS,
+ int32_t const* pByteSize = NULL);
+ virtual int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize);
+ virtual int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength);
+ virtual void Flush();
+ virtual FX_BOOL SetLength(int32_t iLength);
+ virtual int32_t GetBOM(uint8_t bom[4]) const;
+ virtual FX_WORD GetCodePage() const;
+ virtual FX_WORD SetCodePage(FX_WORD wCodePage);
+ virtual IFX_Stream* CreateSharedStream(FX_DWORD dwAccess,
+ int32_t iOffset,
+ int32_t iLength);
+
+ protected:
+ FX_STREAMTYPE m_eStreamType;
+ CFX_StreamImp* m_pStreamImp;
+ FX_DWORD m_dwAccess;
+ int32_t m_iTotalSize;
+ int32_t m_iPosition;
+ int32_t m_iStart;
+ int32_t m_iLength;
+ int32_t m_iRefCount;
+};
+
+class CFX_TextStream : public IFX_Stream {
+ public:
+ CFX_TextStream(IFX_Stream* pStream, FX_BOOL bDelStream);
+ ~CFX_TextStream();
+ virtual void Release();
+ virtual IFX_Stream* Retain();
+
+ virtual FX_DWORD GetAccessModes() const;
+ virtual int32_t GetLength() const;
+ virtual int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset);
+ virtual int32_t GetPosition();
+ virtual FX_BOOL IsEOF() const;
+
+ virtual int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize);
+ virtual int32_t ReadString(FX_WCHAR* pStr,
+ int32_t iMaxLength,
+ FX_BOOL& bEOS,
+ int32_t const* pByteSize = NULL);
+ virtual int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize);
+ virtual int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength);
+ virtual void Flush();
+ virtual FX_BOOL SetLength(int32_t iLength);
+
+ virtual int32_t GetBOM(uint8_t bom[4]) const;
+ virtual FX_WORD GetCodePage() const;
+ virtual FX_WORD SetCodePage(FX_WORD wCodePage);
+
+ virtual IFX_Stream* CreateSharedStream(FX_DWORD dwAccess,
+ int32_t iOffset,
+ int32_t iLength);
+
+ protected:
+ FX_WORD m_wCodePage;
+ int32_t m_wBOMLength;
+ FX_DWORD m_dwBOM;
+ uint8_t* m_pBuf;
+ int32_t m_iBufSize;
+ FX_BOOL m_bDelStream;
+ IFX_Stream* m_pStreamImp;
+ int32_t m_iRefCount;
+ void InitStream();
+};
+
+class CFGAS_FileRead : public IFX_FileRead {
+ public:
+ CFGAS_FileRead(IFX_Stream* pStream, FX_BOOL bReleaseStream);
+ virtual ~CFGAS_FileRead();
+ virtual void Release() { delete this; }
+ virtual FX_FILESIZE GetSize();
+ virtual FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size);
+
+ protected:
+ FX_BOOL m_bReleaseStream;
+ IFX_Stream* m_pStream;
+};
+
+class CFX_BufferAccImp : public IFX_FileRead {
+ public:
+ CFX_BufferAccImp(IFX_BufferRead* pBufferRead,
+ FX_FILESIZE iFileSize,
+ FX_BOOL bReleaseStream);
+ virtual ~CFX_BufferAccImp();
+ virtual void Release() { delete this; }
+ virtual FX_FILESIZE GetSize();
+ virtual FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size);
+
+ protected:
+ IFX_BufferRead* m_pBufferRead;
+ FX_BOOL m_bReleaseStream;
+ FX_FILESIZE m_iBufSize;
+};
+
+class CFGAS_FileWrite : public IFX_FileWrite {
+ public:
+ CFGAS_FileWrite(IFX_Stream* pStream, FX_BOOL bReleaseStream);
+ virtual ~CFGAS_FileWrite();
+ virtual void Release() { delete this; }
+ virtual FX_FILESIZE GetSize();
+ virtual FX_BOOL Flush();
+ virtual FX_BOOL WriteBlock(const void* pData, size_t size);
+ virtual FX_BOOL WriteBlock(const void* pData,
+ FX_FILESIZE offset,
+ size_t size);
+
+ protected:
+ IFX_Stream* m_pStream;
+ FX_BOOL m_bReleaseStream;
+};
+
+} // namespace
+
+IFX_Stream* IFX_Stream::CreateStream(IFX_BufferRead* pBufferRead,
+ FX_DWORD dwAccess,
+ int32_t iFileSize,
+ FX_BOOL bReleaseBufferRead) {
+ CFX_Stream* pSR = new CFX_Stream;
+ if (!pSR->LoadBufferRead(pBufferRead, iFileSize, dwAccess,
+ bReleaseBufferRead)) {
+ pSR->Release();
+ return NULL;
+ }
+ if (dwAccess & FX_STREAMACCESS_Text) {
+ return new CFX_TextStream(pSR, TRUE);
+ }
+ return pSR;
+}
+IFX_Stream* IFX_Stream::CreateStream(IFX_FileRead* pFileRead,
+ FX_DWORD dwAccess) {
+ CFX_Stream* pSR = new CFX_Stream;
+ if (!pSR->LoadFileRead(pFileRead, dwAccess)) {
+ pSR->Release();
+ return NULL;
+ }
+ if (dwAccess & FX_STREAMACCESS_Text) {
+ return new CFX_TextStream(pSR, TRUE);
+ }
+ return pSR;
+}
+IFX_Stream* IFX_Stream::CreateStream(IFX_FileWrite* pFileWrite,
+ FX_DWORD dwAccess) {
+ CFX_Stream* pSR = new CFX_Stream;
+ if (!pSR->LoadFileWrite(pFileWrite, dwAccess)) {
+ pSR->Release();
+ return NULL;
+ }
+ if (dwAccess & FX_STREAMACCESS_Text) {
+ return new CFX_TextStream(pSR, TRUE);
+ }
+ return pSR;
+}
+IFX_Stream* IFX_Stream::CreateStream(const FX_WCHAR* pszFileName,
+ FX_DWORD dwAccess) {
+ CFX_Stream* pSR = new CFX_Stream;
+ if (!pSR->LoadFile(pszFileName, dwAccess)) {
+ pSR->Release();
+ return NULL;
+ }
+ if (dwAccess & FX_STREAMACCESS_Text) {
+ return new CFX_TextStream(pSR, TRUE);
+ }
+ return pSR;
+}
+IFX_Stream* IFX_Stream::CreateStream(uint8_t* pData,
+ int32_t length,
+ FX_DWORD dwAccess) {
+ CFX_Stream* pSR = new CFX_Stream;
+ if (!pSR->LoadBuffer(pData, length, dwAccess)) {
+ pSR->Release();
+ return NULL;
+ }
+ if (dwAccess & FX_STREAMACCESS_Text) {
+ return new CFX_TextStream(pSR, TRUE);
+ }
+ return pSR;
+}
+
+CFX_StreamImp::CFX_StreamImp() : m_dwAccess(0) {}
+CFX_FileStreamImp::CFX_FileStreamImp()
+ : CFX_StreamImp(), m_hFile(NULL), m_iLength(0) {}
+CFX_FileStreamImp::~CFX_FileStreamImp() {
+ if (m_hFile != NULL) {
+ FXSYS_fclose(m_hFile);
+ }
+}
+FX_BOOL CFX_FileStreamImp::LoadFile(const FX_WCHAR* pszSrcFileName,
+ FX_DWORD dwAccess) {
+ FXSYS_assert(m_hFile == NULL);
+ FXSYS_assert(pszSrcFileName != NULL && FXSYS_wcslen(pszSrcFileName) > 0);
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || \
+ _FX_OS_ == _FX_WIN64_
+ CFX_WideString wsMode;
+ if (dwAccess & FX_STREAMACCESS_Write) {
+ if (dwAccess & FX_STREAMACCESS_Append) {
+ wsMode = L"a+b";
+ } else if (dwAccess & FX_STREAMACCESS_Truncate) {
+ wsMode = L"w+b";
+ } else {
+ wsMode = L"r+b";
+ }
+ } else {
+ wsMode = L"rb";
+ }
+ m_hFile = FXSYS_wfopen(pszSrcFileName, wsMode);
+
+ if (!m_hFile) {
+ if (dwAccess & FX_STREAMACCESS_Write) {
+ if (dwAccess & FX_STREAMACCESS_Create)
+ m_hFile = FXSYS_wfopen(pszSrcFileName, L"w+b");
+
+ if (!m_hFile) {
+ m_hFile = FXSYS_wfopen(pszSrcFileName, L"r+b");
+ if (!m_hFile)
+ return FALSE;
+
+ if (dwAccess & FX_STREAMACCESS_Truncate)
+ FX_fsetsize(m_hFile, 0);
+ }
+ } else {
+ return FALSE;
+ }
+ }
+#else
+ CFX_ByteString wsMode;
+ if (dwAccess & FX_STREAMACCESS_Write) {
+ if (dwAccess & FX_STREAMACCESS_Append) {
+ wsMode = "a+b";
+ } else if (dwAccess & FX_STREAMACCESS_Truncate) {
+ wsMode = "w+b";
+ } else {
+ wsMode = "r+b";
+ }
+ } else {
+ wsMode = "rb";
+ }
+ CFX_ByteString szFileName = CFX_ByteString::FromUnicode(pszSrcFileName);
+ m_hFile = FXSYS_fopen(szFileName, wsMode);
+ if (m_hFile == NULL) {
+ if (dwAccess & FX_STREAMACCESS_Write) {
+ if (dwAccess & FX_STREAMACCESS_Create) {
+ m_hFile = FXSYS_fopen(szFileName, "w+b");
+ }
+ if (m_hFile == NULL) {
+ m_hFile = FXSYS_fopen(szFileName, "r+b");
+ if (m_hFile == NULL) {
+ return FALSE;
+ }
+ if (dwAccess & FX_STREAMACCESS_Truncate) {
+ FX_fsetsize(m_hFile, 0);
+ }
+ }
+ } else {
+ return FALSE;
+ }
+ }
+#endif
+ m_dwAccess = dwAccess;
+ if ((dwAccess & (FX_STREAMACCESS_Write | FX_STREAMACCESS_Truncate)) ==
+ (FX_STREAMACCESS_Write | FX_STREAMACCESS_Truncate)) {
+ m_iLength = 0;
+ } else {
+ m_iLength = FX_filelength(m_hFile);
+ }
+ return TRUE;
+}
+int32_t CFX_FileStreamImp::GetLength() const {
+ FXSYS_assert(m_hFile != NULL);
+ return m_iLength;
+}
+int32_t CFX_FileStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
+ FXSYS_assert(m_hFile != NULL);
+ FXSYS_fseek(m_hFile, iOffset, eSeek);
+ return FXSYS_ftell(m_hFile);
+}
+int32_t CFX_FileStreamImp::GetPosition() {
+ FXSYS_assert(m_hFile != NULL);
+ return FXSYS_ftell(m_hFile);
+}
+FX_BOOL CFX_FileStreamImp::IsEOF() const {
+ FXSYS_assert(m_hFile != NULL);
+ return FXSYS_ftell(m_hFile) >= m_iLength;
+}
+int32_t CFX_FileStreamImp::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
+ FXSYS_assert(m_hFile != NULL);
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ return FXSYS_fread(pBuffer, 1, iBufferSize, m_hFile);
+}
+int32_t CFX_FileStreamImp::ReadString(FX_WCHAR* pStr,
+ int32_t iMaxLength,
+ FX_BOOL& bEOS) {
+ FXSYS_assert(m_hFile != NULL);
+ FXSYS_assert(pStr != NULL && iMaxLength > 0);
+ if (m_iLength <= 0) {
+ return 0;
+ }
+ int32_t iPosition = FXSYS_ftell(m_hFile);
+ int32_t iLen = std::min((m_iLength - iPosition) / 2, iMaxLength);
+ if (iLen <= 0) {
+ return 0;
+ }
+ iLen = FXSYS_fread(pStr, 2, iLen, m_hFile);
+ int32_t iCount = 0;
+ while (*pStr != L'\0' && iCount < iLen) {
+ pStr++, iCount++;
+ }
+ iPosition += iCount * 2;
+ if (FXSYS_ftell(m_hFile) != iPosition) {
+ FXSYS_fseek(m_hFile, iPosition, 0);
+ }
+ bEOS = (iPosition >= m_iLength);
+ return iCount;
+}
+int32_t CFX_FileStreamImp::WriteData(const uint8_t* pBuffer,
+ int32_t iBufferSize) {
+ FXSYS_assert(m_hFile != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ int32_t iRet = FXSYS_fwrite(pBuffer, 1, iBufferSize, m_hFile);
+ if (iRet != 0) {
+ int32_t iPos = FXSYS_ftell(m_hFile);
+ if (iPos > m_iLength) {
+ m_iLength = iPos;
+ }
+ }
+ return iRet;
+}
+int32_t CFX_FileStreamImp::WriteString(const FX_WCHAR* pStr, int32_t iLength) {
+ FXSYS_assert(m_hFile != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
+ FXSYS_assert(pStr != NULL && iLength > 0);
+ int32_t iRet = FXSYS_fwrite(pStr, 2, iLength, m_hFile);
+ if (iRet != 0) {
+ int32_t iPos = FXSYS_ftell(m_hFile);
+ if (iPos > m_iLength) {
+ m_iLength = iPos;
+ }
+ }
+ return iRet;
+}
+void CFX_FileStreamImp::Flush() {
+ FXSYS_assert(m_hFile != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
+ FXSYS_fflush(m_hFile);
+}
+FX_BOOL CFX_FileStreamImp::SetLength(int32_t iLength) {
+ FXSYS_assert(m_hFile != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
+ FX_BOOL bRet = FX_fsetsize(m_hFile, iLength);
+ m_iLength = FX_filelength(m_hFile);
+ return bRet;
+}
+CFX_FileReadStreamImp::CFX_FileReadStreamImp()
+ : m_pFileRead(NULL), m_iPosition(0), m_iLength(0) {}
+FX_BOOL CFX_FileReadStreamImp::LoadFileRead(IFX_FileRead* pFileRead,
+ FX_DWORD dwAccess) {
+ FXSYS_assert(m_pFileRead == NULL && pFileRead != NULL);
+ if (dwAccess & FX_STREAMACCESS_Write) {
+ return FALSE;
+ }
+ m_pFileRead = pFileRead;
+ m_iLength = m_pFileRead->GetSize();
+ return TRUE;
+}
+int32_t CFX_FileReadStreamImp::GetLength() const {
+ return m_iLength;
+}
+int32_t CFX_FileReadStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
+ switch (eSeek) {
+ case FX_STREAMSEEK_Begin:
+ m_iPosition = iOffset;
+ break;
+ case FX_STREAMSEEK_Current:
+ m_iPosition += iOffset;
+ break;
+ case FX_STREAMSEEK_End:
+ m_iPosition = m_iLength + iOffset;
+ break;
+ }
+ if (m_iPosition < 0) {
+ m_iPosition = 0;
+ } else if (m_iPosition >= m_iLength) {
+ m_iPosition = m_iLength;
+ }
+ return m_iPosition;
+}
+FX_BOOL CFX_FileReadStreamImp::IsEOF() const {
+ return m_iPosition >= m_iLength;
+}
+int32_t CFX_FileReadStreamImp::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
+ FXSYS_assert(m_pFileRead != NULL);
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ if (iBufferSize > m_iLength - m_iPosition) {
+ iBufferSize = m_iLength - m_iPosition;
+ }
+ if (m_pFileRead->ReadBlock(pBuffer, m_iPosition, iBufferSize)) {
+ m_iPosition += iBufferSize;
+ return iBufferSize;
+ }
+ return 0;
+}
+int32_t CFX_FileReadStreamImp::ReadString(FX_WCHAR* pStr,
+ int32_t iMaxLength,
+ FX_BOOL& bEOS) {
+ FXSYS_assert(m_pFileRead != NULL);
+ FXSYS_assert(pStr != NULL && iMaxLength > 0);
+ iMaxLength = ReadData((uint8_t*)pStr, iMaxLength * 2) / 2;
+ if (iMaxLength <= 0) {
+ return 0;
+ }
+ int32_t i = 0;
+ while (i < iMaxLength && pStr[i] != L'\0') {
+ ++i;
+ }
+ bEOS = (m_iPosition >= m_iLength) || pStr[i] == L'\0';
+ return i;
+}
+CFX_BufferReadStreamImp::CFX_BufferReadStreamImp()
+ : m_pBufferRead(NULL),
+ m_bReleaseBufferRead(FALSE),
+ m_iPosition(0),
+ m_iBufferSize(0) {}
+CFX_BufferReadStreamImp::~CFX_BufferReadStreamImp() {
+ if (m_bReleaseBufferRead && m_pBufferRead != NULL) {
+ m_pBufferRead->Release();
+ }
+}
+FX_BOOL CFX_BufferReadStreamImp::LoadBufferRead(IFX_BufferRead* pBufferRead,
+ int32_t iFileSize,
+ FX_DWORD dwAccess,
+ FX_BOOL bReleaseBufferRead) {
+ FXSYS_assert(m_pBufferRead == NULL && pBufferRead != NULL);
+ if (dwAccess & FX_STREAMACCESS_Write) {
+ return FALSE;
+ }
+ m_bReleaseBufferRead = bReleaseBufferRead;
+ m_pBufferRead = pBufferRead;
+ m_iBufferSize = iFileSize;
+ if (m_iBufferSize >= 0) {
+ return TRUE;
+ }
+ if (!m_pBufferRead->ReadNextBlock(TRUE)) {
+ return FALSE;
+ }
+ m_iBufferSize = m_pBufferRead->GetBlockSize();
+ while (!m_pBufferRead->IsEOF()) {
+ m_pBufferRead->ReadNextBlock(FALSE);
+ m_iBufferSize += m_pBufferRead->GetBlockSize();
+ }
+ return TRUE;
+}
+int32_t CFX_BufferReadStreamImp::GetLength() const {
+ return m_iBufferSize;
+}
+int32_t CFX_BufferReadStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
+ int32_t iLength = GetLength();
+ switch (eSeek) {
+ case FX_STREAMSEEK_Begin:
+ m_iPosition = iOffset;
+ break;
+ case FX_STREAMSEEK_Current:
+ m_iPosition += iOffset;
+ break;
+ case FX_STREAMSEEK_End:
+ m_iPosition = iLength + iOffset;
+ break;
+ }
+ if (m_iPosition < 0) {
+ m_iPosition = 0;
+ } else if (m_iPosition >= iLength) {
+ m_iPosition = iLength;
+ }
+ return m_iPosition;
+}
+FX_BOOL CFX_BufferReadStreamImp::IsEOF() const {
+ return m_pBufferRead ? m_pBufferRead->IsEOF() : TRUE;
+}
+int32_t CFX_BufferReadStreamImp::ReadData(uint8_t* pBuffer,
+ int32_t iBufferSize) {
+ FXSYS_assert(m_pBufferRead != NULL);
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ int32_t iLength = GetLength();
+ if (m_iPosition >= iLength) {
+ return 0;
+ }
+ if (iBufferSize > iLength - m_iPosition) {
+ iBufferSize = iLength - m_iPosition;
+ }
+ FX_DWORD dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ FX_DWORD dwBlockSize = m_pBufferRead->GetBlockSize();
+ if (m_iPosition < (int32_t)dwBlockOffset) {
+ if (!m_pBufferRead->ReadNextBlock(TRUE)) {
+ return 0;
+ }
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ }
+ while (m_iPosition < (int32_t)dwBlockOffset ||
+ m_iPosition >= (int32_t)(dwBlockOffset + dwBlockSize)) {
+ if (m_pBufferRead->IsEOF() || !m_pBufferRead->ReadNextBlock(FALSE)) {
+ break;
+ }
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ }
+ if (m_iPosition < (int32_t)dwBlockOffset ||
+ m_iPosition >= (int32_t)(dwBlockOffset + dwBlockSize)) {
+ return 0;
+ }
+ const uint8_t* pBufferTmp = m_pBufferRead->GetBlockBuffer();
+ FX_DWORD dwOffsetTmp = m_iPosition - dwBlockOffset;
+ FX_DWORD dwCopySize =
+ std::min(iBufferSize, (int32_t)(dwBlockSize - dwOffsetTmp));
+ FXSYS_memcpy(pBuffer, pBufferTmp + dwOffsetTmp, dwCopySize);
+ dwOffsetTmp = dwCopySize;
+ iBufferSize -= dwCopySize;
+ while (iBufferSize > 0) {
+ if (!m_pBufferRead->ReadNextBlock(FALSE)) {
+ break;
+ }
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ pBufferTmp = m_pBufferRead->GetBlockBuffer();
+ dwCopySize = std::min((FX_DWORD)iBufferSize, dwBlockSize);
+ FXSYS_memcpy(pBuffer + dwOffsetTmp, pBufferTmp, dwCopySize);
+ dwOffsetTmp += dwCopySize;
+ iBufferSize -= dwCopySize;
+ }
+ m_iPosition += dwOffsetTmp;
+ return dwOffsetTmp;
+}
+int32_t CFX_BufferReadStreamImp::ReadString(FX_WCHAR* pStr,
+ int32_t iMaxLength,
+ FX_BOOL& bEOS) {
+ FXSYS_assert(m_pBufferRead != NULL);
+ FXSYS_assert(pStr != NULL && iMaxLength > 0);
+ iMaxLength = ReadData((uint8_t*)pStr, iMaxLength * 2) / 2;
+ if (iMaxLength <= 0) {
+ return 0;
+ }
+ int32_t i = 0;
+ while (i < iMaxLength && pStr[i] != L'\0') {
+ ++i;
+ }
+ bEOS = (m_iPosition >= GetLength()) || pStr[i] == L'\0';
+ return i;
+}
+CFX_FileWriteStreamImp::CFX_FileWriteStreamImp()
+ : m_pFileWrite(NULL), m_iPosition(0) {}
+FX_BOOL CFX_FileWriteStreamImp::LoadFileWrite(IFX_FileWrite* pFileWrite,
+ FX_DWORD dwAccess) {
+ FXSYS_assert(m_pFileWrite == NULL && pFileWrite != NULL);
+ if (dwAccess & FX_STREAMACCESS_Read) {
+ return FALSE;
+ }
+ if (dwAccess & FX_STREAMACCESS_Append) {
+ m_iPosition = pFileWrite->GetSize();
+ }
+ m_pFileWrite = pFileWrite;
+ return TRUE;
+}
+int32_t CFX_FileWriteStreamImp::GetLength() const {
+ if (!m_pFileWrite) {
+ return 0;
+ }
+ return (int32_t)m_pFileWrite->GetSize();
+}
+int32_t CFX_FileWriteStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
+ int32_t iLength = GetLength();
+ switch (eSeek) {
+ case FX_STREAMSEEK_Begin:
+ m_iPosition = iOffset;
+ break;
+ case FX_STREAMSEEK_Current:
+ m_iPosition += iOffset;
+ break;
+ case FX_STREAMSEEK_End:
+ m_iPosition = iLength + iOffset;
+ break;
+ }
+ if (m_iPosition < 0) {
+ m_iPosition = 0;
+ } else if (m_iPosition >= iLength) {
+ m_iPosition = iLength;
+ }
+ return m_iPosition;
+}
+FX_BOOL CFX_FileWriteStreamImp::IsEOF() const {
+ return m_iPosition >= GetLength();
+}
+int32_t CFX_FileWriteStreamImp::WriteData(const uint8_t* pBuffer,
+ int32_t iBufferSize) {
+ if (!m_pFileWrite) {
+ return 0;
+ }
+ if (m_pFileWrite->WriteBlock(pBuffer, m_iPosition, iBufferSize)) {
+ m_iPosition += iBufferSize;
+ }
+ return iBufferSize;
+}
+int32_t CFX_FileWriteStreamImp::WriteString(const FX_WCHAR* pStr,
+ int32_t iLength) {
+ return WriteData((const uint8_t*)pStr, iLength * sizeof(FX_WCHAR));
+}
+void CFX_FileWriteStreamImp::Flush() {
+ if (m_pFileWrite) {
+ m_pFileWrite->Flush();
+ }
+}
+CFX_BufferStreamImp::CFX_BufferStreamImp()
+ : CFX_StreamImp(),
+ m_pData(NULL),
+ m_iTotalSize(0),
+ m_iPosition(0),
+ m_iLength(0) {}
+FX_BOOL CFX_BufferStreamImp::LoadBuffer(uint8_t* pData,
+ int32_t iTotalSize,
+ FX_DWORD dwAccess) {
+ FXSYS_assert(m_pData == NULL);
+ FXSYS_assert(pData != NULL && iTotalSize > 0);
+ m_dwAccess = dwAccess;
+ m_pData = pData;
+ m_iTotalSize = iTotalSize;
+ m_iPosition = 0;
+ m_iLength = (dwAccess & FX_STREAMACCESS_Write) != 0 ? 0 : iTotalSize;
+ return TRUE;
+}
+int32_t CFX_BufferStreamImp::GetLength() const {
+ FXSYS_assert(m_pData != NULL);
+ return m_iLength;
+}
+int32_t CFX_BufferStreamImp::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
+ FXSYS_assert(m_pData != NULL);
+ if (eSeek == FX_STREAMSEEK_Begin) {
+ m_iPosition = iOffset;
+ } else if (eSeek == FX_STREAMSEEK_Current) {
+ m_iPosition += iOffset;
+ } else if (eSeek == FX_STREAMSEEK_End) {
+ m_iPosition = m_iLength + iOffset;
+ }
+ if (m_iPosition > m_iLength) {
+ m_iPosition = m_iLength;
+ }
+ if (m_iPosition < 0) {
+ m_iPosition = 0;
+ }
+ return m_iPosition;
+}
+int32_t CFX_BufferStreamImp::GetPosition() {
+ FXSYS_assert(m_pData != NULL);
+ return m_iPosition;
+}
+FX_BOOL CFX_BufferStreamImp::IsEOF() const {
+ FXSYS_assert(m_pData != NULL);
+ return m_iPosition >= m_iLength;
+}
+int32_t CFX_BufferStreamImp::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
+ FXSYS_assert(m_pData != NULL);
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ int32_t iLen = std::min(m_iLength - m_iPosition, iBufferSize);
+ if (iLen <= 0) {
+ return 0;
+ }
+ FXSYS_memcpy(pBuffer, m_pData + m_iPosition, iLen);
+ m_iPosition += iLen;
+ return iLen;
+}
+int32_t CFX_BufferStreamImp::ReadString(FX_WCHAR* pStr,
+ int32_t iMaxLength,
+ FX_BOOL& bEOS) {
+ FXSYS_assert(m_pData != NULL);
+ FXSYS_assert(pStr != NULL && iMaxLength > 0);
+ int32_t iLen = std::min((m_iLength - m_iPosition) / 2, iMaxLength);
+ if (iLen <= 0) {
+ return 0;
+ }
+ const FX_WCHAR* pSrc = (const FX_WCHAR*)(FX_CHAR*)(m_pData + m_iPosition);
+ int32_t iCount = 0;
+ while (*pSrc != L'\0' && iCount < iLen) {
+ *pStr++ = *pSrc++, iCount++;
+ }
+ m_iPosition += iCount * 2;
+ bEOS = (*pSrc == L'\0') || (m_iPosition >= m_iLength);
+ return iCount;
+}
+int32_t CFX_BufferStreamImp::WriteData(const uint8_t* pBuffer,
+ int32_t iBufferSize) {
+ FXSYS_assert(m_pData != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ int32_t iLen = std::min(m_iTotalSize - m_iPosition, iBufferSize);
+ if (iLen <= 0) {
+ return 0;
+ }
+ FXSYS_memcpy(m_pData + m_iPosition, pBuffer, iLen);
+ m_iPosition += iLen;
+ if (m_iPosition > m_iLength) {
+ m_iLength = m_iPosition;
+ }
+ return iLen;
+}
+int32_t CFX_BufferStreamImp::WriteString(const FX_WCHAR* pStr,
+ int32_t iLength) {
+ FXSYS_assert(m_pData != NULL && (m_dwAccess & FX_STREAMACCESS_Write) != 0);
+ FXSYS_assert(pStr != NULL && iLength > 0);
+ int32_t iLen = std::min((m_iTotalSize - m_iPosition) / 2, iLength);
+ if (iLen <= 0) {
+ return 0;
+ }
+ FXSYS_memcpy(m_pData + m_iPosition, pStr, iLen * 2);
+ m_iPosition += iLen * 2;
+ if (m_iPosition > m_iLength) {
+ m_iLength = m_iPosition;
+ }
+ return iLen;
+}
+IFX_Stream* IFX_Stream::CreateTextStream(IFX_Stream* pBaseStream,
+ FX_BOOL bDeleteOnRelease) {
+ FXSYS_assert(pBaseStream != NULL);
+ return new CFX_TextStream(pBaseStream, bDeleteOnRelease);
+}
+CFX_TextStream::CFX_TextStream(IFX_Stream* pStream, FX_BOOL bDelStream)
+ : m_wCodePage(FX_CODEPAGE_DefANSI),
+ m_wBOMLength(0),
+ m_dwBOM(0),
+ m_pBuf(NULL),
+ m_iBufSize(0),
+ m_bDelStream(bDelStream),
+ m_pStreamImp(pStream),
+ m_iRefCount(1) {
+ FXSYS_assert(m_pStreamImp != NULL);
+ m_pStreamImp->Retain();
+ InitStream();
+}
+CFX_TextStream::~CFX_TextStream() {
+ m_pStreamImp->Release();
+ if (m_bDelStream) {
+ m_pStreamImp->Release();
+ }
+ if (m_pBuf != NULL) {
+ FX_Free(m_pBuf);
+ }
+}
+void CFX_TextStream::InitStream() {
+ int32_t iPosition = m_pStreamImp->GetPosition();
+ m_pStreamImp->Seek(FX_STREAMSEEK_Begin, 0);
+ m_pStreamImp->ReadData((uint8_t*)&m_dwBOM, 3);
+#if _FX_ENDIAN_ == _FX_LITTLE_ENDIAN_
+ m_dwBOM &= 0x00FFFFFF;
+ if (m_dwBOM == 0x00BFBBEF) {
+ m_wBOMLength = 3;
+ m_wCodePage = FX_CODEPAGE_UTF8;
+ } else {
+ m_dwBOM &= 0x0000FFFF;
+ if (m_dwBOM == 0x0000FFFE) {
+ m_wBOMLength = 2;
+ m_wCodePage = FX_CODEPAGE_UTF16BE;
+ } else if (m_dwBOM == 0x0000FEFF) {
+ m_wBOMLength = 2;
+ m_wCodePage = FX_CODEPAGE_UTF16LE;
+ } else {
+ m_wBOMLength = 0;
+ m_dwBOM = 0;
+ m_wCodePage = FXSYS_GetACP();
+ }
+ }
+#else
+ m_dwBOM &= 0xFFFFFF00;
+ if (m_dwBOM == 0xEFBBBF00) {
+ m_wBOMLength = 3;
+ m_wCodePage = FX_CODEPAGE_UTF8;
+ } else {
+ m_dwBOM &= 0xFFFF0000;
+ if (m_dwBOM == 0xFEFF0000) {
+ m_wBOMLength = 2;
+ m_wCodePage = FX_CODEPAGE_UTF16BE;
+ } else if (m_dwBOM == 0xFFFE0000) {
+ m_wBOMLength = 2;
+ m_wCodePage = FX_CODEPAGE_UTF16LE;
+ } else {
+ m_wBOMLength = 0;
+ m_dwBOM = 0;
+ m_wCodePage = FXSYS_GetACP();
+ }
+ }
+#endif
+ m_pStreamImp->Seek(FX_STREAMSEEK_Begin, std::max(m_wBOMLength, iPosition));
+}
+void CFX_TextStream::Release() {
+ if (--m_iRefCount < 1) {
+ delete this;
+ }
+}
+IFX_Stream* CFX_TextStream::Retain() {
+ m_iRefCount++;
+ return this;
+}
+FX_DWORD CFX_TextStream::GetAccessModes() const {
+ return m_pStreamImp->GetAccessModes() | FX_STREAMACCESS_Text;
+}
+int32_t CFX_TextStream::GetLength() const {
+ return m_pStreamImp->GetLength();
+}
+int32_t CFX_TextStream::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
+ return m_pStreamImp->Seek(eSeek, iOffset);
+}
+int32_t CFX_TextStream::GetPosition() {
+ return m_pStreamImp->GetPosition();
+}
+FX_BOOL CFX_TextStream::IsEOF() const {
+ return m_pStreamImp->IsEOF();
+}
+int32_t CFX_TextStream::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
+ return m_pStreamImp->ReadData(pBuffer, iBufferSize);
+}
+int32_t CFX_TextStream::WriteData(const uint8_t* pBuffer, int32_t iBufferSize) {
+ return m_pStreamImp->WriteData(pBuffer, iBufferSize);
+}
+void CFX_TextStream::Flush() {
+ m_pStreamImp->Flush();
+}
+FX_BOOL CFX_TextStream::SetLength(int32_t iLength) {
+ return m_pStreamImp->SetLength(iLength);
+}
+FX_WORD CFX_TextStream::GetCodePage() const {
+ return m_wCodePage;
+}
+IFX_Stream* CFX_TextStream::CreateSharedStream(FX_DWORD dwAccess,
+ int32_t iOffset,
+ int32_t iLength) {
+ IFX_Stream* pSR =
+ m_pStreamImp->CreateSharedStream(dwAccess, iOffset, iLength);
+ if (pSR == NULL) {
+ return NULL;
+ }
+ if (dwAccess & FX_STREAMACCESS_Text) {
+ return new CFX_TextStream(pSR, TRUE);
+ }
+ return pSR;
+}
+int32_t CFX_TextStream::GetBOM(uint8_t bom[4]) const {
+ if (m_wBOMLength < 1) {
+ return 0;
+ }
+ *(FX_DWORD*)bom = m_dwBOM;
+ return m_wBOMLength;
+}
+FX_WORD CFX_TextStream::SetCodePage(FX_WORD wCodePage) {
+ if (m_wBOMLength > 0) {
+ return m_wCodePage;
+ }
+ FX_WORD v = m_wCodePage;
+ m_wCodePage = wCodePage;
+ return v;
+}
+int32_t CFX_TextStream::ReadString(FX_WCHAR* pStr,
+ int32_t iMaxLength,
+ FX_BOOL& bEOS,
+ int32_t const* pByteSize) {
+ FXSYS_assert(pStr != NULL && iMaxLength > 0);
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ int32_t iLen;
+ if (m_wCodePage == FX_CODEPAGE_UTF16LE ||
+ m_wCodePage == FX_CODEPAGE_UTF16BE) {
+ int32_t iBytes = pByteSize == NULL ? iMaxLength * 2 : *pByteSize;
+ iLen = m_pStreamImp->ReadData((uint8_t*)pStr, iBytes);
+ iMaxLength = iLen / 2;
+ if (sizeof(FX_WCHAR) > 2) {
+ FX_UTF16ToWChar(pStr, iMaxLength);
+ }
+#if _FX_ENDIAN_ == _FX_BIG_ENDIAN_
+ if (m_wCodePage == FX_CODEPAGE_UTF16LE) {
+ FX_SwapByteOrder(pStr, iMaxLength);
+ }
+#else
+ if (m_wCodePage == FX_CODEPAGE_UTF16BE) {
+ FX_SwapByteOrder(pStr, iMaxLength);
+ }
+#endif
+ } else {
+ int32_t pos = m_pStreamImp->GetPosition();
+ int32_t iBytes = pByteSize == NULL ? iMaxLength : *pByteSize;
+ iBytes = std::min(iBytes, m_pStreamImp->GetLength() - pos);
+ if (iBytes > 0) {
+ if (m_pBuf == NULL) {
+ m_pBuf = FX_Alloc(uint8_t, iBytes);
+ m_iBufSize = iBytes;
+ } else if (iBytes > m_iBufSize) {
+ m_pBuf = FX_Realloc(uint8_t, m_pBuf, iBytes);
+ m_iBufSize = iBytes;
+ }
+ iLen = m_pStreamImp->ReadData(m_pBuf, iBytes);
+ int32_t iSrc = iLen;
+ int32_t iDecode = FX_DecodeString(m_wCodePage, (const FX_CHAR*)m_pBuf,
+ &iSrc, pStr, &iMaxLength, TRUE);
+ m_pStreamImp->Seek(FX_STREAMSEEK_Current, iSrc - iLen);
+ if (iDecode < 1) {
+ return -1;
+ }
+ } else {
+ iMaxLength = 0;
+ }
+ }
+ bEOS = m_pStreamImp->IsEOF();
+ return iMaxLength;
+}
+int32_t CFX_TextStream::WriteString(const FX_WCHAR* pStr, int32_t iLength) {
+ FXSYS_assert(pStr != NULL && iLength > 0);
+ if ((m_pStreamImp->GetAccessModes() & FX_STREAMACCESS_Write) == 0) {
+ return -1;
+ }
+ if (m_wCodePage == FX_CODEPAGE_UTF8) {
+ int32_t len = iLength;
+ CFX_UTF8Encoder encoder;
+ while (len-- > 0) {
+ encoder.Input(*pStr++);
+ }
+ CFX_ByteStringC bsResult = encoder.GetResult();
+ m_pStreamImp->WriteData((const uint8_t*)bsResult.GetCStr(),
+ bsResult.GetLength());
+ }
+ return iLength;
+}
+CFX_Stream::CFX_Stream()
+ : m_eStreamType(FX_SREAMTYPE_Unknown),
+ m_pStreamImp(NULL),
+ m_dwAccess(0),
+ m_iTotalSize(0),
+ m_iPosition(0),
+ m_iStart(0),
+ m_iLength(0),
+ m_iRefCount(1) {}
+CFX_Stream::~CFX_Stream() {
+ if (m_eStreamType != FX_STREAMTYPE_Stream && m_pStreamImp != NULL) {
+ m_pStreamImp->Release();
+ }
+}
+FX_BOOL CFX_Stream::LoadFile(const FX_WCHAR* pszSrcFileName,
+ FX_DWORD dwAccess) {
+ if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
+ return FALSE;
+ }
+ if (pszSrcFileName == NULL || FXSYS_wcslen(pszSrcFileName) < 1) {
+ return FALSE;
+ }
+ m_pStreamImp = new CFX_FileStreamImp();
+ FX_BOOL bRet =
+ ((CFX_FileStreamImp*)m_pStreamImp)->LoadFile(pszSrcFileName, dwAccess);
+ if (!bRet) {
+ m_pStreamImp->Release();
+ m_pStreamImp = NULL;
+ } else {
+ m_eStreamType = FX_STREAMTYPE_File;
+ m_dwAccess = dwAccess;
+ m_iLength = m_pStreamImp->GetLength();
+ }
+ return bRet;
+}
+FX_BOOL CFX_Stream::LoadFileRead(IFX_FileRead* pFileRead, FX_DWORD dwAccess) {
+ if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
+ return FALSE;
+ }
+ if (pFileRead == NULL) {
+ return FALSE;
+ }
+ m_pStreamImp = new CFX_FileReadStreamImp();
+ FX_BOOL bRet =
+ ((CFX_FileReadStreamImp*)m_pStreamImp)->LoadFileRead(pFileRead, dwAccess);
+ if (!bRet) {
+ m_pStreamImp->Release();
+ m_pStreamImp = NULL;
+ } else {
+ m_eStreamType = FX_STREAMTYPE_File;
+ m_dwAccess = dwAccess;
+ m_iLength = m_pStreamImp->GetLength();
+ }
+ return bRet;
+}
+FX_BOOL CFX_Stream::LoadFileWrite(IFX_FileWrite* pFileWrite,
+ FX_DWORD dwAccess) {
+ if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
+ return FALSE;
+ }
+ if (pFileWrite == NULL) {
+ return FALSE;
+ }
+ m_pStreamImp = new CFX_FileWriteStreamImp();
+ FX_BOOL bRet = ((CFX_FileWriteStreamImp*)m_pStreamImp)
+ ->LoadFileWrite(pFileWrite, dwAccess);
+ if (!bRet) {
+ m_pStreamImp->Release();
+ m_pStreamImp = NULL;
+ } else {
+ m_eStreamType = FX_STREAMTYPE_File;
+ m_dwAccess = dwAccess;
+ m_iLength = m_pStreamImp->GetLength();
+ }
+ return bRet;
+}
+FX_BOOL CFX_Stream::LoadBuffer(uint8_t* pData,
+ int32_t iTotalSize,
+ FX_DWORD dwAccess) {
+ if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
+ return FALSE;
+ }
+ if (pData == NULL || iTotalSize < 1) {
+ return FALSE;
+ }
+ m_pStreamImp = new CFX_BufferStreamImp();
+ FX_BOOL bRet = ((CFX_BufferStreamImp*)m_pStreamImp)
+ ->LoadBuffer(pData, iTotalSize, dwAccess);
+ if (!bRet) {
+ m_pStreamImp->Release();
+ m_pStreamImp = NULL;
+ } else {
+ m_eStreamType = FX_STREAMTYPE_Buffer;
+ m_dwAccess = dwAccess;
+ m_iLength = m_pStreamImp->GetLength();
+ }
+ return bRet;
+}
+FX_BOOL CFX_Stream::LoadBufferRead(IFX_BufferRead* pBufferRead,
+ int32_t iFileSize,
+ FX_DWORD dwAccess,
+ FX_BOOL bReleaseBufferRead) {
+ if (m_eStreamType != FX_SREAMTYPE_Unknown || m_pStreamImp != NULL) {
+ return FALSE;
+ }
+ if (!pBufferRead) {
+ return FALSE;
+ }
+ m_pStreamImp = new CFX_BufferReadStreamImp;
+ FX_BOOL bRet = ((CFX_BufferReadStreamImp*)m_pStreamImp)
+ ->LoadBufferRead(pBufferRead, iFileSize, dwAccess,
+ bReleaseBufferRead);
+ if (!bRet) {
+ m_pStreamImp->Release();
+ m_pStreamImp = NULL;
+ } else {
+ m_eStreamType = FX_STREAMTYPE_BufferRead;
+ m_dwAccess = dwAccess;
+ m_iLength = m_pStreamImp->GetLength();
+ }
+ return bRet;
+}
+void CFX_Stream::Release() {
+ if (--m_iRefCount < 1) {
+ delete this;
+ }
+}
+IFX_Stream* CFX_Stream::Retain() {
+ m_iRefCount++;
+ return this;
+}
+int32_t CFX_Stream::GetLength() const {
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ if (m_eStreamType == FX_STREAMTYPE_File ||
+ m_eStreamType == FX_STREAMTYPE_Buffer) {
+ return m_pStreamImp->GetLength();
+ }
+ return m_iLength;
+}
+int32_t CFX_Stream::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ if (m_eStreamType == FX_STREAMTYPE_File ||
+ m_eStreamType == FX_STREAMTYPE_Buffer) {
+ return m_iPosition = m_pStreamImp->Seek(eSeek, iOffset);
+ }
+ int32_t iEnd = m_iStart + m_iLength;
+ int32_t iPosition = m_iStart + iOffset;
+ if (eSeek == FX_STREAMSEEK_Begin) {
+ m_iPosition = iPosition;
+ } else if (eSeek == FX_STREAMSEEK_Current) {
+ m_iPosition += iOffset;
+ } else if (eSeek == FX_STREAMSEEK_End) {
+ m_iPosition = iEnd + iOffset;
+ }
+ if (m_iPosition > iEnd) {
+ m_iPosition = iEnd;
+ }
+ if (m_iPosition < m_iStart) {
+ m_iPosition = m_iStart;
+ }
+ return m_iPosition - m_iStart;
+}
+int32_t CFX_Stream::GetPosition() {
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ if (m_eStreamType == FX_STREAMTYPE_File ||
+ m_eStreamType == FX_STREAMTYPE_Buffer) {
+ return m_iPosition = m_pStreamImp->GetPosition();
+ }
+ return m_iPosition - m_iStart;
+}
+FX_BOOL CFX_Stream::IsEOF() const {
+ if (m_pStreamImp == NULL) {
+ return TRUE;
+ }
+ if (m_eStreamType == FX_STREAMTYPE_File ||
+ m_eStreamType == FX_STREAMTYPE_Buffer) {
+ return m_pStreamImp->IsEOF();
+ }
+ return m_iPosition >= m_iStart + m_iLength;
+}
+int32_t CFX_Stream::ReadData(uint8_t* pBuffer, int32_t iBufferSize) {
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ int32_t iLen = std::min(m_iStart + m_iLength - m_iPosition, iBufferSize);
+ if (iLen <= 0) {
+ return 0;
+ }
+ if (m_pStreamImp->GetPosition() != m_iPosition) {
+ m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
+ }
+ iLen = m_pStreamImp->ReadData(pBuffer, iLen);
+ m_iPosition = m_pStreamImp->GetPosition();
+ return iLen;
+}
+int32_t CFX_Stream::ReadString(FX_WCHAR* pStr,
+ int32_t iMaxLength,
+ FX_BOOL& bEOS,
+ int32_t const* pByteSize) {
+ FXSYS_assert(pStr != NULL && iMaxLength > 0);
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ int32_t iEnd = m_iStart + m_iLength;
+ int32_t iLen = iEnd - m_iPosition;
+ if (pByteSize != NULL) {
+ iLen = std::min(iLen, *pByteSize);
+ }
+ iLen = std::min(iEnd / 2, iMaxLength);
+ if (iLen <= 0) {
+ return 0;
+ }
+ if (m_pStreamImp->GetPosition() != m_iPosition) {
+ m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
+ }
+ iLen = m_pStreamImp->ReadString(pStr, iLen, bEOS);
+ m_iPosition = m_pStreamImp->GetPosition();
+ if (iLen > 0 && m_iPosition >= iEnd) {
+ bEOS = TRUE;
+ }
+ return iLen;
+}
+int32_t CFX_Stream::WriteData(const uint8_t* pBuffer, int32_t iBufferSize) {
+ FXSYS_assert(pBuffer != NULL && iBufferSize > 0);
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
+ return -1;
+ }
+ int32_t iLen = iBufferSize;
+ if (m_eStreamType == FX_STREAMTYPE_Stream) {
+ iLen = std::min(m_iStart + m_iTotalSize - m_iPosition, iBufferSize);
+ if (iLen <= 0) {
+ return 0;
+ }
+ }
+ int32_t iEnd = m_iStart + m_iLength;
+ if (m_pStreamImp->GetPosition() != m_iPosition) {
+ m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
+ }
+ iLen = m_pStreamImp->WriteData(pBuffer, iLen);
+ m_iPosition = m_pStreamImp->GetPosition();
+ if (m_iPosition > iEnd) {
+ m_iLength = m_iPosition - m_iStart;
+ }
+ return iLen;
+}
+int32_t CFX_Stream::WriteString(const FX_WCHAR* pStr, int32_t iLength) {
+ FXSYS_assert(pStr != NULL && iLength > 0);
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
+ return -1;
+ }
+ int32_t iLen = iLength;
+ if (m_eStreamType == FX_STREAMTYPE_Stream) {
+ iLen = std::min((m_iStart + m_iTotalSize - m_iPosition) / 2, iLength);
+ if (iLen <= 0) {
+ return 0;
+ }
+ }
+ int32_t iEnd = m_iStart + m_iLength;
+ if (m_pStreamImp->GetPosition() != m_iPosition) {
+ m_pStreamImp->Seek(FX_STREAMSEEK_Begin, m_iPosition);
+ }
+ iLen = m_pStreamImp->WriteString(pStr, iLen);
+ m_iPosition = m_pStreamImp->GetPosition();
+ if (m_iPosition > iEnd) {
+ m_iLength = m_iPosition - m_iStart;
+ }
+ return iLen;
+}
+void CFX_Stream::Flush() {
+ if (m_pStreamImp == NULL) {
+ return;
+ }
+ if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
+ return;
+ }
+ m_pStreamImp->Flush();
+}
+FX_BOOL CFX_Stream::SetLength(int32_t iLength) {
+ if (m_pStreamImp == NULL) {
+ return FALSE;
+ }
+ if ((m_dwAccess & FX_STREAMACCESS_Write) == 0) {
+ return FALSE;
+ }
+ return m_pStreamImp->SetLength(iLength);
+}
+int32_t CFX_Stream::GetBOM(uint8_t bom[4]) const {
+ if (m_pStreamImp == NULL) {
+ return -1;
+ }
+ return 0;
+}
+FX_WORD CFX_Stream::GetCodePage() const {
+#if _FX_ENDIAN_ == _FX_LITTLE_ENDIAN_
+ return FX_CODEPAGE_UTF16LE;
+#else
+ return FX_CODEPAGE_UTF16BE;
+#endif
+}
+FX_WORD CFX_Stream::SetCodePage(FX_WORD wCodePage) {
+#if _FX_ENDIAN_ == _FX_LITTLE_ENDIAN_
+ return FX_CODEPAGE_UTF16LE;
+#else
+ return FX_CODEPAGE_UTF16BE;
+#endif
+}
+IFX_Stream* CFX_Stream::CreateSharedStream(FX_DWORD dwAccess,
+ int32_t iOffset,
+ int32_t iLength) {
+ FXSYS_assert(iLength > 0);
+ if (m_pStreamImp == NULL) {
+ return NULL;
+ }
+ if ((m_dwAccess & FX_STREAMACCESS_Text) != 0 &&
+ (dwAccess & FX_STREAMACCESS_Text) == 0) {
+ return NULL;
+ }
+ if ((m_dwAccess & FX_STREAMACCESS_Write) == 0 &&
+ (dwAccess & FX_STREAMACCESS_Write) != 0) {
+ return NULL;
+ }
+ int32_t iStart = m_iStart + iOffset;
+ int32_t iTotal = m_iStart + m_iLength;
+ if (iStart < m_iStart || iStart >= iTotal) {
+ return NULL;
+ }
+ int32_t iEnd = iStart + iLength;
+ if (iEnd < iStart || iEnd > iTotal) {
+ return NULL;
+ }
+ CFX_Stream* pShared = new CFX_Stream;
+ pShared->m_eStreamType = FX_STREAMTYPE_Stream;
+ pShared->m_pStreamImp = m_pStreamImp;
+ pShared->m_dwAccess = dwAccess;
+ pShared->m_iTotalSize = iLength;
+ pShared->m_iPosition = iStart;
+ pShared->m_iStart = iStart;
+ pShared->m_iLength = (dwAccess & FX_STREAMACCESS_Write) != 0 ? 0 : iLength;
+ if (dwAccess & FX_STREAMACCESS_Text) {
+ return IFX_Stream::CreateTextStream(pShared, TRUE);
+ }
+ return pShared;
+}
+IFX_FileRead* FX_CreateFileRead(IFX_Stream* pBaseStream,
+ FX_BOOL bReleaseStream) {
+ FXSYS_assert(pBaseStream != NULL);
+ return new CFGAS_FileRead(pBaseStream, bReleaseStream);
+}
+CFGAS_FileRead::CFGAS_FileRead(IFX_Stream* pStream, FX_BOOL bReleaseStream)
+ : m_bReleaseStream(bReleaseStream), m_pStream(pStream) {
+ FXSYS_assert(m_pStream != NULL);
+}
+CFGAS_FileRead::~CFGAS_FileRead() {
+ if (m_bReleaseStream) {
+ m_pStream->Release();
+ }
+}
+FX_FILESIZE CFGAS_FileRead::GetSize() {
+ return (FX_FILESIZE)m_pStream->GetLength();
+}
+FX_BOOL CFGAS_FileRead::ReadBlock(void* buffer,
+ FX_FILESIZE offset,
+ size_t size) {
+ m_pStream->Seek(FX_STREAMSEEK_Begin, (int32_t)offset);
+ int32_t iLen = m_pStream->ReadData((uint8_t*)buffer, (int32_t)size);
+ return iLen == (int32_t)size;
+}
+
+IFX_FileRead* FX_CreateFileRead(IFX_BufferRead* pBufferRead,
+ FX_FILESIZE iFileSize,
+ FX_BOOL bReleaseStream) {
+ if (!pBufferRead) {
+ return NULL;
+ }
+ return new CFX_BufferAccImp(pBufferRead, iFileSize, bReleaseStream);
+}
+CFX_BufferAccImp::CFX_BufferAccImp(IFX_BufferRead* pBufferRead,
+ FX_FILESIZE iFileSize,
+ FX_BOOL bReleaseStream)
+ : m_pBufferRead(pBufferRead),
+ m_bReleaseStream(bReleaseStream),
+ m_iBufSize(iFileSize) {
+ FXSYS_assert(m_pBufferRead);
+}
+CFX_BufferAccImp::~CFX_BufferAccImp() {
+ if (m_bReleaseStream && m_pBufferRead) {
+ m_pBufferRead->Release();
+ }
+}
+FX_FILESIZE CFX_BufferAccImp::GetSize() {
+ if (!m_pBufferRead) {
+ return 0;
+ }
+ if (m_iBufSize >= 0) {
+ return m_iBufSize;
+ }
+ if (!m_pBufferRead->ReadNextBlock(TRUE)) {
+ return 0;
+ }
+ m_iBufSize = (FX_FILESIZE)m_pBufferRead->GetBlockSize();
+ while (!m_pBufferRead->IsEOF()) {
+ m_pBufferRead->ReadNextBlock(FALSE);
+ m_iBufSize += (FX_FILESIZE)m_pBufferRead->GetBlockSize();
+ }
+ return m_iBufSize;
+}
+FX_BOOL CFX_BufferAccImp::ReadBlock(void* buffer,
+ FX_FILESIZE offset,
+ size_t size) {
+ if (!m_pBufferRead) {
+ return FALSE;
+ }
+ if (!buffer || !size) {
+ return TRUE;
+ }
+ FX_FILESIZE dwBufSize = GetSize();
+ if (offset >= dwBufSize) {
+ return FALSE;
+ }
+ size_t dwBlockSize = m_pBufferRead->GetBlockSize();
+ FX_FILESIZE dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ if (offset < dwBlockOffset) {
+ if (!m_pBufferRead->ReadNextBlock(TRUE)) {
+ return FALSE;
+ }
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ }
+ while (offset < dwBlockOffset ||
+ offset >= (FX_FILESIZE)(dwBlockOffset + dwBlockSize)) {
+ if (m_pBufferRead->IsEOF() || !m_pBufferRead->ReadNextBlock(FALSE)) {
+ break;
+ }
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ }
+ if (offset < dwBlockOffset ||
+ offset >= (FX_FILESIZE)(dwBlockOffset + dwBlockSize)) {
+ return FALSE;
+ }
+ const uint8_t* pBuffer = m_pBufferRead->GetBlockBuffer();
+ const FX_FILESIZE dwOffset = offset - dwBlockOffset;
+ size_t dwCopySize =
+ std::min(size, static_cast<size_t>(dwBlockSize - dwOffset));
+ FXSYS_memcpy(buffer, pBuffer + dwOffset, dwCopySize);
+ offset = dwCopySize;
+ size -= dwCopySize;
+ while (size) {
+ if (!m_pBufferRead->ReadNextBlock(FALSE)) {
+ break;
+ }
+ dwBlockOffset = m_pBufferRead->GetBlockOffset();
+ dwBlockSize = m_pBufferRead->GetBlockSize();
+ pBuffer = m_pBufferRead->GetBlockBuffer();
+ dwCopySize = std::min(size, dwBlockSize);
+ FXSYS_memcpy(((uint8_t*)buffer) + offset, pBuffer, dwCopySize);
+ offset += dwCopySize;
+ size -= dwCopySize;
+ }
+ return TRUE;
+}
+
+IFX_FileWrite* FX_CreateFileWrite(IFX_Stream* pBaseStream,
+ FX_BOOL bReleaseStream) {
+ FXSYS_assert(pBaseStream != NULL);
+ return new CFGAS_FileWrite(pBaseStream, bReleaseStream);
+}
+
+CFGAS_FileWrite::CFGAS_FileWrite(IFX_Stream* pStream, FX_BOOL bReleaseStream)
+ : m_pStream(pStream), m_bReleaseStream(bReleaseStream) {
+ FXSYS_assert(m_pStream != NULL);
+}
+CFGAS_FileWrite::~CFGAS_FileWrite() {
+ if (m_bReleaseStream) {
+ m_pStream->Release();
+ }
+}
+FX_FILESIZE CFGAS_FileWrite::GetSize() {
+ return m_pStream->GetLength();
+}
+FX_BOOL CFGAS_FileWrite::Flush() {
+ m_pStream->Flush();
+ return TRUE;
+}
+FX_BOOL CFGAS_FileWrite::WriteBlock(const void* pData, size_t size) {
+ return m_pStream->WriteData((const uint8_t*)pData, (int32_t)size) ==
+ (int32_t)size;
+}
+FX_BOOL CFGAS_FileWrite::WriteBlock(const void* pData,
+ FX_FILESIZE offset,
+ size_t size) {
+ m_pStream->Seek(FX_STREAMSEEK_Begin, offset);
+ int32_t iLen = m_pStream->WriteData((uint8_t*)pData, (int32_t)size);
+ return iLen == (int32_t)size;
+}
diff --git a/xfa/src/fgas/crt/fgas_stream.h b/xfa/src/fgas/crt/fgas_stream.h
new file mode 100644
index 0000000000..cc40a76cc6
--- /dev/null
+++ b/xfa/src/fgas/crt/fgas_stream.h
@@ -0,0 +1,78 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_CRT_FGAS_STREAM_H_
+#define XFA_SRC_FGAS_CRT_FGAS_STREAM_H_
+
+#include "core/include/fxcrt/fx_stream.h"
+#include "core/include/fxcrt/fx_system.h"
+
+class IFX_Stream;
+
+IFX_FileRead* FX_CreateFileRead(IFX_Stream* pBaseStream,
+ FX_BOOL bReleaseStream = FALSE);
+IFX_FileRead* FX_CreateFileRead(IFX_BufferRead* pBufferRead,
+ FX_FILESIZE iFileSize = -1,
+ FX_BOOL bReleaseStream = TRUE);
+IFX_FileWrite* FX_CreateFileWrite(IFX_Stream* pBaseStream,
+ FX_BOOL bReleaseStream = FALSE);
+enum FX_STREAMACCESS {
+ FX_STREAMACCESS_Binary = 0x00,
+ FX_STREAMACCESS_Text = 0x01,
+ FX_STREAMACCESS_Read = 0x02,
+ FX_STREAMACCESS_Write = 0x04,
+ FX_STREAMACCESS_Truncate = 0x10,
+ FX_STREAMACCESS_Append = 0x20,
+ FX_STREAMACCESS_Create = 0x80,
+};
+
+enum FX_STREAMSEEK {
+ FX_STREAMSEEK_Begin = 0,
+ FX_STREAMSEEK_Current,
+ FX_STREAMSEEK_End,
+};
+
+class IFX_Stream {
+ public:
+ static IFX_Stream* CreateStream(IFX_FileRead* pFileRead, FX_DWORD dwAccess);
+ static IFX_Stream* CreateStream(IFX_FileWrite* pFileWrite, FX_DWORD dwAccess);
+ static IFX_Stream* CreateStream(const FX_WCHAR* pszFileName,
+ FX_DWORD dwAccess);
+ static IFX_Stream* CreateStream(uint8_t* pData,
+ int32_t length,
+ FX_DWORD dwAccess);
+ static IFX_Stream* CreateStream(IFX_BufferRead* pBufferRead,
+ FX_DWORD dwAccess,
+ int32_t iFileSize = -1,
+ FX_BOOL bReleaseBufferRead = TRUE);
+ static IFX_Stream* CreateTextStream(IFX_Stream* pBaseStream,
+ FX_BOOL bDeleteOnRelease);
+ virtual ~IFX_Stream() {}
+ virtual void Release() = 0;
+ virtual IFX_Stream* Retain() = 0;
+ virtual FX_DWORD GetAccessModes() const = 0;
+ virtual int32_t GetLength() const = 0;
+ virtual int32_t Seek(FX_STREAMSEEK eSeek, int32_t iOffset) = 0;
+ virtual int32_t GetPosition() = 0;
+ virtual FX_BOOL IsEOF() const = 0;
+ virtual int32_t ReadData(uint8_t* pBuffer, int32_t iBufferSize) = 0;
+ virtual int32_t ReadString(FX_WCHAR* pStr,
+ int32_t iMaxLength,
+ FX_BOOL& bEOS,
+ int32_t const* pByteSize = NULL) = 0;
+ virtual int32_t WriteData(const uint8_t* pBuffer, int32_t iBufferSize) = 0;
+ virtual int32_t WriteString(const FX_WCHAR* pStr, int32_t iLength) = 0;
+ virtual void Flush() = 0;
+ virtual FX_BOOL SetLength(int32_t iLength) = 0;
+ virtual int32_t GetBOM(uint8_t bom[4]) const = 0;
+ virtual FX_WORD GetCodePage() const = 0;
+ virtual FX_WORD SetCodePage(FX_WORD wCodePage) = 0;
+ virtual IFX_Stream* CreateSharedStream(FX_DWORD dwAccess,
+ int32_t iOffset,
+ int32_t iLength) = 0;
+};
+
+#endif // XFA_SRC_FGAS_CRT_FGAS_STREAM_H_
diff --git a/xfa/src/fgas/crt/fgas_system.cpp b/xfa/src/fgas/crt/fgas_system.cpp
new file mode 100644
index 0000000000..a4ca7546e0
--- /dev/null
+++ b/xfa/src/fgas/crt/fgas_system.cpp
@@ -0,0 +1,117 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/src/fgas/crt/fgas_system.h"
+
+#include <algorithm>
+
+#include "core/include/fxcrt/fx_system.h"
+
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || \
+ _FX_OS_ == _FX_WIN64_
+#include <io.h>
+#elif _FX_OS_ == _FX_LINUX_DESKTOP_ || _FX_OS_ == _FX_LINUX_Mini_
+#include <sys/times.h>
+#endif
+
+namespace {
+
+inline FX_BOOL FX_isupper(int32_t ch) {
+ return ch >= 'A' && ch <= 'Z';
+}
+
+inline int32_t FX_tolower(int32_t ch) {
+ return FX_isupper(ch) ? (ch + 0x20) : ch;
+}
+
+} // namespace
+
+int32_t FX_wcsnicmp(const FX_WCHAR* s1, const FX_WCHAR* s2, size_t count) {
+ FXSYS_assert(s1 != NULL && s2 != NULL && count > 0);
+ FX_WCHAR wch1 = 0, wch2 = 0;
+ while (count-- > 0) {
+ wch1 = (FX_WCHAR)FX_tolower(*s1++);
+ wch2 = (FX_WCHAR)FX_tolower(*s2++);
+ if (wch1 != wch2) {
+ break;
+ }
+ }
+ return wch1 - wch2;
+}
+
+int32_t FX_filelength(FXSYS_FILE* file) {
+ FXSYS_assert(file != NULL);
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_
+ return _filelength(_fileno(file));
+#else
+ int32_t iPos = FXSYS_ftell(file);
+ FXSYS_fseek(file, 0, FXSYS_SEEK_END);
+ int32_t iLen = FXSYS_ftell(file);
+ FXSYS_fseek(file, iPos, FXSYS_SEEK_SET);
+ return iLen;
+#endif
+}
+
+FX_BOOL FX_fsetsize(FXSYS_FILE* file, int32_t size) {
+ FXSYS_assert(file != NULL);
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_
+ return _chsize(_fileno(file), size) == 0;
+#elif _FX_OS_ == _FX_WIN32_MOBILE_
+ HANDLE hFile = _fileno(file);
+ FX_DWORD dwPos = ::SetFilePointer(hFile, 0, 0, FILE_CURRENT);
+ ::SetFilePointer(hFile, size, 0, FILE_BEGIN);
+ FX_BOOL bRet = ::SetEndOfFile(hFile);
+ ::SetFilePointer(hFile, (int32_t)dwPos, 0, FILE_BEGIN);
+ return bRet;
+#else
+ return FALSE;
+#endif
+}
+
+FX_FLOAT FX_wcstof(const FX_WCHAR* pwsStr, int32_t iLength, int32_t* pUsedLen) {
+ FXSYS_assert(pwsStr != NULL);
+ if (iLength < 0) {
+ iLength = FXSYS_wcslen(pwsStr);
+ }
+ if (iLength == 0) {
+ return 0.0f;
+ }
+ int32_t iUsedLen = 0;
+ FX_BOOL bNegtive = FALSE;
+ switch (pwsStr[iUsedLen]) {
+ case '-':
+ bNegtive = TRUE;
+ case '+':
+ iUsedLen++;
+ break;
+ }
+ FX_FLOAT fValue = 0.0f;
+ while (iUsedLen < iLength) {
+ FX_WCHAR wch = pwsStr[iUsedLen];
+ if (wch >= L'0' && wch <= L'9') {
+ fValue = fValue * 10.0f + (wch - L'0');
+ } else {
+ break;
+ }
+ iUsedLen++;
+ }
+ if (iUsedLen < iLength && pwsStr[iUsedLen] == L'.') {
+ FX_FLOAT fPrecise = 0.1f;
+ while (++iUsedLen < iLength) {
+ FX_WCHAR wch = pwsStr[iUsedLen];
+ if (wch >= L'0' && wch <= L'9') {
+ fValue += (wch - L'0') * fPrecise;
+ fPrecise *= 0.1f;
+ } else {
+ break;
+ }
+ }
+ }
+ if (pUsedLen) {
+ *pUsedLen = iUsedLen;
+ }
+ return bNegtive ? -fValue : fValue;
+}
diff --git a/xfa/src/fgas/crt/fgas_system.h b/xfa/src/fgas/crt/fgas_system.h
new file mode 100644
index 0000000000..fb5a88efb5
--- /dev/null
+++ b/xfa/src/fgas/crt/fgas_system.h
@@ -0,0 +1,23 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_CRT_FGAS_SYSTEM_H_
+#define XFA_SRC_FGAS_CRT_FGAS_SYSTEM_H_
+
+#include "core/include/fxcrt/fx_system.h"
+
+#define FX_RAD2DEG(r) ((r)*180.0f / FX_PI)
+#define FX_DEG2RAD(a) ((a)*FX_PI / 180.0f)
+
+FX_FLOAT FX_wcstof(const FX_WCHAR* pwsStr,
+ int32_t iLength = -1,
+ int32_t* pUsedLen = NULL);
+int32_t FX_wcsnicmp(const FX_WCHAR* s1, const FX_WCHAR* s2, size_t count);
+
+int32_t FX_filelength(FXSYS_FILE* file);
+FX_BOOL FX_fsetsize(FXSYS_FILE* file, int32_t size);
+
+#endif // XFA_SRC_FGAS_CRT_FGAS_SYSTEM_H_
diff --git a/xfa/src/fgas/crt/fgas_utils.cpp b/xfa/src/fgas/crt/fgas_utils.cpp
new file mode 100644
index 0000000000..8b3ed0aa0b
--- /dev/null
+++ b/xfa/src/fgas/crt/fgas_utils.cpp
@@ -0,0 +1,434 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/src/fgas/crt/fgas_utils.h"
+
+#include <algorithm>
+
+#include "core/include/fxcrt/fx_basic.h"
+
+class FX_BASEARRAYDATA : public CFX_Target {
+ public:
+ FX_BASEARRAYDATA(int32_t growsize, int32_t blocksize)
+ : iGrowSize(growsize),
+ iBlockSize(blocksize),
+ iTotalCount(0),
+ iBlockCount(0),
+ pBuffer(nullptr) {}
+
+ ~FX_BASEARRAYDATA() { FX_Free(pBuffer); }
+
+ int32_t iGrowSize;
+ int32_t iBlockSize;
+ int32_t iTotalCount;
+ int32_t iBlockCount;
+ uint8_t* pBuffer;
+};
+CFX_BaseArray::CFX_BaseArray(int32_t iGrowSize, int32_t iBlockSize) {
+ FXSYS_assert(iGrowSize > 0 && iBlockSize > 0);
+ m_pData = new FX_BASEARRAYDATA(iGrowSize, iBlockSize);
+}
+CFX_BaseArray::~CFX_BaseArray() {
+ RemoveAll();
+ delete m_pData;
+}
+int32_t CFX_BaseArray::GetSize() const {
+ return m_pData->iBlockCount;
+}
+int32_t CFX_BaseArray::GetBlockSize() const {
+ return m_pData->iBlockSize;
+}
+uint8_t* CFX_BaseArray::AddSpaceTo(int32_t index) {
+ FXSYS_assert(index > -1);
+ uint8_t*& pBuffer = m_pData->pBuffer;
+ int32_t& iTotalCount = m_pData->iTotalCount;
+ int32_t iBlockSize = m_pData->iBlockSize;
+ if (index >= iTotalCount) {
+ int32_t iGrowSize = m_pData->iGrowSize;
+ iTotalCount = (index / iGrowSize + 1) * iGrowSize;
+ int32_t iNewSize = iTotalCount * iBlockSize;
+ if (!pBuffer) {
+ pBuffer = FX_Alloc(uint8_t, iNewSize);
+ } else {
+ pBuffer = FX_Realloc(uint8_t, pBuffer, iNewSize);
+ }
+ }
+ int32_t& iBlockCount = m_pData->iBlockCount;
+ if (index >= iBlockCount) {
+ iBlockCount = index + 1;
+ }
+ return pBuffer + index * iBlockSize;
+}
+uint8_t* CFX_BaseArray::GetAt(int32_t index) const {
+ FXSYS_assert(index > -1 && index < m_pData->iBlockCount);
+ return m_pData->pBuffer + index * m_pData->iBlockSize;
+}
+uint8_t* CFX_BaseArray::GetBuffer() const {
+ return m_pData->pBuffer;
+}
+int32_t CFX_BaseArray::Append(const CFX_BaseArray& src,
+ int32_t iStart,
+ int32_t iCount) {
+ int32_t iBlockSize = m_pData->iBlockSize;
+ FXSYS_assert(iBlockSize == src.m_pData->iBlockSize);
+ int32_t& iBlockCount = m_pData->iBlockCount;
+ int32_t iAdded = src.GetSize();
+ FXSYS_assert(iStart > -1 && iStart < iAdded);
+ if (iCount < 0) {
+ iCount = iAdded;
+ }
+ if (iStart + iCount > iAdded) {
+ iCount = iAdded - iStart;
+ }
+ if (iCount < 1) {
+ return 0;
+ }
+ uint8_t* pDst = m_pData->pBuffer + iBlockCount * iBlockSize;
+ AddSpaceTo(iBlockCount + iCount - 1);
+ FXSYS_memcpy(pDst, src.m_pData->pBuffer + iStart * iBlockSize,
+ iCount * iBlockSize);
+ return iCount;
+}
+int32_t CFX_BaseArray::Copy(const CFX_BaseArray& src,
+ int32_t iStart,
+ int32_t iCount) {
+ int32_t iBlockSize = m_pData->iBlockSize;
+ FXSYS_assert(iBlockSize == src.m_pData->iBlockSize);
+ int32_t iCopied = src.GetSize();
+ FXSYS_assert(iStart > -1 && iStart < iCopied);
+ if (iCount < 0) {
+ iCount = iCopied;
+ }
+ if (iStart + iCount > iCopied) {
+ iCount = iCopied - iStart;
+ }
+ if (iCount < 1) {
+ return 0;
+ }
+ RemoveAll(TRUE);
+ AddSpaceTo(iCount - 1);
+ FXSYS_memcpy(m_pData->pBuffer, src.m_pData->pBuffer + iStart * iBlockSize,
+ iCount * iBlockSize);
+ return iCount;
+}
+int32_t CFX_BaseArray::RemoveLast(int32_t iCount) {
+ int32_t& iBlockCount = m_pData->iBlockCount;
+ if (iCount < 0 || iCount > iBlockCount) {
+ iCount = iBlockCount;
+ iBlockCount = 0;
+ } else {
+ iBlockCount -= iCount;
+ }
+ return iCount;
+}
+void CFX_BaseArray::RemoveAll(FX_BOOL bLeaveMemory) {
+ if (!bLeaveMemory) {
+ uint8_t*& pBuffer = m_pData->pBuffer;
+ if (pBuffer != NULL) {
+ FX_Free(pBuffer);
+ pBuffer = NULL;
+ }
+ m_pData->iTotalCount = 0;
+ }
+ m_pData->iBlockCount = 0;
+}
+
+CFX_BaseMassArrayImp::CFX_BaseMassArrayImp(int32_t iChunkSize,
+ int32_t iBlockSize)
+ : m_iChunkSize(iChunkSize),
+ m_iBlockSize(iBlockSize),
+ m_iChunkCount(0),
+ m_iBlockCount(0) {
+ FXSYS_assert(m_iChunkSize > 0 && m_iBlockSize > 0);
+ m_pData = new CFX_PtrArray;
+ m_pData->SetSize(16);
+}
+CFX_BaseMassArrayImp::~CFX_BaseMassArrayImp() {
+ RemoveAll();
+ delete m_pData;
+}
+uint8_t* CFX_BaseMassArrayImp::AddSpaceTo(int32_t index) {
+ FXSYS_assert(index > -1);
+ uint8_t* pChunk;
+ if (index < m_iBlockCount) {
+ pChunk = (uint8_t*)m_pData->GetAt(index / m_iChunkSize);
+ } else {
+ int32_t iMemSize = m_iChunkSize * m_iBlockSize;
+ while (TRUE) {
+ if (index < m_iChunkCount * m_iChunkSize) {
+ pChunk = (uint8_t*)m_pData->GetAt(index / m_iChunkSize);
+ break;
+ } else {
+ pChunk = FX_Alloc(uint8_t, iMemSize);
+ if (m_iChunkCount < m_pData->GetSize()) {
+ m_pData->SetAt(m_iChunkCount, pChunk);
+ } else {
+ m_pData->Add(pChunk);
+ }
+ m_iChunkCount++;
+ }
+ }
+ }
+ FXSYS_assert(pChunk != NULL);
+ m_iBlockCount = index + 1;
+ return pChunk + (index % m_iChunkSize) * m_iBlockSize;
+}
+uint8_t* CFX_BaseMassArrayImp::GetAt(int32_t index) const {
+ FXSYS_assert(index > -1 && index < m_iBlockCount);
+ uint8_t* pChunk = (uint8_t*)m_pData->GetAt(index / m_iChunkSize);
+ FXSYS_assert(pChunk != NULL);
+ return pChunk + (index % m_iChunkSize) * m_iBlockSize;
+}
+int32_t CFX_BaseMassArrayImp::Append(const CFX_BaseMassArrayImp& src,
+ int32_t iStart,
+ int32_t iCount) {
+ FXSYS_assert(m_iBlockSize == src.m_iBlockSize);
+ int32_t iAdded = src.m_iBlockCount;
+ FXSYS_assert(iStart > -1 && iStart < iAdded);
+ if (iCount < 0) {
+ iCount = iAdded;
+ }
+ if (iStart + iCount > iAdded) {
+ iCount = iAdded - iStart;
+ }
+ if (iCount < 1) {
+ return m_iBlockCount;
+ }
+ int32_t iBlockCount = m_iBlockCount;
+ int32_t iTotal = m_iBlockCount + iCount;
+ AddSpaceTo(iTotal - 1);
+ Append(iBlockCount, src, iStart, iCount);
+ return m_iBlockCount;
+}
+int32_t CFX_BaseMassArrayImp::Copy(const CFX_BaseMassArrayImp& src,
+ int32_t iStart,
+ int32_t iCount) {
+ FXSYS_assert(m_iBlockSize == src.m_iBlockSize);
+ int32_t iCopied = src.m_iBlockCount;
+ FXSYS_assert(iStart > -1);
+ if (iStart >= iCopied) {
+ return 0;
+ }
+ RemoveAll(TRUE);
+ if (iCount < 0) {
+ iCount = iCopied;
+ }
+ if (iStart + iCount > iCopied) {
+ iCount = iCopied - iStart;
+ }
+ if (iCount < 1) {
+ return 0;
+ }
+ if (m_iBlockCount < iCount) {
+ AddSpaceTo(iCount - 1);
+ }
+ Append(0, src, iStart, iCount);
+ return m_iBlockCount;
+}
+
+void CFX_BaseMassArrayImp::Append(int32_t iDstStart,
+ const CFX_BaseMassArrayImp& src,
+ int32_t iSrcStart,
+ int32_t iSrcCount) {
+ FXSYS_assert(iDstStart > -1);
+ FXSYS_assert(m_iBlockSize == src.m_iBlockSize);
+ FXSYS_assert(src.m_iBlockCount > 0);
+ FXSYS_assert(m_iBlockCount >= iDstStart + iSrcCount);
+ FXSYS_assert(iSrcStart > -1);
+ FXSYS_assert(iSrcStart < src.m_iBlockCount);
+ FXSYS_assert(iSrcCount > 0);
+ FXSYS_assert(iSrcStart + iSrcCount <= src.m_iBlockCount);
+
+ int32_t iDstChunkIndex = iDstStart / m_iChunkSize;
+ int32_t iSrcChunkIndex = iSrcStart / src.m_iChunkSize;
+ uint8_t* pDstChunk = (uint8_t*)GetAt(iDstStart);
+ uint8_t* pSrcChunk = (uint8_t*)src.GetAt(iSrcStart);
+ int32_t iDstChunkSize = m_iChunkSize - (iDstStart % m_iChunkSize);
+ int32_t iSrcChunkSize = src.m_iChunkSize - (iSrcStart % src.m_iChunkSize);
+ int32_t iCopySize =
+ std::min(iSrcCount, std::min(iSrcChunkSize, iDstChunkSize));
+ int32_t iCopyBytes = iCopySize * m_iBlockSize;
+ while (iSrcCount > 0) {
+ FXSYS_assert(pDstChunk != NULL && pSrcChunk != NULL);
+ FXSYS_memcpy(pDstChunk, pSrcChunk, iCopyBytes);
+ iSrcCount -= iCopySize;
+ iSrcChunkSize -= iCopySize;
+ if (iSrcChunkSize < 1) {
+ iSrcChunkSize = src.m_iChunkSize;
+ iSrcChunkIndex++;
+ pSrcChunk = (uint8_t*)src.m_pData->GetAt(iSrcChunkIndex);
+ } else {
+ pSrcChunk += iCopyBytes;
+ }
+ iDstChunkSize -= iCopySize;
+ if (iDstChunkSize < 1) {
+ iDstChunkSize = m_iChunkSize;
+ iDstChunkIndex++;
+ pDstChunk = (uint8_t*)m_pData->GetAt(iDstChunkIndex);
+ } else {
+ pDstChunk += iCopyBytes;
+ }
+ iCopySize = std::min(iSrcCount, std::min(iSrcChunkSize, iDstChunkSize));
+ iCopyBytes = iCopySize * m_iBlockSize;
+ }
+}
+int32_t CFX_BaseMassArrayImp::RemoveLast(int32_t iCount) {
+ if (iCount < 0 || iCount >= m_iBlockCount) {
+ m_iBlockCount = 0;
+ } else {
+ m_iBlockCount -= iCount;
+ }
+ return m_iBlockCount;
+}
+void CFX_BaseMassArrayImp::RemoveAll(FX_BOOL bLeaveMemory) {
+ if (bLeaveMemory) {
+ m_iBlockCount = 0;
+ return;
+ }
+ for (int32_t i = 0; i < m_iChunkCount; i++) {
+ void* p = m_pData->GetAt(i);
+ if (p == NULL) {
+ continue;
+ }
+ FX_Free(p);
+ }
+ m_pData->RemoveAll();
+ m_iChunkCount = 0;
+ m_iBlockCount = 0;
+}
+CFX_BaseMassArray::CFX_BaseMassArray(int32_t iChunkSize, int32_t iBlockSize) {
+ m_pData = new CFX_BaseMassArrayImp(iChunkSize, iBlockSize);
+}
+CFX_BaseMassArray::~CFX_BaseMassArray() {
+ delete m_pData;
+}
+int32_t CFX_BaseMassArray::GetSize() const {
+ return m_pData->m_iBlockCount;
+}
+uint8_t* CFX_BaseMassArray::AddSpaceTo(int32_t index) {
+ return m_pData->AddSpaceTo(index);
+}
+uint8_t* CFX_BaseMassArray::GetAt(int32_t index) const {
+ return m_pData->GetAt(index);
+}
+int32_t CFX_BaseMassArray::Append(const CFX_BaseMassArray& src,
+ int32_t iStart,
+ int32_t iCount) {
+ return m_pData->Append(*(CFX_BaseMassArrayImp*)src.m_pData, iStart, iCount);
+}
+int32_t CFX_BaseMassArray::Copy(const CFX_BaseMassArray& src,
+ int32_t iStart,
+ int32_t iCount) {
+ return m_pData->Copy(*(CFX_BaseMassArrayImp*)src.m_pData, iStart, iCount);
+}
+int32_t CFX_BaseMassArray::RemoveLast(int32_t iCount) {
+ return m_pData->RemoveLast(iCount);
+}
+void CFX_BaseMassArray::RemoveAll(FX_BOOL bLeaveMemory) {
+ m_pData->RemoveAll(bLeaveMemory);
+}
+
+struct FX_BASEDISCRETEARRAYDATA {
+ int32_t iBlockSize;
+ int32_t iChunkSize;
+ int32_t iChunkCount;
+ CFX_PtrArray ChunkBuffer;
+};
+
+CFX_BaseDiscreteArray::CFX_BaseDiscreteArray(int32_t iChunkSize,
+ int32_t iBlockSize) {
+ FXSYS_assert(iChunkSize > 0 && iBlockSize > 0);
+ FX_BASEDISCRETEARRAYDATA* pData = new FX_BASEDISCRETEARRAYDATA;
+ m_pData = pData;
+ pData->ChunkBuffer.SetSize(16);
+ pData->iChunkCount = 0;
+ pData->iChunkSize = iChunkSize;
+ pData->iBlockSize = iBlockSize;
+}
+CFX_BaseDiscreteArray::~CFX_BaseDiscreteArray() {
+ RemoveAll();
+ delete static_cast<FX_BASEDISCRETEARRAYDATA*>(m_pData);
+}
+uint8_t* CFX_BaseDiscreteArray::AddSpaceTo(int32_t index) {
+ FXSYS_assert(index > -1);
+ FX_BASEDISCRETEARRAYDATA* pData = (FX_BASEDISCRETEARRAYDATA*)m_pData;
+ int32_t& iChunkCount = pData->iChunkCount;
+ int32_t iChunkSize = pData->iChunkSize;
+ uint8_t* pChunk = NULL;
+ int32_t iChunk = index / iChunkSize;
+ if (iChunk < iChunkCount) {
+ pChunk = (uint8_t*)pData->ChunkBuffer.GetAt(iChunk);
+ }
+ if (!pChunk) {
+ pChunk = FX_Alloc2D(uint8_t, iChunkSize, pData->iBlockSize);
+ FXSYS_memset(pChunk, 0, iChunkSize * pData->iBlockSize);
+ pData->ChunkBuffer.SetAtGrow(iChunk, pChunk);
+ if (iChunkCount <= iChunk) {
+ iChunkCount = iChunk + 1;
+ }
+ }
+ return pChunk + (index % iChunkSize) * pData->iBlockSize;
+}
+uint8_t* CFX_BaseDiscreteArray::GetAt(int32_t index) const {
+ FXSYS_assert(index > -1);
+ FX_BASEDISCRETEARRAYDATA* pData = (FX_BASEDISCRETEARRAYDATA*)m_pData;
+ int32_t iChunkSize = pData->iChunkSize;
+ int32_t iChunk = index / iChunkSize;
+ if (iChunk >= pData->iChunkCount) {
+ return NULL;
+ }
+ uint8_t* pChunk = (uint8_t*)pData->ChunkBuffer.GetAt(iChunk);
+ if (pChunk == NULL) {
+ return NULL;
+ }
+ return pChunk + (index % iChunkSize) * pData->iBlockSize;
+}
+void CFX_BaseDiscreteArray::RemoveAll() {
+ FX_BASEDISCRETEARRAYDATA* pData = (FX_BASEDISCRETEARRAYDATA*)m_pData;
+ CFX_PtrArray& ChunkBuffer = pData->ChunkBuffer;
+ int32_t& iChunkCount = pData->iChunkCount;
+ for (int32_t i = 0; i < iChunkCount; i++) {
+ void* p = ChunkBuffer.GetAt(i);
+ if (p == NULL) {
+ continue;
+ }
+ FX_Free(p);
+ }
+ ChunkBuffer.RemoveAll();
+ iChunkCount = 0;
+}
+CFX_BaseStack::CFX_BaseStack(int32_t iChunkSize, int32_t iBlockSize) {
+ m_pData = new CFX_BaseMassArrayImp(iChunkSize, iBlockSize);
+}
+CFX_BaseStack::~CFX_BaseStack() {
+ delete (CFX_BaseMassArrayImp*)m_pData;
+}
+uint8_t* CFX_BaseStack::Push() {
+ return m_pData->AddSpace();
+}
+void CFX_BaseStack::Pop() {
+ int32_t& iBlockCount = m_pData->m_iBlockCount;
+ if (iBlockCount < 1) {
+ return;
+ }
+ iBlockCount--;
+}
+uint8_t* CFX_BaseStack::GetTopElement() const {
+ int32_t iSize = m_pData->m_iBlockCount;
+ if (iSize < 1) {
+ return NULL;
+ }
+ return m_pData->GetAt(iSize - 1);
+}
+int32_t CFX_BaseStack::GetSize() const {
+ return m_pData->m_iBlockCount;
+}
+uint8_t* CFX_BaseStack::GetAt(int32_t index) const {
+ return m_pData->GetAt(index);
+}
+void CFX_BaseStack::RemoveAll(FX_BOOL bLeaveMemory) {
+ m_pData->RemoveAll(bLeaveMemory);
+}
diff --git a/xfa/src/fgas/crt/fgas_utils.h b/xfa/src/fgas/crt/fgas_utils.h
new file mode 100644
index 0000000000..f52255a5d3
--- /dev/null
+++ b/xfa/src/fgas/crt/fgas_utils.h
@@ -0,0 +1,737 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_CRT_FGAS_UTILS_H_
+#define XFA_SRC_FGAS_CRT_FGAS_UTILS_H_
+
+#include "core/include/fxcrt/fx_coordinates.h"
+#include "xfa/src/fgas/crt/fgas_memory.h"
+
+class FX_BASEARRAYDATA;
+
+template <class baseType>
+class CFX_CPLTree;
+
+class CFX_BaseArray : public CFX_Target {
+ protected:
+ CFX_BaseArray(int32_t iGrowSize, int32_t iBlockSize);
+ ~CFX_BaseArray();
+ int32_t GetSize() const;
+ int32_t GetBlockSize() const;
+ uint8_t* AddSpaceTo(int32_t index);
+ uint8_t* GetAt(int32_t index) const;
+ uint8_t* GetBuffer() const;
+ int32_t Append(const CFX_BaseArray& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1);
+ int32_t Copy(const CFX_BaseArray& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1);
+ int32_t RemoveLast(int32_t iCount = -1);
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE);
+
+ FX_BASEARRAYDATA* m_pData;
+};
+
+template <class baseType>
+class CFX_BaseArrayTemplate : public CFX_BaseArray {
+ public:
+ CFX_BaseArrayTemplate(int32_t iGrowSize = 100)
+ : CFX_BaseArray(iGrowSize, sizeof(baseType)) {}
+ CFX_BaseArrayTemplate(int32_t iGrowSize, int32_t iBlockSize)
+ : CFX_BaseArray(iGrowSize, iBlockSize) {}
+ int32_t GetSize() const { return CFX_BaseArray::GetSize(); }
+ int32_t GetBlockSize() const { return CFX_BaseArray::GetBlockSize(); }
+ baseType* AddSpace() {
+ return (baseType*)CFX_BaseArray::AddSpaceTo(CFX_BaseArray::GetSize());
+ }
+ int32_t Add(const baseType& element) {
+ int32_t index = CFX_BaseArray::GetSize();
+ *(baseType*)CFX_BaseArray::AddSpaceTo(index) = element;
+ return index;
+ }
+ baseType* GetBuffer() const { return (baseType*)CFX_BaseArray::GetBuffer(); }
+ baseType& GetAt(int32_t index) const {
+ return *(baseType*)CFX_BaseArray::GetAt(index);
+ }
+ baseType* GetPtrAt(int32_t index) const {
+ return (baseType*)CFX_BaseArray::GetAt(index);
+ }
+ void SetAt(int32_t index, const baseType& element) {
+ *(baseType*)CFX_BaseArray::GetAt(index) = element;
+ }
+ void SetAtGrow(int32_t index, const baseType& element) {
+ *(baseType*)CFX_BaseArray::AddSpaceTo(index) = element;
+ }
+ int32_t Append(const CFX_BaseArrayTemplate& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1) {
+ return CFX_BaseArray::Append(src, iStart, iCount);
+ }
+ int32_t Copy(const CFX_BaseArrayTemplate& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1) {
+ return CFX_BaseArray::Copy(src, iStart, iCount);
+ }
+ int32_t RemoveLast(int32_t iCount = -1) {
+ return CFX_BaseArray::RemoveLast(iCount);
+ }
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE) {
+ CFX_BaseArray::RemoveAll(bLeaveMemory);
+ }
+};
+typedef CFX_BaseArrayTemplate<void*> CFDE_PtrArray;
+typedef CFX_BaseArrayTemplate<FX_DWORD> CFDE_DWordArray;
+typedef CFX_BaseArrayTemplate<FX_WORD> CFDE_WordArray;
+
+template <class baseType>
+class CFX_ObjectBaseArrayTemplate : public CFX_BaseArray {
+ public:
+ CFX_ObjectBaseArrayTemplate(int32_t iGrowSize = 100)
+ : CFX_BaseArray(iGrowSize, sizeof(baseType)) {}
+ ~CFX_ObjectBaseArrayTemplate() { RemoveAll(FALSE); }
+ int32_t GetSize() const { return CFX_BaseArray::GetSize(); }
+ int32_t GetBlockSize() const { return CFX_BaseArray::GetBlockSize(); }
+ int32_t Add(const baseType& element) {
+ int32_t index = CFX_BaseArray::GetSize();
+ baseType* p = (baseType*)CFX_BaseArray::AddSpaceTo(index);
+ new ((void*)p) baseType(element);
+ return index;
+ }
+ baseType& GetAt(int32_t index) const {
+ return *(baseType*)CFX_BaseArray::GetAt(index);
+ }
+ baseType* GetPtrAt(int32_t index) const {
+ return (baseType*)CFX_BaseArray::GetAt(index);
+ }
+ int32_t Append(const CFX_ObjectBaseArrayTemplate& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1) {
+ FXSYS_assert(GetBlockSize() == src.GetBlockSize());
+ if (iCount == 0) {
+ return 0;
+ }
+ int32_t iSize = src.GetSize();
+ FXSYS_assert(iStart > -1 && iStart < iSize);
+ if (iCount < 0) {
+ iCount = iSize;
+ }
+ if (iStart + iCount > iSize) {
+ iCount = iSize - iStart;
+ }
+ if (iCount < 1) {
+ return 0;
+ }
+ iSize = CFX_BaseArray::GetSize();
+ CFX_BaseArray::AddSpaceTo(iSize + iCount - 1);
+ uint8_t** pStart = CFX_BaseArray::GetAt(iSize);
+ int32_t iBlockSize = CFX_BaseArray::GetBlockSize();
+ iSize = iStart + iCount;
+ for (int32_t i = iStart; i < iSize; i++) {
+ FXTARGET_NewWith((void*)pStart) baseType(src.GetAt(i));
+ pStart += iBlockSize;
+ }
+ return iCount;
+ }
+ int32_t Copy(const CFX_ObjectBaseArrayTemplate& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1) {
+ FXSYS_assert(GetBlockSize() == src.GetBlockSize());
+ if (iCount == 0) {
+ return 0;
+ }
+ int32_t iSize = src.GetSize();
+ FXSYS_assert(iStart > -1 && iStart < iSize);
+ if (iCount < 0) {
+ iCount = iSize;
+ }
+ if (iStart + iCount > iSize) {
+ iCount = iSize - iStart;
+ }
+ if (iCount < 1) {
+ return 0;
+ }
+ RemoveAll(TRUE);
+ CFX_BaseArray::AddSpaceTo(iCount - 1);
+ uint8_t** pStart = CFX_BaseArray::GetAt(0);
+ int32_t iBlockSize = CFX_BaseArray::GetBlockSize();
+ iSize = iStart + iCount;
+ for (int32_t i = iStart; i < iSize; i++) {
+ new ((void*)pStart) baseType(src.GetAt(i));
+ pStart += iBlockSize;
+ }
+ return iCount;
+ }
+ int32_t RemoveLast(int32_t iCount = -1) {
+ int32_t iSize = CFX_BaseArray::GetSize();
+ if (iCount < 0 || iCount > iSize) {
+ iCount = iSize;
+ }
+ if (iCount == 0) {
+ return iSize;
+ }
+ for (int32_t i = iSize - iCount; i < iSize; i++) {
+ ((baseType*)GetPtrAt(i))->~baseType();
+ }
+ return CFX_BaseArray::RemoveLast(iCount);
+ }
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE) {
+ int32_t iSize = CFX_BaseArray::GetSize();
+ for (int32_t i = 0; i < iSize; i++) {
+ ((baseType*)GetPtrAt(i))->~baseType();
+ }
+ CFX_BaseArray::RemoveAll(bLeaveMemory);
+ }
+};
+
+class CFX_BaseMassArrayImp : public CFX_Target {
+ public:
+ CFX_BaseMassArrayImp(int32_t iChunkSize, int32_t iBlockSize);
+ ~CFX_BaseMassArrayImp();
+ uint8_t* AddSpace() { return AddSpaceTo(m_iBlockCount); }
+ uint8_t* AddSpaceTo(int32_t index);
+ uint8_t* GetAt(int32_t index) const;
+ int32_t Append(const CFX_BaseMassArrayImp& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1);
+ int32_t Copy(const CFX_BaseMassArrayImp& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1);
+ int32_t RemoveLast(int32_t iCount = -1);
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE);
+ int32_t m_iChunkSize;
+ int32_t m_iBlockSize;
+ int32_t m_iChunkCount;
+ int32_t m_iBlockCount;
+ CFX_PtrArray* m_pData;
+
+ protected:
+ void Append(int32_t iDstStart,
+ const CFX_BaseMassArrayImp& src,
+ int32_t iSrcStart = 0,
+ int32_t iSrcCount = -1);
+};
+
+class CFX_BaseMassArray : public CFX_Target {
+ protected:
+ CFX_BaseMassArray(int32_t iChunkSize, int32_t iBlockSize);
+ ~CFX_BaseMassArray();
+ int32_t GetSize() const;
+ uint8_t* AddSpaceTo(int32_t index);
+ uint8_t* GetAt(int32_t index) const;
+ int32_t Append(const CFX_BaseMassArray& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1);
+ int32_t Copy(const CFX_BaseMassArray& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1);
+ int32_t RemoveLast(int32_t iCount = -1);
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE);
+ CFX_BaseMassArrayImp* m_pData;
+};
+
+template <class baseType>
+class CFX_MassArrayTemplate : public CFX_BaseMassArray {
+ public:
+ CFX_MassArrayTemplate(int32_t iChunkSize = 100)
+ : CFX_BaseMassArray(iChunkSize, sizeof(baseType)) {}
+ CFX_MassArrayTemplate(int32_t iChunkSize, int32_t iBlockSize)
+ : CFX_BaseMassArray(iChunkSize, iBlockSize) {}
+ int32_t GetSize() const { return CFX_BaseMassArray::GetSize(); }
+ baseType* AddSpace() {
+ return (baseType*)CFX_BaseMassArray::AddSpaceTo(
+ CFX_BaseMassArray::GetSize());
+ }
+ int32_t Add(const baseType& element) {
+ int32_t index = CFX_BaseMassArray::GetSize();
+ *(baseType*)CFX_BaseMassArray::AddSpaceTo(index) = element;
+ return index;
+ }
+ baseType& GetAt(int32_t index) const {
+ return *(baseType*)CFX_BaseMassArray::GetAt(index);
+ }
+ baseType* GetPtrAt(int32_t index) const {
+ return (baseType*)CFX_BaseMassArray::GetAt(index);
+ }
+ void SetAt(int32_t index, const baseType& element) {
+ *(baseType*)CFX_BaseMassArray::GetAt(index) = element;
+ }
+ void SetAtGrow(int32_t index, const baseType& element) {
+ *(baseType*)CFX_BaseMassArray::AddSpaceTo(index) = element;
+ }
+ int32_t Append(const CFX_MassArrayTemplate& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1) {
+ return CFX_BaseMassArray::Append(src, iStart, iCount);
+ }
+ int32_t Copy(const CFX_MassArrayTemplate& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1) {
+ return CFX_BaseMassArray::Copy(src, iStart, iCount);
+ }
+ int32_t RemoveLast(int32_t iCount = -1) {
+ return CFX_BaseMassArray::RemoveLast(iCount);
+ }
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE) {
+ CFX_BaseMassArray::RemoveAll(bLeaveMemory);
+ }
+};
+typedef CFX_MassArrayTemplate<void*> CFX_PtrMassArray;
+typedef CFX_MassArrayTemplate<int32_t> CFX_Int32MassArray;
+typedef CFX_MassArrayTemplate<FX_DWORD> CFX_DWordMassArray;
+typedef CFX_MassArrayTemplate<FX_WORD> CFX_WordMassArray;
+typedef CFX_MassArrayTemplate<CFX_Rect> CFX_RectMassArray;
+typedef CFX_MassArrayTemplate<CFX_RectF> CFX_RectFMassArray;
+
+template <class baseType>
+class CFX_ObjectMassArrayTemplate : public CFX_BaseMassArray {
+ public:
+ CFX_ObjectMassArrayTemplate(int32_t iChunkSize = 100)
+ : CFX_BaseMassArray(iChunkSize, sizeof(baseType)) {}
+ ~CFX_ObjectMassArrayTemplate() { RemoveAll(FALSE); }
+ int32_t GetSize() const { return CFX_BaseMassArray::GetSize(); }
+ int32_t Add(const baseType& element) {
+ int32_t index = CFX_BaseMassArray::GetSize();
+ baseType* p = (baseType*)CFX_BaseMassArray::AddSpaceTo(index);
+ new ((void*)p) baseType(element);
+ return index;
+ }
+ baseType& GetAt(int32_t index) const {
+ return *(baseType*)CFX_BaseMassArray::GetAt(index);
+ }
+ baseType* GetPtrAt(int32_t index) const {
+ return (baseType*)CFX_BaseMassArray::GetAt(index);
+ }
+ int32_t Append(const CFX_ObjectMassArrayTemplate& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1) {
+ if (iCount == 0) {
+ return CFX_BaseMassArray::GetSize();
+ }
+ int32_t iSize = src.GetSize();
+ FXSYS_assert(iStart > -1 && iStart < iSize);
+ if (iCount < 0) {
+ iCount = iSize;
+ }
+ int32_t iEnd = iStart + iCount;
+ if (iEnd > iSize) {
+ iEnd = iSize;
+ }
+ for (int32_t i = iStart; i < iEnd; i++) {
+ Add(src.GetAt(i));
+ }
+ return CFX_BaseMassArray::GetSize();
+ }
+ int32_t Copy(const CFX_ObjectMassArrayTemplate& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1) {
+ if (iCount == 0) {
+ return CFX_BaseMassArray::GetSize();
+ }
+ int32_t iSize = src.GetSize();
+ FXSYS_assert(iStart > -1 && iStart < iSize);
+ if (iCount < 0) {
+ iCount = iSize;
+ }
+ int32_t iEnd = iStart + iCount;
+ if (iEnd > iSize) {
+ iEnd = iSize;
+ }
+ RemoveAll(TRUE);
+ for (int32_t i = iStart; i < iEnd; i++) {
+ Add(src.GetAt(i));
+ }
+ return CFX_BaseMassArray::GetSize();
+ }
+ int32_t RemoveLast(int32_t iCount = -1) {
+ int32_t iSize = CFX_BaseMassArray::GetSize();
+ if (iCount < 0 || iCount > iSize) {
+ iCount = iSize;
+ }
+ if (iCount == 0) {
+ return iSize;
+ }
+ for (int32_t i = iSize - iCount; i < iSize; i++) {
+ ((baseType*)GetPtrAt(i))->~baseType();
+ }
+ return CFX_BaseMassArray::RemoveLast(iCount);
+ }
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE) {
+ int32_t iSize = CFX_BaseMassArray::GetSize();
+ for (int32_t i = 0; i < iSize; i++) {
+ ((baseType*)GetPtrAt(i))->~baseType();
+ }
+ CFX_BaseMassArray::RemoveAll(bLeaveMemory);
+ }
+};
+
+class CFX_BaseDiscreteArray : public CFX_Target {
+ protected:
+ CFX_BaseDiscreteArray(int32_t iChunkSize, int32_t iBlockSize);
+ ~CFX_BaseDiscreteArray();
+ uint8_t* AddSpaceTo(int32_t index);
+ uint8_t* GetAt(int32_t index) const;
+ void RemoveAll();
+ void* m_pData;
+};
+
+template <class baseType>
+class CFX_DiscreteArrayTemplate : public CFX_BaseDiscreteArray {
+ public:
+ CFX_DiscreteArrayTemplate(int32_t iChunkSize = 100)
+ : CFX_BaseDiscreteArray(iChunkSize, sizeof(baseType)) {}
+ baseType& GetAt(int32_t index, const baseType& defValue) const {
+ baseType* p = (baseType*)CFX_BaseDiscreteArray::GetAt(index);
+ return p == NULL ? (baseType&)defValue : *p;
+ }
+ baseType* GetPtrAt(int32_t index) const {
+ return (baseType*)CFX_BaseDiscreteArray::GetAt(index);
+ }
+ void SetAtGrow(int32_t index, const baseType& element) {
+ *(baseType*)CFX_BaseDiscreteArray::AddSpaceTo(index) = element;
+ }
+ void RemoveAll() { CFX_BaseDiscreteArray::RemoveAll(); }
+};
+typedef CFX_DiscreteArrayTemplate<void*> CFX_PtrDiscreteArray;
+typedef CFX_DiscreteArrayTemplate<FX_DWORD> CFX_DWordDiscreteArray;
+typedef CFX_DiscreteArrayTemplate<FX_WORD> CFX_WordDiscreteArray;
+
+class CFX_BaseStack : public CFX_Target {
+ protected:
+ CFX_BaseStack(int32_t iChunkSize, int32_t iBlockSize);
+ ~CFX_BaseStack();
+ uint8_t* Push();
+ void Pop();
+ uint8_t* GetTopElement() const;
+ int32_t GetSize() const;
+ uint8_t* GetAt(int32_t index) const;
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE);
+ CFX_BaseMassArrayImp* m_pData;
+};
+
+template <class baseType>
+class CFX_StackTemplate : public CFX_BaseStack {
+ public:
+ CFX_StackTemplate(int32_t iChunkSize = 100)
+ : CFX_BaseStack(iChunkSize, sizeof(baseType)) {}
+ int32_t Push(const baseType& element) {
+ int32_t index = CFX_BaseStack::GetSize();
+ *(baseType*)CFX_BaseStack::Push() = element;
+ return index;
+ }
+ void Pop() { CFX_BaseStack::Pop(); }
+ baseType* GetTopElement() const {
+ return (baseType*)CFX_BaseStack::GetTopElement();
+ }
+ int32_t GetSize() const { return CFX_BaseStack::GetSize(); }
+ baseType* GetAt(int32_t index) const {
+ return (baseType*)CFX_BaseStack::GetAt(index);
+ }
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE) {
+ CFX_BaseStack::RemoveAll(bLeaveMemory);
+ }
+};
+typedef CFX_StackTemplate<void*> CFX_PtrStack;
+typedef CFX_StackTemplate<FX_DWORD> CFX_DWordStack;
+typedef CFX_StackTemplate<FX_WORD> CFX_WordStack;
+typedef CFX_StackTemplate<int32_t> CFX_Int32Stack;
+
+template <class baseType>
+class CFX_ObjectStackTemplate : public CFX_BaseStack {
+ public:
+ CFX_ObjectStackTemplate(int32_t iChunkSize = 100)
+ : CFX_BaseStack(iChunkSize, sizeof(baseType)) {}
+ ~CFX_ObjectStackTemplate() { RemoveAll(); }
+ int32_t Push(const baseType& element) {
+ int32_t index = CFX_BaseStack::GetSize();
+ baseType* p = (baseType*)CFX_BaseStack::Push();
+ new ((void*)p) baseType(element);
+ return index;
+ }
+ void Pop() {
+ baseType* p = (baseType*)CFX_BaseStack::GetTopElement();
+ if (p != NULL) {
+ p->~baseType();
+ }
+ CFX_BaseStack::Pop();
+ }
+ baseType* GetTopElement() const {
+ return (baseType*)CFX_BaseStack::GetTopElement();
+ }
+ int32_t GetSize() const { return CFX_BaseStack::GetSize(); }
+ baseType* GetAt(int32_t index) const {
+ return (baseType*)CFX_BaseStack::GetAt(index);
+ }
+ void RemoveAll(FX_BOOL bLeaveMemory = FALSE) {
+ int32_t iSize = CFX_BaseStack::GetSize();
+ for (int32_t i = 0; i < iSize; i++) {
+ ((baseType*)CFX_BaseStack::GetAt(i))->~baseType();
+ }
+ CFX_BaseStack::RemoveAll(bLeaveMemory);
+ }
+ int32_t Copy(const CFX_ObjectStackTemplate& src,
+ int32_t iStart = 0,
+ int32_t iCount = -1) {
+ if (iCount == 0) {
+ return CFX_BaseStack::GetSize();
+ }
+ int32_t iSize = src.GetSize();
+ FXSYS_assert(iStart > -1 && iStart < iSize);
+ if (iCount < 0) {
+ iCount = iSize;
+ }
+ int32_t iEnd = iStart + iCount;
+ if (iEnd > iSize) {
+ iEnd = iSize;
+ }
+ RemoveAll(TRUE);
+ for (int32_t i = iStart; i < iEnd; i++) {
+ Push(*src.GetAt(i));
+ }
+ return CFX_BaseStack::GetSize();
+ }
+};
+
+template <class baseType>
+class CFX_CPLTreeNode : public CFX_Target {
+ public:
+ typedef CFX_CPLTreeNode<baseType> CPLTreeNode;
+ CFX_CPLTreeNode()
+ : m_pParentNode(NULL),
+ m_pChildNode(NULL),
+ m_pPrevNode(NULL),
+ m_pNextNode(NULL),
+ m_Data() {}
+ enum TreeNode {
+ Root = 0,
+ Parent,
+ FirstSibling,
+ PreviousSibling,
+ NextSibling,
+ LastSibling,
+ FirstNeighbor,
+ PreviousNeighbor,
+ NextNeighbor,
+ LastNeighbor,
+ FirstChild,
+ LastChild
+ };
+ CPLTreeNode* GetNode(TreeNode eNode) const {
+ switch (eNode) {
+ case Root: {
+ CPLTreeNode* pParent = (CPLTreeNode*)this;
+ CPLTreeNode* pTemp;
+ while ((pTemp = pParent->m_pParentNode) != NULL) {
+ pParent = pTemp;
+ }
+ return pParent;
+ }
+ case Parent:
+ return m_pParentNode;
+ case FirstSibling: {
+ CPLTreeNode* pNode = (CPLTreeNode*)this;
+ CPLTreeNode* pTemp;
+ while ((pTemp = pNode->m_pPrevNode) != NULL) {
+ pNode = pTemp;
+ }
+ return pNode == (CPLTreeNode*)this ? NULL : pNode;
+ }
+ case PreviousSibling:
+ return m_pPrevNode;
+ case NextSibling:
+ return m_pNextNode;
+ case LastSibling: {
+ CPLTreeNode* pNode = (CPLTreeNode*)this;
+ CPLTreeNode* pTemp;
+ while ((pTemp = pNode->m_pNextNode) != NULL) {
+ pNode = pTemp;
+ }
+ return pNode == (CPLTreeNode*)this ? NULL : pNode;
+ }
+ case FirstNeighbor: {
+ CPLTreeNode* pParent = (CPLTreeNode*)this;
+ CPLTreeNode* pTemp;
+ while ((pTemp = pParent->m_pParentNode) != NULL) {
+ pParent = pTemp;
+ }
+ return pParent == (CPLTreeNode*)this ? NULL : pParent;
+ }
+ case PreviousNeighbor: {
+ if (m_pPrevNode == NULL) {
+ return m_pParentNode;
+ }
+ CPLTreeNode* pNode = m_pPrevNode;
+ CPLTreeNode* pTemp;
+ while ((pTemp = pNode->m_pChildNode) != NULL) {
+ pNode = pTemp;
+ while ((pTemp = pNode->m_pNextNode) != NULL) {
+ pNode = pTemp;
+ }
+ }
+ return pNode;
+ }
+ case NextNeighbor: {
+ if (m_pChildNode != NULL) {
+ return m_pChildNode;
+ }
+ if (m_pNextNode != NULL) {
+ return m_pNextNode;
+ }
+ CPLTreeNode* pNode = m_pParentNode;
+ while (pNode != NULL) {
+ if (pNode->m_pNextNode != NULL) {
+ return pNode->m_pNextNode;
+ }
+ pNode = pNode->m_pParentNode;
+ }
+ return NULL;
+ }
+ case LastNeighbor: {
+ CPLTreeNode* pNode = (CPLTreeNode*)this;
+ CPLTreeNode* pTemp;
+ while ((pTemp = pNode->m_pParentNode) != NULL) {
+ pNode = pTemp;
+ }
+ while (TRUE) {
+ CPLTreeNode* pTemp;
+ while ((pTemp = pNode->m_pNextNode) != NULL) {
+ pNode = pTemp;
+ }
+ if (pNode->m_pChildNode == NULL) {
+ break;
+ }
+ pNode = pNode->m_pChildNode;
+ }
+ return pNode == (CPLTreeNode*)this ? NULL : pNode;
+ }
+ case FirstChild:
+ return m_pChildNode;
+ case LastChild: {
+ if (m_pChildNode == NULL) {
+ return NULL;
+ }
+ CPLTreeNode* pChild = m_pChildNode;
+ CPLTreeNode* pTemp;
+ while ((pTemp = pChild->m_pNextNode) != NULL) {
+ pChild = pTemp;
+ }
+ return pChild;
+ }
+ default:
+ break;
+ }
+ return NULL;
+ }
+ void SetParentNode(CPLTreeNode* pNode) { m_pParentNode = pNode; }
+ int32_t CountChildNodes() const {
+ int32_t iCount = 0;
+ CPLTreeNode* pNode = m_pChildNode;
+ while (pNode) {
+ iCount++;
+ pNode = pNode->m_pNextNode;
+ }
+ return iCount;
+ }
+ CPLTreeNode* GetChildNode(int32_t iIndex) const {
+ int32_t iCount = 0;
+ CPLTreeNode* pNode = m_pChildNode;
+ while (pNode) {
+ if (iIndex == iCount) {
+ return pNode;
+ }
+ iCount++;
+ pNode = pNode->m_pNextNode;
+ }
+ return NULL;
+ }
+ int32_t GetNodeIndex() const {
+ int32_t index = 0;
+ CPLTreeNode* pNode = m_pPrevNode;
+ while (pNode != NULL) {
+ index++;
+ pNode = pNode->m_pPrevNode;
+ }
+ return index;
+ }
+ FX_BOOL IsParentNode(const CPLTreeNode* pNode) const {
+ CPLTreeNode* pParent = m_pParentNode;
+ while (pParent != NULL) {
+ if (pParent == pNode) {
+ return TRUE;
+ }
+ pParent = pParent->GetTreeNode(Parent);
+ }
+ return FALSE;
+ }
+ FX_BOOL IsChildNode(const CPLTreeNode* pNode) const {
+ if (pNode == NULL) {
+ return FALSE;
+ }
+ return pNode->IsParentNode((const CPLTreeNode*)this);
+ }
+ void SetChildNode(CPLTreeNode* pNode) { m_pChildNode = pNode; }
+ void SetPrevNode(CPLTreeNode* pNode) { m_pPrevNode = pNode; }
+ void SetNextNode(CPLTreeNode* pNode) { m_pNextNode = pNode; }
+ int32_t GetNodeLevel() const {
+ int32_t iLevel = 0;
+ CPLTreeNode* pNode = (CPLTreeNode*)this;
+ while ((pNode = pNode->m_pParentNode) != NULL) {
+ iLevel++;
+ }
+ return iLevel;
+ }
+ bool IsRootNode() const { return !m_pParentNode; }
+ baseType GetData() const { return m_Data; }
+ void SetData(baseType data) { m_Data = data; }
+
+ protected:
+ CPLTreeNode* m_pParentNode;
+ CPLTreeNode* m_pChildNode;
+ CPLTreeNode* m_pPrevNode;
+ CPLTreeNode* m_pNextNode;
+ baseType m_Data;
+ friend class CFX_CPLTree<baseType>;
+};
+
+template <class baseType>
+class CFX_CPLTree {
+ public:
+ typedef CFX_CPLTreeNode<baseType> CPLTreeNode;
+ CFX_CPLTree() : m_Root() {}
+ ~CFX_CPLTree() {
+ CPLTreeNode* pNode = m_Root.GetNode(CPLTreeNode::LastNeighbor);
+ while (pNode != NULL) {
+ if (pNode->IsRootNode()) {
+ break;
+ }
+ CPLTreeNode* pTemp = pNode->GetNode(CPLTreeNode::PreviousNeighbor);
+ delete pNode;
+ pNode = pTemp;
+ }
+ }
+ CPLTreeNode* GetRoot() { return &m_Root; }
+ CPLTreeNode* AddChild(baseType data, CPLTreeNode* pParent = NULL) {
+ if (pParent == NULL) {
+ pParent = &m_Root;
+ }
+ CPLTreeNode* pChild = new CPLTreeNode;
+ pChild->SetParentNode(pParent);
+ pChild->SetData(data);
+ if (pParent->m_pChildNode == NULL) {
+ pParent->m_pChildNode = pChild;
+ } else {
+ CPLTreeNode* pLast = pParent->GetNode(CPLTreeNode::LastChild);
+ pChild->SetPrevNode(pLast);
+ pLast->SetNextNode(pChild);
+ }
+ return pChild;
+ }
+
+ protected:
+ CPLTreeNode m_Root;
+};
+
+#endif // XFA_SRC_FGAS_CRT_FGAS_UTILS_H_