mscorlib(4.0.0.0) API with additions
TextInfo.cs
4 using System.Security;
5 using System.Text;
6 
7 namespace System.Globalization
8 {
10  [Serializable]
11  [ComVisible(true)]
12  [__DynamicallyInvokable]
14  {
15  [OptionalField(VersionAdded = 2)]
16  private string m_listSeparator;
17 
18  [OptionalField(VersionAdded = 2)]
19  private bool m_isReadOnly;
20 
21  [OptionalField(VersionAdded = 3)]
22  private string m_cultureName;
23 
24  [NonSerialized]
25  private CultureData m_cultureData;
26 
27  [NonSerialized]
28  private string m_textInfoName;
29 
30  [NonSerialized]
31  private IntPtr m_dataHandle;
32 
33  [NonSerialized]
34  private IntPtr m_handleOrigin;
35 
36  [NonSerialized]
37  private bool? m_IsAsciiCasingSameAsInvariant;
38 
39  internal static volatile TextInfo s_Invariant;
40 
41  [OptionalField(VersionAdded = 2)]
42  private string customCultureName;
43 
44  [OptionalField(VersionAdded = 1)]
45  internal int m_nDataItem;
46 
47  [OptionalField(VersionAdded = 1)]
48  internal bool m_useUserOverride;
49 
50  [OptionalField(VersionAdded = 1)]
51  internal int m_win32LangID;
52 
53  private const int wordSeparatorMask = 536672256;
54 
55  internal static TextInfo Invariant
56  {
57  get
58  {
59  if (s_Invariant == null)
60  {
61  s_Invariant = new TextInfo(CultureData.Invariant);
62  }
63  return s_Invariant;
64  }
65  }
66 
69  public virtual int ANSICodePage => m_cultureData.IDEFAULTANSICODEPAGE;
70 
73  public virtual int OEMCodePage => m_cultureData.IDEFAULTOEMCODEPAGE;
74 
77  public virtual int MacCodePage => m_cultureData.IDEFAULTMACCODEPAGE;
78 
81  public virtual int EBCDICCodePage => m_cultureData.IDEFAULTEBCDICCODEPAGE;
82 
85  [ComVisible(false)]
86  public int LCID
87  {
88  get
89  {
90  return CultureInfo.GetCultureInfo(m_textInfoName).LCID;
91  }
92  }
93 
96  [ComVisible(false)]
97  [__DynamicallyInvokable]
98  public string CultureName
99  {
100  [__DynamicallyInvokable]
101  get
102  {
103  return m_textInfoName;
104  }
105  }
106 
110  [ComVisible(false)]
111  [__DynamicallyInvokable]
112  public bool IsReadOnly
113  {
114  [__DynamicallyInvokable]
115  get
116  {
117  return m_isReadOnly;
118  }
119  }
120 
125  [__DynamicallyInvokable]
126  public virtual string ListSeparator
127  {
128  [SecuritySafeCritical]
129  [__DynamicallyInvokable]
130  get
131  {
132  if (m_listSeparator == null)
133  {
134  m_listSeparator = m_cultureData.SLIST;
135  }
136  return m_listSeparator;
137  }
138  [ComVisible(false)]
139  [__DynamicallyInvokable]
140  set
141  {
142  if (value == null)
143  {
144  throw new ArgumentNullException("value", Environment.GetResourceString("ArgumentNull_String"));
145  }
146  VerifyWritable();
147  m_listSeparator = value;
148  }
149  }
150 
151  private bool IsAsciiCasingSameAsInvariant
152  {
153  get
154  {
155  if (!m_IsAsciiCasingSameAsInvariant.HasValue)
156  {
157  m_IsAsciiCasingSameAsInvariant = (CultureInfo.GetCultureInfo(m_textInfoName).CompareInfo.Compare("abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", CompareOptions.IgnoreCase) == 0);
158  }
159  return m_IsAsciiCasingSameAsInvariant.Value;
160  }
161  }
162 
166  [ComVisible(false)]
167  [__DynamicallyInvokable]
168  public bool IsRightToLeft
169  {
170  [__DynamicallyInvokable]
171  get
172  {
173  return m_cultureData.IsRightToLeft;
174  }
175  }
176 
177  internal TextInfo(CultureData cultureData)
178  {
179  m_cultureData = cultureData;
180  m_cultureName = m_cultureData.CultureName;
181  m_textInfoName = m_cultureData.STEXTINFO;
182  m_dataHandle = CompareInfo.InternalInitSortHandle(m_textInfoName, out IntPtr handleOrigin);
183  m_handleOrigin = handleOrigin;
184  }
185 
186  [OnDeserializing]
187  private void OnDeserializing(StreamingContext ctx)
188  {
189  m_cultureData = null;
190  m_cultureName = null;
191  }
192 
193  private void OnDeserialized()
194  {
195  if (m_cultureData != null)
196  {
197  return;
198  }
199  if (m_cultureName == null)
200  {
201  if (customCultureName != null)
202  {
203  m_cultureName = customCultureName;
204  }
205  else if (m_win32LangID == 0)
206  {
207  m_cultureName = "ar-SA";
208  }
209  else
210  {
211  m_cultureName = CultureInfo.GetCultureInfo(m_win32LangID).m_cultureData.CultureName;
212  }
213  }
214  m_cultureData = CultureInfo.GetCultureInfo(m_cultureName).m_cultureData;
215  m_textInfoName = m_cultureData.STEXTINFO;
216  m_dataHandle = CompareInfo.InternalInitSortHandle(m_textInfoName, out IntPtr handleOrigin);
217  m_handleOrigin = handleOrigin;
218  }
219 
220  [OnDeserialized]
221  private void OnDeserialized(StreamingContext ctx)
222  {
223  OnDeserialized();
224  }
225 
226  [OnSerializing]
227  private void OnSerializing(StreamingContext ctx)
228  {
229  m_useUserOverride = false;
230  customCultureName = m_cultureName;
231  m_win32LangID = CultureInfo.GetCultureInfo(m_cultureName).LCID;
232  }
233 
234  internal static int GetHashCodeOrdinalIgnoreCase(string s)
235  {
236  return GetHashCodeOrdinalIgnoreCase(s, forceRandomizedHashing: false, 0L);
237  }
238 
239  internal static int GetHashCodeOrdinalIgnoreCase(string s, bool forceRandomizedHashing, long additionalEntropy)
240  {
241  return Invariant.GetCaseInsensitiveHashCode(s, forceRandomizedHashing, additionalEntropy);
242  }
243 
244  [SecuritySafeCritical]
245  internal static bool TryFastFindStringOrdinalIgnoreCase(int searchFlags, string source, int startIndex, string value, int count, ref int foundIndex)
246  {
247  return InternalTryFindStringOrdinalIgnoreCase(searchFlags, source, count, startIndex, value, value.Length, ref foundIndex);
248  }
249 
250  [SecuritySafeCritical]
251  internal static int CompareOrdinalIgnoreCase(string str1, string str2)
252  {
253  return InternalCompareStringOrdinalIgnoreCase(str1, 0, str2, 0, str1.Length, str2.Length);
254  }
255 
256  [SecuritySafeCritical]
257  internal static int CompareOrdinalIgnoreCaseEx(string strA, int indexA, string strB, int indexB, int lengthA, int lengthB)
258  {
259  return InternalCompareStringOrdinalIgnoreCase(strA, indexA, strB, indexB, lengthA, lengthB);
260  }
261 
262  internal static int IndexOfStringOrdinalIgnoreCase(string source, string value, int startIndex, int count)
263  {
264  if (source.Length == 0 && value.Length == 0)
265  {
266  return 0;
267  }
268  int foundIndex = -1;
269  if (TryFastFindStringOrdinalIgnoreCase(4194304, source, startIndex, value, count, ref foundIndex))
270  {
271  return foundIndex;
272  }
273  int num = startIndex + count;
274  int num2 = num - value.Length;
275  while (startIndex <= num2)
276  {
277  if (CompareOrdinalIgnoreCaseEx(source, startIndex, value, 0, value.Length, value.Length) == 0)
278  {
279  return startIndex;
280  }
281  startIndex++;
282  }
283  return -1;
284  }
285 
286  internal static int LastIndexOfStringOrdinalIgnoreCase(string source, string value, int startIndex, int count)
287  {
288  if (value.Length == 0)
289  {
290  return startIndex;
291  }
292  int foundIndex = -1;
293  if (TryFastFindStringOrdinalIgnoreCase(8388608, source, startIndex, value, count, ref foundIndex))
294  {
295  return foundIndex;
296  }
297  int num = startIndex - count + 1;
298  if (value.Length > 0)
299  {
300  startIndex -= value.Length - 1;
301  }
302  while (startIndex >= num)
303  {
304  if (CompareOrdinalIgnoreCaseEx(source, startIndex, value, 0, value.Length, value.Length) == 0)
305  {
306  return startIndex;
307  }
308  startIndex--;
309  }
310  return -1;
311  }
312 
315  [ComVisible(false)]
316  public virtual object Clone()
317  {
318  object obj = MemberwiseClone();
319  ((TextInfo)obj).SetReadOnlyState(readOnly: false);
320  return obj;
321  }
322 
328  [ComVisible(false)]
329  public static TextInfo ReadOnly(TextInfo textInfo)
330  {
331  if (textInfo == null)
332  {
333  throw new ArgumentNullException("textInfo");
334  }
335  if (textInfo.IsReadOnly)
336  {
337  return textInfo;
338  }
339  TextInfo textInfo2 = (TextInfo)textInfo.MemberwiseClone();
340  textInfo2.SetReadOnlyState(readOnly: true);
341  return textInfo2;
342  }
343 
344  private void VerifyWritable()
345  {
346  if (m_isReadOnly)
347  {
348  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
349  }
350  }
351 
352  internal void SetReadOnlyState(bool readOnly)
353  {
354  m_isReadOnly = readOnly;
355  }
356 
360  [SecuritySafeCritical]
361  [__DynamicallyInvokable]
362  public virtual char ToLower(char c)
363  {
364  if (IsAscii(c) && IsAsciiCasingSameAsInvariant)
365  {
366  return ToLowerAsciiInvariant(c);
367  }
368  return InternalChangeCaseChar(m_dataHandle, m_handleOrigin, m_textInfoName, c, isToUpper: false);
369  }
370 
376  [SecuritySafeCritical]
377  [__DynamicallyInvokable]
378  public virtual string ToLower(string str)
379  {
380  if (str == null)
381  {
382  throw new ArgumentNullException("str");
383  }
384  return InternalChangeCaseString(m_dataHandle, m_handleOrigin, m_textInfoName, str, isToUpper: false);
385  }
386 
387  private static char ToLowerAsciiInvariant(char c)
388  {
389  if ('A' <= c && c <= 'Z')
390  {
391  c = (char)(c | 0x20);
392  }
393  return c;
394  }
395 
399  [SecuritySafeCritical]
400  [__DynamicallyInvokable]
401  public virtual char ToUpper(char c)
402  {
403  if (IsAscii(c) && IsAsciiCasingSameAsInvariant)
404  {
405  return ToUpperAsciiInvariant(c);
406  }
407  return InternalChangeCaseChar(m_dataHandle, m_handleOrigin, m_textInfoName, c, isToUpper: true);
408  }
409 
415  [SecuritySafeCritical]
416  [__DynamicallyInvokable]
417  public virtual string ToUpper(string str)
418  {
419  if (str == null)
420  {
421  throw new ArgumentNullException("str");
422  }
423  return InternalChangeCaseString(m_dataHandle, m_handleOrigin, m_textInfoName, str, isToUpper: true);
424  }
425 
426  private static char ToUpperAsciiInvariant(char c)
427  {
428  if ('a' <= c && c <= 'z')
429  {
430  c = (char)(c & -33);
431  }
432  return c;
433  }
434 
435  private static bool IsAscii(char c)
436  {
437  return c < '\u0080';
438  }
439 
444  [__DynamicallyInvokable]
445  public override bool Equals(object obj)
446  {
447  TextInfo textInfo = obj as TextInfo;
448  if (textInfo != null)
449  {
450  return CultureName.Equals(textInfo.CultureName);
451  }
452  return false;
453  }
454 
457  [__DynamicallyInvokable]
458  public override int GetHashCode()
459  {
460  return CultureName.GetHashCode();
461  }
462 
465  [__DynamicallyInvokable]
466  public override string ToString()
467  {
468  return "TextInfo - " + m_cultureData.CultureName;
469  }
470 
476  public string ToTitleCase(string str)
477  {
478  if (str == null)
479  {
480  throw new ArgumentNullException("str");
481  }
482  if (str.Length == 0)
483  {
484  return str;
485  }
486  StringBuilder result = new StringBuilder();
487  string text = null;
488  int num;
489  for (num = 0; num < str.Length; num++)
490  {
491  UnicodeCategory unicodeCategory = CharUnicodeInfo.InternalGetUnicodeCategory(str, num, out int charLength);
492  if (char.CheckLetter(unicodeCategory))
493  {
494  num = AddTitlecaseLetter(ref result, ref str, num, charLength) + 1;
495  int num2 = num;
496  bool flag = unicodeCategory == UnicodeCategory.LowercaseLetter;
497  while (num < str.Length)
498  {
499  unicodeCategory = CharUnicodeInfo.InternalGetUnicodeCategory(str, num, out charLength);
500  if (IsLetterCategory(unicodeCategory))
501  {
502  if (unicodeCategory == UnicodeCategory.LowercaseLetter)
503  {
504  flag = true;
505  }
506  num += charLength;
507  }
508  else if (str[num] == '\'')
509  {
510  num++;
511  if (flag)
512  {
513  if (text == null)
514  {
515  text = ToLower(str);
516  }
517  result.Append(text, num2, num - num2);
518  }
519  else
520  {
521  result.Append(str, num2, num - num2);
522  }
523  num2 = num;
524  flag = true;
525  }
526  else
527  {
528  if (IsWordSeparator(unicodeCategory))
529  {
530  break;
531  }
532  num += charLength;
533  }
534  }
535  int num3 = num - num2;
536  if (num3 > 0)
537  {
538  if (flag)
539  {
540  if (text == null)
541  {
542  text = ToLower(str);
543  }
544  result.Append(text, num2, num3);
545  }
546  else
547  {
548  result.Append(str, num2, num3);
549  }
550  }
551  if (num < str.Length)
552  {
553  num = AddNonLetter(ref result, ref str, num, charLength);
554  }
555  }
556  else
557  {
558  num = AddNonLetter(ref result, ref str, num, charLength);
559  }
560  }
561  return result.ToString();
562  }
563 
564  private static int AddNonLetter(ref StringBuilder result, ref string input, int inputIndex, int charLen)
565  {
566  if (charLen == 2)
567  {
568  result.Append(input[inputIndex++]);
569  result.Append(input[inputIndex]);
570  }
571  else
572  {
573  result.Append(input[inputIndex]);
574  }
575  return inputIndex;
576  }
577 
578  private int AddTitlecaseLetter(ref StringBuilder result, ref string input, int inputIndex, int charLen)
579  {
580  if (charLen == 2)
581  {
582  result.Append(ToUpper(input.Substring(inputIndex, charLen)));
583  inputIndex++;
584  }
585  else
586  {
587  switch (input[inputIndex])
588  {
589  case 'DŽ':
590  case 'Dž':
591  case 'dž':
592  result.Append('Dž');
593  break;
594  case 'LJ':
595  case 'Lj':
596  case 'lj':
597  result.Append('Lj');
598  break;
599  case 'NJ':
600  case 'Nj':
601  case 'nj':
602  result.Append('Nj');
603  break;
604  case 'DZ':
605  case 'Dz':
606  case 'dz':
607  result.Append('Dz');
608  break;
609  default:
610  result.Append(ToUpper(input[inputIndex]));
611  break;
612  }
613  }
614  return inputIndex;
615  }
616 
617  private static bool IsWordSeparator(UnicodeCategory category)
618  {
619  return (0x1FFCF800 & (1 << (int)category)) != 0;
620  }
621 
622  private static bool IsLetterCategory(UnicodeCategory uc)
623  {
624  if (uc != 0 && uc != UnicodeCategory.LowercaseLetter && uc != UnicodeCategory.TitlecaseLetter && uc != UnicodeCategory.ModifierLetter)
625  {
626  return uc == UnicodeCategory.OtherLetter;
627  }
628  return true;
629  }
630 
633  void IDeserializationCallback.OnDeserialization(object sender)
634  {
635  OnDeserialized();
636  }
637 
638  [SecuritySafeCritical]
639  internal int GetCaseInsensitiveHashCode(string str)
640  {
641  return GetCaseInsensitiveHashCode(str, forceRandomizedHashing: false, 0L);
642  }
643 
644  [SecuritySafeCritical]
645  internal int GetCaseInsensitiveHashCode(string str, bool forceRandomizedHashing, long additionalEntropy)
646  {
647  if (str == null)
648  {
649  throw new ArgumentNullException("str");
650  }
651  return InternalGetCaseInsHash(m_dataHandle, m_handleOrigin, m_textInfoName, str, forceRandomizedHashing, additionalEntropy);
652  }
653 
654  [MethodImpl(MethodImplOptions.InternalCall)]
655  [SecurityCritical]
656  private static extern char InternalChangeCaseChar(IntPtr handle, IntPtr handleOrigin, string localeName, char ch, bool isToUpper);
657 
658  [MethodImpl(MethodImplOptions.InternalCall)]
659  [SecurityCritical]
660  private static extern string InternalChangeCaseString(IntPtr handle, IntPtr handleOrigin, string localeName, string str, bool isToUpper);
661 
662  [MethodImpl(MethodImplOptions.InternalCall)]
663  [SecurityCritical]
664  private static extern int InternalGetCaseInsHash(IntPtr handle, IntPtr handleOrigin, string localeName, string str, bool forceRandomizedHashing, long additionalEntropy);
665 
666  [DllImport("QCall", CharSet = CharSet.Unicode)]
667  [SecurityCritical]
668  [SuppressUnmanagedCodeSecurity]
669  private static extern int InternalCompareStringOrdinalIgnoreCase(string string1, int index1, string string2, int index2, int length1, int length2);
670 
671  [DllImport("QCall", CharSet = CharSet.Unicode)]
672  [SecurityCritical]
673  [SuppressUnmanagedCodeSecurity]
674  [return: MarshalAs(UnmanagedType.Bool)]
675  private static extern bool InternalTryFindStringOrdinalIgnoreCase(int searchFlags, string source, int sourceCount, int startIndex, string target, int targetCount, ref int foundIndex);
676  }
677 }
string ToTitleCase(string str)
Converts the specified string to title case (except for words that are entirely in uppercase,...
Definition: TextInfo.cs:476
The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method th...
bool IsRightToLeft
Gets a value indicating whether the current T:System.Globalization.TextInfo object represents a writi...
Definition: TextInfo.cs:169
override bool Equals(object obj)
Determines whether the specified object represents the same writing system as the current T:System....
Definition: TextInfo.cs:445
unsafe override string ToString()
Converts the value of this instance to a T:System.String.
virtual CompareInfo? CompareInfo
Gets the T:System.Globalization.CompareInfo that defines how to compare strings for the culture.
Definition: CultureInfo.cs:447
virtual string ToLower(string str)
Converts the specified string to lowercase.
Definition: TextInfo.cs:378
Indicates that a class is to be notified when deserialization of the entire object graph has been com...
virtual int MacCodePage
Gets the Macintosh code page used by the writing system represented by the current T:System....
Definition: TextInfo.cs:77
Definition: __Canon.cs:3
Describes the source and destination of a given serialized stream, and provides an additional caller-...
virtual string ListSeparator
Gets or sets the string that separates items in a list.
Definition: TextInfo.cs:127
virtual string ToUpper(string str)
Converts the specified string to uppercase.
Definition: TextInfo.cs:417
static CultureInfo GetCultureInfo(int culture)
Retrieves a cached, read-only instance of a culture by using the specified culture identifier.
static TextInfo ReadOnly(TextInfo textInfo)
Returns a read-only version of the specified T:System.Globalization.TextInfo object.
Definition: TextInfo.cs:329
Provides information about, and means to manipulate, the current environment and platform....
Definition: Environment.cs:21
UnmanagedType
Identifies how to marshal parameters or fields to unmanaged code.
Definition: UnmanagedType.cs:7
void OnDeserialization(object sender)
Runs when the entire object graph has been deserialized.
virtual int Compare(string string1, string string2)
Compares two strings.
Definition: CompareInfo.cs:313
virtual object Clone()
Creates a new object that is a copy of the current T:System.Globalization.TextInfo object.
Definition: TextInfo.cs:316
Implements a set of methods for culture-sensitive string comparisons.
Definition: CompareInfo.cs:13
A platform-specific type that is used to represent a pointer or a handle.
Definition: IntPtr.cs:14
virtual char ToLower(char c)
Converts the specified character to lowercase.
Definition: TextInfo.cs:362
Supports cloning, which creates a new instance of a class with the same value as an existing instance...
Definition: ICloneable.cs:7
MethodImplOptions
Defines the details of how a method is implemented.
CharSet
Dictates which character set marshaled strings should use.
Definition: CharSet.cs:7
Represents a mutable string of characters. This class cannot be inherited.To browse the ....
override int GetHashCode()
Serves as a hash function for the current T:System.Globalization.TextInfo, suitable for hashing algor...
Definition: TextInfo.cs:458
virtual int ANSICodePage
Gets the American National Standards Institute (ANSI) code page used by the writing system represente...
Definition: TextInfo.cs:69
Retrieves information about a Unicode character. This class cannot be inherited.
virtual int OEMCodePage
Gets the original equipment manufacturer (OEM) code page used by the writing system represented by th...
Definition: TextInfo.cs:73
UnicodeCategory
Defines the Unicode category of a character.
virtual int EBCDICCodePage
Gets the Extended Binary Coded Decimal Interchange Code (EBCDIC) code page used by the writing system...
Definition: TextInfo.cs:81
int LCID
Gets the culture identifier for the culture associated with the current T:System.Globalization....
Definition: TextInfo.cs:87
Specifies that the class can be serialized.
string CultureName
Gets the name of the culture associated with the current T:System.Globalization.TextInfo object.
Definition: TextInfo.cs:99
The exception that is thrown when a method call is invalid for the object's current state.
virtual int LCID
Gets the culture identifier for the current T:System.Globalization.CultureInfo.
Definition: CultureInfo.cs:304
Defines text properties and behaviors, such as casing, that are specific to a writing system.
Definition: TextInfo.cs:13
Provides information about a specific culture (called a locale for unmanaged code development)....
Definition: CultureInfo.cs:16
CompareOptions
Defines the string comparison options to use with T:System.Globalization.CompareInfo.
override string ToString()
Returns a string that represents the current T:System.Globalization.TextInfo.
Definition: TextInfo.cs:466
virtual char ToUpper(char c)
Converts the specified character to uppercase.
Definition: TextInfo.cs:401
bool IsReadOnly
Gets a value indicating whether the current T:System.Globalization.TextInfo object is read-only.
Definition: TextInfo.cs:113