Refactoring the ARM Hardware Intrinsics based on the latest design decisions. (#26895)
[mono-project.git] / netcore / System.Private.CoreLib / shared / System / Text / DecoderReplacementFallback.cs
blob87db1d0e51c1fa013804b440f0480789d8db04d8
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System.Diagnostics;
7 namespace System.Text
9 public sealed class DecoderReplacementFallback : DecoderFallback
11 // Our variables
12 private readonly string _strDefault;
14 // Construction. Default replacement fallback uses no best fit and ? replacement string
15 public DecoderReplacementFallback() : this("?")
19 public DecoderReplacementFallback(string replacement)
21 if (replacement == null)
22 throw new ArgumentNullException(nameof(replacement));
24 // Make sure it doesn't have bad surrogate pairs
25 bool bFoundHigh = false;
26 for (int i = 0; i < replacement.Length; i++)
28 // Found a surrogate?
29 if (char.IsSurrogate(replacement, i))
31 // High or Low?
32 if (char.IsHighSurrogate(replacement, i))
34 // if already had a high one, stop
35 if (bFoundHigh)
36 break; // break & throw at the bFoundHIgh below
37 bFoundHigh = true;
39 else
41 // Low, did we have a high?
42 if (!bFoundHigh)
44 // Didn't have one, make if fail when we stop
45 bFoundHigh = true;
46 break;
49 // Clear flag
50 bFoundHigh = false;
53 // If last was high we're in trouble (not surrogate so not low surrogate, so break)
54 else if (bFoundHigh)
55 break;
57 if (bFoundHigh)
58 throw new ArgumentException(SR.Format(SR.Argument_InvalidCharSequenceNoIndex, nameof(replacement)));
60 _strDefault = replacement;
63 public string DefaultString => _strDefault;
65 public override DecoderFallbackBuffer CreateFallbackBuffer() =>
66 new DecoderReplacementFallbackBuffer(this);
68 // Maximum number of characters that this instance of this fallback could return
69 public override int MaxCharCount => _strDefault.Length;
71 public override bool Equals(object? value) =>
72 value is DecoderReplacementFallback that &&
73 _strDefault == that._strDefault;
75 public override int GetHashCode() => _strDefault.GetHashCode();
78 public sealed class DecoderReplacementFallbackBuffer : DecoderFallbackBuffer
80 // Store our default string
81 private readonly string _strDefault;
82 private int _fallbackCount = -1;
83 private int _fallbackIndex = -1;
85 // Construction
86 public DecoderReplacementFallbackBuffer(DecoderReplacementFallback fallback)
88 _strDefault = fallback.DefaultString;
91 // Fallback Methods
92 public override bool Fallback(byte[] bytesUnknown, int index)
94 // We expect no previous fallback in our buffer
95 // We can't call recursively but others might (note, we don't test on last char!!!)
96 if (_fallbackCount >= 1)
98 ThrowLastBytesRecursive(bytesUnknown);
101 // Go ahead and get our fallback
102 if (_strDefault.Length == 0)
103 return false;
105 _fallbackCount = _strDefault.Length;
106 _fallbackIndex = -1;
108 return true;
111 public override char GetNextChar()
113 // We want it to get < 0 because == 0 means that the current/last character is a fallback
114 // and we need to detect recursion. We could have a flag but we already have this counter.
115 _fallbackCount--;
116 _fallbackIndex++;
118 // Do we have anything left? 0 is now last fallback char, negative is nothing left
119 if (_fallbackCount < 0)
120 return '\0';
122 // Need to get it out of the buffer.
123 // Make sure it didn't wrap from the fast count-- path
124 if (_fallbackCount == int.MaxValue)
126 _fallbackCount = -1;
127 return '\0';
130 // Now make sure its in the expected range
131 Debug.Assert(_fallbackIndex < _strDefault.Length && _fallbackIndex >= 0,
132 "Index exceeds buffer range");
134 return _strDefault[_fallbackIndex];
137 public override bool MovePrevious()
139 // Back up one, only if we just processed the last character (or earlier)
140 if (_fallbackCount >= -1 && _fallbackIndex >= 0)
142 _fallbackIndex--;
143 _fallbackCount++;
144 return true;
147 // Return false 'cause we couldn't do it.
148 return false;
151 // How many characters left to output?
152 public override int Remaining =>
153 // Our count is 0 for 1 character left.
154 (_fallbackCount < 0) ? 0 : _fallbackCount;
156 // Clear the buffer
157 public override unsafe void Reset()
159 _fallbackCount = -1;
160 _fallbackIndex = -1;
161 byteStart = null;
164 // This version just counts the fallback and doesn't actually copy anything.
165 internal override unsafe int InternalFallback(byte[] bytes, byte* pBytes) =>
166 // Right now this has both bytes and bytes[], since we might have extra bytes,
167 // hence the array, and we might need the index, hence the byte*.
168 // Return our replacement string Length
169 _strDefault.Length;