diff options
Diffstat (limited to 'src/mscorlib/src/System/Text/DecoderReplacementFallback.cs')
-rw-r--r-- | src/mscorlib/src/System/Text/DecoderReplacementFallback.cs | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Text/DecoderReplacementFallback.cs b/src/mscorlib/src/System/Text/DecoderReplacementFallback.cs new file mode 100644 index 0000000000..c732d15816 --- /dev/null +++ b/src/mscorlib/src/System/Text/DecoderReplacementFallback.cs @@ -0,0 +1,209 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Text +{ + using System; + using System.Diagnostics.Contracts; + + [Serializable] + public sealed class DecoderReplacementFallback : DecoderFallback + { + // Our variables + private String strDefault; + + // Construction. Default replacement fallback uses no best fit and ? replacement string + public DecoderReplacementFallback() : this("?") + { + } + + public DecoderReplacementFallback(String replacement) + { + if (replacement == null) + throw new ArgumentNullException("replacement"); + Contract.EndContractBlock(); + + // Make sure it doesn't have bad surrogate pairs + bool bFoundHigh=false; + for (int i = 0; i < replacement.Length; i++) + { + // Found a surrogate? + if (Char.IsSurrogate(replacement,i)) + { + // High or Low? + if (Char.IsHighSurrogate(replacement, i)) + { + // if already had a high one, stop + if (bFoundHigh) + break; // break & throw at the bFoundHIgh below + bFoundHigh = true; + } + else + { + // Low, did we have a high? + if (!bFoundHigh) + { + // Didn't have one, make if fail when we stop + bFoundHigh = true; + break; + } + + // Clear flag + bFoundHigh = false; + } + } + // If last was high we're in trouble (not surrogate so not low surrogate, so break) + else if (bFoundHigh) + break; + } + if (bFoundHigh) + throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex", "replacement")); + + strDefault = replacement; + } + + public String DefaultString + { + get + { + return strDefault; + } + } + + public override DecoderFallbackBuffer CreateFallbackBuffer() + { + return new DecoderReplacementFallbackBuffer(this); + } + + // Maximum number of characters that this instance of this fallback could return + public override int MaxCharCount + { + get + { + return strDefault.Length; + } + } + + public override bool Equals(Object value) + { + DecoderReplacementFallback that = value as DecoderReplacementFallback; + if (that != null) + { + return (this.strDefault == that.strDefault); + } + return (false); + } + + public override int GetHashCode() + { + return strDefault.GetHashCode(); + } + } + + + + public sealed class DecoderReplacementFallbackBuffer : DecoderFallbackBuffer + { + // Store our default string + private String strDefault; + int fallbackCount = -1; + int fallbackIndex = -1; + + // Construction + public DecoderReplacementFallbackBuffer(DecoderReplacementFallback fallback) + { + this.strDefault = fallback.DefaultString; + } + + // Fallback Methods + public override bool Fallback(byte[] bytesUnknown, int index) + { + // We expect no previous fallback in our buffer + // We can't call recursively but others might (note, we don't test on last char!!!) + if (fallbackCount >= 1) + { + ThrowLastBytesRecursive(bytesUnknown); + } + + // Go ahead and get our fallback + if (strDefault.Length == 0) + return false; + + fallbackCount = strDefault.Length; + fallbackIndex = -1; + + return true; + } + + public override char GetNextChar() + { + // We want it to get < 0 because == 0 means that the current/last character is a fallback + // and we need to detect recursion. We could have a flag but we already have this counter. + fallbackCount--; + fallbackIndex++; + + // Do we have anything left? 0 is now last fallback char, negative is nothing left + if (fallbackCount < 0) + return '\0'; + + // Need to get it out of the buffer. + // Make sure it didn't wrap from the fast count-- path + if (fallbackCount == int.MaxValue) + { + fallbackCount = -1; + return '\0'; + } + + // Now make sure its in the expected range + Contract.Assert(fallbackIndex < strDefault.Length && fallbackIndex >= 0, + "Index exceeds buffer range"); + + return strDefault[fallbackIndex]; + } + + public override bool MovePrevious() + { + // Back up one, only if we just processed the last character (or earlier) + if (fallbackCount >= -1 && fallbackIndex >= 0) + { + fallbackIndex--; + fallbackCount++; + return true; + } + + // Return false 'cause we couldn't do it. + return false; + } + + // How many characters left to output? + public override int Remaining + { + get + { + // Our count is 0 for 1 character left. + return (fallbackCount < 0) ? 0 : fallbackCount; + } + } + + // Clear the buffer + [System.Security.SecuritySafeCritical] // auto-generated + public override unsafe void Reset() + { + fallbackCount = -1; + fallbackIndex = -1; + byteStart = null; + } + + // This version just counts the fallback and doesn't actually copy anything. + [System.Security.SecurityCritical] // auto-generated + internal unsafe override int InternalFallback(byte[] bytes, byte* pBytes) + // Right now this has both bytes and bytes[], since we might have extra bytes, hence the + // array, and we might need the index, hence the byte* + { + // return our replacement string Length + return strDefault.Length; + } + } +} + |