Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
TextInfo.cs
Go to the documentation of this file.
5using System.Text;
8
10
12{
13 private enum Tristate : byte
14 {
16 False,
17 True
18 }
19
20 [StructLayout(LayoutKind.Sequential, Size = 1)]
21 private readonly struct ToUpperConversion
22 {
23 }
24
25 [StructLayout(LayoutKind.Sequential, Size = 1)]
26 private readonly struct ToLowerConversion
27 {
28 }
29
30 private string _listSeparator;
31
32 private bool _isReadOnly;
33
34 private readonly string _cultureName;
35
36 private readonly CultureData _cultureData;
37
38 private readonly string _textInfoName;
39
41
46
48
50
52
54
56
58
60
61 public string CultureName => _textInfoName;
62
63 public bool IsReadOnly => _isReadOnly;
64
65 public string ListSeparator
66 {
67 get
68 {
70 }
71 set
72 {
73 if (value == null)
74 {
75 throw new ArgumentNullException("value");
76 }
79 }
80 }
81
83 {
84 [MethodImpl(MethodImplOptions.AggressiveInlining)]
85 get
86 {
87 if (_isAsciiCasingSameAsInvariant == Tristate.NotInitialized)
88 {
90 }
92 }
93 }
94
96
97 private bool IsInvariant => _cultureName.Length == 0;
98
109
115
117 {
119 }
120
121 public object Clone()
122 {
123 object obj = MemberwiseClone();
124 ((TextInfo)obj).SetReadOnlyState(readOnly: false);
125 return obj;
126 }
127
129 {
130 if (textInfo == null)
131 {
132 throw new ArgumentNullException("textInfo");
133 }
134 if (textInfo.IsReadOnly)
135 {
136 return textInfo;
137 }
138 TextInfo textInfo2 = (TextInfo)textInfo.MemberwiseClone();
140 return textInfo2;
141 }
142
143 private void VerifyWritable()
144 {
145 if (_isReadOnly)
146 {
148 }
149 }
150
151 internal void SetReadOnlyState(bool readOnly)
152 {
154 }
155
156 public char ToLower(char c)
157 {
159 {
161 }
163 {
164 return ToLowerAsciiInvariant(c);
165 }
166 return ChangeCase(c, toUpper: false);
167 }
168
169 internal static char ToLowerInvariant(char c)
170 {
172 {
174 }
176 {
177 return ToLowerAsciiInvariant(c);
178 }
179 return Invariant.ChangeCase(c, toUpper: false);
180 }
181
182 public string ToLower(string str)
183 {
184 if (str == null)
185 {
186 throw new ArgumentNullException("str");
187 }
189 {
191 }
193 }
194
195 private unsafe char ChangeCase(char c, bool toUpper)
196 {
197 char result = '\0';
198 ChangeCaseCore(&c, 1, &result, 1, toUpper);
199 return result;
200 }
201
202 [MethodImpl(MethodImplOptions.AggressiveInlining)]
207
208 [MethodImpl(MethodImplOptions.AggressiveInlining)]
213
214 [MethodImpl(MethodImplOptions.AggressiveInlining)]
219
220 private unsafe void ChangeCaseCommon<TConversion>(ref char source, ref char destination, int charCount) where TConversion : struct
221 {
223 if (charCount == 0)
224 {
225 return;
226 }
227 fixed (char* ptr = &source)
228 {
229 fixed (char* ptr2 = &destination)
230 {
231 nuint num = 0u;
233 {
234 if (charCount < 4)
235 {
236 goto IL_00e5;
237 }
238 nuint num2 = (uint)(charCount - 4);
239 while (true)
240 {
241 uint value = Unsafe.ReadUnaligned<uint>(ptr + num);
243 {
244 break;
245 }
247 Unsafe.WriteUnaligned(ptr2 + num, value);
248 value = Unsafe.ReadUnaligned<uint>(ptr + num + 2);
250 {
252 Unsafe.WriteUnaligned(ptr2 + num + 2, value);
253 num += 4;
254 if (num <= num2)
255 {
256 continue;
257 }
258 goto IL_00e5;
259 }
260 num += 2;
261 break;
262 }
263 goto IL_0171;
264 }
265 goto IL_0178;
266 IL_0178:
267 ChangeCaseCore(ptr + num, charCount, ptr2 + num, charCount, flag);
268 return;
269 IL_0171:
270 charCount -= (int)num;
271 goto IL_0178;
272 IL_00e5:
273 if (((uint)charCount & 2u) != 0)
274 {
275 uint value2 = Unsafe.ReadUnaligned<uint>(ptr + num);
277 {
278 goto IL_0171;
279 }
281 Unsafe.WriteUnaligned(ptr2 + num, value2);
282 num += 2;
283 }
284 if (((uint)charCount & (true ? 1u : 0u)) != 0)
285 {
286 uint num3 = ptr[num];
287 if (num3 <= 127)
288 {
290 ptr2[num] = (char)num3;
291 return;
292 }
293 goto IL_0171;
294 }
295 }
296 }
297 }
298
299 private unsafe string ChangeCaseCommon<TConversion>(string source) where TConversion : struct
300 {
302 if (source.Length == 0)
303 {
304 return string.Empty;
305 }
306 fixed (char* ptr = source)
307 {
308 nuint num = 0u;
310 {
311 if (source.Length < 2)
312 {
313 goto IL_0095;
314 }
315 nuint num2 = (uint)(source.Length - 2);
316 while (true)
317 {
318 uint value = Unsafe.ReadUnaligned<uint>(ptr + num);
320 {
321 break;
322 }
324 {
325 num += 2;
326 if (num <= num2)
327 {
328 continue;
329 }
330 goto IL_0095;
331 }
332 goto IL_00d1;
333 }
334 }
335 goto IL_0121;
336 IL_0121:
337 string text = string.FastAllocateString(source.Length);
338 if (num != 0)
339 {
340 Span<char> destination = new Span<char>(ref text.GetRawStringData(), text.Length);
341 source.AsSpan(0, (int)num).CopyTo(destination);
342 }
343 fixed (char* ptr2 = text)
344 {
345 ChangeCaseCore(ptr + num, source.Length - (int)num, ptr2 + num, text.Length - (int)num, flag);
346 }
347 return text;
348 IL_0095:
349 if (((uint)source.Length & (true ? 1u : 0u)) != 0)
350 {
351 uint num3 = ptr[num];
352 if (num3 > 127)
353 {
354 goto IL_0121;
355 }
356 if (flag ? (num3 - 97 <= 25) : (num3 - 65 <= 25))
357 {
358 goto IL_00d1;
359 }
360 }
361 return source;
362 IL_00d1:
363 string text2 = string.FastAllocateString(source.Length);
364 Span<char> destination2 = new Span<char>(ref text2.GetRawStringData(), text2.Length);
365 source.AsSpan(0, (int)num).CopyTo(destination2);
366 ChangeCaseCommon<TConversion>(source.AsSpan((int)num), destination2.Slice((int)num));
367 return text2;
368 }
369 }
370
371 internal unsafe static string ToLowerAsciiInvariant(string s)
372 {
373 if (s.Length == 0)
374 {
375 return string.Empty;
376 }
377 fixed (char* ptr = s)
378 {
379 int i;
380 for (i = 0; i < s.Length && (uint)(ptr[i] - 65) > 25u; i++)
381 {
382 }
383 if (i >= s.Length)
384 {
385 return s;
386 }
387 string text = string.FastAllocateString(s.Length);
388 fixed (char* ptr2 = text)
389 {
390 for (int j = 0; j < i; j++)
391 {
392 ptr2[j] = ptr[j];
393 }
394 ptr2[i] = (char)(ptr[i] | 0x20u);
395 for (i++; i < s.Length; i++)
396 {
398 }
399 }
400 return text;
401 }
402 }
403
404 [MethodImpl(MethodImplOptions.AggressiveInlining)]
405 private static char ToLowerAsciiInvariant(char c)
406 {
408 {
409 c = (char)(byte)(c | 0x20u);
410 }
411 return c;
412 }
413
414 public char ToUpper(char c)
415 {
417 {
419 }
421 {
422 return ToUpperAsciiInvariant(c);
423 }
424 return ChangeCase(c, toUpper: true);
425 }
426
427 internal static char ToUpperInvariant(char c)
428 {
430 {
432 }
434 {
435 return ToUpperAsciiInvariant(c);
436 }
437 return Invariant.ChangeCase(c, toUpper: true);
438 }
439
440 public string ToUpper(string str)
441 {
442 if (str == null)
443 {
444 throw new ArgumentNullException("str");
445 }
447 {
449 }
451 }
452
453 [MethodImpl(MethodImplOptions.AggressiveInlining)]
454 private static char ToUpperAsciiInvariant(char c)
455 {
456 if (UnicodeUtility.IsInRangeInclusive(c, 97u, 122u))
457 {
458 c = (char)(c & 0x5Fu);
459 }
460 return c;
461 }
462
463 [MethodImpl(MethodImplOptions.NoInlining)]
465 {
466 bool flag = CultureInfo.GetCultureInfo(_textInfoName).CompareInfo.Compare("abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", CompareOptions.IgnoreCase) == 0;
467 _isAsciiCasingSameAsInvariant = ((!flag) ? Tristate.False : Tristate.True);
468 }
469
470 public override bool Equals([NotNullWhen(true)] object? obj)
471 {
473 {
474 return CultureName.Equals(textInfo.CultureName);
475 }
476 return false;
477 }
478
479 public override int GetHashCode()
480 {
481 return CultureName.GetHashCode();
482 }
483
484 public override string ToString()
485 {
486 return "TextInfo - " + _cultureData.CultureName;
487 }
488
489 public string ToTitleCase(string str)
490 {
491 if (str == null)
492 {
493 throw new ArgumentNullException("str");
494 }
495 if (str.Length == 0)
496 {
497 return str;
498 }
499 StringBuilder result = new StringBuilder();
500 string text = null;
501 bool flag = CultureName.StartsWith("nl-", StringComparison.OrdinalIgnoreCase);
502 int num;
503 for (num = 0; num < str.Length; num++)
504 {
506 if (char.CheckLetter(unicodeCategoryInternal))
507 {
508 if (flag && num < str.Length - 1 && (str[num] == 'i' || str[num] == 'I') && (str[num + 1] == 'j' || str[num + 1] == 'J'))
509 {
510 result.Append("IJ");
511 num += 2;
512 }
513 else
514 {
515 num = AddTitlecaseLetter(ref result, ref str, num, charLength) + 1;
516 }
517 int num2 = num;
518 bool flag2 = unicodeCategoryInternal == UnicodeCategory.LowercaseLetter;
519 while (num < str.Length)
520 {
523 {
524 if (unicodeCategoryInternal == UnicodeCategory.LowercaseLetter)
525 {
526 flag2 = true;
527 }
528 num += charLength;
529 }
530 else if (str[num] == '\'')
531 {
532 num++;
533 if (flag2)
534 {
535 if (text == null)
536 {
537 text = ToLower(str);
538 }
539 result.Append(text, num2, num - num2);
540 }
541 else
542 {
543 result.Append(str, num2, num - num2);
544 }
545 num2 = num;
546 flag2 = true;
547 }
548 else
549 {
551 {
552 break;
553 }
554 num += charLength;
555 }
556 }
557 int num3 = num - num2;
558 if (num3 > 0)
559 {
560 if (flag2)
561 {
562 if (text == null)
563 {
564 text = ToLower(str);
565 }
566 result.Append(text, num2, num3);
567 }
568 else
569 {
570 result.Append(str, num2, num3);
571 }
572 }
573 if (num < str.Length)
574 {
575 num = AddNonLetter(ref result, ref str, num, charLength);
576 }
577 }
578 else
579 {
580 num = AddNonLetter(ref result, ref str, num, charLength);
581 }
582 }
583 return result.ToString();
584 }
585
586 private static int AddNonLetter(ref StringBuilder result, ref string input, int inputIndex, int charLen)
587 {
588 if (charLen == 2)
589 {
590 result.Append(input[inputIndex++]);
591 result.Append(input[inputIndex]);
592 }
593 else
594 {
595 result.Append(input[inputIndex]);
596 }
597 return inputIndex;
598 }
599
600 private int AddTitlecaseLetter(ref StringBuilder result, ref string input, int inputIndex, int charLen)
601 {
602 if (charLen == 2)
603 {
606 {
608 result.Append(hr);
609 result.Append(lr);
610 }
611 else
612 {
613 Span<char> span = stackalloc char[2];
615 result.Append(span);
616 }
617 inputIndex++;
618 }
619 else
620 {
621 switch (input[inputIndex])
622 {
623 case 'Ç„':
624 case 'Ç…':
625 case 'dž':
626 result.Append('Ç…');
627 break;
628 case 'LJ':
629 case 'Lj':
630 case 'lj':
631 result.Append('Lj');
632 break;
633 case 'ÇŠ':
634 case 'Ç‹':
635 case 'nj':
636 result.Append('Ç‹');
637 break;
638 case 'DZ':
639 case 'Dz':
640 case 'dz':
641 result.Append('Dz');
642 break;
643 default:
645 break;
646 }
647 }
648 return inputIndex;
649 }
650
651 private unsafe void ChangeCaseCore(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper)
652 {
654 {
656 }
657 else
658 {
660 }
661 }
662
663 private static bool IsWordSeparator(UnicodeCategory category)
664 {
665 return (0x1FFCF800 & (1 << (int)category)) != 0;
666 }
667
669 {
670 if (uc != 0 && uc != UnicodeCategory.LowercaseLetter && uc != UnicodeCategory.TitlecaseLetter && uc != UnicodeCategory.ModifierLetter)
671 {
672 return uc == UnicodeCategory.OtherLetter;
673 }
674 return true;
675 }
676
677 private static bool NeedsTurkishCasing(string localeName)
678 {
679 return CultureInfo.GetCultureInfo(localeName).CompareInfo.Compare("ı", "I", CompareOptions.IgnoreCase) == 0;
680 }
681
682 internal unsafe void IcuChangeCase(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper)
683 {
684 if (IsInvariant)
685 {
687 return;
688 }
689 if (_needsTurkishCasing == Tristate.NotInitialized)
690 {
692 }
693 if (_needsTurkishCasing == Tristate.True)
694 {
696 }
697 else
698 {
700 }
701 }
702
703 private unsafe void NlsChangeCase(char* pSource, int pSourceLen, char* pResult, int pResultLen, bool toUpper)
704 {
705 uint num = ((!IsInvariantLocale(_textInfoName)) ? 16777216u : 0u);
706 if (Interop.Kernel32.LCMapStringEx((_sortHandle != IntPtr.Zero) ? null : _textInfoName, num | (toUpper ? 512u : 256u), pSource, pSourceLen, pResult, pSourceLen, null, null, _sortHandle) == 0)
707 {
709 }
710 }
711
712 private static bool IsInvariantLocale(string localeName)
713 {
714 return localeName == "";
715 }
716}
static unsafe void ChangeCaseInvariant(char *src, int srcLen, char *dstBuffer, int dstBufferCapacity, bool bToUpper)
static unsafe void ChangeCaseTurkish(char *src, int srcLen, char *dstBuffer, int dstBufferCapacity, bool bToUpper)
static unsafe void ChangeCase(char *src, int srcLen, char *dstBuffer, int dstBufferCapacity, bool bToUpper)
static unsafe int LCMapStringEx(string lpLocaleName, uint dwMapFlags, char *lpSrcStr, int cchSrc, void *lpDestStr, int cchDest, void *lpVersionInformation, void *lpReserved, IntPtr sortHandle)
static UnicodeCategory GetUnicodeCategoryInternal(string value, int index)
static unsafe IntPtr NlsGetSortHandle(string cultureName)
static CultureInfo GetCultureInfo(int culture)
static void ToUpper(char h, char l, out char hr, out char lr)
static bool NeedsTurkishCasing(string localeName)
Definition TextInfo.cs:677
void ChangeCaseToLower(ReadOnlySpan< char > source, Span< char > destination)
Definition TextInfo.cs:203
int AddTitlecaseLetter(ref StringBuilder result, ref string input, int inputIndex, int charLen)
Definition TextInfo.cs:600
static bool IsInvariantLocale(string localeName)
Definition TextInfo.cs:712
TextInfo(CultureData cultureData)
Definition TextInfo.cs:99
readonly CultureData _cultureData
Definition TextInfo.cs:36
static bool IsWordSeparator(UnicodeCategory category)
Definition TextInfo.cs:663
unsafe void IcuChangeCase(char *src, int srcLen, char *dstBuffer, int dstBufferCapacity, bool bToUpper)
Definition TextInfo.cs:682
override bool Equals([NotNullWhen(true)] object? obj)
Definition TextInfo.cs:470
void SetReadOnlyState(bool readOnly)
Definition TextInfo.cs:151
void ChangeCaseToUpper(ReadOnlySpan< char > source, Span< char > destination)
Definition TextInfo.cs:209
string ToUpper(string str)
Definition TextInfo.cs:440
string ToTitleCase(string str)
Definition TextInfo.cs:489
static bool IsLetterCategory(UnicodeCategory uc)
Definition TextInfo.cs:668
Tristate _isAsciiCasingSameAsInvariant
Definition TextInfo.cs:40
unsafe char ChangeCase(char c, bool toUpper)
Definition TextInfo.cs:195
static char ToLowerInvariant(char c)
Definition TextInfo.cs:169
static TextInfo ReadOnly(TextInfo textInfo)
Definition TextInfo.cs:128
unsafe void ChangeCaseCore(char *src, int srcLen, char *dstBuffer, int dstBufferCapacity, bool bToUpper)
Definition TextInfo.cs:651
void PopulateIsAsciiCasingSameAsInvariant()
Definition TextInfo.cs:464
void ChangeCaseCommon< TConversion >(ReadOnlySpan< char > source, Span< char > destination)
Definition TextInfo.cs:215
static unsafe string ToLowerAsciiInvariant(string s)
Definition TextInfo.cs:371
readonly string _cultureName
Definition TextInfo.cs:34
unsafe void NlsChangeCase(char *pSource, int pSourceLen, char *pResult, int pResultLen, bool toUpper)
Definition TextInfo.cs:703
readonly string _textInfoName
Definition TextInfo.cs:38
static readonly TextInfo Invariant
Definition TextInfo.cs:42
static int AddNonLetter(ref StringBuilder result, ref string input, int inputIndex, int charLen)
Definition TextInfo.cs:586
override string ToString()
Definition TextInfo.cs:484
static char ToUpperInvariant(char c)
Definition TextInfo.cs:427
static char ToUpperAsciiInvariant(char c)
Definition TextInfo.cs:454
static char ToLowerAsciiInvariant(char c)
Definition TextInfo.cs:405
TextInfo(CultureData cultureData, bool readOnly)
Definition TextInfo.cs:110
string ToLower(string str)
Definition TextInfo.cs:182
static string InvalidOperation_ReadOnly
Definition SR.cs:1504
Definition SR.cs:7
override string ToString()
StringBuilder Append(char value, int repeatCount)
static bool IsInRangeInclusive(uint value, uint lowerBound, uint upperBound)
static bool IsAsciiCodePoint(uint value)
static uint ConvertAllAsciiCharsInUInt32ToLowercase(uint value)
static bool AllCharsInUInt32AreAscii(uint value)
static uint ConvertAllAsciiCharsInUInt32ToUppercase(uint value)
static bool UInt32ContainsAnyUppercaseAsciiChar(uint value)
static bool UInt32ContainsAnyLowercaseAsciiChar(uint value)
static readonly IntPtr Zero
Definition IntPtr.cs:18