2 // System.Globalization.CompareInfo
5 // Rodrigo Moya (rodrigo@ximian.com)
6 // Dick Porter (dick@ximian.com)
8 // (C) Ximian, Inc. 2002
11 using System.Reflection;
12 using System.Runtime.Serialization;
13 using System.Runtime.CompilerServices;
15 namespace System.Globalization
18 public class CompareInfo : IDeserializationCallback
20 // Keep in synch with MonoCompareInfo in the runtime.
23 private string icu_name;
25 private IntPtr ICU_collator;
26 private int win32LCID; // Unused, but MS.NET serializes this
28 /* Hide the .ctor() */
31 [MethodImplAttribute (MethodImplOptions.InternalCall)]
32 private extern void construct_compareinfo (string locale);
34 internal CompareInfo (CultureInfo ci)
36 this.culture = ci.LCID;
37 this.icu_name = ci.IcuName;
38 this.construct_compareinfo (icu_name);
41 [MethodImplAttribute (MethodImplOptions.InternalCall)]
42 private extern void free_internal_collator ();
46 free_internal_collator ();
50 [MethodImplAttribute (MethodImplOptions.InternalCall)]
51 private extern int internal_compare (string str1, int offset1,
52 int length1, string str2,
53 int offset2, int length2,
54 CompareOptions options);
56 public virtual int Compare (string string1, string string2)
59 if(string1.Length == 0) {
60 if(string2.Length == 0) {
65 } else if(string2.Length == 0) {
69 return(internal_compare (string1, 0, string1.Length,
70 string2, 0, string2.Length,
71 CompareOptions.None));
74 public virtual int Compare (string string1, string string2,
75 CompareOptions options)
78 if(string1.Length == 0) {
79 if(string2.Length == 0) {
84 } else if(string2.Length == 0) {
88 return(internal_compare (string1, 0, string1.Length,
89 string2, 0, string2.Length,
93 public virtual int Compare (string string1, int offset1,
94 string string2, int offset2)
96 /* Not in the spec, but ms does these short
97 * cuts before checking the offsets (breaking
98 * the offset >= string length specified check
101 if(string1.Length == 0 ||
102 offset1 == string1.Length) {
103 if(string2.Length == 0 ||
104 offset2 == string2.Length) {
109 } else if(string2.Length == 0 ||
110 offset2 == string2.Length) {
114 if(offset1 < 0 || offset2 < 0) {
115 throw new ArgumentOutOfRangeException ("Offsets must not be less than zero");
118 if(offset1 > string1.Length) {
119 throw new ArgumentOutOfRangeException ("Offset1 is greater than or equal to the length of string1");
122 if(offset2 > string2.Length) {
123 throw new ArgumentOutOfRangeException ("Offset2 is greater than or equal to the length of string2");
126 return(internal_compare (string1, offset1,
127 string1.Length-offset1,
129 string2.Length-offset2,
130 CompareOptions.None));
133 public virtual int Compare (string string1, int offset1,
134 string string2, int offset2,
135 CompareOptions options)
137 /* Not in the spec, but ms does these short
138 * cuts before checking the offsets (breaking
139 * the offset >= string length specified check
142 if(string1.Length == 0 ||
143 offset1 == string1.Length) {
144 if(string2.Length == 0 ||
145 offset2 == string2.Length) {
150 } else if(string2.Length == 0 ||
151 offset2 == string2.Length) {
155 if(offset1 < 0 || offset2 < 0) {
156 throw new ArgumentOutOfRangeException ("Offsets must not be less than zero");
159 if(offset1 > string1.Length) {
160 throw new ArgumentOutOfRangeException ("Offset1 is greater than or equal to the length of string1");
163 if(offset2 > string2.Length) {
164 throw new ArgumentOutOfRangeException ("Offset2 is greater than or equal to the length of string2");
167 return(internal_compare (string1, offset1,
168 string1.Length-offset1,
170 string2.Length-offset1,
174 public virtual int Compare (string string1, int offset1,
175 int length1, string string2,
176 int offset2, int length2)
178 /* Not in the spec, but ms does these short
179 * cuts before checking the offsets (breaking
180 * the offset >= string length specified check
183 if(string1.Length == 0 ||
184 offset1 == string1.Length ||
186 if(string2.Length == 0 ||
187 offset2 == string2.Length ||
193 } else if(string2.Length == 0 ||
194 offset2 == string2.Length ||
199 if(offset1 < 0 || length1 < 0 ||
200 offset2 < 0 || length2 < 0) {
201 throw new ArgumentOutOfRangeException ("Offsets and lengths must not be less than zero");
204 if(offset1 > string1.Length) {
205 throw new ArgumentOutOfRangeException ("Offset1 is greater than or equal to the length of string1");
208 if(offset2 > string2.Length) {
209 throw new ArgumentOutOfRangeException ("Offset2 is greater than or equal to the length of string2");
212 if(length1 > string1.Length-offset1) {
213 throw new ArgumentOutOfRangeException ("Length1 is greater than the number of characters from offset1 to the end of string1");
216 if(length2 > string2.Length-offset2) {
217 throw new ArgumentOutOfRangeException ("Length2 is greater than the number of characters from offset2 to the end of string2");
220 return(internal_compare (string1, offset1, length1,
221 string2, offset2, length2,
222 CompareOptions.None));
225 public virtual int Compare (string string1, int offset1,
226 int length1, string string2,
227 int offset2, int length2,
228 CompareOptions options)
230 /* Not in the spec, but ms does these short
231 * cuts before checking the offsets (breaking
232 * the offset >= string length specified check
235 if(string1.Length == 0 ||
236 offset1 == string1.Length ||
238 if(string2.Length == 0 ||
239 offset2 == string2.Length ||
245 } else if(string2.Length == 0 ||
246 offset2 == string2.Length ||
251 if(offset1 < 0 || length1 < 0 ||
252 offset2 < 0 || length2 < 0) {
253 throw new ArgumentOutOfRangeException ("Offsets and lengths must not be less than zero");
256 if(offset1 > string1.Length) {
257 throw new ArgumentOutOfRangeException ("Offset1 is greater than or equal to the length of string1");
260 if(offset2 > string2.Length) {
261 throw new ArgumentOutOfRangeException ("Offset2 is greater than or equal to the length of string2");
264 if(length1 > string1.Length-offset1) {
265 throw new ArgumentOutOfRangeException ("Length1 is greater than the number of characters from offset1 to the end of string1");
268 if(length2 > string2.Length-offset2) {
269 throw new ArgumentOutOfRangeException ("Length2 is greater than the number of characters from offset2 to the end of string2");
272 return(internal_compare (string1, offset1, length1,
273 string2, offset2, length2,
277 public override bool Equals(object value)
279 CompareInfo other=value as CompareInfo;
284 return(other.culture==culture);
287 public static CompareInfo GetCompareInfo(int culture)
289 return(new CultureInfo (culture).CompareInfo);
292 public static CompareInfo GetCompareInfo(string name)
295 throw new ArgumentNullException("name");
297 return(new CultureInfo (name).CompareInfo);
300 public static CompareInfo GetCompareInfo(int culture,
303 /* The assembly parameter is supposedly there
304 * to allow some sort of compare algorithm
307 if(assembly == null) {
308 throw new ArgumentNullException("assembly");
310 if(assembly!=typeof (Object).Module.Assembly) {
311 throw new ArgumentException ("Assembly is an invalid type");
313 return(GetCompareInfo (culture));
316 public static CompareInfo GetCompareInfo(string name,
319 /* The assembly parameter is supposedly there
320 * to allow some sort of compare algorithm
324 throw new ArgumentNullException("name");
326 if(assembly == null) {
327 throw new ArgumentNullException("assembly");
329 if(assembly!=typeof (Object).Module.Assembly) {
330 throw new ArgumentException ("Assembly is an invalid type");
332 return(GetCompareInfo (name));
335 public override int GetHashCode()
340 [MethodImplAttribute (MethodImplOptions.InternalCall)]
341 private extern void assign_sortkey (object key, string source,
342 CompareOptions options);
344 public virtual SortKey GetSortKey(string source)
346 return(GetSortKey (source, CompareOptions.None));
349 public virtual SortKey GetSortKey(string source,
350 CompareOptions options)
352 SortKey key=new SortKey (culture, source, options);
354 /* Need to do the icall here instead of in the
355 * SortKey constructor, as we need access to
356 * this instance's collator.
358 assign_sortkey (key, source, options);
363 public virtual int IndexOf (string source, char value)
365 return(IndexOf (source, value, 0, source.Length,
366 CompareOptions.None));
369 public virtual int IndexOf (string source, string value)
371 return(IndexOf (source, value, 0, source.Length,
372 CompareOptions.None));
375 public virtual int IndexOf (string source, char value,
376 CompareOptions options)
378 return(IndexOf (source, value, 0, source.Length,
382 public virtual int IndexOf (string source, char value,
385 return(IndexOf (source, value, startIndex,
386 source.Length - startIndex,
387 CompareOptions.None));
390 public virtual int IndexOf (string source, string value,
391 CompareOptions options)
393 return(IndexOf (source, value, 0, source.Length,
397 public virtual int IndexOf (string source, string value,
400 return(IndexOf (source, value, startIndex,
401 source.Length - startIndex,
402 CompareOptions.None));
405 public virtual int IndexOf (string source, char value,
407 CompareOptions options)
409 return(IndexOf (source, value, startIndex,
410 source.Length - startIndex, options));
413 public virtual int IndexOf (string source, char value,
414 int startIndex, int count)
416 return IndexOf (source, value, startIndex, count,
417 CompareOptions.None);
420 public virtual int IndexOf (string source, string value,
422 CompareOptions options)
424 return(IndexOf (source, value, startIndex,
425 source.Length - startIndex, options));
428 public virtual int IndexOf (string source, string value,
429 int startIndex, int count)
431 return(IndexOf (source, value, startIndex, count,
432 CompareOptions.None));
435 [MethodImplAttribute (MethodImplOptions.InternalCall)]
436 private extern int internal_index (string source, int sindex,
437 int count, char value,
438 CompareOptions options,
441 public virtual int IndexOf (string source, char value,
442 int startIndex, int count,
443 CompareOptions options)
446 throw new ArgumentNullException ("source");
449 throw new ArgumentOutOfRangeException ("startIndex");
451 if(count<0 || (source.Length - startIndex) < count) {
452 throw new ArgumentOutOfRangeException ("count");
454 if((options & CompareOptions.StringSort)!=0) {
455 throw new ArgumentException ("StringSort is not a valid CompareOption for this method");
462 if((options & CompareOptions.Ordinal)!=0) {
463 for(int pos=startIndex;
464 pos < startIndex + count;
466 if(source[pos]==value) {
472 return (internal_index (source, startIndex,
473 count, value, options,
478 [MethodImplAttribute (MethodImplOptions.InternalCall)]
479 private extern int internal_index (string source, int sindex,
480 int count, string value,
481 CompareOptions options,
484 public virtual int IndexOf (string source, string value,
485 int startIndex, int count,
486 CompareOptions options)
489 throw new ArgumentNullException ("source");
492 throw new ArgumentNullException ("value");
495 throw new ArgumentOutOfRangeException ("startIndex");
497 if(count<0 || (source.Length - startIndex) < count) {
498 throw new ArgumentOutOfRangeException ("count");
504 return (internal_index (source, startIndex, count,
505 value, options, true));
508 public virtual bool IsPrefix(string source, string prefix)
510 return(IsPrefix (source, prefix, CompareOptions.None));
513 public virtual bool IsPrefix(string source, string prefix,
514 CompareOptions options)
517 throw new ArgumentNullException("source");
520 throw new ArgumentNullException("prefix");
523 if(source.Length < prefix.Length) {
526 return(Compare (source, 0, prefix.Length,
527 prefix, 0, prefix.Length,
532 public virtual bool IsSuffix(string source, string suffix)
534 return(IsSuffix (source, suffix, CompareOptions.None));
537 public virtual bool IsSuffix(string source, string suffix,
538 CompareOptions options)
541 throw new ArgumentNullException("source");
544 throw new ArgumentNullException("suffix");
547 if(source.Length < suffix.Length) {
550 return(Compare (source,
551 source.Length - suffix.Length,
552 suffix.Length, suffix, 0,
553 suffix.Length, options)==0);
557 public virtual int LastIndexOf(string source, char value)
559 return(LastIndexOf (source, value, 0, source.Length,
560 CompareOptions.None));
563 public virtual int LastIndexOf(string source, string value)
565 return(LastIndexOf (source, value, 0, source.Length,
566 CompareOptions.None));
569 public virtual int LastIndexOf(string source, char value,
570 CompareOptions options)
572 return(LastIndexOf (source, value, 0, source.Length,
576 public virtual int LastIndexOf(string source, char value,
579 return(LastIndexOf (source, value, startIndex,
580 source.Length - startIndex,
581 CompareOptions.None));
584 public virtual int LastIndexOf(string source, string value,
585 CompareOptions options)
587 return(LastIndexOf (source, value, 0, source.Length,
591 public virtual int LastIndexOf(string source, string value,
594 return(LastIndexOf (source, value, startIndex,
595 source.Length - startIndex,
596 CompareOptions.None));
599 public virtual int LastIndexOf(string source, char value,
601 CompareOptions options)
603 return(LastIndexOf (source, value, startIndex,
604 source.Length - startIndex,
608 public virtual int LastIndexOf(string source, char value,
609 int startIndex, int count)
611 return(LastIndexOf (source, value, startIndex, count,
612 CompareOptions.None));
615 public virtual int LastIndexOf(string source, string value,
617 CompareOptions options)
619 return(LastIndexOf (source, value, startIndex,
620 source.Length - startIndex,
624 public virtual int LastIndexOf(string source, string value,
625 int startIndex, int count)
627 return(LastIndexOf (source, value, startIndex, count,
628 CompareOptions.None));
631 public virtual int LastIndexOf(string source, char value,
632 int startIndex, int count,
633 CompareOptions options)
636 throw new ArgumentNullException("source");
639 throw new ArgumentOutOfRangeException ("startIndex");
641 if(count < 0 || (startIndex - count) < -1) {
642 throw new ArgumentOutOfRangeException("count");
644 if((options & CompareOptions.StringSort)!=0) {
645 throw new ArgumentException ("StringSort is not a valid CompareOption for this method");
652 if((options & CompareOptions.Ordinal)!=0) {
653 for(int pos=startIndex;
654 pos > startIndex - count;
656 if(source[pos]==value) {
662 return (internal_index (source, startIndex,
663 count, value, options,
668 public virtual int LastIndexOf(string source, string value,
669 int startIndex, int count,
670 CompareOptions options)
673 throw new ArgumentNullException("source");
676 throw new ArgumentNullException("value");
679 throw new ArgumentOutOfRangeException ("startIndex");
681 if(count < 0 || (startIndex - count) < -1) {
682 throw new ArgumentOutOfRangeException("count");
688 int valuelen=value.Length;
693 return(internal_index (source, startIndex, count,
694 value, options, false));
697 public override string ToString()
699 return("CompareInfo - "+culture);
702 void IDeserializationCallback.OnDeserialization(object sender)
704 /* This will build the ICU collator, and store
705 * the pointer in ICU_collator
708 this.construct_compareinfo (icu_name);
710 ICU_collator=IntPtr.Zero;
714 /* LAMESPEC: not mentioned in the spec, but corcompare
715 * shows it. Some documentation about what it does