| // 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/fgas/crt/fgas_codepage.h" |
| |
| void FX_SwapByteOrder(FX_WCHAR* pStr, int32_t iLength) { |
| ASSERT(pStr != NULL); |
| if (iLength < 0) { |
| iLength = FXSYS_wcslen(pStr); |
| } |
| uint16_t wch; |
| if (sizeof(FX_WCHAR) > 2) { |
| while (iLength-- > 0) { |
| wch = (uint16_t)*pStr; |
| wch = (wch >> 8) | (wch << 8); |
| wch &= 0x00FF; |
| *pStr++ = wch; |
| } |
| } else { |
| while (iLength-- > 0) { |
| wch = (uint16_t)*pStr; |
| wch = (wch >> 8) | (wch << 8); |
| *pStr++ = wch; |
| } |
| } |
| } |
| void FX_SwapByteOrderCopy(const FX_WCHAR* pSrc, |
| FX_WCHAR* pDst, |
| int32_t iLength) { |
| ASSERT(pSrc != NULL && pDst != NULL); |
| if (iLength < 0) { |
| iLength = FXSYS_wcslen(pSrc); |
| } |
| uint16_t wch; |
| if (sizeof(FX_WCHAR) > 2) { |
| while (iLength-- > 0) { |
| wch = (uint16_t)*pSrc++; |
| wch = (wch >> 8) | (wch << 8); |
| wch &= 0x00FF; |
| *pDst++ = wch; |
| } |
| } else { |
| while (iLength-- > 0) { |
| wch = (uint16_t)*pSrc++; |
| wch = (wch >> 8) | (wch << 8); |
| *pDst++ = wch; |
| } |
| } |
| } |
| void FX_UTF16ToWChar(void* pBuffer, int32_t iLength) { |
| ASSERT(pBuffer != NULL && iLength > 0); |
| if (sizeof(FX_WCHAR) == 2) { |
| return; |
| } |
| uint16_t* pSrc = (uint16_t*)pBuffer; |
| FX_WCHAR* pDst = (FX_WCHAR*)pBuffer; |
| while (--iLength >= 0) { |
| pDst[iLength] = (FX_WCHAR)pSrc[iLength]; |
| } |
| } |
| void FX_UTF16ToWCharCopy(const uint16_t* pUTF16, |
| FX_WCHAR* pWChar, |
| int32_t iLength) { |
| 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) { |
| ASSERT(pBuffer != NULL && iLength > 0); |
| if (sizeof(FX_WCHAR) == 2) { |
| return; |
| } |
| const FX_WCHAR* pSrc = (const FX_WCHAR*)pBuffer; |
| uint16_t* pDst = (uint16_t*)pBuffer; |
| while (--iLength >= 0) { |
| *pDst++ = (uint16_t)*pSrc++; |
| } |
| } |
| void FX_WCharToUTF16Copy(const FX_WCHAR* pWChar, |
| uint16_t* pUTF16, |
| int32_t iLength) { |
| 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++ = (uint16_t)*pWChar++; |
| } |
| } |
| } |
| inline uint32_t FX_DWordFromBytes(const uint8_t* pStr) { |
| return FXBSTR_ID(pStr[3], pStr[2], pStr[1], pStr[0]); |
| } |
| inline uint16_t FX_WordFromBytes(const uint8_t* pStr) { |
| return (pStr[1] << 8 | pStr[0]); |
| } |
| int32_t FX_DecodeString(uint16_t 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); |
| uint32_t 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; |
| } |