[System.Security.SecurityCritical] // auto-generated internal unsafe EncodingCharBuffer(EncodingNLS enc, DecoderNLS decoder, char* charStart, int charCount, byte* byteStart, int byteCount) { _enc = enc; _decoder = decoder; _chars = charStart; _charStart = charStart; _charEnd = charStart + charCount; _byteStart = byteStart; _bytes = byteStart; _byteEnd = byteStart + byteCount; if (_decoder == null) _fallbackBuffer = enc.DecoderFallback.CreateFallbackBuffer(); else _fallbackBuffer = _decoder.FallbackBuffer; // If we're getting chars or getting char count we don't expect to have // to remember fallbacks between calls (so it should be empty) Debug.Assert(_fallbackBuffer.Remaining == 0, "[Encoding.EncodingCharBuffer.EncodingCharBuffer]Expected empty fallback buffer for getchars/charcount"); _fallbackBufferHelper = new DecoderFallbackBufferHelper(_fallbackBuffer); _fallbackBufferHelper.InternalInitialize(_bytes, _charEnd); }
[System.Security.SecurityCritical] // auto-generated public override unsafe int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already Debug.Assert(bytes != null, "[DBCSCodePageEncoding.GetChars]bytes is null"); Debug.Assert(byteCount >= 0, "[DBCSCodePageEncoding.GetChars]byteCount is negative"); Debug.Assert(chars != null, "[DBCSCodePageEncoding.GetChars]chars is null"); Debug.Assert(charCount >= 0, "[DBCSCodePageEncoding.GetChars]charCount is negative"); CheckMemorySection(); // Fix our decoder DBCSDecoder decoder = (DBCSDecoder)baseDecoder; // We'll need to know where the end is byte* byteStart = bytes; byte* byteEnd = bytes + byteCount; char* charStart = chars; char* charEnd = chars + charCount; bool bUsedDecoder = false; // Get our fallback DecoderFallbackBuffer fallbackBuffer = null; // Shouldn't have anything in fallback buffer for GetChars Debug.Assert(decoder == null || !decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[DBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start"); DecoderFallbackBufferHelper fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer); // If we have a left over byte, use it if (decoder != null && decoder.bLeftOver > 0) { // We have a left over byte? if (byteCount == 0) { // No input though if (!decoder.MustFlush) { // Don't have to flush return 0; } // Well, we're flushing, so use '?' or fallback // fallback leftover byte Debug.Assert(fallbackBuffer == null, "[DBCSCodePageEncoding.GetChars]Expected empty fallback"); fallbackBuffer = decoder.FallbackBuffer; fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(bytes, charEnd); // If no room, it's hopeless, this was 1st fallback byte[] byteBuffer = new byte[] { unchecked((byte)decoder.bLeftOver) }; if (!fallbackHelper.InternalFallback(byteBuffer, bytes, ref chars)) ThrowCharsOverflow(decoder, true); decoder.bLeftOver = 0; // Done, return it return (int)(chars - charStart); } // Get our full info int iBytes = decoder.bLeftOver << 8; iBytes |= (*bytes); bytes++; // Look up our bytes char cDecoder = mapBytesToUnicode[iBytes]; if (cDecoder == UNKNOWN_CHAR_FLAG && iBytes != 0) { Debug.Assert(fallbackBuffer == null, "[DBCSCodePageEncoding.GetChars]Expected empty fallback for two bytes"); fallbackBuffer = decoder.FallbackBuffer; fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(byteEnd - byteCount, charEnd); byte[] byteBuffer = new byte[] { unchecked((byte)(iBytes >> 8)), unchecked((byte)iBytes) }; if (!fallbackHelper.InternalFallback(byteBuffer, bytes, ref chars)) ThrowCharsOverflow(decoder, true); } else { // Do we have output room?, hopeless if not, this is first char if (chars >= charEnd) ThrowCharsOverflow(decoder, true); *(chars++) = cDecoder; } } // Loop, paying attention to our fallbacks. while (bytes < byteEnd) { // Faster if don't use *bytes++; int iBytes = *bytes; bytes++; char c = mapBytesToUnicode[iBytes]; // See if it was a double byte character if (c == LEAD_BYTE_CHAR) { // Its a lead byte if (bytes < byteEnd) { // Have another to use, so use it iBytes <<= 8; iBytes |= *bytes; bytes++; c = mapBytesToUnicode[iBytes]; } else { // No input left if (decoder == null || decoder.MustFlush) { // have to flush anyway, set to unknown so we use fallback c = UNKNOWN_CHAR_FLAG; } else { // Stick it in decoder bUsedDecoder = true; decoder.bLeftOver = (byte)iBytes; break; } } } // See if it was unknown if (c == UNKNOWN_CHAR_FLAG && iBytes != 0) { if (fallbackBuffer == null) { if (decoder == null) fallbackBuffer = DecoderFallback.CreateFallbackBuffer(); else fallbackBuffer = decoder.FallbackBuffer; fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(byteEnd - byteCount, charEnd); } // Do fallback byte[] byteBuffer = null; if (iBytes < 0x100) byteBuffer = new byte[] { unchecked((byte)iBytes) }; else byteBuffer = new byte[] { unchecked((byte)(iBytes >> 8)), unchecked((byte)iBytes) }; if (!fallbackHelper.InternalFallback(byteBuffer, bytes, ref chars)) { // May or may not throw, but we didn't get these byte(s) Debug.Assert(bytes >= byteStart + byteBuffer.Length, "[DBCSCodePageEncoding.GetChars]Expected bytes to have advanced for fallback"); bytes -= byteBuffer.Length; // didn't use these byte(s) fallbackHelper.InternalReset(); // Didn't fall this back ThrowCharsOverflow(decoder, bytes == byteStart); // throw? break; // don't throw, but stop loop } } else { // Do we have buffer room? if (chars >= charEnd) { // May or may not throw, but we didn't get these byte(s) Debug.Assert(bytes > byteStart, "[DBCSCodePageEncoding.GetChars]Expected bytes to have advanced for lead byte"); bytes--; // unused byte if (iBytes >= 0x100) { Debug.Assert(bytes > byteStart, "[DBCSCodePageEncoding.GetChars]Expected bytes to have advanced for trail byte"); bytes--; // 2nd unused byte } ThrowCharsOverflow(decoder, bytes == byteStart); // throw? break; // don't throw, but stop loop } *(chars++) = c; } } // We already stuck it in encoder if necessary, but we have to clear cases where nothing new got into decoder if (decoder != null) { // Clear it in case of MustFlush if (bUsedDecoder == false) { decoder.bLeftOver = 0; } // Remember our count decoder.m_bytesUsed = (int)(bytes - byteStart); } // Shouldn't have anything in fallback buffer for GetChars Debug.Assert(decoder == null || !decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[DBCSCodePageEncoding.GetChars]Expected empty fallback buffer at end"); // Return length of our output return (int)(chars - charStart); }
[System.Security.SecurityCritical] // auto-generated public override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder) { // Just assert, we're called internally so these should be safe, checked already Debug.Assert(bytes != null, "[DBCSCodePageEncoding.GetCharCount]bytes is null"); Debug.Assert(count >= 0, "[DBCSCodePageEncoding.GetCharCount]byteCount is negative"); CheckMemorySection(); // Fix our decoder DBCSDecoder decoder = (DBCSDecoder)baseDecoder; // Get our fallback DecoderFallbackBuffer fallbackBuffer = null; // We'll need to know where the end is byte* byteEnd = bytes + count; int charCount = count; // Assume 1 char / byte // Shouldn't have anything in fallback buffer for GetCharCount // (don't have to check m_throwOnOverflow for count) Debug.Assert(decoder == null || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer at start"); DecoderFallbackBufferHelper fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer); // If we have a left over byte, use it if (decoder != null && decoder.bLeftOver > 0) { // We have a left over byte? if (count == 0) { // No input though if (!decoder.MustFlush) { // Don't have to flush return 0; } Debug.Assert(fallbackBuffer == null, "[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer"); fallbackBuffer = decoder.FallbackBuffer; fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(bytes, null); byte[] byteBuffer = new byte[] { unchecked((byte)decoder.bLeftOver) }; return fallbackHelper.InternalFallback(byteBuffer, bytes); } // Get our full info int iBytes = decoder.bLeftOver << 8; iBytes |= (*bytes); bytes++; // This is either 1 known char or fallback // Already counted 1 char // Look up our bytes char cDecoder = mapBytesToUnicode[iBytes]; if (cDecoder == 0 && iBytes != 0) { // Deallocate preallocated one charCount--; // We'll need a fallback Debug.Assert(fallbackBuffer == null, "[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer for unknown pair"); fallbackBuffer = decoder.FallbackBuffer; fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(byteEnd - count, null); // Do fallback, we know there are 2 bytes byte[] byteBuffer = new byte[] { unchecked((byte)(iBytes >> 8)), unchecked((byte)iBytes) }; charCount += fallbackHelper.InternalFallback(byteBuffer, bytes); } // else we already reserved space for this one. } // Loop, watch out for fallbacks while (bytes < byteEnd) { // Faster if don't use *bytes++; int iBytes = *bytes; bytes++; char c = mapBytesToUnicode[iBytes]; // See if it was a double byte character if (c == LEAD_BYTE_CHAR) { // It's a lead byte charCount--; // deallocate preallocated lead byte if (bytes < byteEnd) { // Have another to use, so use it iBytes <<= 8; iBytes |= *bytes; bytes++; c = mapBytesToUnicode[iBytes]; } else { // No input left if (decoder == null || decoder.MustFlush) { // have to flush anyway, set to unknown so we use fallback charCount++; // reallocate deallocated lead byte c = UNKNOWN_CHAR_FLAG; } else { // We'll stick it in decoder break; } } } // See if it was unknown. // Unknown and known chars already allocated, but fallbacks aren't if (c == UNKNOWN_CHAR_FLAG && iBytes != 0) { if (fallbackBuffer == null) { if (decoder == null) fallbackBuffer = DecoderFallback.CreateFallbackBuffer(); else fallbackBuffer = decoder.FallbackBuffer; fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(byteEnd - count, null); } // Do fallback charCount--; // Get rid of preallocated extra char byte[] byteBuffer = null; if (iBytes < 0x100) byteBuffer = new byte[] { unchecked((byte)iBytes) }; else byteBuffer = new byte[] { unchecked((byte)(iBytes >> 8)), unchecked((byte)iBytes) }; charCount += fallbackHelper.InternalFallback(byteBuffer, bytes); } } // Shouldn't have anything in fallback buffer for GetChars Debug.Assert(decoder == null || !decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer at end"); // Return our count return charCount; }
public override unsafe int GetChars(byte *bytes, int byteCount, char *chars, int charCount, DecoderNLS decoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already Debug.Assert(bytes != null, "[SBCSCodePageEncoding.GetChars]bytes is null"); Debug.Assert(byteCount >= 0, "[SBCSCodePageEncoding.GetChars]byteCount is negative"); Debug.Assert(chars != null, "[SBCSCodePageEncoding.GetChars]chars is null"); Debug.Assert(charCount >= 0, "[SBCSCodePageEncoding.GetChars]charCount is negative"); CheckMemorySection(); // See if we have best fit bool bUseBestFit = false; // Do it fast way if using ? replacement or best fit fallbacks byte *byteEnd = bytes + byteCount; byte *byteStart = bytes; char *charStart = chars; // Only need decoder fallback buffer if not using default replacement fallback or best fit fallback. DecoderReplacementFallback fallback = null; if (decoder == null) { fallback = DecoderFallback as DecoderReplacementFallback; bUseBestFit = DecoderFallback is InternalDecoderBestFitFallback; } else { fallback = decoder.Fallback as DecoderReplacementFallback; bUseBestFit = decoder.Fallback is InternalDecoderBestFitFallback; Debug.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[SBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start"); } if (bUseBestFit || (fallback != null && fallback.MaxCharCount == 1)) { // Try it the fast way char replacementChar; if (fallback == null) { replacementChar = '?'; // Best fit always has ? for fallback for SBCS } else { replacementChar = fallback.DefaultString[0]; } // Need byteCount chars, otherwise too small buffer if (charCount < byteCount) { // Need at least 1 output byte, throw if must throw ThrowCharsOverflow(decoder, charCount < 1); // Not throwing, use what we can byteEnd = bytes + charCount; } // Quick loop, just do '?' replacement because we don't have fallbacks for decodings. while (bytes < byteEnd) { char c; if (bUseBestFit) { if (arrayBytesBestFit == null) { ReadBestFitTable(); } c = arrayBytesBestFit[*bytes]; } else { c = _mapBytesToUnicode[*bytes]; } bytes++; if (c == UNKNOWN_CHAR) { // This is an invalid byte in the ASCII encoding. *chars = replacementChar; } else { *chars = c; } chars++; } // bytes & chars used are the same if (decoder != null) { decoder.m_bytesUsed = (int)(bytes - byteStart); } return((int)(chars - charStart)); } // Slower way's going to need a fallback buffer DecoderFallbackBuffer fallbackBuffer = null; byte[] byteBuffer = new byte[1]; char * charEnd = chars + charCount; DecoderFallbackBufferHelper fallbackHelper = new DecoderFallbackBufferHelper(null); // Not quite so fast loop while (bytes < byteEnd) { // Faster if don't use *bytes++; char c = _mapBytesToUnicode[*bytes]; bytes++; // See if it was unknown if (c == UNKNOWN_CHAR) { // Make sure we have a fallback buffer if (fallbackBuffer == null) { if (decoder == null) { fallbackBuffer = DecoderFallback.CreateFallbackBuffer(); } else { fallbackBuffer = decoder.FallbackBuffer; } fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(byteEnd - byteCount, charEnd); } // Use fallback buffer Debug.Assert(bytes > byteStart, "[SBCSCodePageEncoding.GetChars]Expected bytes to have advanced already (unknown byte)"); byteBuffer[0] = *(bytes - 1); // Fallback adds fallback to chars, but doesn't increment chars unless the whole thing fits. if (!fallbackHelper.InternalFallback(byteBuffer, bytes, ref chars)) { // May or may not throw, but we didn't get this byte bytes--; // unused byte fallbackHelper.InternalReset(); // Didn't fall this back ThrowCharsOverflow(decoder, bytes == byteStart); // throw? break; // don't throw, but stop loop } } else { // Make sure we have buffer space if (chars >= charEnd) { Debug.Assert(bytes > byteStart, "[SBCSCodePageEncoding.GetChars]Expected bytes to have advanced already (known byte)"); bytes--; // unused byte ThrowCharsOverflow(decoder, bytes == byteStart); // throw? break; // don't throw, but stop loop } *(chars) = c; chars++; } } // Might have had decoder fallback stuff. if (decoder != null) { decoder.m_bytesUsed = (int)(bytes - byteStart); } // Expect Empty fallback buffer for GetChars Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[SBCSEncoding.GetChars]Expected Empty fallback buffer at end"); return((int)(chars - charStart)); }
// This is internal and called by something else, public override unsafe int GetCharCount(byte *bytes, int count, DecoderNLS decoder) { // Just assert, we're called internally so these should be safe, checked already Debug.Assert(bytes != null, "[SBCSCodePageEncoding.GetCharCount]bytes is null"); Debug.Assert(count >= 0, "[SBCSCodePageEncoding.GetCharCount]byteCount is negative"); CheckMemorySection(); // See if we have best fit bool bUseBestFit = false; // Only need decoder fallback buffer if not using default replacement fallback or best fit fallback. DecoderReplacementFallback fallback = null; if (decoder == null) { fallback = DecoderFallback as DecoderReplacementFallback; bUseBestFit = DecoderFallback is InternalDecoderBestFitFallback; } else { fallback = decoder.Fallback as DecoderReplacementFallback; bUseBestFit = decoder.Fallback is InternalDecoderBestFitFallback; Debug.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[SBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start"); } if (bUseBestFit || (fallback != null && fallback.MaxCharCount == 1)) { // Just return length, SBCS stay the same length because they don't map to surrogate // pairs and we don't have a decoder fallback. return(count); } // Might need one of these later DecoderFallbackBuffer fallbackBuffer = null; DecoderFallbackBufferHelper fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer); // Have to do it the hard way. // Assume charCount will be == count int charCount = count; byte[] byteBuffer = new byte[1]; // Do it our fast way byte *byteEnd = bytes + count; // Quick loop while (bytes < byteEnd) { // Faster if don't use *bytes++; char c; c = _mapBytesToUnicode[*bytes]; bytes++; // If unknown we have to do fallback count if (c == UNKNOWN_CHAR) { // Must have a fallback buffer if (fallbackBuffer == null) { // Need to adjust count so we get real start if (decoder == null) { fallbackBuffer = DecoderFallback.CreateFallbackBuffer(); } else { fallbackBuffer = decoder.FallbackBuffer; } fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(byteEnd - count, null); } // Use fallback buffer byteBuffer[0] = *(bytes - 1); charCount--; // We'd already reserved one for *(bytes-1) charCount += fallbackHelper.InternalFallback(byteBuffer, bytes); } } // Fallback buffer must be empty Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[SBCSEncoding.GetCharCount]Expected Empty fallback buffer at end"); // Converted sequence is same length as input return(charCount); }
public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS decoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already Debug.Assert(bytes != null, "[SBCSCodePageEncoding.GetChars]bytes is null"); Debug.Assert(byteCount >= 0, "[SBCSCodePageEncoding.GetChars]byteCount is negative"); Debug.Assert(chars != null, "[SBCSCodePageEncoding.GetChars]chars is null"); Debug.Assert(charCount >= 0, "[SBCSCodePageEncoding.GetChars]charCount is negative"); CheckMemorySection(); // See if we have best fit bool bUseBestFit = false; // Do it fast way if using ? replacement or best fit fallbacks byte* byteEnd = bytes + byteCount; byte* byteStart = bytes; char* charStart = chars; // Only need decoder fallback buffer if not using default replacement fallback or best fit fallback. DecoderReplacementFallback fallback = null; if (decoder == null) { fallback = DecoderFallback as DecoderReplacementFallback; bUseBestFit = DecoderFallback is InternalDecoderBestFitFallback; } else { fallback = decoder.Fallback as DecoderReplacementFallback; bUseBestFit = decoder.Fallback is InternalDecoderBestFitFallback; Debug.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[SBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start"); } if (bUseBestFit || (fallback != null && fallback.MaxCharCount == 1)) { // Try it the fast way char replacementChar; if (fallback == null) replacementChar = '?'; // Best fit always has ? for fallback for SBCS else replacementChar = fallback.DefaultString[0]; // Need byteCount chars, otherwise too small buffer if (charCount < byteCount) { // Need at least 1 output byte, throw if must throw ThrowCharsOverflow(decoder, charCount < 1); // Not throwing, use what we can byteEnd = bytes + charCount; } // Quick loop, just do '?' replacement because we don't have fallbacks for decodings. while (bytes < byteEnd) { char c; if (bUseBestFit) { if (arrayBytesBestFit == null) { ReadBestFitTable(); } c = arrayBytesBestFit[*bytes]; } else c = _mapBytesToUnicode[*bytes]; bytes++; if (c == UNKNOWN_CHAR) // This is an invalid byte in the ASCII encoding. *chars = replacementChar; else *chars = c; chars++; } // bytes & chars used are the same if (decoder != null) decoder.m_bytesUsed = (int)(bytes - byteStart); return (int)(chars - charStart); } // Slower way's going to need a fallback buffer DecoderFallbackBuffer fallbackBuffer = null; byte[] byteBuffer = new byte[1]; char* charEnd = chars + charCount; DecoderFallbackBufferHelper fallbackHelper = new DecoderFallbackBufferHelper( decoder != null ? decoder.FallbackBuffer : DecoderFallback.CreateFallbackBuffer()); // Not quite so fast loop while (bytes < byteEnd) { // Faster if don't use *bytes++; char c = _mapBytesToUnicode[*bytes]; bytes++; // See if it was unknown if (c == UNKNOWN_CHAR) { // Make sure we have a fallback buffer if (fallbackBuffer == null) { if (decoder == null) fallbackBuffer = DecoderFallback.CreateFallbackBuffer(); else fallbackBuffer = decoder.FallbackBuffer; fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(byteEnd - byteCount, charEnd); } // Use fallback buffer Debug.Assert(bytes > byteStart, "[SBCSCodePageEncoding.GetChars]Expected bytes to have advanced already (unknown byte)"); byteBuffer[0] = *(bytes - 1); // Fallback adds fallback to chars, but doesn't increment chars unless the whole thing fits. if (!fallbackHelper.InternalFallback(byteBuffer, bytes, ref chars)) { // May or may not throw, but we didn't get this byte bytes--; // unused byte fallbackHelper.InternalReset(); // Didn't fall this back ThrowCharsOverflow(decoder, bytes == byteStart); // throw? break; // don't throw, but stop loop } } else { // Make sure we have buffer space if (chars >= charEnd) { Debug.Assert(bytes > byteStart, "[SBCSCodePageEncoding.GetChars]Expected bytes to have advanced already (known byte)"); bytes--; // unused byte ThrowCharsOverflow(decoder, bytes == byteStart); // throw? break; // don't throw, but stop loop } *(chars) = c; chars++; } } // Might have had decoder fallback stuff. if (decoder != null) decoder.m_bytesUsed = (int)(bytes - byteStart); // Expect Empty fallback buffer for GetChars Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[SBCSEncoding.GetChars]Expected Empty fallback buffer at end"); return (int)(chars - charStart); }
public unsafe override int GetCharCount(byte* bytes, int count, DecoderNLS decoder) { // Just assert, we're called internally so these should be safe, checked already Debug.Assert(bytes != null, "[SBCSCodePageEncoding.GetCharCount]bytes is null"); Debug.Assert(count >= 0, "[SBCSCodePageEncoding.GetCharCount]byteCount is negative"); CheckMemorySection(); // See if we have best fit bool bUseBestFit = false; // Only need decoder fallback buffer if not using default replacement fallback or best fit fallback. DecoderReplacementFallback fallback = null; if (decoder == null) { fallback = DecoderFallback as DecoderReplacementFallback; bUseBestFit = DecoderFallback is InternalDecoderBestFitFallback; } else { fallback = decoder.Fallback as DecoderReplacementFallback; bUseBestFit = decoder.Fallback is InternalDecoderBestFitFallback; Debug.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0, "[SBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start"); } if (bUseBestFit || (fallback != null && fallback.MaxCharCount == 1)) { // Just return length, SBCS stay the same length because they don't map to surrogate // pairs and we don't have a decoder fallback. return count; } // Might need one of these later DecoderFallbackBuffer fallbackBuffer = null; DecoderFallbackBufferHelper fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer); // Have to do it the hard way. // Assume charCount will be == count int charCount = count; byte[] byteBuffer = new byte[1]; // Do it our fast way byte* byteEnd = bytes + count; // Quick loop while (bytes < byteEnd) { // Faster if don't use *bytes++; char c; c = _mapBytesToUnicode[*bytes]; bytes++; // If unknown we have to do fallback count if (c == UNKNOWN_CHAR) { // Must have a fallback buffer if (fallbackBuffer == null) { // Need to adjust count so we get real start if (decoder == null) fallbackBuffer = DecoderFallback.CreateFallbackBuffer(); else fallbackBuffer = decoder.FallbackBuffer; fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(byteEnd - count, null); } // Use fallback buffer byteBuffer[0] = *(bytes - 1); charCount--; // We'd already reserved one for *(bytes-1) charCount += fallbackHelper.InternalFallback(byteBuffer, bytes); } } // Fallback buffer must be empty Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[SBCSEncoding.GetCharCount]Expected Empty fallback buffer at end"); // Converted sequence is same length as input return charCount; }