[System.Security.SecurityCritical] // auto-generated public override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already Debug.Assert(count >= 0, "[DBCSCodePageEncoding.GetByteCount]count is negative"); Debug.Assert(chars != null, "[DBCSCodePageEncoding.GetByteCount]chars is null"); // Assert because we shouldn't be able to have a null encoder. Debug.Assert(EncoderFallback != null, "[DBCSCodePageEncoding.GetByteCount]Attempting to use null fallback"); CheckMemorySection(); // Get any left over characters char charLeftOver = (char)0; if (encoder != null) { charLeftOver = encoder.charLeftOver; // Only count if encoder.m_throwOnOverflow if (encoder.InternalHasFallbackBuffer && encoder.FallbackBuffer.Remaining > 0) throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, EncodingName, encoder.Fallback.GetType())); } // prepare our end int byteCount = 0; char* charEnd = chars + count; // For fallback we will need a fallback buffer EncoderFallbackBuffer fallbackBuffer = null; EncoderFallbackBufferHelper fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); // We may have a left over character from last time, try and process it. if (charLeftOver > 0) { Debug.Assert(Char.IsHighSurrogate(charLeftOver), "[DBCSCodePageEncoding.GetByteCount]leftover character should be high surrogate"); Debug.Assert(encoder != null, "[DBCSCodePageEncoding.GetByteCount]Expect to have encoder if we have a charLeftOver"); // Since left over char was a surrogate, it'll have to be fallen back. // Get Fallback fallbackBuffer = encoder.FallbackBuffer; fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(chars, charEnd, encoder, false); // This will fallback a pair if *chars is a low surrogate fallbackHelper.InternalFallback(charLeftOver, ref chars); } // Now we may have fallback char[] already (from the encoder) // We have to use fallback method. char ch; while ((ch = (fallbackBuffer == null) ? '\0' : fallbackHelper.InternalGetNextChar()) != 0 || chars < charEnd) { // First unwind any fallback if (ch == 0) { // No fallback, just get next char ch = *chars; chars++; } // get byte for this char ushort sTemp = mapUnicodeToBytes[ch]; // Check for fallback, this'll catch surrogate pairs too. if (sTemp == 0 && ch != (char)0) { if (fallbackBuffer == null) { // Initialize the buffer if (encoder == null) fallbackBuffer = EncoderFallback.CreateFallbackBuffer(); else fallbackBuffer = encoder.FallbackBuffer; fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(charEnd - count, charEnd, encoder, false); } // Get Fallback fallbackHelper.InternalFallback(ch, ref chars); continue; } // We'll use this one byteCount++; if (sTemp >= 0x100) byteCount++; } return (int)byteCount; }
[System.Security.SecurityCritical] // auto-generated public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already Debug.Assert(bytes != null, "[DBCSCodePageEncoding.GetBytes]bytes is null"); Debug.Assert(byteCount >= 0, "[DBCSCodePageEncoding.GetBytes]byteCount is negative"); Debug.Assert(chars != null, "[DBCSCodePageEncoding.GetBytes]chars is null"); Debug.Assert(charCount >= 0, "[DBCSCodePageEncoding.GetBytes]charCount is negative"); // Assert because we shouldn't be able to have a null encoder. Debug.Assert(EncoderFallback != null, "[DBCSCodePageEncoding.GetBytes]Attempting to use null encoder fallback"); CheckMemorySection(); // For fallback we will need a fallback buffer EncoderFallbackBuffer fallbackBuffer = null; // prepare our end char* charEnd = chars + charCount; char* charStart = chars; byte* byteStart = bytes; byte* byteEnd = bytes + byteCount; EncoderFallbackBufferHelper fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); // Get any left over characters char charLeftOver = (char)0; if (encoder != null) { charLeftOver = encoder.charLeftOver; Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), "[DBCSCodePageEncoding.GetBytes]leftover character should be high surrogate"); // Go ahead and get the fallback buffer (need leftover fallback if converting) fallbackBuffer = encoder.FallbackBuffer; fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(chars, charEnd, encoder, true); // If we're not converting we must not have a fallback buffer if (encoder.m_throwOnOverflow && fallbackBuffer.Remaining > 0) throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, EncodingName, encoder.Fallback.GetType())); // We may have a left over character from last time, try and process it. if (charLeftOver > 0) { Debug.Assert(encoder != null, "[DBCSCodePageEncoding.GetBytes]Expect to have encoder if we have a charLeftOver"); // Since left over char was a surrogate, it'll have to be fallen back. // Get Fallback fallbackHelper.InternalFallback(charLeftOver, ref chars); } } // Now we may have fallback char[] already from the encoder // Go ahead and do it, including the fallback. char ch; while ((ch = (fallbackBuffer == null) ? '\0' : fallbackHelper.InternalGetNextChar()) != 0 || chars < charEnd) { // First unwind any fallback if (ch == 0) { // No fallback, just get next char ch = *chars; chars++; } // get byte for this char ushort sTemp = mapUnicodeToBytes[ch]; // Check for fallback, this'll catch surrogate pairs too. if (sTemp == 0 && ch != (char)0) { if (fallbackBuffer == null) { // Initialize the buffer Debug.Assert(encoder == null, "[DBCSCodePageEncoding.GetBytes]Expected delayed create fallback only if no encoder."); fallbackBuffer = EncoderFallback.CreateFallbackBuffer(); fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(charEnd - charCount, charEnd, encoder, true); } // Get Fallback fallbackHelper.InternalFallback(ch, ref chars); continue; } // We'll use this one (or two) // Bounds check // Go ahead and add it, lead byte 1st if necessary if (sTemp >= 0x100) { if (bytes + 1 >= byteEnd) { // didn't use this char, we'll throw or use buffer if (fallbackBuffer == null || fallbackHelper.bFallingBack == false) { Debug.Assert(chars > charStart, "[DBCSCodePageEncoding.GetBytes]Expected chars to have advanced (double byte case)"); chars--; // don't use last char } else fallbackBuffer.MovePrevious(); // don't use last fallback ThrowBytesOverflow(encoder, chars == charStart); // throw ? break; // don't throw, stop } *bytes = unchecked((byte)(sTemp >> 8)); bytes++; } // Single byte else if (bytes >= byteEnd) { // didn't use this char, we'll throw or use buffer if (fallbackBuffer == null || fallbackHelper.bFallingBack == false) { Debug.Assert(chars > charStart, "[DBCSCodePageEncoding.GetBytes]Expected chars to have advanced (single byte case)"); chars--; // don't use last char } else fallbackBuffer.MovePrevious(); // don't use last fallback ThrowBytesOverflow(encoder, chars == charStart); // throw ? break; // don't throw, stop } *bytes = unchecked((byte)(sTemp & 0xff)); bytes++; } // encoder stuff if we have one if (encoder != null) { // Fallback stuck it in encoder if necessary, but we have to clear MustFlush cases if (fallbackBuffer != null && !fallbackHelper.bUsedEncoder) // Clear it in case of MustFlush encoder.charLeftOver = (char)0; // Set our chars used count encoder.m_charsUsed = (int)(chars - charStart); } return (int)(bytes - byteStart); }
public override unsafe int GetBytes(char *chars, int charCount, byte *bytes, int byteCount, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already Debug.Assert(bytes != null, "[SBCSCodePageEncoding.GetBytes]bytes is null"); Debug.Assert(byteCount >= 0, "[SBCSCodePageEncoding.GetBytes]byteCount is negative"); Debug.Assert(chars != null, "[SBCSCodePageEncoding.GetBytes]chars is null"); Debug.Assert(charCount >= 0, "[SBCSCodePageEncoding.GetBytes]charCount is negative"); // Assert because we shouldn't be able to have a null encoder. Debug.Assert(EncoderFallback != null, "[SBCSCodePageEncoding.GetBytes]Attempting to use null encoder fallback"); CheckMemorySection(); // Need to test fallback EncoderReplacementFallback fallback = null; // Get any left over characters char charLeftOver = (char)0; if (encoder != null) { charLeftOver = encoder.charLeftOver; Debug.Assert(charLeftOver == 0 || char.IsHighSurrogate(charLeftOver), "[SBCSCodePageEncoding.GetBytes]leftover character should be high surrogate"); fallback = encoder.Fallback as EncoderReplacementFallback; // Verify that we have no fallbackbuffer, for SBCS its always empty, so just assert Debug.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || encoder.FallbackBuffer.Remaining == 0, "[SBCSCodePageEncoding.GetBytes]Expected empty fallback buffer at start"); // if (encoder.m_throwOnOverflow && encoder.InternalHasFallbackBuffer && // encoder.FallbackBuffer.Remaining > 0) // throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", // EncodingName, encoder.Fallback.GetType())); } else { // If we aren't using default fallback then we may have a complicated count. fallback = EncoderFallback as EncoderReplacementFallback; } // prepare our end char *charEnd = chars + charCount; byte *byteStart = bytes; char *charStart = chars; // See if we do the fast default or slightly slower fallback if (fallback != null && fallback.MaxCharCount == 1) { // Make sure our fallback character is valid first byte bReplacement = _mapUnicodeToBytes[fallback.DefaultString[0]]; // Check for replacements in range, otherwise fall back to slow version. if (bReplacement != 0) { // We should have exactly as many output bytes as input bytes, unless there's a leftover // character, in which case we may need one more. // If we had a leftover character we will have to add a ? (This happens if they had a funky // fallback last time, but not this time. We can't spit any out though, // because with fallback encoder each surrogate is treated as a separate code point) if (charLeftOver > 0) { // Have to have room // Throw even if doing no throw version because this is just 1 char, // so buffer will never be big enough if (byteCount == 0) { ThrowBytesOverflow(encoder, true); } // This'll make sure we still have more room and also make sure our return value is correct. *(bytes++) = bReplacement; byteCount--; // We used one of the ones we were counting. } // This keeps us from overrunning our output buffer if (byteCount < charCount) { // Throw or make buffer smaller? ThrowBytesOverflow(encoder, byteCount < 1); // Just use what we can charEnd = chars + byteCount; } // Simple way while (chars < charEnd) { char ch2 = *chars; chars++; byte bTemp = _mapUnicodeToBytes[ch2]; // Check for fallback if (bTemp == 0 && ch2 != (char)0) { *bytes = bReplacement; } else { *bytes = bTemp; } bytes++; } // Clear encoder if (encoder != null) { encoder.charLeftOver = (char)0; encoder.m_charsUsed = (int)(chars - charStart); } return((int)(bytes - byteStart)); } } // Slower version, have to do real fallback. // For fallback we may need a fallback buffer, we know we aren't default fallback EncoderFallbackBuffer fallbackBuffer = null; // prepare our end byte *byteEnd = bytes + byteCount; EncoderFallbackBufferHelper fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); // We may have a left over character from last time, try and process it. if (charLeftOver > 0) { // Since left over char was a surrogate, it'll have to be fallen back. // Get Fallback Debug.Assert(encoder != null, "[SBCSCodePageEncoding.GetBytes]Expect to have encoder if we have a charLeftOver"); fallbackBuffer = encoder.FallbackBuffer; fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(chars, charEnd, encoder, true); // This will fallback a pair if *chars is a low surrogate fallbackHelper.InternalFallback(charLeftOver, ref chars); if (fallbackBuffer.Remaining > byteEnd - bytes) { // Throw it, if we don't have enough for this we never will ThrowBytesOverflow(encoder, true); } } // Now we may have fallback char[] already from the encoder fallback above // Go ahead and do it, including the fallback. char ch; while ((ch = (fallbackBuffer == null) ? '\0' : fallbackHelper.InternalGetNextChar()) != 0 || chars < charEnd) { // First unwind any fallback if (ch == 0) { // No fallback, just get next char ch = *chars; chars++; } // get byte for this char byte bTemp = _mapUnicodeToBytes[ch]; // Check for fallback, this'll catch surrogate pairs too. if (bTemp == 0 && ch != (char)0) { // Get Fallback if (fallbackBuffer == null) { // Create & init fallback buffer if (encoder == null) { fallbackBuffer = EncoderFallback.CreateFallbackBuffer(); } else { fallbackBuffer = encoder.FallbackBuffer; } fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); // chars has moved so we need to remember figure it out so Exception fallback // index will be correct fallbackHelper.InternalInitialize(charEnd - charCount, charEnd, encoder, true); } // Make sure we have enough room. Each fallback char will be 1 output char // (or recursion exception will be thrown) fallbackHelper.InternalFallback(ch, ref chars); if (fallbackBuffer.Remaining > byteEnd - bytes) { // Didn't use this char, reset it Debug.Assert(chars > charStart, "[SBCSCodePageEncoding.GetBytes]Expected chars to have advanced (fallback)"); chars--; fallbackHelper.InternalReset(); // Throw it & drop this data ThrowBytesOverflow(encoder, chars == charStart); break; } continue; } // We'll use this one // Bounds check if (bytes >= byteEnd) { // didn't use this char, we'll throw or use buffer Debug.Assert(fallbackBuffer == null || fallbackHelper.bFallingBack == false, "[SBCSCodePageEncoding.GetBytes]Expected to NOT be falling back"); if (fallbackBuffer == null || fallbackHelper.bFallingBack == false) { Debug.Assert(chars > charStart, "[SBCSCodePageEncoding.GetBytes]Expected chars to have advanced (normal)"); chars--; // don't use last char } ThrowBytesOverflow(encoder, chars == charStart); // throw ? break; // don't throw, stop } // Go ahead and add it *bytes = bTemp; bytes++; } // encoder stuff if we have one if (encoder != null) { // Fallback stuck it in encoder if necessary, but we have to clear MustFlush cases if (fallbackBuffer != null && !fallbackHelper.bUsedEncoder) { // Clear it in case of MustFlush encoder.charLeftOver = (char)0; } // Set our chars used count encoder.m_charsUsed = (int)(chars - charStart); } // Expect Empty fallback buffer for SBCS Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[SBCSEncoding.GetBytes]Expected Empty fallback buffer at end"); return((int)(bytes - byteStart)); }
// GetByteCount // Note: We start by assuming that the output will be the same as count. Having // an encoder or fallback may change that assumption public override unsafe int GetByteCount(char *chars, int count, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already Debug.Assert(count >= 0, "[SBCSCodePageEncoding.GetByteCount]count is negative"); Debug.Assert(chars != null, "[SBCSCodePageEncoding.GetByteCount]chars is null"); // Assert because we shouldn't be able to have a null encoder. Debug.Assert(EncoderFallback != null, "[SBCSCodePageEncoding.GetByteCount]Attempting to use null fallback"); CheckMemorySection(); // Need to test fallback EncoderReplacementFallback fallback = null; // Get any left over characters char charLeftOver = (char)0; if (encoder != null) { charLeftOver = encoder.charLeftOver; Debug.Assert(charLeftOver == 0 || char.IsHighSurrogate(charLeftOver), "[SBCSCodePageEncoding.GetByteCount]leftover character should be high surrogate"); fallback = encoder.Fallback as EncoderReplacementFallback; // Verify that we have no fallbackbuffer, actually for SBCS this is always empty, so just assert Debug.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || encoder.FallbackBuffer.Remaining == 0, "[SBCSCodePageEncoding.GetByteCount]Expected empty fallback buffer at start"); } else { // If we aren't using default fallback then we may have a complicated count. fallback = EncoderFallback as EncoderReplacementFallback; } if ((fallback != null && fallback.MaxCharCount == 1) /* || bIsBestFit*/) { // Replacement fallback encodes surrogate pairs as two ?? (or two whatever), so return size is always // same as input size. // Note that no existing SBCS code pages map code points to supplementary characters, so this is easy. // We could however have 1 extra byte if the last call had an encoder and a funky fallback and // if we don't use the funky fallback this time. // Do we have an extra char left over from last time? if (charLeftOver > 0) { count++; } return(count); } // It had a funky fallback, so it's more complicated // May need buffer later EncoderFallbackBuffer fallbackBuffer = null; // prepare our end int byteCount = 0; char *charEnd = chars + count; EncoderFallbackBufferHelper fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); // We may have a left over character from last time, try and process it. if (charLeftOver > 0) { // Since leftover char was a surrogate, it'll have to be fallen back. // Get fallback Debug.Assert(encoder != null, "[SBCSCodePageEncoding.GetByteCount]Expect to have encoder if we have a charLeftOver"); fallbackBuffer = encoder.FallbackBuffer; fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(chars, charEnd, encoder, false); // This will fallback a pair if *chars is a low surrogate fallbackHelper.InternalFallback(charLeftOver, ref chars); } // Now we may have fallback char[] already from the encoder // Go ahead and do it, including the fallback. char ch; while ((ch = (fallbackBuffer == null) ? '\0' : fallbackHelper.InternalGetNextChar()) != 0 || chars < charEnd) { // First unwind any fallback if (ch == 0) { // No fallback, just get next char ch = *chars; chars++; } // get byte for this char byte bTemp = _mapUnicodeToBytes[ch]; // Check for fallback, this'll catch surrogate pairs too. if (bTemp == 0 && ch != (char)0) { if (fallbackBuffer == null) { // Create & init fallback buffer if (encoder == null) { fallbackBuffer = EncoderFallback.CreateFallbackBuffer(); } else { fallbackBuffer = encoder.FallbackBuffer; } fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); // chars has moved so we need to remember figure it out so Exception fallback // index will be correct fallbackHelper.InternalInitialize(charEnd - count, charEnd, encoder, false); } // Get Fallback fallbackHelper.InternalFallback(ch, ref chars); continue; } // We'll use this one byteCount++; } Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[SBCSEncoding.GetByteCount]Expected Empty fallback buffer at end"); return((int)byteCount); }
internal unsafe bool Fallback(char charFallback) { // Do the fallback return(fallbackBufferHelper.InternalFallback(charFallback, ref _chars)); }
public unsafe override int GetByteCount(char* chars, int count, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already Debug.Assert(count >= 0, "[SBCSCodePageEncoding.GetByteCount]count is negative"); Debug.Assert(chars != null, "[SBCSCodePageEncoding.GetByteCount]chars is null"); // Assert because we shouldn't be able to have a null encoder. Debug.Assert(EncoderFallback != null, "[SBCSCodePageEncoding.GetByteCount]Attempting to use null fallback"); CheckMemorySection(); // Need to test fallback EncoderReplacementFallback fallback = null; // Get any left over characters char charLeftOver = (char)0; if (encoder != null) { charLeftOver = encoder.charLeftOver; Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), "[SBCSCodePageEncoding.GetByteCount]leftover character should be high surrogate"); fallback = encoder.Fallback as EncoderReplacementFallback; // Verify that we have no fallbackbuffer, actually for SBCS this is always empty, so just assert Debug.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || encoder.FallbackBuffer.Remaining == 0, "[SBCSCodePageEncoding.GetByteCount]Expected empty fallback buffer at start"); } else { // If we aren't using default fallback then we may have a complicated count. fallback = EncoderFallback as EncoderReplacementFallback; } if ((fallback != null && fallback.MaxCharCount == 1)/* || bIsBestFit*/) { // Replacement fallback encodes surrogate pairs as two ?? (or two whatever), so return size is always // same as input size. // Note that no existing SBCS code pages map code points to supplementary characters, so this is easy. // We could however have 1 extra byte if the last call had an encoder and a funky fallback and // if we don't use the funky fallback this time. // Do we have an extra char left over from last time? if (charLeftOver > 0) count++; return (count); } // It had a funky fallback, so it's more complicated // May need buffer later EncoderFallbackBuffer fallbackBuffer = null; // prepare our end int byteCount = 0; char* charEnd = chars + count; EncoderFallbackBufferHelper fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); // We may have a left over character from last time, try and process it. if (charLeftOver > 0) { // Since leftover char was a surrogate, it'll have to be fallen back. // Get fallback Debug.Assert(encoder != null, "[SBCSCodePageEncoding.GetByteCount]Expect to have encoder if we have a charLeftOver"); fallbackBuffer = encoder.FallbackBuffer; fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(chars, charEnd, encoder, false); // This will fallback a pair if *chars is a low surrogate fallbackHelper.InternalFallback(charLeftOver, ref chars); } // Now we may have fallback char[] already from the encoder // Go ahead and do it, including the fallback. char ch; while ((ch = (fallbackBuffer == null) ? '\0' : fallbackHelper.InternalGetNextChar()) != 0 || chars < charEnd) { // First unwind any fallback if (ch == 0) { // No fallback, just get next char ch = *chars; chars++; } // get byte for this char byte bTemp = _mapUnicodeToBytes[ch]; // Check for fallback, this'll catch surrogate pairs too. if (bTemp == 0 && ch != (char)0) { if (fallbackBuffer == null) { // Create & init fallback buffer if (encoder == null) fallbackBuffer = EncoderFallback.CreateFallbackBuffer(); else fallbackBuffer = encoder.FallbackBuffer; fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); // chars has moved so we need to remember figure it out so Exception fallback // index will be correct fallbackHelper.InternalInitialize(charEnd - count, charEnd, encoder, false); } // Get Fallback fallbackHelper.InternalFallback(ch, ref chars); continue; } // We'll use this one byteCount++; } Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[SBCSEncoding.GetByteCount]Expected Empty fallback buffer at end"); return (int)byteCount; }
public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder) { // Just need to ASSERT, this is called by something else internal that checked parameters already Debug.Assert(bytes != null, "[SBCSCodePageEncoding.GetBytes]bytes is null"); Debug.Assert(byteCount >= 0, "[SBCSCodePageEncoding.GetBytes]byteCount is negative"); Debug.Assert(chars != null, "[SBCSCodePageEncoding.GetBytes]chars is null"); Debug.Assert(charCount >= 0, "[SBCSCodePageEncoding.GetBytes]charCount is negative"); // Assert because we shouldn't be able to have a null encoder. Debug.Assert(EncoderFallback != null, "[SBCSCodePageEncoding.GetBytes]Attempting to use null encoder fallback"); CheckMemorySection(); // Need to test fallback EncoderReplacementFallback fallback = null; // Get any left over characters char charLeftOver = (char)0; if (encoder != null) { charLeftOver = encoder.charLeftOver; Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver), "[SBCSCodePageEncoding.GetBytes]leftover character should be high surrogate"); fallback = encoder.Fallback as EncoderReplacementFallback; // Verify that we have no fallbackbuffer, for SBCS its always empty, so just assert Debug.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer || encoder.FallbackBuffer.Remaining == 0, "[SBCSCodePageEncoding.GetBytes]Expected empty fallback buffer at start"); // if (encoder.m_throwOnOverflow && encoder.InternalHasFallbackBuffer && // encoder.FallbackBuffer.Remaining > 0) // throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", // EncodingName, encoder.Fallback.GetType())); } else { // If we aren't using default fallback then we may have a complicated count. fallback = EncoderFallback as EncoderReplacementFallback; } // prepare our end char* charEnd = chars + charCount; byte* byteStart = bytes; char* charStart = chars; // See if we do the fast default or slightly slower fallback if (fallback != null && fallback.MaxCharCount == 1) { // Make sure our fallback character is valid first byte bReplacement = _mapUnicodeToBytes[fallback.DefaultString[0]]; // Check for replacements in range, otherwise fall back to slow version. if (bReplacement != 0) { // We should have exactly as many output bytes as input bytes, unless there's a leftover // character, in which case we may need one more. // If we had a leftover character we will have to add a ? (This happens if they had a funky // fallback last time, but not this time. We can't spit any out though, // because with fallback encoder each surrogate is treated as a separate code point) if (charLeftOver > 0) { // Have to have room // Throw even if doing no throw version because this is just 1 char, // so buffer will never be big enough if (byteCount == 0) ThrowBytesOverflow(encoder, true); // This'll make sure we still have more room and also make sure our return value is correct. *(bytes++) = bReplacement; byteCount--; // We used one of the ones we were counting. } // This keeps us from overrunning our output buffer if (byteCount < charCount) { // Throw or make buffer smaller? ThrowBytesOverflow(encoder, byteCount < 1); // Just use what we can charEnd = chars + byteCount; } // Simple way while (chars < charEnd) { char ch2 = *chars; chars++; byte bTemp = _mapUnicodeToBytes[ch2]; // Check for fallback if (bTemp == 0 && ch2 != (char)0) *bytes = bReplacement; else *bytes = bTemp; bytes++; } // Clear encoder if (encoder != null) { encoder.charLeftOver = (char)0; encoder.m_charsUsed = (int)(chars - charStart); } return (int)(bytes - byteStart); } } // Slower version, have to do real fallback. // For fallback we may need a fallback buffer, we know we aren't default fallback EncoderFallbackBuffer fallbackBuffer = null; // prepare our end byte* byteEnd = bytes + byteCount; EncoderFallbackBufferHelper fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); // We may have a left over character from last time, try and process it. if (charLeftOver > 0) { // Since left over char was a surrogate, it'll have to be fallen back. // Get Fallback Debug.Assert(encoder != null, "[SBCSCodePageEncoding.GetBytes]Expect to have encoder if we have a charLeftOver"); fallbackBuffer = encoder.FallbackBuffer; fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); fallbackHelper.InternalInitialize(chars, charEnd, encoder, true); // This will fallback a pair if *chars is a low surrogate fallbackHelper.InternalFallback(charLeftOver, ref chars); if (fallbackBuffer.Remaining > byteEnd - bytes) { // Throw it, if we don't have enough for this we never will ThrowBytesOverflow(encoder, true); } } // Now we may have fallback char[] already from the encoder fallback above // Go ahead and do it, including the fallback. char ch; while ((ch = (fallbackBuffer == null) ? '\0' : fallbackHelper.InternalGetNextChar()) != 0 || chars < charEnd) { // First unwind any fallback if (ch == 0) { // No fallback, just get next char ch = *chars; chars++; } // get byte for this char byte bTemp = _mapUnicodeToBytes[ch]; // Check for fallback, this'll catch surrogate pairs too. if (bTemp == 0 && ch != (char)0) { // Get Fallback if (fallbackBuffer == null) { // Create & init fallback buffer if (encoder == null) fallbackBuffer = EncoderFallback.CreateFallbackBuffer(); else fallbackBuffer = encoder.FallbackBuffer; fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer); // chars has moved so we need to remember figure it out so Exception fallback // index will be correct fallbackHelper.InternalInitialize(charEnd - charCount, charEnd, encoder, true); } // Make sure we have enough room. Each fallback char will be 1 output char // (or recursion exception will be thrown) fallbackHelper.InternalFallback(ch, ref chars); if (fallbackBuffer.Remaining > byteEnd - bytes) { // Didn't use this char, reset it Debug.Assert(chars > charStart, "[SBCSCodePageEncoding.GetBytes]Expected chars to have advanced (fallback)"); chars--; fallbackHelper.InternalReset(); // Throw it & drop this data ThrowBytesOverflow(encoder, chars == charStart); break; } continue; } // We'll use this one // Bounds check if (bytes >= byteEnd) { // didn't use this char, we'll throw or use buffer Debug.Assert(fallbackBuffer == null || fallbackHelper.bFallingBack == false, "[SBCSCodePageEncoding.GetBytes]Expected to NOT be falling back"); if (fallbackBuffer == null || fallbackHelper.bFallingBack == false) { Debug.Assert(chars > charStart, "[SBCSCodePageEncoding.GetBytes]Expected chars to have advanced (normal)"); chars--; // don't use last char } ThrowBytesOverflow(encoder, chars == charStart); // throw ? break; // don't throw, stop } // Go ahead and add it *bytes = bTemp; bytes++; } // encoder stuff if we have one if (encoder != null) { // Fallback stuck it in encoder if necessary, but we have to clear MustFlush cases if (fallbackBuffer != null && !fallbackHelper.bUsedEncoder) // Clear it in case of MustFlush encoder.charLeftOver = (char)0; // Set our chars used count encoder.m_charsUsed = (int)(chars - charStart); } // Expect Empty fallback buffer for SBCS Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0, "[SBCSEncoding.GetBytes]Expected Empty fallback buffer at end"); return (int)(bytes - byteStart); }