michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "unicpriv.h" michael@0: #include "nsUnicodeDecodeHelper.h" michael@0: #include "nsAutoPtr.h" michael@0: michael@0: //---------------------------------------------------------------------- michael@0: // Class nsUnicodeDecodeHelper [implementation] michael@0: nsresult nsUnicodeDecodeHelper::ConvertByTable( michael@0: const char * aSrc, michael@0: int32_t * aSrcLength, michael@0: char16_t * aDest, michael@0: int32_t * aDestLength, michael@0: uScanClassID aScanClass, michael@0: uShiftInTable * aShiftInTable, michael@0: uMappingTable * aMappingTable, michael@0: bool aErrorSignal) michael@0: { michael@0: const char * src = aSrc; michael@0: int32_t srcLen = *aSrcLength; michael@0: char16_t * dest = aDest; michael@0: char16_t * destEnd = aDest + *aDestLength; michael@0: michael@0: char16_t med; michael@0: int32_t bcr; // byte count for read michael@0: nsresult res = NS_OK; michael@0: michael@0: while ((srcLen > 0) && (dest < destEnd)) { michael@0: bool charFound; michael@0: if (aScanClass == uMultibytesCharset) { michael@0: NS_ASSERTION(aShiftInTable, "shift table missing"); michael@0: charFound = uScanShift(aShiftInTable, nullptr, (uint8_t *)src, michael@0: reinterpret_cast(&med), srcLen, michael@0: (uint32_t *)&bcr); michael@0: } else { michael@0: charFound = uScan(aScanClass, nullptr, (uint8_t *)src, michael@0: reinterpret_cast(&med), michael@0: srcLen, (uint32_t *)&bcr); michael@0: } michael@0: if (!charFound) { michael@0: res = NS_OK_UDEC_MOREINPUT; michael@0: break; michael@0: } michael@0: michael@0: if (!uMapCode((uTable*) aMappingTable, static_cast(med), reinterpret_cast(dest))) { michael@0: if (med < 0x20) { michael@0: // somehow some table miss the 0x00 - 0x20 part michael@0: *dest = med; michael@0: } else { michael@0: if (aErrorSignal) { michael@0: res = NS_ERROR_ILLEGAL_INPUT; michael@0: break; michael@0: } michael@0: // Unicode replacement value for unmappable chars michael@0: *dest = 0xfffd; michael@0: } michael@0: } michael@0: michael@0: src += bcr; michael@0: srcLen -= bcr; michael@0: dest++; michael@0: } michael@0: michael@0: if ((srcLen > 0) && (res == NS_OK)) res = NS_OK_UDEC_MOREOUTPUT; michael@0: michael@0: *aSrcLength = src - aSrc; michael@0: *aDestLength = dest - aDest; michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsUnicodeDecodeHelper::ConvertByMultiTable( michael@0: const char * aSrc, michael@0: int32_t * aSrcLength, michael@0: char16_t * aDest, michael@0: int32_t * aDestLength, michael@0: int32_t aTableCount, michael@0: const uRange * aRangeArray, michael@0: uScanClassID * aScanClassArray, michael@0: uMappingTable ** aMappingTable, michael@0: bool aErrorSignal) michael@0: { michael@0: uint8_t * src = (uint8_t *)aSrc; michael@0: int32_t srcLen = *aSrcLength; michael@0: char16_t * dest = aDest; michael@0: char16_t * destEnd = aDest + *aDestLength; michael@0: michael@0: char16_t med; michael@0: int32_t bcr; // byte count for read michael@0: nsresult res = NS_OK; michael@0: int32_t i; michael@0: michael@0: while ((srcLen > 0) && (dest < destEnd)) michael@0: { michael@0: bool done= false; michael@0: bool passRangeCheck = false; michael@0: bool passScan = false; michael@0: for (i=0; (!done) && (i(&med), srcLen, michael@0: (uint32_t *)&bcr)) michael@0: { michael@0: passScan = true; michael@0: done = uMapCode((uTable*) aMappingTable[i], michael@0: static_cast(med), michael@0: reinterpret_cast(dest)); michael@0: } // if (uScan ... ) michael@0: } // if Range michael@0: } // for loop michael@0: michael@0: if(passRangeCheck && (! passScan)) michael@0: { michael@0: if (res != NS_ERROR_ILLEGAL_INPUT) michael@0: res = NS_OK_UDEC_MOREINPUT; michael@0: break; michael@0: } michael@0: if(! done) michael@0: { michael@0: bcr = 1; michael@0: if ((uint8_t)*src < 0x20) { michael@0: // somehow some table miss the 0x00 - 0x20 part michael@0: *dest = *src; michael@0: } else if(*src == (uint8_t) 0xa0) { michael@0: // handle nbsp michael@0: *dest = 0x00a0; michael@0: } else { michael@0: // we need to decide how many byte we skip. We can use uScan to do this michael@0: for (i=0; i(&med), srcLen, michael@0: (uint32_t*)&bcr)) michael@0: { michael@0: // match the patten michael@0: michael@0: int32_t k; michael@0: for(k = 1; k < bcr; k++) michael@0: { michael@0: if(0 == (src[k] & 0x80)) michael@0: { // only skip if all bytes > 0x80 michael@0: // if we hit bytes <= 0x80, skip only one byte michael@0: bcr = 1; michael@0: break; michael@0: } michael@0: } michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: // treat it as NSBR if bcr == 1 and it is 0xa0 michael@0: if ((1==bcr)&&(*src == (uint8_t)0xa0 )) { michael@0: *dest = 0x00a0; michael@0: } else { michael@0: if (aErrorSignal) { michael@0: res = NS_ERROR_ILLEGAL_INPUT; michael@0: break; michael@0: } michael@0: *dest = 0xfffd; michael@0: } michael@0: } michael@0: } michael@0: michael@0: src += bcr; michael@0: srcLen -= bcr; michael@0: dest++; michael@0: } // while michael@0: michael@0: if ((srcLen > 0) && (res == NS_OK)) res = NS_OK_UDEC_MOREOUTPUT; michael@0: michael@0: *aSrcLength = src - (uint8_t *)aSrc; michael@0: *aDestLength = dest - aDest; michael@0: return res; michael@0: } michael@0: michael@0: nsresult nsUnicodeDecodeHelper::ConvertByFastTable( michael@0: const char * aSrc, michael@0: int32_t * aSrcLength, michael@0: char16_t * aDest, michael@0: int32_t * aDestLength, michael@0: const char16_t * aFastTable, michael@0: int32_t aTableSize, michael@0: bool aErrorSignal) michael@0: { michael@0: uint8_t * src = (uint8_t *)aSrc; michael@0: uint8_t * srcEnd = src; michael@0: char16_t * dest = aDest; michael@0: michael@0: nsresult res; michael@0: if (*aSrcLength > *aDestLength) { michael@0: srcEnd += (*aDestLength); michael@0: res = NS_PARTIAL_MORE_OUTPUT; michael@0: } else { michael@0: srcEnd += (*aSrcLength); michael@0: res = NS_OK; michael@0: } michael@0: michael@0: for (; src buff(new char [buffSize]); michael@0: michael@0: char * p = buff; michael@0: for (int32_t i=0; i