Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
TextEncoder.cs
Go to the documentation of this file.
4using System.IO;
8
10
11public abstract class TextEncoder
12{
13 [EditorBrowsable(EditorBrowsableState.Never)]
14 public abstract int MaxOutputCharactersPerInputCharacter { get; }
15
16 [CLSCompliant(false)]
17 [EditorBrowsable(EditorBrowsableState.Never)]
18 public unsafe abstract bool TryEncodeUnicodeScalar(int unicodeScalar, char* buffer, int bufferLength, out int numberOfCharactersWritten);
19
20 [MethodImpl(MethodImplOptions.AggressiveInlining)]
21 private unsafe bool TryEncodeUnicodeScalar(uint unicodeScalar, Span<char> buffer, out int charsWritten)
22 {
23 fixed (char* buffer2 = &MemoryMarshal.GetReference(buffer))
24 {
25 return TryEncodeUnicodeScalar((int)unicodeScalar, buffer2, buffer.Length, out charsWritten);
26 }
27 }
28
29 private bool TryEncodeUnicodeScalarUtf8(uint unicodeScalar, Span<char> utf16ScratchBuffer, Span<byte> utf8Destination, out int bytesWritten)
30 {
31 if (!TryEncodeUnicodeScalar(unicodeScalar, utf16ScratchBuffer, out var charsWritten))
32 {
34 }
35 utf16ScratchBuffer = utf16ScratchBuffer.Slice(0, charsWritten);
36 int num = 0;
37 while (!utf16ScratchBuffer.IsEmpty)
38 {
39 if (Rune.DecodeFromUtf16(utf16ScratchBuffer, out var result, out var charsConsumed) != 0)
40 {
42 }
43 uint num2 = (uint)UnicodeHelpers.GetUtf8RepresentationForScalarValue((uint)result.Value);
44 do
45 {
46 if (SpanUtility.IsValidIndex(utf8Destination, num))
47 {
48 utf8Destination[num++] = (byte)num2;
49 continue;
50 }
51 bytesWritten = 0;
52 return false;
53 }
54 while ((num2 >>= 8) != 0);
55 utf16ScratchBuffer = utf16ScratchBuffer.Slice(charsConsumed);
56 }
57 bytesWritten = num;
58 return true;
59 }
60
61 [CLSCompliant(false)]
62 [EditorBrowsable(EditorBrowsableState.Never)]
63 public unsafe abstract int FindFirstCharacterToEncode(char* text, int textLength);
64
65 [EditorBrowsable(EditorBrowsableState.Never)]
66 public abstract bool WillEncode(int unicodeScalar);
67
68 public virtual string Encode(string value)
69 {
70 if (value == null)
71 {
73 }
74 int num = FindFirstCharacterToEncode(value.AsSpan());
75 if (num < 0)
76 {
77 return value;
78 }
79 return EncodeToNewString(value.AsSpan(), num);
80 }
81
82 private string EncodeToNewString(ReadOnlySpan<char> value, int indexOfFirstCharToEncode)
83 {
84 ReadOnlySpan<char> source = value.Slice(indexOfFirstCharToEncode);
85 Span<char> initialBuffer = stackalloc char[1024];
86 System.Text.ValueStringBuilder valueStringBuilder = new System.Text.ValueStringBuilder(initialBuffer);
88 do
89 {
90 Span<char> destination = valueStringBuilder.AppendSpan(Math.Max(source.Length, val));
91 EncodeCore(source, destination, out var charsConsumed, out var charsWritten, isFinalBlock: true);
92 if (charsWritten == 0 || (uint)charsWritten > (uint)destination.Length)
93 {
95 }
96 source = source.Slice(charsConsumed);
97 valueStringBuilder.Length -= destination.Length - charsWritten;
98 }
99 while (!source.IsEmpty);
100 string result = string.Concat(value.Slice(0, indexOfFirstCharToEncode), valueStringBuilder.AsSpan());
101 valueStringBuilder.Dispose();
102 return result;
103 }
104
105 public void Encode(TextWriter output, string value)
106 {
107 Encode(output, value, 0, value.Length);
108 }
109
110 public virtual void Encode(TextWriter output, string value, int startIndex, int characterCount)
111 {
112 if (value == null)
113 {
114 throw new ArgumentNullException("value");
115 }
116 if (output == null)
117 {
118 throw new ArgumentNullException("output");
119 }
120 ValidateRanges(startIndex, characterCount, value.Length);
121 int num = FindFirstCharacterToEncode(value.AsSpan(startIndex, characterCount));
122 if (num < 0)
123 {
124 num = characterCount;
125 }
126 output.WritePartialString(value, startIndex, num);
127 if (num != characterCount)
128 {
129 EncodeCore(output, value.AsSpan(startIndex + num, characterCount - num));
130 }
131 }
132
133 public virtual void Encode(TextWriter output, char[] value, int startIndex, int characterCount)
134 {
135 if (value == null)
136 {
137 throw new ArgumentNullException("value");
138 }
139 if (output == null)
140 {
141 throw new ArgumentNullException("output");
142 }
143 ValidateRanges(startIndex, characterCount, value.Length);
144 int num = FindFirstCharacterToEncode(value.AsSpan(startIndex, characterCount));
145 if (num < 0)
146 {
147 num = characterCount;
148 }
149 output.Write(value, startIndex, num);
150 if (num != characterCount)
151 {
152 EncodeCore(output, value.AsSpan(startIndex + num, characterCount - num));
153 }
154 }
155
156 public virtual OperationStatus EncodeUtf8(ReadOnlySpan<byte> utf8Source, Span<byte> utf8Destination, out int bytesConsumed, out int bytesWritten, bool isFinalBlock = true)
157 {
158 ReadOnlySpan<byte> utf8Text = utf8Source;
159 if (utf8Destination.Length < utf8Source.Length)
160 {
161 utf8Text = utf8Source.Slice(0, utf8Destination.Length);
162 }
163 int num = FindFirstCharacterToEncodeUtf8(utf8Text);
164 if (num < 0)
165 {
166 num = utf8Text.Length;
167 }
168 utf8Source.Slice(0, num).CopyTo(utf8Destination);
169 if (num == utf8Source.Length)
170 {
171 bytesConsumed = utf8Source.Length;
172 bytesWritten = utf8Source.Length;
173 return OperationStatus.Done;
174 }
175 int bytesConsumed2;
176 int bytesWritten2;
177 OperationStatus result = EncodeUtf8Core(utf8Source.Slice(num), utf8Destination.Slice(num), out bytesConsumed2, out bytesWritten2, isFinalBlock);
178 bytesConsumed = num + bytesConsumed2;
179 bytesWritten = num + bytesWritten2;
180 return result;
181 }
182
183 private protected virtual OperationStatus EncodeUtf8Core(ReadOnlySpan<byte> utf8Source, Span<byte> utf8Destination, out int bytesConsumed, out int bytesWritten, bool isFinalBlock)
184 {
185 int length = utf8Source.Length;
186 int length2 = utf8Destination.Length;
187 Span<char> utf16ScratchBuffer = stackalloc char[24];
188 OperationStatus result2;
189 while (true)
190 {
191 int bytesConsumed2;
192 int num2;
193 if (!utf8Source.IsEmpty)
194 {
195 Rune result;
196 OperationStatus operationStatus = Rune.DecodeFromUtf8(utf8Source, out result, out bytesConsumed2);
197 if (operationStatus != 0)
198 {
199 if (!isFinalBlock && operationStatus == OperationStatus.NeedMoreData)
200 {
201 result2 = OperationStatus.NeedMoreData;
202 break;
203 }
204 }
205 else if (!WillEncode(result.Value))
206 {
207 uint num = (uint)UnicodeHelpers.GetUtf8RepresentationForScalarValue((uint)result.Value);
208 num2 = 0;
209 while ((uint)num2 < (uint)utf8Destination.Length)
210 {
211 utf8Destination[num2++] = (byte)num;
212 if ((num >>= 8) != 0)
213 {
214 continue;
215 }
216 goto IL_008d;
217 }
218 goto IL_00f9;
219 }
220 if (TryEncodeUnicodeScalarUtf8((uint)result.Value, utf16ScratchBuffer, utf8Destination, out var bytesWritten2))
221 {
222 utf8Source = utf8Source.Slice(bytesConsumed2);
223 utf8Destination = utf8Destination.Slice(bytesWritten2);
224 continue;
225 }
226 goto IL_00f9;
227 }
228 result2 = OperationStatus.Done;
229 break;
230 IL_008d:
231 utf8Source = utf8Source.Slice(bytesConsumed2);
232 utf8Destination = utf8Destination.Slice(num2);
233 continue;
234 IL_00f9:
235 result2 = OperationStatus.DestinationTooSmall;
236 break;
237 }
238 bytesConsumed = length - utf8Source.Length;
239 bytesWritten = length2 - utf8Destination.Length;
240 return result2;
241 }
242
243 public virtual OperationStatus Encode(ReadOnlySpan<char> source, Span<char> destination, out int charsConsumed, out int charsWritten, bool isFinalBlock = true)
244 {
246 if (destination.Length < source.Length)
247 {
248 text = source.Slice(0, destination.Length);
249 }
251 if (num < 0)
252 {
253 num = text.Length;
254 }
255 source.Slice(0, num).CopyTo(destination);
256 if (num == source.Length)
257 {
258 charsConsumed = source.Length;
259 charsWritten = source.Length;
260 return OperationStatus.Done;
261 }
262 int charsConsumed2;
263 int charsWritten2;
264 OperationStatus result = EncodeCore(source.Slice(num), destination.Slice(num), out charsConsumed2, out charsWritten2, isFinalBlock);
265 charsConsumed = num + charsConsumed2;
266 charsWritten = num + charsWritten2;
267 return result;
268 }
269
270 private protected virtual OperationStatus EncodeCore(ReadOnlySpan<char> source, Span<char> destination, out int charsConsumed, out int charsWritten, bool isFinalBlock)
271 {
272 int length = source.Length;
273 int length2 = destination.Length;
274 OperationStatus result2;
275 while (true)
276 {
277 if (!source.IsEmpty)
278 {
279 Rune result;
280 int charsConsumed2;
281 OperationStatus operationStatus = Rune.DecodeFromUtf16(source, out result, out charsConsumed2);
282 if (operationStatus != 0)
283 {
284 if (!isFinalBlock && operationStatus == OperationStatus.NeedMoreData)
285 {
286 result2 = OperationStatus.NeedMoreData;
287 break;
288 }
289 }
290 else if (!WillEncode(result.Value))
291 {
292 if (result.TryEncodeToUtf16(destination, out var _))
293 {
294 source = source.Slice(charsConsumed2);
295 destination = destination.Slice(charsConsumed2);
296 continue;
297 }
298 goto IL_00ad;
299 }
300 if (TryEncodeUnicodeScalar((uint)result.Value, destination, out var charsWritten3))
301 {
302 source = source.Slice(charsConsumed2);
303 destination = destination.Slice(charsWritten3);
304 continue;
305 }
306 goto IL_00ad;
307 }
308 result2 = OperationStatus.Done;
309 break;
310 IL_00ad:
311 result2 = OperationStatus.DestinationTooSmall;
312 break;
313 }
314 charsConsumed = length - source.Length;
315 charsWritten = length2 - destination.Length;
316 return result2;
317 }
318
320 {
322 char[] array = ArrayPool<char>.Shared.Rent(Math.Max(value.Length, val));
324 do
325 {
326 EncodeCore(value, destination, out var charsConsumed, out var charsWritten, isFinalBlock: true);
327 if (charsWritten == 0 || (uint)charsWritten > (uint)destination.Length)
328 {
330 }
331 output.Write(array, 0, charsWritten);
332 value = value.Slice(charsConsumed);
333 }
334 while (!value.IsEmpty);
336 }
337
338 private protected unsafe virtual int FindFirstCharacterToEncode(ReadOnlySpan<char> text)
339 {
340 fixed (char* text2 = &MemoryMarshal.GetReference(text))
341 {
342 return FindFirstCharacterToEncode(text2, text.Length);
343 }
344 }
345
346 [EditorBrowsable(EditorBrowsableState.Never)]
348 {
349 int length = utf8Text.Length;
350 Rune result;
351 int bytesConsumed;
352 while (!utf8Text.IsEmpty && Rune.DecodeFromUtf8(utf8Text, out result, out bytesConsumed) == OperationStatus.Done && !WillEncode(result.Value))
353 {
354 utf8Text = utf8Text.Slice(bytesConsumed);
355 }
356 if (!utf8Text.IsEmpty)
357 {
358 return length - utf8Text.Length;
359 }
360 return -1;
361 }
362
363 private static void ValidateRanges(int startIndex, int characterCount, int actualInputLength)
364 {
365 if (startIndex < 0 || startIndex > actualInputLength)
366 {
367 throw new ArgumentOutOfRangeException("startIndex");
368 }
369 if (characterCount < 0 || characterCount > actualInputLength - startIndex)
370 {
371 throw new ArgumentOutOfRangeException("characterCount");
372 }
373 }
374
375 [DoesNotReturn]
380}
static ArrayPool< T > Shared
Definition ArrayPool.cs:7
virtual void Write(char value)
static byte Max(byte val1, byte val2)
Definition Math.cs:738
static string TextEncoderDoesNotImplementMaxOutputCharsPerInputChar
Definition SR.cs:14
Definition SR.cs:7
string EncodeToNewString(ReadOnlySpan< char > value, int indexOfFirstCharToEncode)
void EncodeCore(TextWriter output, ReadOnlySpan< char > value)
virtual OperationStatus EncodeUtf8Core(ReadOnlySpan< byte > utf8Source, Span< byte > utf8Destination, out int bytesConsumed, out int bytesWritten, bool isFinalBlock)
virtual unsafe int FindFirstCharacterToEncode(ReadOnlySpan< char > text)
bool TryEncodeUnicodeScalarUtf8(uint unicodeScalar, Span< char > utf16ScratchBuffer, Span< byte > utf8Destination, out int bytesWritten)
bool WillEncode(int unicodeScalar)
virtual OperationStatus EncodeUtf8(ReadOnlySpan< byte > utf8Source, Span< byte > utf8Destination, out int bytesConsumed, out int bytesWritten, bool isFinalBlock=true)
virtual void Encode(TextWriter output, string value, int startIndex, int characterCount)
virtual OperationStatus EncodeCore(ReadOnlySpan< char > source, Span< char > destination, out int charsConsumed, out int charsWritten, bool isFinalBlock)
virtual OperationStatus Encode(ReadOnlySpan< char > source, Span< char > destination, out int charsConsumed, out int charsWritten, bool isFinalBlock=true)
virtual int FindFirstCharacterToEncodeUtf8(ReadOnlySpan< byte > utf8Text)
virtual string Encode(string value)
unsafe bool TryEncodeUnicodeScalar(uint unicodeScalar, Span< char > buffer, out int charsWritten)
virtual void Encode(TextWriter output, char[] value, int startIndex, int characterCount)
static void ThrowArgumentException_MaxOutputCharsPerInputChar()
unsafe int FindFirstCharacterToEncode(char *text, int textLength)
static void ValidateRanges(int startIndex, int characterCount, int actualInputLength)
void Encode(TextWriter output, string value)
unsafe bool TryEncodeUnicodeScalar(int unicodeScalar, char *buffer, int bufferLength, out int numberOfCharactersWritten)
static void ThrowArgumentNullException(ExceptionArgument argument)
Definition ThrowHelper.cs:8
static int GetUtf8RepresentationForScalarValue(uint scalar)
ReadOnlySpan< T > Slice(int start)
bool IsEmpty
Definition Span.cs:79
Span< T > Slice(int start)
Definition Span.cs:271
int Length
Definition Span.cs:70
static OperationStatus DecodeFromUtf16(ReadOnlySpan< char > source, out Rune result, out int charsConsumed)
Definition Rune.cs:168
static OperationStatus DecodeFromUtf8(ReadOnlySpan< byte > source, out Rune result, out int bytesConsumed)
Definition Rune.cs:202
bool TryEncodeToUtf16(Span< char > destination, out int charsWritten)
Definition Rune.cs:553
ReadOnlySpan< char > AsSpan(bool terminate)
Span< char > AppendSpan(int length)