**** Merged from MCS ****
[mono-project.git] / mcs / class / corlib / System.Globalization / NumberFormatInfo.cs
blobe884daad5a7f9bc3c68410be4154118b2ba16943
1 //
2 // System.Globalization.NumberFormatInfo.cs
3 //
4 // Author:
5 // Derek Holden (dholden@draper.com)
6 // Bob Smith (bob@thestuff.net)
7 // Mohammad DAMT (mdamt@cdl2000.com)
8 //
9 // (C) Derek Holden
10 // (C) Bob Smith http://www.thestuff.net
11 // (c) 2003, PT Cakram Datalingga Duaribu http://www.cdl2000.com
15 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
17 // Permission is hereby granted, free of charge, to any person obtaining
18 // a copy of this software and associated documentation files (the
19 // "Software"), to deal in the Software without restriction, including
20 // without limitation the rights to use, copy, modify, merge, publish,
21 // distribute, sublicense, and/or sell copies of the Software, and to
22 // permit persons to whom the Software is furnished to do so, subject to
23 // the following conditions:
24 //
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
27 //
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 // NumberFormatInfo. One can only assume it is the class gotten
39 // back from a GetFormat() method from an IFormatProvider /
40 // IFormattable implementer. There are some discrepencies with the
41 // ECMA spec and the SDK docs, surprisingly. See my conversation
42 // with myself on it at:
43 // http://lists.ximian.com/archives/public/mono-list/2001-July/000794.html
44 //
45 // Other than that this is totally ECMA compliant.
48 namespace System.Globalization {
50 [Serializable]
51 public sealed class NumberFormatInfo : ICloneable, IFormatProvider {
52 private bool isReadOnly;
53 // used for temporary storage. Used in InitPatterns ()
54 string decimalFormats;
55 string currencyFormats;
56 string percentFormats;
57 string digitPattern = "#";
58 string zeroPattern = "0";
60 // Currency Related Format Info
61 private int currencyDecimalDigits;
62 private string currencyDecimalSeparator;
63 private string currencyGroupSeparator;
64 private int[] currencyGroupSizes;
65 private int currencyNegativePattern;
66 private int currencyPositivePattern;
67 private string currencySymbol;
69 private string nanSymbol;
70 private string negativeInfinitySymbol;
71 private string negativeSign;
73 // Number Related Format Info
74 private int numberDecimalDigits;
75 private string numberDecimalSeparator;
76 private string numberGroupSeparator;
77 private int[] numberGroupSizes;
78 private int numberNegativePattern;
80 // Percent Related Format Info
81 private int percentDecimalDigits;
82 private string percentDecimalSeparator;
83 private string percentGroupSeparator;
84 private int[] percentGroupSizes;
85 private int percentNegativePattern;
86 private int percentPositivePattern;
87 private string percentSymbol;
89 private string perMilleSymbol;
90 private string positiveInfinitySymbol;
91 private string positiveSign;
93 string ansiCurrencySymbol; // TODO, MS.NET serializes this.
94 int m_dataItem; // Unused, but MS.NET serializes this.
95 bool m_useUserOverride; // Unused, but MS.NET serializes this.
96 bool validForParseAsNumber; // Unused, but MS.NET serializes this.
97 bool validForParseAsCurrency; // Unused, but MS.NET serializes this.
99 internal NumberFormatInfo (int lcid)
101 //FIXME: should add more LCID
102 // CultureInfo uses this one also.
103 if (lcid != 0x007F)
104 lcid = 0x007F;
106 switch (lcid){
108 // The Invariant Culture Info ID.
109 case 0x007f:
110 isReadOnly = false;
112 // Currency Related Format Info
113 currencyDecimalDigits = 2;
114 currencyDecimalSeparator = ".";
115 currencyGroupSeparator = ",";
116 currencyGroupSizes = new int[1] { 3 };
117 currencyNegativePattern = 0;
118 currencyPositivePattern = 0;
119 currencySymbol = "$";
121 nanSymbol = "NaN";
122 negativeInfinitySymbol = "-Infinity";
123 negativeSign = "-";
125 // Number Related Format Info
126 numberDecimalDigits = 2;
127 numberDecimalSeparator = ".";
128 numberGroupSeparator = ",";
129 numberGroupSizes = new int[1] { 3 };
130 numberNegativePattern = 1;
132 // Percent Related Format Info
133 percentDecimalDigits = 2;
134 percentDecimalSeparator = ".";
135 percentGroupSeparator = ",";
136 percentGroupSizes = new int[1] { 3 };
137 percentNegativePattern = 0;
138 percentPositivePattern = 0;
139 percentSymbol= "%";
141 perMilleSymbol = "\u2030";
142 positiveInfinitySymbol = "Infinity";
143 positiveSign = "+";
144 break;
148 public NumberFormatInfo () : this (0x007f)
152 // this is called by mono/mono/metadata/locales.c
153 void InitPatterns ()
155 string [] partOne, partTwo;
156 string [] posNeg = decimalFormats.Split (new char [1] {';'}, 2);
158 if (posNeg.Length == 2) {
160 partOne = posNeg [0].Split (new char [1] {'.'}, 2);
162 if (partOne.Length == 2) {
163 // assumed same for both positive and negative
164 // decimal digit side
165 numberDecimalDigits = 0;
166 for (int i = 0; i < partOne [1].Length; i ++) {
167 if (partOne [1][i] == digitPattern [0]) {
168 numberDecimalDigits ++;
169 } else
170 break;
173 // decimal grouping side
174 partTwo = partOne [0].Split (',');
175 if (partTwo.Length > 1) {
176 numberGroupSizes = new int [partTwo.Length - 1];
177 for (int i = 0; i < numberGroupSizes.Length; i ++) {
178 string pat = partTwo [i + 1];
179 numberGroupSizes [i] = pat.Length;
181 } else {
182 numberGroupSizes = new int [1] { 0 };
185 if (posNeg [1].StartsWith ("(") && posNeg [1].EndsWith (")")) {
186 numberNegativePattern = 0;
187 } else if (posNeg [1].StartsWith ("- ")) {
188 numberNegativePattern = 2;
189 } else if (posNeg [1].StartsWith ("-")) {
190 numberNegativePattern = 1;
191 } else if (posNeg [1].EndsWith (" -")) {
192 numberNegativePattern = 4;
193 } else if (posNeg [1].EndsWith ("-")) {
194 numberNegativePattern = 3;
195 } else {
196 numberNegativePattern = 1;
201 posNeg = currencyFormats.Split (new char [1] {';'}, 2);
202 if (posNeg.Length == 2) {
203 partOne = posNeg [0].Split (new char [1] {'.'}, 2);
205 if (partOne.Length == 2) {
206 // assumed same for both positive and negative
207 // decimal digit side
208 currencyDecimalDigits = 0;
209 for (int i = 0; i < partOne [1].Length; i ++) {
210 if (partOne [1][i] == zeroPattern [0])
211 currencyDecimalDigits ++;
212 else
213 break;
216 // decimal grouping side
217 partTwo = partOne [0].Split (',');
218 if (partTwo.Length > 1) {
219 currencyGroupSizes = new int [partTwo.Length - 1];
220 for (int i = 0; i < currencyGroupSizes.Length; i ++) {
221 string pat = partTwo [i + 1];
222 currencyGroupSizes [i] = pat.Length;
224 } else {
225 currencyGroupSizes = new int [1] { 0 };
228 if (posNeg [1].StartsWith ("(\u00a4 ") && posNeg [1].EndsWith (")")) {
229 currencyNegativePattern = 14;
230 } else if (posNeg [1].StartsWith ("(\u00a4") && posNeg [1].EndsWith (")")) {
231 currencyNegativePattern = 0;
232 } else if (posNeg [1].StartsWith ("\u00a4 ") && posNeg [1].EndsWith ("-")) {
233 currencyNegativePattern = 11;
234 } else if (posNeg [1].StartsWith ("\u00a4") && posNeg [1].EndsWith ("-")) {
235 currencyNegativePattern = 3;
236 } else if (posNeg [1].StartsWith ("(") && posNeg [1].EndsWith (" \u00a4")) {
237 currencyNegativePattern = 15;
238 } else if (posNeg [1].StartsWith ("(") && posNeg [1].EndsWith ("\u00a4")) {
239 currencyNegativePattern = 4;
240 } else if (posNeg [1].StartsWith ("-") && posNeg [1].EndsWith (" \u00a4")) {
241 currencyNegativePattern = 8;
242 } else if (posNeg [1].StartsWith ("-") && posNeg [1].EndsWith ("\u00a4")) {
243 currencyNegativePattern = 5;
244 } else if (posNeg [1].StartsWith ("-\u00a4 ")) {
245 currencyNegativePattern = 9;
246 } else if (posNeg [1].StartsWith ("-\u00a4")) {
247 currencyNegativePattern = 1;
248 } else if (posNeg [1].StartsWith ("\u00a4 -")) {
249 currencyNegativePattern = 12;
250 } else if (posNeg [1].StartsWith ("\u00a4-")) {
251 currencyNegativePattern = 2;
252 } else if (posNeg [1].EndsWith (" \u00a4-")) {
253 currencyNegativePattern = 10;
254 } else if (posNeg [1].EndsWith ("\u00a4-")) {
255 currencyNegativePattern = 7;
256 } else if (posNeg [1].EndsWith ("- \u00a4")) {
257 currencyNegativePattern = 13;
258 } else if (posNeg [1].EndsWith ("-\u00a4")) {
259 currencyNegativePattern = 6;
260 } else {
261 currencyNegativePattern = 0;
264 if (posNeg [0].StartsWith ("\u00a4 ")) {
265 currencyPositivePattern = 2;
266 } else if (posNeg [0].StartsWith ("\u00a4")) {
267 currencyPositivePattern = 0;
268 } else if (posNeg [0].EndsWith (" \u00a4")) {
269 currencyPositivePattern = 3;
270 } else if (posNeg [0].EndsWith ("\u00a4")) {
271 currencyPositivePattern = 1;
272 } else {
273 currencyPositivePattern = 0;
278 // we don't have percentNegativePattern in CLDR so
279 // the percentNegativePattern are just guesses
280 if (percentFormats.StartsWith ("%")) {
281 percentPositivePattern = 2;
282 percentNegativePattern = 2;
283 } else if (percentFormats.EndsWith (" %")) {
284 percentPositivePattern = 0;
285 percentNegativePattern = 0;
286 } else if (percentFormats.EndsWith ("%")) {
287 percentPositivePattern = 1;
288 percentNegativePattern = 1;
289 } else {
290 percentPositivePattern = 0;
291 percentNegativePattern = 0;
294 partOne = percentFormats.Split (new char [1] {'.'}, 2);
296 if (partOne.Length == 2) {
297 // assumed same for both positive and negative
298 // decimal digit side
299 percentDecimalDigits = 0;
300 for (int i = 0; i < partOne [1].Length; i ++) {
301 if (partOne [1][i] == digitPattern [0])
302 percentDecimalDigits ++;
303 else
304 break;
307 // percent grouping side
308 partTwo = partOne [0].Split (',');
309 if (partTwo.Length > 1) {
310 percentGroupSizes = new int [partTwo.Length - 1];
311 for (int i = 0; i < percentGroupSizes.Length; i ++) {
312 string pat = partTwo [i + 1];
313 percentGroupSizes [i] = pat.Length;
315 } else {
316 percentGroupSizes = new int [1] { 0 };
322 // =========== Currency Format Properties =========== //
324 public int CurrencyDecimalDigits {
325 get {
326 return currencyDecimalDigits;
329 set {
330 if (value < 0 || value > 99)
331 throw new ArgumentOutOfRangeException
332 ("The value specified for the property is less than 0 or greater than 99");
334 if (isReadOnly)
335 throw new InvalidOperationException
336 ("The current instance is read-only and a set operation was attempted");
338 currencyDecimalDigits = value;
342 public string CurrencyDecimalSeparator {
343 get {
344 return currencyDecimalSeparator;
347 set {
348 if (value == null)
349 throw new ArgumentNullException
350 ("The value specified for the property is a null reference");
352 if (isReadOnly)
353 throw new InvalidOperationException
354 ("The current instance is read-only and a set operation was attempted");
356 currencyDecimalSeparator = value;
361 public string CurrencyGroupSeparator {
362 get {
363 return currencyGroupSeparator;
366 set {
367 if (value == null)
368 throw new ArgumentNullException
369 ("The value specified for the property is a null reference");
371 if (isReadOnly)
372 throw new InvalidOperationException
373 ("The current instance is read-only and a set operation was attempted");
375 currencyGroupSeparator = value;
379 public int[] CurrencyGroupSizes {
380 get {
381 return (int []) currencyGroupSizes.Clone ();
384 set {
385 if (value == null || value.Length == 0)
386 throw new ArgumentNullException
387 ("The value specified for the property is a null reference");
389 if (isReadOnly)
390 throw new InvalidOperationException
391 ("The current instance is read-only and a set operation was attempted");
393 // All elements except last need to be in range 1 - 9, last can be 0.
394 int last = value.Length - 1;
396 for (int i = 0; i < last; i++)
397 if (value[i] < 1 || value[i] > 9)
398 throw new ArgumentOutOfRangeException
399 ("One of the elements in the array specified is not between 1 and 9");
401 if (value[last] < 0 || value[last] > 9)
402 throw new ArgumentOutOfRangeException
403 ("Last element in the array specified is not between 0 and 9");
405 currencyGroupSizes = (int[]) value.Clone();
409 public int CurrencyNegativePattern {
410 get {
411 // See ECMA NumberFormatInfo page 8
412 return currencyNegativePattern;
415 set {
416 if (value < 0 || value > 15)
417 throw new ArgumentOutOfRangeException
418 ("The value specified for the property is less than 0 or greater than 15");
420 if (isReadOnly)
421 throw new InvalidOperationException
422 ("The current instance is read-only and a set operation was attempted");
424 currencyNegativePattern = value;
428 public int CurrencyPositivePattern {
429 get {
430 // See ECMA NumberFormatInfo page 11
431 return currencyPositivePattern;
434 set {
435 if (value < 0 || value > 3)
436 throw new ArgumentOutOfRangeException
437 ("The value specified for the property is less than 0 or greater than 3");
439 if (isReadOnly)
440 throw new InvalidOperationException
441 ("The current instance is read-only and a set operation was attempted");
443 currencyPositivePattern = value;
447 public string CurrencySymbol {
448 get {
449 return currencySymbol;
452 set {
453 if (value == null)
454 throw new ArgumentNullException
455 ("The value specified for the property is a null reference");
457 if (isReadOnly)
458 throw new InvalidOperationException
459 ("The current instance is read-only and a set operation was attempted");
461 currencySymbol = value;
465 // =========== Static Read-Only Properties =========== //
467 public static NumberFormatInfo CurrentInfo {
468 get {
469 NumberFormatInfo nfi = (NumberFormatInfo) System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat;
470 nfi.isReadOnly = true;
471 return nfi;
475 public static NumberFormatInfo InvariantInfo {
476 get {
477 // This uses invariant info, which is same as in the constructor
478 NumberFormatInfo nfi = new NumberFormatInfo ();
479 nfi.NumberNegativePattern = 1;
480 nfi.isReadOnly = true;
481 return nfi;
485 public bool IsReadOnly {
486 get {
487 return isReadOnly;
493 public string NaNSymbol {
494 get {
495 return nanSymbol;
498 set {
499 if (value == null)
500 throw new ArgumentNullException
501 ("The value specified for the property is a null reference");
503 if (isReadOnly)
504 throw new InvalidOperationException
505 ("The current instance is read-only and a set operation was attempted");
507 nanSymbol = value;
511 public string NegativeInfinitySymbol {
512 get {
513 return negativeInfinitySymbol;
516 set {
517 if (value == null)
518 throw new ArgumentNullException
519 ("The value specified for the property is a null reference");
521 if (isReadOnly)
522 throw new InvalidOperationException
523 ("The current instance is read-only and a set operation was attempted");
525 negativeInfinitySymbol = value;
529 public string NegativeSign {
530 get {
531 return negativeSign;
534 set {
535 if (value == null)
536 throw new ArgumentNullException
537 ("The value specified for the property is a null reference");
539 if (isReadOnly)
540 throw new InvalidOperationException
541 ("The current instance is read-only and a set operation was attempted");
543 negativeSign = value;
547 // =========== Number Format Properties =========== //
549 public int NumberDecimalDigits {
550 get {
551 return numberDecimalDigits;
554 set {
555 if (value < 0 || value > 99)
556 throw new ArgumentOutOfRangeException
557 ("The value specified for the property is less than 0 or greater than 99");
559 if (isReadOnly)
560 throw new InvalidOperationException
561 ("The current instance is read-only and a set operation was attempted");
563 numberDecimalDigits = value;
567 public string NumberDecimalSeparator {
568 get {
569 return numberDecimalSeparator;
572 set {
573 if (value == null)
574 throw new ArgumentNullException
575 ("The value specified for the property is a null reference");
577 if (isReadOnly)
578 throw new InvalidOperationException
579 ("The current instance is read-only and a set operation was attempted");
581 numberDecimalSeparator = value;
586 public string NumberGroupSeparator {
587 get {
588 return numberGroupSeparator;
591 set {
592 if (value == null)
593 throw new ArgumentNullException
594 ("The value specified for the property is a null reference");
596 if (isReadOnly)
597 throw new InvalidOperationException
598 ("The current instance is read-only and a set operation was attempted");
600 numberGroupSeparator = value;
604 public int[] NumberGroupSizes {
605 get {
606 return (int []) numberGroupSizes.Clone ();
609 set {
610 if (value == null || value.Length == 0)
611 throw new ArgumentNullException
612 ("The value specified for the property is a null reference");
614 if (isReadOnly)
615 throw new InvalidOperationException
616 ("The current instance is read-only and a set operation was attempted");
618 // All elements except last need to be in range 1 - 9, last can be 0.
619 int last = value.Length - 1;
621 for (int i = 0; i < last; i++)
622 if (value[i] < 1 || value[i] > 9)
623 throw new ArgumentOutOfRangeException
624 ("One of the elements in the array specified is not between 1 and 9");
626 if (value[last] < 0 || value[last] > 9)
627 throw new ArgumentOutOfRangeException
628 ("Last element in the array specified is not between 0 and 9");
630 numberGroupSizes = (int[]) value.Clone();
634 public int NumberNegativePattern {
635 get {
636 // See ECMA NumberFormatInfo page 27
637 return numberNegativePattern;
640 set {
641 if (value < 0 || value > 4)
642 throw new ArgumentOutOfRangeException
643 ("The value specified for the property is less than 0 or greater than 15");
645 if (isReadOnly)
646 throw new InvalidOperationException
647 ("The current instance is read-only and a set operation was attempted");
649 numberNegativePattern = value;
653 // =========== Percent Format Properties =========== //
655 public int PercentDecimalDigits {
656 get {
657 return percentDecimalDigits;
660 set {
661 if (value < 0 || value > 99)
662 throw new ArgumentOutOfRangeException
663 ("The value specified for the property is less than 0 or greater than 99");
665 if (isReadOnly)
666 throw new InvalidOperationException
667 ("The current instance is read-only and a set operation was attempted");
669 percentDecimalDigits = value;
673 public string PercentDecimalSeparator {
674 get {
675 return percentDecimalSeparator;
678 set {
679 if (value == null)
680 throw new ArgumentNullException
681 ("The value specified for the property is a null reference");
683 if (isReadOnly)
684 throw new InvalidOperationException
685 ("The current instance is read-only and a set operation was attempted");
687 percentDecimalSeparator = value;
692 public string PercentGroupSeparator {
693 get {
694 return percentGroupSeparator;
697 set {
698 if (value == null)
699 throw new ArgumentNullException
700 ("The value specified for the property is a null reference");
702 if (isReadOnly)
703 throw new InvalidOperationException
704 ("The current instance is read-only and a set operation was attempted");
706 percentGroupSeparator = value;
710 public int[] PercentGroupSizes {
711 get {
712 return (int []) percentGroupSizes.Clone ();
715 set {
716 if (value == null || value.Length == 0)
717 throw new ArgumentNullException
718 ("The value specified for the property is a null reference");
720 if (isReadOnly)
721 throw new InvalidOperationException
722 ("The current instance is read-only and a set operation was attempted");
724 if (this == CultureInfo.CurrentCulture.NumberFormat)
725 throw new Exception ("HERE the value was modified");
726 // All elements except last need to be in range 1 - 9, last can be 0.
727 int last = value.Length - 1;
729 for (int i = 0; i < last; i++)
730 if (value[i] < 1 || value[i] > 9)
731 throw new ArgumentOutOfRangeException
732 ("One of the elements in the array specified is not between 1 and 9");
734 if (value[last] < 0 || value[last] > 9)
735 throw new ArgumentOutOfRangeException
736 ("Last element in the array specified is not between 0 and 9");
738 percentGroupSizes = (int[]) value.Clone();
742 public int PercentNegativePattern {
743 get {
744 // See ECMA NumberFormatInfo page 8
745 return percentNegativePattern;
748 set {
749 if (value < 0 || value > 2)
750 throw new ArgumentOutOfRangeException
751 ("The value specified for the property is less than 0 or greater than 15");
753 if (isReadOnly)
754 throw new InvalidOperationException
755 ("The current instance is read-only and a set operation was attempted");
757 percentNegativePattern = value;
761 public int PercentPositivePattern {
762 get {
763 // See ECMA NumberFormatInfo page 11
764 return percentPositivePattern;
767 set {
768 if (value < 0 || value > 2)
769 throw new ArgumentOutOfRangeException
770 ("The value specified for the property is less than 0 or greater than 3");
772 if (isReadOnly)
773 throw new InvalidOperationException
774 ("The current instance is read-only and a set operation was attempted");
776 percentPositivePattern = value;
780 public string PercentSymbol {
781 get {
782 return percentSymbol;
785 set {
786 if (value == null)
787 throw new ArgumentNullException
788 ("The value specified for the property is a null reference");
790 if (isReadOnly)
791 throw new InvalidOperationException
792 ("The current instance is read-only and a set operation was attempted");
794 percentSymbol = value;
798 public string PerMilleSymbol {
799 get {
800 return perMilleSymbol;
803 set {
804 if (value == null)
805 throw new ArgumentNullException
806 ("The value specified for the property is a null reference");
808 if (isReadOnly)
809 throw new InvalidOperationException
810 ("The current instance is read-only and a set operation was attempted");
812 perMilleSymbol = value;
816 public string PositiveInfinitySymbol {
817 get {
818 return positiveInfinitySymbol;
821 set {
822 if (value == null)
823 throw new ArgumentNullException
824 ("The value specified for the property is a null reference");
826 if (isReadOnly)
827 throw new InvalidOperationException
828 ("The current instance is read-only and a set operation was attempted");
830 positiveInfinitySymbol = value;
834 public string PositiveSign {
835 get {
836 return positiveSign;
839 set {
840 if (value == null)
841 throw new ArgumentNullException
842 ("The value specified for the property is a null reference");
844 if (isReadOnly)
845 throw new InvalidOperationException
846 ("The current instance is read-only and a set operation was attempted");
848 positiveSign = value;
852 public object GetFormat (Type formatType)
854 // work around http://bugzilla.ximian.com/show_bug.cgi?id=55978
855 // the comparison fails because formatType likely comes from another domain
856 //return (formatType == typeof (NumberFormatInfo)) ? this : null;
857 return this;
860 public object Clone ()
862 NumberFormatInfo clone = (NumberFormatInfo) MemberwiseClone();
863 // clone is not read only
864 clone.isReadOnly = false;
865 return clone;
868 public static NumberFormatInfo ReadOnly (NumberFormatInfo nfi)
870 NumberFormatInfo copy = (NumberFormatInfo)nfi.Clone();
871 copy.isReadOnly = true;
872 return copy;
875 public static NumberFormatInfo GetInstance(IFormatProvider provider)
877 if (provider != null) {
878 NumberFormatInfo nfi;
879 nfi = (NumberFormatInfo)provider.GetFormat(typeof(NumberFormatInfo));
880 if (nfi != null)
881 return nfi;
884 return CurrentInfo;