b2a395b5c1d090a2da921b1612c18922cd612e19
[mono.git] / mcs / class / corlib / System.Globalization / CompareInfo.cs
1 //
2 // System.Globalization.CompareInfo
3 //
4 // Authors:
5 //   Rodrigo Moya (rodrigo@ximian.com)
6 //   Dick Porter (dick@ximian.com)
7 //
8 // (C) Ximian, Inc. 2002
9 //
10
11 //
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System.Reflection;
35 using System.Runtime.Serialization;
36 using System.Runtime.CompilerServices;
37 using Mono.Globalization.Unicode;
38
39 namespace System.Globalization
40 {
41         [Serializable]
42         public class CompareInfo : IDeserializationCallback
43         {
44                 static readonly bool useManagedCollation =
45                         Environment.GetEnvironmentVariable ("MONO_USE_MANAGED_COLLATION")
46                         == "yes";
47
48                 public static bool UseManagedCollation {
49                         get { return useManagedCollation && MSCompatUnicodeTable.IsReady; }
50                 }
51
52                 // Keep in synch with MonoCompareInfo in the runtime. 
53                 private int culture;
54                 [NonSerialized]
55                 private string icu_name;
56                 [NonSerialized]
57                 private IntPtr ICU_collator;
58                 private int win32LCID;  // Unused, but MS.NET serializes this
59
60                 [NonSerialized]
61                 SimpleCollator collator;
62                 
63                 /* Hide the .ctor() */
64                 CompareInfo() {}
65                 
66                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
67                 private extern void construct_compareinfo (string locale);
68                 
69                 internal CompareInfo (CultureInfo ci)
70                 {
71                         this.culture = ci.LCID;
72                         if (UseManagedCollation) 
73                                 collator = new SimpleCollator (ci);
74                         else {
75                                 this.icu_name = ci.IcuName;
76                                 this.construct_compareinfo (icu_name);
77                         }
78                 }
79                 
80                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
81                 private extern void free_internal_collator ();
82
83                 ~CompareInfo ()
84                 {
85                         free_internal_collator ();
86                 }
87
88                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
89                 private extern int internal_compare (string str1, int offset1,
90                                                      int length1, string str2,
91                                                      int offset2, int length2,
92                                                      CompareOptions options);
93
94                 private int internal_compare_managed (string str1, int offset1,
95                                                 int length1, string str2,
96                                                 int offset2, int length2,
97                                                 CompareOptions options)
98                 {
99                         return collator.Compare (str1, offset1, length1,
100                                 str2, offset2, length2, options);
101                 }
102
103                 private int internal_compare_switch (string str1, int offset1,
104                                                 int length1, string str2,
105                                                 int offset2, int length2,
106                                                 CompareOptions options)
107                 {
108                         return UseManagedCollation ?
109                                 internal_compare_managed (str1, offset1, length1,
110                                 str2, offset2, length2, options) :
111                                 internal_compare (str1, offset1, length1,
112                                 str2, offset2, length2, options);
113                 }
114
115                 public virtual int Compare (string string1, string string2)
116                 {
117                         /* Short cut... */
118                         if(string1.Length == 0 && string2.Length == 0)
119                                 return(0);
120
121                         return(internal_compare_switch (string1, 0, string1.Length,
122                                                  string2, 0, string2.Length,
123                                                  CompareOptions.None));
124                 }
125
126                 public virtual int Compare (string string1, string string2,
127                                             CompareOptions options)
128                 {
129                         /* Short cut... */
130                         if(string1.Length == 0 && string2.Length == 0)
131                                 return(0);
132
133                         return(internal_compare_switch (string1, 0, string1.Length,
134                                                  string2, 0, string2.Length,
135                                                  options));
136                 }
137
138                 public virtual int Compare (string string1, int offset1,
139                                             string string2, int offset2)
140                 {
141                         /* Not in the spec, but ms does these short
142                          * cuts before checking the offsets (breaking
143                          * the offset >= string length specified check
144                          * in the process...)
145                          */
146                         if ((string1.Length == 0 || offset1 == string1.Length) &&
147                                 (string2.Length == 0 || offset2 == string2.Length))
148                                 return(0);
149
150                         if(offset1 < 0 || offset2 < 0) {
151                                 throw new ArgumentOutOfRangeException ("Offsets must not be less than zero");
152                         }
153                         
154                         if(offset1 > string1.Length) {
155                                 throw new ArgumentOutOfRangeException ("Offset1 is greater than or equal to the length of string1");
156                         }
157                         
158                         if(offset2 > string2.Length) {
159                                 throw new ArgumentOutOfRangeException ("Offset2 is greater than or equal to the length of string2");
160                         }
161                         
162                         return(internal_compare_switch (string1, offset1,
163                                                  string1.Length-offset1,
164                                                  string2, offset2,
165                                                  string2.Length-offset2,
166                                                  CompareOptions.None));
167                 }
168
169                 public virtual int Compare (string string1, int offset1,
170                                             string string2, int offset2,
171                                             CompareOptions options)
172                 {
173                         /* Not in the spec, but ms does these short
174                          * cuts before checking the offsets (breaking
175                          * the offset >= string length specified check
176                          * in the process...)
177                          */
178                         if((string1.Length == 0 || offset1 == string1.Length) &&
179                                 (string2.Length == 0 || offset2 == string2.Length))
180                                 return(0);
181
182                         if(offset1 < 0 || offset2 < 0) {
183                                 throw new ArgumentOutOfRangeException ("Offsets must not be less than zero");
184                         }
185                         
186                         if(offset1 > string1.Length) {
187                                 throw new ArgumentOutOfRangeException ("Offset1 is greater than or equal to the length of string1");
188                         }
189                         
190                         if(offset2 > string2.Length) {
191                                 throw new ArgumentOutOfRangeException ("Offset2 is greater than or equal to the length of string2");
192                         }
193                         
194                         return(internal_compare_switch (string1, offset1,
195                                                  string1.Length-offset1,
196                                                  string2, offset2,
197                                                  string2.Length-offset1,
198                                                  options));
199                 }
200
201                 public virtual int Compare (string string1, int offset1,
202                                             int length1, string string2,
203                                             int offset2, int length2)
204                 {
205                         /* Not in the spec, but ms does these short
206                          * cuts before checking the offsets (breaking
207                          * the offset >= string length specified check
208                          * in the process...)
209                          */
210                         if((string1.Length == 0 ||
211                                 offset1 == string1.Length ||
212                                 length1 == 0) &&
213                                 (string2.Length == 0 ||
214                                 offset2 == string2.Length ||
215                                 length2 == 0))
216                                 return(0);
217
218                         if(offset1 < 0 || length1 < 0 ||
219                            offset2 < 0 || length2 < 0) {
220                                 throw new ArgumentOutOfRangeException ("Offsets and lengths must not be less than zero");
221                         }
222                         
223                         if(offset1 > string1.Length) {
224                                 throw new ArgumentOutOfRangeException ("Offset1 is greater than or equal to the length of string1");
225                         }
226                         
227                         if(offset2 > string2.Length) {
228                                 throw new ArgumentOutOfRangeException ("Offset2 is greater than or equal to the length of string2");
229                         }
230                         
231                         if(length1 > string1.Length-offset1) {
232                                 throw new ArgumentOutOfRangeException ("Length1 is greater than the number of characters from offset1 to the end of string1");
233                         }
234                         
235                         if(length2 > string2.Length-offset2) {
236                                 throw new ArgumentOutOfRangeException ("Length2 is greater than the number of characters from offset2 to the end of string2");
237                         }
238                         
239                         return(internal_compare_switch (string1, offset1, length1,
240                                                  string2, offset2, length2,
241                                                  CompareOptions.None));
242                 }
243
244                 public virtual int Compare (string string1, int offset1,
245                                             int length1, string string2,
246                                             int offset2, int length2,
247                                             CompareOptions options)
248                 {
249                         /* Not in the spec, but ms does these short
250                          * cuts before checking the offsets (breaking
251                          * the offset >= string length specified check
252                          * in the process...)
253                          */
254                         if((string1.Length == 0 ||
255                                 offset1 == string1.Length ||
256                                 length1 == 0) &&
257                                 (string2.Length == 0 ||
258                                 offset2 == string2.Length ||
259                                 length2 == 0))
260                                         return(0);
261
262                         if(offset1 < 0 || length1 < 0 ||
263                            offset2 < 0 || length2 < 0) {
264                                 throw new ArgumentOutOfRangeException ("Offsets and lengths must not be less than zero");
265                         }
266                         
267                         if(offset1 > string1.Length) {
268                                 throw new ArgumentOutOfRangeException ("Offset1 is greater than or equal to the length of string1");
269                         }
270                         
271                         if(offset2 > string2.Length) {
272                                 throw new ArgumentOutOfRangeException ("Offset2 is greater than or equal to the length of string2");
273                         }
274                         
275                         if(length1 > string1.Length-offset1) {
276                                 throw new ArgumentOutOfRangeException ("Length1 is greater than the number of characters from offset1 to the end of string1");
277                         }
278                         
279                         if(length2 > string2.Length-offset2) {
280                                 throw new ArgumentOutOfRangeException ("Length2 is greater than the number of characters from offset2 to the end of string2");
281                         }
282                         
283                         return(internal_compare_switch (string1, offset1, length1,
284                                                  string2, offset2, length2,
285                                                  options));
286                 }
287
288                 public override bool Equals(object value)
289                 {
290                         CompareInfo other=value as CompareInfo;
291                         if(other==null) {
292                                 return(false);
293                         }
294                         
295                         return(other.culture==culture);
296                 }
297
298                 public static CompareInfo GetCompareInfo(int culture)
299                 {
300                         return(new CultureInfo (culture).CompareInfo);
301                 }
302
303                 public static CompareInfo GetCompareInfo(string name)
304                 {
305                         if(name == null) {
306                                 throw new ArgumentNullException("name");
307                         }
308                         return(new CultureInfo (name).CompareInfo);
309                 }
310
311                 public static CompareInfo GetCompareInfo(int culture,
312                                                          Assembly assembly)
313                 {
314                         /* The assembly parameter is supposedly there
315                          * to allow some sort of compare algorithm
316                          * versioning.
317                          */
318                         if(assembly == null) {
319                                 throw new ArgumentNullException("assembly");
320                         }
321                         if(assembly!=typeof (Object).Module.Assembly) {
322                                 throw new ArgumentException ("Assembly is an invalid type");
323                         }
324                         return(GetCompareInfo (culture));
325                 }
326
327                 public static CompareInfo GetCompareInfo(string name,
328                                                          Assembly assembly)
329                 {
330                         /* The assembly parameter is supposedly there
331                          * to allow some sort of compare algorithm
332                          * versioning.
333                          */
334                         if(name == null) {
335                                 throw new ArgumentNullException("name");
336                         }
337                         if(assembly == null) {
338                                 throw new ArgumentNullException("assembly");
339                         }
340                         if(assembly!=typeof (Object).Module.Assembly) {
341                                 throw new ArgumentException ("Assembly is an invalid type");
342                         }
343                         return(GetCompareInfo (name));
344                 }
345
346                 public override int GetHashCode()
347                 {
348                         return(LCID);
349                 }
350
351                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
352                 private extern void assign_sortkey (object key, string source,
353                                                     CompareOptions options);
354                 
355                 public virtual SortKey GetSortKey(string source)
356                 {
357                         return(GetSortKey (source, CompareOptions.None));
358                 }
359
360                 public virtual SortKey GetSortKey(string source,
361                                                   CompareOptions options)
362                 {
363                         if (UseManagedCollation)
364                                 return collator.GetSortKey (source, options);
365                         SortKey key=new SortKey (culture, source, options);
366
367                         /* Need to do the icall here instead of in the
368                          * SortKey constructor, as we need access to
369                          * this instance's collator.
370                          */
371                         assign_sortkey (key, source, options);
372                         
373                         return(key);
374                 }
375
376                 public virtual int IndexOf (string source, char value)
377                 {
378                         return(IndexOf (source, value, 0, source.Length,
379                                         CompareOptions.None));
380                 }
381
382                 public virtual int IndexOf (string source, string value)
383                 {
384                         return(IndexOf (source, value, 0, source.Length,
385                                         CompareOptions.None));
386                 }
387
388                 public virtual int IndexOf (string source, char value,
389                                             CompareOptions options)
390                 {
391                         return(IndexOf (source, value, 0, source.Length,
392                                         options));
393                 }
394
395                 public virtual int IndexOf (string source, char value,
396                                             int startIndex)
397                 {
398                         return(IndexOf (source, value, startIndex,
399                                         source.Length - startIndex,
400                                         CompareOptions.None));
401                 }
402                 
403                 public virtual int IndexOf (string source, string value,
404                                             CompareOptions options)
405                 {
406                         return(IndexOf (source, value, 0, source.Length,
407                                         options));
408                 }
409
410                 public virtual int IndexOf (string source, string value,
411                                             int startIndex)
412                 {
413                         return(IndexOf (source, value, startIndex,
414                                         source.Length - startIndex,
415                                         CompareOptions.None));
416                 }
417
418                 public virtual int IndexOf (string source, char value,
419                                             int startIndex,
420                                             CompareOptions options)
421                 {
422                         return(IndexOf (source, value, startIndex,
423                                         source.Length - startIndex, options));
424                 }
425
426                 public virtual int IndexOf (string source, char value,
427                                             int startIndex, int count)
428                 {
429                         return IndexOf (source, value, startIndex, count,
430                                         CompareOptions.None);
431                 }
432
433                 public virtual int IndexOf (string source, string value,
434                                             int startIndex,
435                                             CompareOptions options)
436                 {
437                         return(IndexOf (source, value, startIndex,
438                                         source.Length - startIndex, options));
439                 }
440
441                 public virtual int IndexOf (string source, string value,
442                                             int startIndex, int count)
443                 {
444                         return(IndexOf (source, value, startIndex, count,
445                                         CompareOptions.None));
446                 }
447
448                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
449                 private extern int internal_index (string source, int sindex,
450                                                    int count, char value,
451                                                    CompareOptions options,
452                                                    bool first);
453
454                 private int internal_index_managed (string s, int sindex,
455                         int count, char c, CompareOptions opt,
456                         bool first)
457                 {
458                         return first ?
459                                 collator.IndexOf (s, c, sindex, count, opt) :
460                                 collator.LastIndexOf (s, c, sindex, count, opt);
461                 }
462
463                 private int internal_index_switch (string s, int sindex,
464                         int count, char c, CompareOptions opt,
465                         bool first)
466                 {
467                         return UseManagedCollation &&
468                                 (CompareOptions.Ordinal & opt) == 0 ?
469                                 internal_index_managed (s, sindex, count, c, opt, first) :
470                                 internal_index (s, sindex, count, c, opt, first);
471                 }
472
473                 public virtual int IndexOf (string source, char value,
474                                             int startIndex, int count,
475                                             CompareOptions options)
476                 {
477                         if(source==null) {
478                                 throw new ArgumentNullException ("source");
479                         }
480                         if(startIndex<0) {
481                                 throw new ArgumentOutOfRangeException ("startIndex");
482                         }
483                         if(count<0 || (source.Length - startIndex) < count) {
484                                 throw new ArgumentOutOfRangeException ("count");
485                         }
486                         if((options & CompareOptions.StringSort)!=0) {
487                                 throw new ArgumentException ("StringSort is not a valid CompareOption for this method");
488                         }
489                         
490                         if(count==0) {
491                                 return(-1);
492                         }
493
494                         if((options & CompareOptions.Ordinal)!=0) {
495                                 for(int pos=startIndex;
496                                     pos < startIndex + count;
497                                     pos++) {
498                                         if(source[pos]==value) {
499                                                 return(pos);
500                                         }
501                                 }
502                                 return(-1);
503                         } else {
504                                 return (internal_index_switch (source, startIndex,
505                                                         count, value, options,
506                                                         true));
507                         }
508                 }
509
510                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
511                 private extern int internal_index (string source, int sindex,
512                                                    int count, string value,
513                                                    CompareOptions options,
514                                                    bool first);
515
516                 private int internal_index_managed (string s1, int sindex,
517                         int count, string s2, CompareOptions opt,
518                         bool first)
519                 {
520                         return first ?
521                                 collator.IndexOf (s1, s2, sindex, count, opt) :
522                                 collator.LastIndexOf (s1, s2, sindex, count, opt);
523                 }
524
525                 private int internal_index_switch (string s1, int sindex,
526                         int count, string s2, CompareOptions opt,
527                         bool first)
528                 {
529                         return UseManagedCollation &&
530                                 (CompareOptions.Ordinal & opt) == 0 ?
531                                 internal_index_managed (s1, sindex, count, s2, opt, first) :
532                                 internal_index (s1, sindex, count, s2, opt, first);
533                 }
534
535                 public virtual int IndexOf (string source, string value,
536                                             int startIndex, int count,
537                                             CompareOptions options)
538                 {
539                         if(source==null) {
540                                 throw new ArgumentNullException ("source");
541                         }
542                         if(value==null) {
543                                 throw new ArgumentNullException ("value");
544                         }
545                         if(startIndex<0) {
546                                 throw new ArgumentOutOfRangeException ("startIndex");
547                         }
548                         if(count<0 || (source.Length - startIndex) < count) {
549                                 throw new ArgumentOutOfRangeException ("count");
550                         }
551                         if(count==0) {
552                                 return(-1);
553                         }
554
555                         return (internal_index_switch (source, startIndex, count,
556                                                 value, options, true));
557                 }
558
559                 public virtual bool IsPrefix(string source, string prefix)
560                 {
561                         return(IsPrefix (source, prefix, CompareOptions.None));
562                 }
563
564                 public virtual bool IsPrefix(string source, string prefix,
565                                              CompareOptions options)
566                 {
567                         if(source == null) {
568                                 throw new ArgumentNullException("source");
569                         }
570                         if(prefix == null) {
571                                 throw new ArgumentNullException("prefix");
572                         }
573
574                         if (UseManagedCollation)
575                                 return collator.IsPrefix (source, prefix, options);
576
577                         if(source.Length < prefix.Length) {
578                                 return(false);
579                         } else {
580                                 return(Compare (source, 0, prefix.Length,
581                                                 prefix, 0, prefix.Length,
582                                                 options)==0);
583                         }
584                 }
585
586                 public virtual bool IsSuffix(string source, string suffix)
587                 {
588                         return(IsSuffix (source, suffix, CompareOptions.None));
589                 }
590
591                 public virtual bool IsSuffix(string source, string suffix,
592                                              CompareOptions options)
593                 {
594                         if(source == null) {
595                                 throw new ArgumentNullException("source");
596                         }
597                         if(suffix == null) {
598                                 throw new ArgumentNullException("suffix");
599                         }
600
601                         if (UseManagedCollation)
602                                 return collator.IsSuffix (source, suffix, options);
603
604                         if(source.Length < suffix.Length) {
605                                 return(false);
606                         } else {
607                                 return(Compare (source,
608                                                 source.Length - suffix.Length,
609                                                 suffix.Length, suffix, 0,
610                                                 suffix.Length, options)==0);
611                         }
612                 }
613
614                 public virtual int LastIndexOf(string source, char value)
615                 {
616                         return(LastIndexOf (source, value, source.Length - 1,
617                                             source.Length, CompareOptions.None));
618                 }
619
620                 public virtual int LastIndexOf(string source, string value)
621                 {
622                         return(LastIndexOf (source, value, source.Length - 1,
623                                             source.Length, CompareOptions.None));
624                 }
625
626                 public virtual int LastIndexOf(string source, char value,
627                                                CompareOptions options)
628                 {
629                         return(LastIndexOf (source, value, source.Length - 1,
630                                             source.Length, options));
631                 }
632
633                 public virtual int LastIndexOf(string source, char value,
634                                                int startIndex)
635                 {
636                         return(LastIndexOf (source, value, startIndex,
637                                             startIndex + 1,
638                                             CompareOptions.None));
639                 }
640
641                 public virtual int LastIndexOf(string source, string value,
642                                                CompareOptions options)
643                 {
644                         return(LastIndexOf (source, value, source.Length - 1,
645                                             source.Length, options));
646                 }
647
648                 public virtual int LastIndexOf(string source, string value,
649                                                int startIndex)
650                 {
651                         return(LastIndexOf (source, value, startIndex,
652                                             startIndex + 1,
653                                             CompareOptions.None));
654                 }
655
656                 public virtual int LastIndexOf(string source, char value,
657                                                int startIndex,
658                                                CompareOptions options)
659                 {
660                         return(LastIndexOf (source, value, startIndex,
661                                             startIndex + 1,
662                                             options));
663                 }
664
665                 public virtual int LastIndexOf(string source, char value,
666                                                int startIndex, int count)
667                 {
668                         return(LastIndexOf (source, value, startIndex, count,
669                                             CompareOptions.None));
670                 }
671
672                 public virtual int LastIndexOf(string source, string value,
673                                                int startIndex,
674                                                CompareOptions options)
675                 {
676                         return(LastIndexOf (source, value, startIndex,
677                                             startIndex + 1,
678                                             options));
679                 }
680
681                 public virtual int LastIndexOf(string source, string value,
682                                                int startIndex, int count)
683                 {
684                         return(LastIndexOf (source, value, startIndex, count,
685                                             CompareOptions.None));
686                 }
687
688                 public virtual int LastIndexOf(string source, char value,
689                                                int startIndex, int count,
690                                                CompareOptions options)
691                 {
692                         if(source == null) {
693                                 throw new ArgumentNullException("source");
694                         }
695                         if(startIndex < 0) {
696                                 throw new ArgumentOutOfRangeException ("startIndex");
697                         }
698                         if(count < 0 || (startIndex - count) < -1) {
699                                 throw new ArgumentOutOfRangeException("count");
700                         }
701                         if((options & CompareOptions.StringSort)!=0) {
702                                 throw new ArgumentException ("StringSort is not a valid CompareOption for this method");
703                         }
704                         
705                         if(count==0) {
706                                 return(-1);
707                         }
708
709                         if((options & CompareOptions.Ordinal)!=0) {
710                                 for(int pos=startIndex;
711                                     pos > startIndex - count;
712                                     pos--) {
713                                         if(source[pos]==value) {
714                                                 return(pos);
715                                         }
716                                 }
717                                 return(-1);
718                         } else {
719                                 return (internal_index_switch (source, startIndex,
720                                                         count, value, options,
721                                                         false));
722                         }
723                 }
724
725                 public virtual int LastIndexOf(string source, string value,
726                                                int startIndex, int count,
727                                                CompareOptions options)
728                 {
729                         if(source == null) {
730                                 throw new ArgumentNullException("source");
731                         }
732                         if(value == null) {
733                                 throw new ArgumentNullException("value");
734                         }
735                         if(startIndex < 0) {
736                                 throw new ArgumentOutOfRangeException ("startIndex");
737                         }
738                         if(count < 0 || (startIndex - count) < -1) {
739                                 throw new ArgumentOutOfRangeException("count");
740                         }
741                         if(count == 0) {
742                                 return(-1);
743                         }
744
745                         int valuelen=value.Length;
746                         if(valuelen==0) {
747                                 return(0);
748                         }
749
750                         return(internal_index_switch (source, startIndex, count,
751                                                value, options, false));
752                 }
753
754                 public override string ToString()
755                 {
756                         return("CompareInfo - "+culture);
757                 }
758
759                 void IDeserializationCallback.OnDeserialization(object sender)
760                 {
761                         if (UseManagedCollation) {
762                                 collator = new SimpleCollator (new CultureInfo (culture));
763                         } else {
764                                 /* This will build the ICU collator, and store
765                                  * the pointer in ICU_collator
766                                  */
767                                 try {
768                                         this.construct_compareinfo (icu_name);
769                                 } catch {
770                                         ICU_collator=IntPtr.Zero;
771                                 }
772                         }
773                 }
774
775                 /* LAMESPEC: not mentioned in the spec, but corcompare
776                  * shows it.  Some documentation about what it does
777                  * would be nice.
778                  */
779                 public int LCID
780                 {
781                         get {
782                                 return(culture);
783                         }
784                 }
785         }
786 }