Fix IDE0025 (use expression body for properties)
[mono-project.git] / netcore / System.Private.CoreLib / shared / System / Text / EncoderReplacementFallback.cs
blob27aa98e6f7332abccd6d1a7fb2988a250b476fab
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;
6 using System.Runtime;
7 using System.Diagnostics;
9 namespace System.Text
11 public sealed class EncoderReplacementFallback : EncoderFallback
13 // Our variables
14 private readonly string _strDefault;
16 // Construction. Default replacement fallback uses no best fit and ? replacement string
17 public EncoderReplacementFallback() : this("?")
21 public EncoderReplacementFallback(string replacement)
23 // Must not be null
24 if (replacement == null)
25 throw new ArgumentNullException(nameof(replacement));
27 // Make sure it doesn't have bad surrogate pairs
28 bool bFoundHigh = false;
29 for (int i = 0; i < replacement.Length; i++)
31 // Found a surrogate?
32 if (char.IsSurrogate(replacement, i))
34 // High or Low?
35 if (char.IsHighSurrogate(replacement, i))
37 // if already had a high one, stop
38 if (bFoundHigh)
39 break; // break & throw at the bFoundHIgh below
40 bFoundHigh = true;
42 else
44 // Low, did we have a high?
45 if (!bFoundHigh)
47 // Didn't have one, make if fail when we stop
48 bFoundHigh = true;
49 break;
52 // Clear flag
53 bFoundHigh = false;
56 // If last was high we're in trouble (not surrogate so not low surrogate, so break)
57 else if (bFoundHigh)
58 break;
60 if (bFoundHigh)
61 throw new ArgumentException(SR.Format(SR.Argument_InvalidCharSequenceNoIndex, nameof(replacement)));
63 _strDefault = replacement;
66 public string DefaultString => _strDefault;
68 public override EncoderFallbackBuffer CreateFallbackBuffer() =>
69 new EncoderReplacementFallbackBuffer(this);
71 // Maximum number of characters that this instance of this fallback could return
72 public override int MaxCharCount => _strDefault.Length;
74 public override bool Equals(object? value) =>
75 value is EncoderReplacementFallback that &&
76 _strDefault == that._strDefault;
78 public override int GetHashCode() => _strDefault.GetHashCode();
81 public sealed class EncoderReplacementFallbackBuffer : EncoderFallbackBuffer
83 // Store our default string
84 private readonly string _strDefault;
85 private int _fallbackCount = -1;
86 private int _fallbackIndex = -1;
88 // Construction
89 public EncoderReplacementFallbackBuffer(EncoderReplacementFallback fallback)
91 // 2X in case we're a surrogate pair
92 _strDefault = fallback.DefaultString + fallback.DefaultString;
95 // Fallback Methods
96 public override bool Fallback(char charUnknown, int index)
98 // If we had a buffer already we're being recursive, throw, it's probably at the suspect
99 // character in our array.
100 if (_fallbackCount >= 1)
102 // If we're recursive we may still have something in our buffer that makes this a surrogate
103 if (char.IsHighSurrogate(charUnknown) && _fallbackCount >= 0 &&
104 char.IsLowSurrogate(_strDefault[_fallbackIndex + 1]))
105 ThrowLastCharRecursive(char.ConvertToUtf32(charUnknown, _strDefault[_fallbackIndex + 1]));
107 // Nope, just one character
108 ThrowLastCharRecursive(unchecked((int)charUnknown));
111 // Go ahead and get our fallback
112 // Divide by 2 because we aren't a surrogate pair
113 _fallbackCount = _strDefault.Length / 2;
114 _fallbackIndex = -1;
116 return _fallbackCount != 0;
119 public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
121 // Double check input surrogate pair
122 if (!char.IsHighSurrogate(charUnknownHigh))
123 throw new ArgumentOutOfRangeException(nameof(charUnknownHigh),
124 SR.Format(SR.ArgumentOutOfRange_Range, 0xD800, 0xDBFF));
126 if (!char.IsLowSurrogate(charUnknownLow))
127 throw new ArgumentOutOfRangeException(nameof(charUnknownLow),
128 SR.Format(SR.ArgumentOutOfRange_Range, 0xDC00, 0xDFFF));
130 // If we had a buffer already we're being recursive, throw, it's probably at the suspect
131 // character in our array.
132 if (_fallbackCount >= 1)
133 ThrowLastCharRecursive(char.ConvertToUtf32(charUnknownHigh, charUnknownLow));
135 // Go ahead and get our fallback
136 _fallbackCount = _strDefault.Length;
137 _fallbackIndex = -1;
139 return _fallbackCount != 0;
142 public override char GetNextChar()
144 // We want it to get < 0 because == 0 means that the current/last character is a fallback
145 // and we need to detect recursion. We could have a flag but we already have this counter.
146 _fallbackCount--;
147 _fallbackIndex++;
149 // Do we have anything left? 0 is now last fallback char, negative is nothing left
150 if (_fallbackCount < 0)
151 return '\0';
153 // Need to get it out of the buffer.
154 // Make sure it didn't wrap from the fast count-- path
155 if (_fallbackCount == int.MaxValue)
157 _fallbackCount = -1;
158 return '\0';
161 // Now make sure its in the expected range
162 Debug.Assert(_fallbackIndex < _strDefault.Length && _fallbackIndex >= 0,
163 "Index exceeds buffer range");
165 return _strDefault[_fallbackIndex];
168 public override bool MovePrevious()
170 // Back up one, only if we just processed the last character (or earlier)
171 if (_fallbackCount >= -1 && _fallbackIndex >= 0)
173 _fallbackIndex--;
174 _fallbackCount++;
175 return true;
178 // Return false 'cause we couldn't do it.
179 return false;
182 // How many characters left to output?
183 public override int Remaining =>
184 // Our count is 0 for 1 character left.
185 (_fallbackCount < 0) ? 0 : _fallbackCount;
187 // Clear the buffer
188 public override unsafe void Reset()
190 _fallbackCount = -1;
191 _fallbackIndex = 0;
192 charStart = null;
193 bFallingBack = false;