Convert all line endings to LF.
[pdfium.git] / core / src / fxcrt / fx_basic_util.cpp
index af4d42c..1d947d3 100644 (file)
-// Copyright 2014 PDFium Authors. All rights reserved.\r
-// Use of this source code is governed by a BSD-style license that can be\r
-// found in the LICENSE file.\r
\r
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
-\r
-#include "../../include/fxcrt/fx_basic.h"\r
-#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_\r
-#include <sys/types.h>\r
-#include <dirent.h>\r
-#else\r
-#include <direct.h>\r
-#endif\r
-CFX_PrivateData::~CFX_PrivateData()\r
-{\r
-    ClearAll();\r
-}\r
-void FX_PRIVATEDATA::FreeData()\r
-{\r
-    if (m_pData == NULL) {\r
-        return;\r
-    }\r
-    if (m_bSelfDestruct) {\r
-        delete (CFX_DestructObject*)m_pData;\r
-    } else if (m_pCallback) {\r
-        m_pCallback(m_pData);\r
-    }\r
-}\r
-void CFX_PrivateData::AddData(FX_LPVOID pModuleId, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback, FX_BOOL bSelfDestruct)\r
-{\r
-    if (pModuleId == NULL) {\r
-        return;\r
-    }\r
-    FX_PRIVATEDATA* pList = m_DataList.GetData();\r
-    int count = m_DataList.GetSize();\r
-    for (int i = 0; i < count; i ++) {\r
-        if (pList[i].m_pModuleId == pModuleId) {\r
-            pList[i].FreeData();\r
-            pList[i].m_pData = pData;\r
-            pList[i].m_pCallback = callback;\r
-            return;\r
-        }\r
-    }\r
-    FX_PRIVATEDATA data = {pModuleId, pData, callback, bSelfDestruct};\r
-    m_DataList.Add(data);\r
-}\r
-void CFX_PrivateData::SetPrivateData(FX_LPVOID pModuleId, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback)\r
-{\r
-    AddData(pModuleId, pData, callback, FALSE);\r
-}\r
-void CFX_PrivateData::SetPrivateObj(FX_LPVOID pModuleId, CFX_DestructObject* pObj)\r
-{\r
-    AddData(pModuleId, pObj, NULL, TRUE);\r
-}\r
-FX_BOOL CFX_PrivateData::RemovePrivateData(FX_LPVOID pModuleId)\r
-{\r
-    if (pModuleId == NULL) {\r
-        return FALSE;\r
-    }\r
-    FX_PRIVATEDATA* pList = m_DataList.GetData();\r
-    int count = m_DataList.GetSize();\r
-    for (int i = 0; i < count; i ++) {\r
-        if (pList[i].m_pModuleId == pModuleId) {\r
-            m_DataList.RemoveAt(i);\r
-            return TRUE;\r
-        }\r
-    }\r
-    return FALSE;\r
-}\r
-FX_LPVOID CFX_PrivateData::GetPrivateData(FX_LPVOID pModuleId)\r
-{\r
-    if (pModuleId == NULL) {\r
-        return NULL;\r
-    }\r
-    FX_PRIVATEDATA* pList = m_DataList.GetData();\r
-    int count = m_DataList.GetSize();\r
-    for (int i = 0; i < count; i ++) {\r
-        if (pList[i].m_pModuleId == pModuleId) {\r
-            return pList[i].m_pData;\r
-        }\r
-    }\r
-    return NULL;\r
-}\r
-void CFX_PrivateData::ClearAll()\r
-{\r
-    FX_PRIVATEDATA* pList = m_DataList.GetData();\r
-    int count = m_DataList.GetSize();\r
-    for (int i = 0; i < count; i ++) {\r
-        pList[i].FreeData();\r
-    }\r
-    m_DataList.RemoveAll();\r
-}\r
-void FX_atonum(FX_BSTR strc, FX_BOOL& bInteger, void* pData)\r
-{\r
-    if (FXSYS_memchr(strc.GetPtr(), '.', strc.GetLength()) == NULL) {\r
-        bInteger = TRUE;\r
-        int cc = 0, integer = 0;\r
-        FX_LPCSTR str = strc.GetCStr();\r
-        int len = strc.GetLength();\r
-        FX_BOOL bNegative = FALSE;\r
-        if (str[0] == '+') {\r
-            cc++;\r
-        } else if (str[0] == '-') {\r
-            bNegative = TRUE;\r
-            cc++;\r
-        }\r
-        while (cc < len) {\r
-            if (str[cc] < '0' || str[cc] > '9') {\r
-                break;\r
-            }\r
-            integer = integer * 10 + str[cc] - '0';\r
-            if (integer < 0) {\r
-                break;\r
-            }\r
-            cc ++;\r
-        }\r
-        if (bNegative) {\r
-            integer = -integer;\r
-        }\r
-        *(int*)pData = integer;\r
-    } else {\r
-        bInteger = FALSE;\r
-        *(FX_FLOAT*)pData = FX_atof(strc);\r
-    }\r
-}\r
-FX_FLOAT FX_atof(FX_BSTR strc)\r
-{\r
-    if (strc.GetLength() == 0) {\r
-        return 0.0;\r
-    }\r
-    int cc = 0;\r
-    FX_BOOL bNegative = FALSE;\r
-    FX_LPCSTR str = strc.GetCStr();\r
-    int len = strc.GetLength();\r
-    if (str[0] == '+') {\r
-        cc++;\r
-    } else if (str[0] == '-') {\r
-        bNegative = TRUE;\r
-        cc++;\r
-    }\r
-    while (cc < len) {\r
-        if (str[cc] != '+' && str[cc] != '-') {\r
-            break;\r
-        }\r
-        cc ++;\r
-    }\r
-    FX_FLOAT value = 0;\r
-    while (cc < len) {\r
-        if (str[cc] == '.') {\r
-            break;\r
-        }\r
-        value = value * 10 + str[cc] - '0';\r
-        cc ++;\r
-    }\r
-    static const FX_FLOAT fraction_scales[] = {0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f,\r
-                                               0.0000001f, 0.00000001f, 0.000000001f, 0.0000000001f, 0.00000000001f\r
-                                              };\r
-    int scale = 0;\r
-    if (cc < len && str[cc] == '.') {\r
-        cc ++;\r
-        while (cc < len) {\r
-            value += fraction_scales[scale] * (str[cc] - '0');\r
-            scale ++;\r
-            if (scale == sizeof fraction_scales / sizeof(FX_FLOAT)) {\r
-                break;\r
-            }\r
-            cc ++;\r
-        }\r
-    }\r
-    return bNegative ? -value : value;\r
-}\r
-static FX_BOOL FX_IsDigit(FX_BYTE ch)\r
-{\r
-    return (ch >= '0' && ch <= '9') ? TRUE : FALSE;\r
-}\r
-static FX_BOOL FX_IsXDigit(FX_BYTE ch)\r
-{\r
-    return (FX_IsDigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) ? TRUE : FALSE;\r
-}\r
-static FX_BYTE FX_MakeUpper(FX_BYTE ch)\r
-{\r
-    if (ch < 'a' || ch > 'z') {\r
-        return ch;\r
-    }\r
-    return ch - 32;\r
-}\r
-static int FX_HexToI(FX_BYTE ch)\r
-{\r
-    ch = FX_MakeUpper(ch);\r
-    return FX_IsDigit(ch) ? (ch - '0') : (ch - 55);\r
-}\r
-static const unsigned char url_encodeTable[128] = {\r
-    1,  1,  1,  1,             1,  1,  1,  1,\r
-    1,  1,  1,  1,             1,  1,  1,  1,\r
-    1,  1,  1,  1,             1,  1,  1,  1,\r
-    1,  1,  1,  1,             1,  1,  1,  1,\r
-    1,  0,  1,  1,             0,  1,  0,  0,\r
-    0,  0,  0,  0,             0,  0,  0,  0,\r
-    0,  0,  0,  0,             0,  0,  0,  0,\r
-    0,  0,  0,  0,             1,  0,  1,  0,\r
-    0,  0,  0,  0,             0,  0,  0,  0,\r
-    0,  0,  0,  0,             0,  0,  0,  0,\r
-    0,  0,  0,  0,             0,  0,  0,  0,\r
-    0,  0,  0,  1,             1,  1,  1,  0,\r
-    1,  0,  0,  0,             0,  0,  0,  0,\r
-    0,  0,  0,  0,             0,  0,  0,  0,\r
-    0,  0,  0,  0,             0,  0,  0,  0,\r
-    0,  0,  0,  1,             1,  1,  1,  1,\r
-};\r
-CFX_ByteString FX_UrlEncode(const CFX_WideString& wsUrl)\r
-{\r
-    const char arDigits[] = "0123456789ABCDEF";\r
-    CFX_ByteString rUrl;\r
-    int nLength = wsUrl.GetLength();\r
-    for (int i = 0; i < nLength; i++) {\r
-        FX_DWORD word = wsUrl.GetAt(i);\r
-        if (word > 0x7F || url_encodeTable[word] == 1) {\r
-            CFX_ByteString bsUri = CFX_ByteString::FromUnicode((FX_WORD)word);\r
-            int nByte = bsUri.GetLength();\r
-            for (int j = 0; j < nByte; j++) {\r
-                rUrl += '%';\r
-                FX_BYTE code = bsUri.GetAt(j);\r
-                rUrl += arDigits[code >> 4];\r
-                rUrl += arDigits[code & 0x0F];\r
-            }\r
-        } else {\r
-            rUrl += CFX_ByteString::FromUnicode((FX_WORD)word);\r
-        }\r
-    }\r
-    return rUrl;\r
-}\r
-CFX_WideString FX_UrlDecode(const CFX_ByteString& bsUrl)\r
-{\r
-    CFX_ByteString rUrl;\r
-    int nLength = bsUrl.GetLength();\r
-    for (int i = 0; i < nLength; i++) {\r
-        if (i < nLength - 2 && bsUrl[i] == '%' && FX_IsXDigit(bsUrl[i + 1]) && FX_IsXDigit(bsUrl[i + 2])) {\r
-            rUrl += (FX_HexToI(bsUrl[i + 1]) << 4 | FX_HexToI(bsUrl[i + 2]));\r
-            i += 2;\r
-        } else {\r
-            rUrl += bsUrl[i];\r
-        }\r
-    }\r
-    return CFX_WideString::FromLocal(rUrl);\r
-}\r
-CFX_ByteString FX_EncodeURI(const CFX_WideString& wsURI)\r
-{\r
-    const char arDigits[] = "0123456789ABCDEF";\r
-    CFX_ByteString rURI;\r
-    CFX_ByteString bsUri = wsURI.UTF8Encode();\r
-    int nLength = bsUri.GetLength();\r
-    for (int i = 0; i < nLength; i++) {\r
-        FX_BYTE code = bsUri.GetAt(i);\r
-        if (code > 0x7F || url_encodeTable[code] == 1) {\r
-            rURI += '%';\r
-            rURI += arDigits[code >> 4];\r
-            rURI += arDigits[code & 0x0F];\r
-        } else {\r
-            rURI += code;\r
-        }\r
-    }\r
-    return rURI;\r
-}\r
-CFX_WideString FX_DecodeURI(const CFX_ByteString& bsURI)\r
-{\r
-    CFX_ByteString rURI;\r
-    int nLength = bsURI.GetLength();\r
-    for (int i = 0; i < nLength; i++) {\r
-        if (i < nLength - 2 && bsURI[i] == '%' && FX_IsXDigit(bsURI[i + 1]) && FX_IsXDigit(bsURI[i + 2])) {\r
-            rURI += (FX_HexToI(bsURI[i + 1]) << 4 | FX_HexToI(bsURI[i + 2]));\r
-            i += 2;\r
-        } else {\r
-            rURI += bsURI[i];\r
-        }\r
-    }\r
-    return CFX_WideString::FromUTF8(rURI);\r
-}\r
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_\r
-class CFindFileData : public CFX_Object\r
-{\r
-public:\r
-    virtual ~CFindFileData() {}\r
-    HANDLE                             m_Handle;\r
-    FX_BOOL                            m_bEnd;\r
-};\r
-class CFindFileDataA : public CFindFileData\r
-{\r
-public:\r
-    virtual ~CFindFileDataA() {}\r
-    WIN32_FIND_DATAA   m_FindData;\r
-};\r
-class CFindFileDataW : public CFindFileData\r
-{\r
-public:\r
-    virtual ~CFindFileDataW() {}\r
-    WIN32_FIND_DATAW   m_FindData;\r
-};\r
-#endif\r
-void* FX_OpenFolder(FX_LPCSTR path)\r
-{\r
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_\r
-#ifndef _WIN32_WCE\r
-    CFindFileDataA* pData = FX_NEW CFindFileDataA;\r
-    if (!pData) {\r
-        return NULL;\r
-    }\r
-#ifdef _FX_WINAPI_PARTITION_DESKTOP_\r
-    pData->m_Handle = FindFirstFileA(CFX_ByteString(path) + "/*.*", &pData->m_FindData);\r
-#else\r
-    pData->m_Handle = FindFirstFileExA(CFX_ByteString(path) + "/*.*", FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0);\r
-#endif\r
-#else\r
-    CFindFileDataW* pData = FX_NEW CFindFileDataW;\r
-    if (!pData) {\r
-        return NULL;\r
-    }\r
-    pData->m_Handle = FindFirstFileW(CFX_WideString::FromLocal(path) + L"/*.*", &pData->m_FindData);\r
-#endif\r
-    if (pData->m_Handle == INVALID_HANDLE_VALUE) {\r
-        delete pData;\r
-        return NULL;\r
-    }\r
-    pData->m_bEnd = FALSE;\r
-    return pData;\r
-#else\r
-    DIR* dir = opendir(path);\r
-    return dir;\r
-#endif\r
-}\r
-void* FX_OpenFolder(FX_LPCWSTR path)\r
-{\r
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_\r
-    CFindFileDataW* pData = FX_NEW CFindFileDataW;\r
-    if (!pData) {\r
-        return NULL;\r
-    }\r
-#ifdef _FX_WINAPI_PARTITION_DESKTOP_\r
-    pData->m_Handle = FindFirstFileW(CFX_WideString(path) + L"/*.*", &pData->m_FindData);\r
-#else\r
-    pData->m_Handle = FindFirstFileExW(CFX_WideString(path) + L"/*.*", FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0);\r
-#endif\r
-    if (pData->m_Handle == INVALID_HANDLE_VALUE) {\r
-        delete pData;\r
-        return NULL;\r
-    }\r
-    pData->m_bEnd = FALSE;\r
-    return pData;\r
-#else\r
-    DIR* dir = opendir(CFX_ByteString::FromUnicode(path));\r
-    return dir;\r
-#endif\r
-}\r
-FX_BOOL FX_GetNextFile(void* handle, CFX_ByteString& filename, FX_BOOL& bFolder)\r
-{\r
-    if (handle == NULL) {\r
-        return FALSE;\r
-    }\r
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_\r
-#ifndef _WIN32_WCE\r
-    CFindFileDataA* pData = (CFindFileDataA*)handle;\r
-    if (pData->m_bEnd) {\r
-        return FALSE;\r
-    }\r
-    filename = pData->m_FindData.cFileName;\r
-    bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;\r
-    if (!FindNextFileA(pData->m_Handle, &pData->m_FindData)) {\r
-        pData->m_bEnd = TRUE;\r
-    }\r
-    return TRUE;\r
-#else\r
-    CFindFileDataW* pData = (CFindFileDataW*)handle;\r
-    if (pData->m_bEnd) {\r
-        return FALSE;\r
-    }\r
-    filename = CFX_ByteString::FromUnicode(pData->m_FindData.cFileName);\r
-    bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;\r
-    if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) {\r
-        pData->m_bEnd = TRUE;\r
-    }\r
-    return TRUE;\r
-#endif\r
-#elif defined(__native_client__)\r
-    abort();\r
-    return FALSE;\r
-#else\r
-    struct dirent *de = readdir((DIR*)handle);\r
-    if (de == NULL) {\r
-        return FALSE;\r
-    }\r
-    filename = de->d_name;\r
-    bFolder = de->d_type == DT_DIR;\r
-    return TRUE;\r
-#endif\r
-}\r
-FX_BOOL FX_GetNextFile(void* handle, CFX_WideString& filename, FX_BOOL& bFolder)\r
-{\r
-    if (handle == NULL) {\r
-        return FALSE;\r
-    }\r
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_\r
-    CFindFileDataW* pData = (CFindFileDataW*)handle;\r
-    if (pData->m_bEnd) {\r
-        return FALSE;\r
-    }\r
-    filename = pData->m_FindData.cFileName;\r
-    bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;\r
-    if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) {\r
-        pData->m_bEnd = TRUE;\r
-    }\r
-    return TRUE;\r
-#elif defined(__native_client__)\r
-    abort();\r
-    return FALSE;\r
-#else\r
-    struct dirent *de = readdir((DIR*)handle);\r
-    if (de == NULL) {\r
-        return FALSE;\r
-    }\r
-    filename = CFX_WideString::FromLocal(de->d_name);\r
-    bFolder = de->d_type == DT_DIR;\r
-    return TRUE;\r
-#endif\r
-}\r
-void FX_CloseFolder(void* handle)\r
-{\r
-    if (handle == NULL) {\r
-        return;\r
-    }\r
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_\r
-    CFindFileData* pData = (CFindFileData*)handle;\r
-    FindClose(pData->m_Handle);\r
-    delete pData;\r
-#else\r
-    closedir((DIR*)handle);\r
-#endif\r
-}\r
-FX_WCHAR FX_GetFolderSeparator()\r
-{\r
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_\r
-    return '\\';\r
-#else\r
-    return '/';\r
-#endif\r
-}\r
+// 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 "../../include/fxcrt/fx_basic.h"
+#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
+#include <sys/types.h>
+#include <dirent.h>
+#else
+#include <direct.h>
+#endif
+CFX_PrivateData::~CFX_PrivateData()
+{
+    ClearAll();
+}
+void FX_PRIVATEDATA::FreeData()
+{
+    if (m_pData == NULL) {
+        return;
+    }
+    if (m_bSelfDestruct) {
+        delete (CFX_DestructObject*)m_pData;
+    } else if (m_pCallback) {
+        m_pCallback(m_pData);
+    }
+}
+void CFX_PrivateData::AddData(FX_LPVOID pModuleId, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback, FX_BOOL bSelfDestruct)
+{
+    if (pModuleId == NULL) {
+        return;
+    }
+    FX_PRIVATEDATA* pList = m_DataList.GetData();
+    int count = m_DataList.GetSize();
+    for (int i = 0; i < count; i ++) {
+        if (pList[i].m_pModuleId == pModuleId) {
+            pList[i].FreeData();
+            pList[i].m_pData = pData;
+            pList[i].m_pCallback = callback;
+            return;
+        }
+    }
+    FX_PRIVATEDATA data = {pModuleId, pData, callback, bSelfDestruct};
+    m_DataList.Add(data);
+}
+void CFX_PrivateData::SetPrivateData(FX_LPVOID pModuleId, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback)
+{
+    AddData(pModuleId, pData, callback, FALSE);
+}
+void CFX_PrivateData::SetPrivateObj(FX_LPVOID pModuleId, CFX_DestructObject* pObj)
+{
+    AddData(pModuleId, pObj, NULL, TRUE);
+}
+FX_BOOL CFX_PrivateData::RemovePrivateData(FX_LPVOID pModuleId)
+{
+    if (pModuleId == NULL) {
+        return FALSE;
+    }
+    FX_PRIVATEDATA* pList = m_DataList.GetData();
+    int count = m_DataList.GetSize();
+    for (int i = 0; i < count; i ++) {
+        if (pList[i].m_pModuleId == pModuleId) {
+            m_DataList.RemoveAt(i);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+FX_LPVOID CFX_PrivateData::GetPrivateData(FX_LPVOID pModuleId)
+{
+    if (pModuleId == NULL) {
+        return NULL;
+    }
+    FX_PRIVATEDATA* pList = m_DataList.GetData();
+    int count = m_DataList.GetSize();
+    for (int i = 0; i < count; i ++) {
+        if (pList[i].m_pModuleId == pModuleId) {
+            return pList[i].m_pData;
+        }
+    }
+    return NULL;
+}
+void CFX_PrivateData::ClearAll()
+{
+    FX_PRIVATEDATA* pList = m_DataList.GetData();
+    int count = m_DataList.GetSize();
+    for (int i = 0; i < count; i ++) {
+        pList[i].FreeData();
+    }
+    m_DataList.RemoveAll();
+}
+void FX_atonum(FX_BSTR strc, FX_BOOL& bInteger, void* pData)
+{
+    if (FXSYS_memchr(strc.GetPtr(), '.', strc.GetLength()) == NULL) {
+        bInteger = TRUE;
+        int cc = 0, integer = 0;
+        FX_LPCSTR str = strc.GetCStr();
+        int len = strc.GetLength();
+        FX_BOOL bNegative = FALSE;
+        if (str[0] == '+') {
+            cc++;
+        } else if (str[0] == '-') {
+            bNegative = TRUE;
+            cc++;
+        }
+        while (cc < len) {
+            if (str[cc] < '0' || str[cc] > '9') {
+                break;
+            }
+            integer = integer * 10 + str[cc] - '0';
+            if (integer < 0) {
+                break;
+            }
+            cc ++;
+        }
+        if (bNegative) {
+            integer = -integer;
+        }
+        *(int*)pData = integer;
+    } else {
+        bInteger = FALSE;
+        *(FX_FLOAT*)pData = FX_atof(strc);
+    }
+}
+FX_FLOAT FX_atof(FX_BSTR strc)
+{
+    if (strc.GetLength() == 0) {
+        return 0.0;
+    }
+    int cc = 0;
+    FX_BOOL bNegative = FALSE;
+    FX_LPCSTR str = strc.GetCStr();
+    int len = strc.GetLength();
+    if (str[0] == '+') {
+        cc++;
+    } else if (str[0] == '-') {
+        bNegative = TRUE;
+        cc++;
+    }
+    while (cc < len) {
+        if (str[cc] != '+' && str[cc] != '-') {
+            break;
+        }
+        cc ++;
+    }
+    FX_FLOAT value = 0;
+    while (cc < len) {
+        if (str[cc] == '.') {
+            break;
+        }
+        value = value * 10 + str[cc] - '0';
+        cc ++;
+    }
+    static const FX_FLOAT fraction_scales[] = {0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f,
+                                               0.0000001f, 0.00000001f, 0.000000001f, 0.0000000001f, 0.00000000001f
+                                              };
+    int scale = 0;
+    if (cc < len && str[cc] == '.') {
+        cc ++;
+        while (cc < len) {
+            value += fraction_scales[scale] * (str[cc] - '0');
+            scale ++;
+            if (scale == sizeof fraction_scales / sizeof(FX_FLOAT)) {
+                break;
+            }
+            cc ++;
+        }
+    }
+    return bNegative ? -value : value;
+}
+static FX_BOOL FX_IsDigit(FX_BYTE ch)
+{
+    return (ch >= '0' && ch <= '9') ? TRUE : FALSE;
+}
+static FX_BOOL FX_IsXDigit(FX_BYTE ch)
+{
+    return (FX_IsDigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) ? TRUE : FALSE;
+}
+static FX_BYTE FX_MakeUpper(FX_BYTE ch)
+{
+    if (ch < 'a' || ch > 'z') {
+        return ch;
+    }
+    return ch - 32;
+}
+static int FX_HexToI(FX_BYTE ch)
+{
+    ch = FX_MakeUpper(ch);
+    return FX_IsDigit(ch) ? (ch - '0') : (ch - 55);
+}
+static const unsigned char url_encodeTable[128] = {
+    1,  1,  1,  1,             1,  1,  1,  1,
+    1,  1,  1,  1,             1,  1,  1,  1,
+    1,  1,  1,  1,             1,  1,  1,  1,
+    1,  1,  1,  1,             1,  1,  1,  1,
+    1,  0,  1,  1,             0,  1,  0,  0,
+    0,  0,  0,  0,             0,  0,  0,  0,
+    0,  0,  0,  0,             0,  0,  0,  0,
+    0,  0,  0,  0,             1,  0,  1,  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,             1,  1,  1,  0,
+    1,  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,             1,  1,  1,  1,
+};
+CFX_ByteString FX_UrlEncode(const CFX_WideString& wsUrl)
+{
+    const char arDigits[] = "0123456789ABCDEF";
+    CFX_ByteString rUrl;
+    int nLength = wsUrl.GetLength();
+    for (int i = 0; i < nLength; i++) {
+        FX_DWORD word = wsUrl.GetAt(i);
+        if (word > 0x7F || url_encodeTable[word] == 1) {
+            CFX_ByteString bsUri = CFX_ByteString::FromUnicode((FX_WORD)word);
+            int nByte = bsUri.GetLength();
+            for (int j = 0; j < nByte; j++) {
+                rUrl += '%';
+                FX_BYTE code = bsUri.GetAt(j);
+                rUrl += arDigits[code >> 4];
+                rUrl += arDigits[code & 0x0F];
+            }
+        } else {
+            rUrl += CFX_ByteString::FromUnicode((FX_WORD)word);
+        }
+    }
+    return rUrl;
+}
+CFX_WideString FX_UrlDecode(const CFX_ByteString& bsUrl)
+{
+    CFX_ByteString rUrl;
+    int nLength = bsUrl.GetLength();
+    for (int i = 0; i < nLength; i++) {
+        if (i < nLength - 2 && bsUrl[i] == '%' && FX_IsXDigit(bsUrl[i + 1]) && FX_IsXDigit(bsUrl[i + 2])) {
+            rUrl += (FX_HexToI(bsUrl[i + 1]) << 4 | FX_HexToI(bsUrl[i + 2]));
+            i += 2;
+        } else {
+            rUrl += bsUrl[i];
+        }
+    }
+    return CFX_WideString::FromLocal(rUrl);
+}
+CFX_ByteString FX_EncodeURI(const CFX_WideString& wsURI)
+{
+    const char arDigits[] = "0123456789ABCDEF";
+    CFX_ByteString rURI;
+    CFX_ByteString bsUri = wsURI.UTF8Encode();
+    int nLength = bsUri.GetLength();
+    for (int i = 0; i < nLength; i++) {
+        FX_BYTE code = bsUri.GetAt(i);
+        if (code > 0x7F || url_encodeTable[code] == 1) {
+            rURI += '%';
+            rURI += arDigits[code >> 4];
+            rURI += arDigits[code & 0x0F];
+        } else {
+            rURI += code;
+        }
+    }
+    return rURI;
+}
+CFX_WideString FX_DecodeURI(const CFX_ByteString& bsURI)
+{
+    CFX_ByteString rURI;
+    int nLength = bsURI.GetLength();
+    for (int i = 0; i < nLength; i++) {
+        if (i < nLength - 2 && bsURI[i] == '%' && FX_IsXDigit(bsURI[i + 1]) && FX_IsXDigit(bsURI[i + 2])) {
+            rURI += (FX_HexToI(bsURI[i + 1]) << 4 | FX_HexToI(bsURI[i + 2]));
+            i += 2;
+        } else {
+            rURI += bsURI[i];
+        }
+    }
+    return CFX_WideString::FromUTF8(rURI);
+}
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+class CFindFileData : public CFX_Object
+{
+public:
+    virtual ~CFindFileData() {}
+    HANDLE                             m_Handle;
+    FX_BOOL                            m_bEnd;
+};
+class CFindFileDataA : public CFindFileData
+{
+public:
+    virtual ~CFindFileDataA() {}
+    WIN32_FIND_DATAA   m_FindData;
+};
+class CFindFileDataW : public CFindFileData
+{
+public:
+    virtual ~CFindFileDataW() {}
+    WIN32_FIND_DATAW   m_FindData;
+};
+#endif
+void* FX_OpenFolder(FX_LPCSTR path)
+{
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+#ifndef _WIN32_WCE
+    CFindFileDataA* pData = FX_NEW CFindFileDataA;
+    if (!pData) {
+        return NULL;
+    }
+#ifdef _FX_WINAPI_PARTITION_DESKTOP_
+    pData->m_Handle = FindFirstFileA(CFX_ByteString(path) + "/*.*", &pData->m_FindData);
+#else
+    pData->m_Handle = FindFirstFileExA(CFX_ByteString(path) + "/*.*", FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0);
+#endif
+#else
+    CFindFileDataW* pData = FX_NEW CFindFileDataW;
+    if (!pData) {
+        return NULL;
+    }
+    pData->m_Handle = FindFirstFileW(CFX_WideString::FromLocal(path) + L"/*.*", &pData->m_FindData);
+#endif
+    if (pData->m_Handle == INVALID_HANDLE_VALUE) {
+        delete pData;
+        return NULL;
+    }
+    pData->m_bEnd = FALSE;
+    return pData;
+#else
+    DIR* dir = opendir(path);
+    return dir;
+#endif
+}
+void* FX_OpenFolder(FX_LPCWSTR path)
+{
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+    CFindFileDataW* pData = FX_NEW CFindFileDataW;
+    if (!pData) {
+        return NULL;
+    }
+#ifdef _FX_WINAPI_PARTITION_DESKTOP_
+    pData->m_Handle = FindFirstFileW(CFX_WideString(path) + L"/*.*", &pData->m_FindData);
+#else
+    pData->m_Handle = FindFirstFileExW(CFX_WideString(path) + L"/*.*", FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0);
+#endif
+    if (pData->m_Handle == INVALID_HANDLE_VALUE) {
+        delete pData;
+        return NULL;
+    }
+    pData->m_bEnd = FALSE;
+    return pData;
+#else
+    DIR* dir = opendir(CFX_ByteString::FromUnicode(path));
+    return dir;
+#endif
+}
+FX_BOOL FX_GetNextFile(void* handle, CFX_ByteString& filename, FX_BOOL& bFolder)
+{
+    if (handle == NULL) {
+        return FALSE;
+    }
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+#ifndef _WIN32_WCE
+    CFindFileDataA* pData = (CFindFileDataA*)handle;
+    if (pData->m_bEnd) {
+        return FALSE;
+    }
+    filename = pData->m_FindData.cFileName;
+    bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
+    if (!FindNextFileA(pData->m_Handle, &pData->m_FindData)) {
+        pData->m_bEnd = TRUE;
+    }
+    return TRUE;
+#else
+    CFindFileDataW* pData = (CFindFileDataW*)handle;
+    if (pData->m_bEnd) {
+        return FALSE;
+    }
+    filename = CFX_ByteString::FromUnicode(pData->m_FindData.cFileName);
+    bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
+    if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) {
+        pData->m_bEnd = TRUE;
+    }
+    return TRUE;
+#endif
+#elif defined(__native_client__)
+    abort();
+    return FALSE;
+#else
+    struct dirent *de = readdir((DIR*)handle);
+    if (de == NULL) {
+        return FALSE;
+    }
+    filename = de->d_name;
+    bFolder = de->d_type == DT_DIR;
+    return TRUE;
+#endif
+}
+FX_BOOL FX_GetNextFile(void* handle, CFX_WideString& filename, FX_BOOL& bFolder)
+{
+    if (handle == NULL) {
+        return FALSE;
+    }
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+    CFindFileDataW* pData = (CFindFileDataW*)handle;
+    if (pData->m_bEnd) {
+        return FALSE;
+    }
+    filename = pData->m_FindData.cFileName;
+    bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
+    if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) {
+        pData->m_bEnd = TRUE;
+    }
+    return TRUE;
+#elif defined(__native_client__)
+    abort();
+    return FALSE;
+#else
+    struct dirent *de = readdir((DIR*)handle);
+    if (de == NULL) {
+        return FALSE;
+    }
+    filename = CFX_WideString::FromLocal(de->d_name);
+    bFolder = de->d_type == DT_DIR;
+    return TRUE;
+#endif
+}
+void FX_CloseFolder(void* handle)
+{
+    if (handle == NULL) {
+        return;
+    }
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+    CFindFileData* pData = (CFindFileData*)handle;
+    FindClose(pData->m_Handle);
+    delete pData;
+#else
+    closedir((DIR*)handle);
+#endif
+}
+FX_WCHAR FX_GetFolderSeparator()
+{
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+    return '\\';
+#else
+    return '/';
+#endif
+}