* added DateTimeFormatInfo.cs
[mono.git] / mcs / class / corlib / System.Globalization / NumberFormatInfo.cs
1 //
2 // System.Globalization.NumberFormatInfo.cs
3 //
4 // Author:
5 //   Derek Holden (dholden@draper.com)
6 //
7 // (C) Derek Holden
8 //
9
10 //
11 // NumberFormatInfo. One can only assume it is the class gottten
12 // back from a GetFormat() method from an IFormatProvider / 
13 // IFormattable implementer. There are some discrepencies with the
14 // ECMA spec and the SDK docs, surprisingly. See my conversation
15 // with myself on it at:
16 // http://lists.ximian.com/archives/public/mono-list/2001-July/000794.html
17 // 
18 // Other than that this is totally ECMA compliant.
19 //
20
21 namespace System.Globalization {
22
23         public sealed class NumberFormatInfo : ICloneable, IFormatProvider {
24                 private bool readOnly;
25                 
26                 // Currency Related Format Info
27                 private int currencyDecimalDigits;
28                 private string currencyDecimalSeparator;
29                 private string currencyGroupSeparator;
30                 private int[] currencyGroupSizes;
31                 private int currencyNegativePattern;
32                 private int currencyPositivePattern;
33                 private string currencySymbol;
34
35                 private string naNSymbol;
36                 private string negativeInfinitySymbol;
37                 private string negativeSign;
38
39                 // Number Related Format Info
40                 private int numberDecimalDigits;
41                 private string numberDecimalSeparator;
42                 private string numberGroupSeparator;
43                 private int[] numberGroupSizes;
44                 private int numberNegativePattern;
45
46                 // Percent Related Format Info
47                 private int percentDecimalDigits;
48                 private string percentDecimalSeparator;
49                 private string percentGroupSeparator;
50                 private int[] percentGroupSizes;
51                 private int percentNegativePattern;
52                 private int percentPositivePattern;
53                 private string percentSymbol;
54
55                 private string perMilleSymbol;
56                 private string positiveInfinitySymbol;
57                 private string positiveSign;
58
59                 internal NumberFormatInfo (int lcid)
60                 {
61                         switch (lcid){
62
63                                 // The Invariant Culture Info ID.
64                         case 0x007f:
65                                 readOnly = false;
66                                 
67                                 // Currency Related Format Info
68                                 currencyDecimalDigits =       2;
69                                 currencyDecimalSeparator =    ".";
70                                 currencyGroupSeparator =      ",";
71                                 currencyGroupSizes =          new int[1] { 3 };
72                                 currencyNegativePattern =     0;
73                                 currencyPositivePattern =     0;
74                                 currencySymbol =              "$";
75                                 
76                                 naNSymbol =                   "NaN";
77                                 negativeInfinitySymbol =      "-Infinity";
78                                 negativeSign =                "-";
79                                 
80                                 // Number Related Format Info
81                                 numberDecimalDigits =         2;
82                                 numberDecimalSeparator =      ".";
83                                 numberGroupSeparator =        ",";
84                                 numberGroupSizes =            new int[1] { 3 };
85                                 numberNegativePattern =       0;
86                                 
87                                 // Percent Related Format Info
88                                 percentDecimalDigits =        2;
89                                 percentDecimalSeparator =     ".";
90                                 percentGroupSeparator =       ",";
91                                 percentGroupSizes =           new int[1] { 3 };
92                                 percentNegativePattern =      0;
93                                 percentPositivePattern =      0;
94                                 percentSymbol=                "%";
95                                 
96                                 perMilleSymbol =              "\u2030";
97                                 positiveInfinitySymbol =      "Infinity";
98                                 positiveSign =                "+";
99                                 break;
100                         }
101                 }
102                 
103                 public NumberFormatInfo () : this (0x007f)
104                 {
105                 }
106                                 
107                 // =========== Currency Format Properties =========== //
108
109                 public int CurrencyDecimalDigits {
110                         get {
111                                 return currencyDecimalDigits;
112                         }
113                         
114                         set {
115                                 if (value < 0 || value > 99) 
116                                         throw new ArgumentOutOfRangeException
117                                         ("The value specified for the property is less than 0 or greater than 99");
118                                 
119                                 if (readOnly)
120                                         throw new InvalidOperationException
121                                         ("The current instance is read-only and a set operation was attempted");
122
123                                 currencyDecimalDigits = value;
124                         }
125                 }
126
127                 public string CurrencyDecimalSeparator {
128                         get {
129                                 return currencyDecimalSeparator;
130                         }
131                         
132                         set {
133                                 if (value == null) 
134                                         throw new ArgumentNullException
135                                         ("The value specified for the property is a null reference");
136                                 
137                                 if (readOnly)
138                                         throw new InvalidOperationException
139                                         ("The current instance is read-only and a set operation was attempted");
140                                 
141                                 currencyDecimalSeparator = value;
142                         }
143                 }
144
145
146                 public string CurrencyGroupSeparator {
147                         get {
148                                 return currencyGroupSeparator;
149                         }
150                         
151                         set {
152                                 if (value == null) 
153                                         throw new ArgumentNullException
154                                         ("The value specified for the property is a null reference");
155                         
156                                 if (readOnly)
157                                         throw new InvalidOperationException
158                                         ("The current instance is read-only and a set operation was attempted");        
159                                 
160                                 currencyGroupSeparator = value;
161                         }
162                 }
163
164                 public int[] CurrencyGroupSizes {
165                         get {
166                                 return currencyGroupSizes;
167                         }
168                         
169                         set {
170                                 if (value == null || value.Length == 0) 
171                                         throw new ArgumentNullException
172                                         ("The value specified for the property is a null reference");
173                                 
174                                 if (readOnly)
175                                         throw new InvalidOperationException
176                                         ("The current instance is read-only and a set operation was attempted");
177                                 
178                                 // All elements except last need to be in range 1 - 9, last can be 0.
179                                 int last = value.Length - 1;
180
181                                 for (int i = 0; i < last; i++)
182                                         if (value[i] < 1 || value[i] > 9)
183                                                 throw new ArgumentOutOfRangeException
184                                                 ("One of the elements in the array specified is not between 1 and 9");
185
186                                 if (value[last] < 0 || value[last] > 9)
187                                         throw new ArgumentOutOfRangeException
188                                         ("Last element in the array specified is not between 0 and 9");
189                                 
190                                 currencyGroupSizes = (int[]) value.Clone();
191                         }
192                 }
193
194                 public int CurrencyNegativePattern {
195                         get {
196                                 // See ECMA NumberFormatInfo page 8
197                                 return currencyNegativePattern;
198                         }
199                         
200                         set {
201                                 if (value < 0 || value > 15) 
202                                         throw new ArgumentOutOfRangeException
203                                         ("The value specified for the property is less than 0 or greater than 15");
204                                 
205                                 if (readOnly)
206                                         throw new InvalidOperationException
207                                         ("The current instance is read-only and a set operation was attempted");
208
209                                 currencyNegativePattern = value;
210                         }
211                 }
212
213                 public int CurrencyPositivePattern {
214                         get {
215                                 // See ECMA NumberFormatInfo page 11 
216                                 return currencyPositivePattern;
217                         }
218                         
219                         set {
220                                 if (value < 0 || value > 3) 
221                                         throw new ArgumentOutOfRangeException
222                                         ("The value specified for the property is less than 0 or greater than 3");
223                                 
224                                 if (readOnly)
225                                         throw new InvalidOperationException
226                                         ("The current instance is read-only and a set operation was attempted");
227
228                                 currencyPositivePattern = value;
229                         }
230                 }
231
232                 public string CurrencySymbol {
233                         get {
234                                 return currencySymbol;
235                         }
236                         
237                         set {
238                                 if (value == null) 
239                                         throw new ArgumentNullException
240                                         ("The value specified for the property is a null reference");
241                         
242                                 if (readOnly)
243                                         throw new InvalidOperationException
244                                         ("The current instance is read-only and a set operation was attempted");        
245                                 
246                                 currencySymbol = value;
247                         }
248                 }
249
250                 // =========== Static Read-Only Properties =========== //
251
252                 public static NumberFormatInfo CurrentInfo {
253                         get {
254                                 // This should be culture specific
255                                 NumberFormatInfo nfi = new NumberFormatInfo ();
256                                 nfi.readOnly = true;
257                                 return nfi;
258                         }                      
259                 }
260
261                 public static NumberFormatInfo InvariantInfo {
262                         get {
263                                 // This uses invariant info, which is same as in the constructor
264                                 NumberFormatInfo nfi = new NumberFormatInfo ();
265                                 nfi.readOnly = true;
266                                 return nfi;
267                         }                      
268                 }
269
270                 public bool IsReadOnly {
271                         get {
272                                 return readOnly;
273                         }
274                 }
275
276
277
278                 public string NaNSymbol {
279                         get {
280                                 return naNSymbol;
281                         }
282                         
283                         set {
284                                 if (value == null) 
285                                         throw new ArgumentNullException
286                                         ("The value specified for the property is a null reference");
287                         
288                                 if (readOnly)
289                                         throw new InvalidOperationException
290                                         ("The current instance is read-only and a set operation was attempted");        
291                                 
292                                 naNSymbol = value;
293                         }
294                 }
295                 
296                 public string NegativeInfinitySymbol {
297                         get {
298                                 return negativeInfinitySymbol;
299                         }
300                         
301                         set {
302                                 if (value == null) 
303                                         throw new ArgumentNullException
304                                         ("The value specified for the property is a null reference");
305                         
306                                 if (readOnly)
307                                         throw new InvalidOperationException
308                                         ("The current instance is read-only and a set operation was attempted");        
309                                 
310                                 negativeInfinitySymbol = value;
311                         }
312                 }
313
314                 public string NegativeSign {
315                         get {
316                                 return negativeSign;
317                         }
318                         
319                         set {
320                                 if (value == null) 
321                                         throw new ArgumentNullException
322                                         ("The value specified for the property is a null reference");
323                         
324                                 if (readOnly)
325                                         throw new InvalidOperationException
326                                         ("The current instance is read-only and a set operation was attempted");        
327                                 
328                                 negativeSign = value;
329                         }
330                 }
331                 
332                 // =========== Number Format Properties =========== //
333
334                 public int NumberDecimalDigits {
335                         get {
336                                 return numberDecimalDigits;
337                         }
338                         
339                         set {
340                                 if (value < 0 || value > 99) 
341                                         throw new ArgumentOutOfRangeException
342                                         ("The value specified for the property is less than 0 or greater than 99");
343                                 
344                                 if (readOnly)
345                                         throw new InvalidOperationException
346                                         ("The current instance is read-only and a set operation was attempted");
347
348                                 numberDecimalDigits = value;
349                         }
350                 }               
351
352                 public string NumberDecimalSeparator {
353                         get {
354                                 return numberDecimalSeparator;
355                         }
356                         
357                         set {
358                                 if (value == null) 
359                                         throw new ArgumentNullException
360                                         ("The value specified for the property is a null reference");
361                                 
362                                 if (readOnly)
363                                         throw new InvalidOperationException
364                                         ("The current instance is read-only and a set operation was attempted");
365                                 
366                                 numberDecimalSeparator = value;
367                         }
368                 }
369
370
371                 public string NumberGroupSeparator {
372                         get {
373                                 return numberGroupSeparator;
374                         }
375                         
376                         set {
377                                 if (value == null) 
378                                         throw new ArgumentNullException
379                                         ("The value specified for the property is a null reference");
380                         
381                                 if (readOnly)
382                                         throw new InvalidOperationException
383                                         ("The current instance is read-only and a set operation was attempted");        
384                                 
385                                 numberGroupSeparator = value;
386                         }
387                 }
388
389                 public int[] NumberGroupSizes {
390                         get {
391                                 return numberGroupSizes;
392                         }
393                         
394                         set {
395                                 if (value == null || value.Length == 0) 
396                                         throw new ArgumentNullException
397                                         ("The value specified for the property is a null reference");
398                                 
399                                 if (readOnly)
400                                         throw new InvalidOperationException
401                                         ("The current instance is read-only and a set operation was attempted");
402                                 
403                                 // All elements except last need to be in range 1 - 9, last can be 0.
404                                 int last = value.Length - 1;
405
406                                 for (int i = 0; i < last; i++)
407                                         if (value[i] < 1 || value[i] > 9)
408                                                 throw new ArgumentOutOfRangeException
409                                                 ("One of the elements in the array specified is not between 1 and 9");
410
411                                 if (value[last] < 0 || value[last] > 9)
412                                         throw new ArgumentOutOfRangeException
413                                         ("Last element in the array specified is not between 0 and 9");
414                                 
415                                 numberGroupSizes = (int[]) value.Clone();
416                         }
417                 }
418
419                 public int NumberNegativePattern {
420                         get {
421                                 // See ECMA NumberFormatInfo page 27
422                                 return numberNegativePattern;
423                         }
424                         
425                         set {
426                                 if (value < 0 || value > 4) 
427                                         throw new ArgumentOutOfRangeException
428                                         ("The value specified for the property is less than 0 or greater than 15");
429                                 
430                                 if (readOnly)
431                                         throw new InvalidOperationException
432                                         ("The current instance is read-only and a set operation was attempted");
433
434                                 numberNegativePattern = value;
435                         }
436                 }
437
438                 // =========== Percent Format Properties =========== //
439
440                 public int PercentDecimalDigits {
441                         get {
442                                 return percentDecimalDigits;
443                         }
444                         
445                         set {
446                                 if (value < 0 || value > 99) 
447                                         throw new ArgumentOutOfRangeException
448                                         ("The value specified for the property is less than 0 or greater than 99");
449                                 
450                                 if (readOnly)
451                                         throw new InvalidOperationException
452                                         ("The current instance is read-only and a set operation was attempted");
453
454                                 percentDecimalDigits = value;
455                         }
456                 }
457
458                 public string PercentDecimalSeparator {
459                         get {
460                                 return percentDecimalSeparator;
461                         }
462                         
463                         set {
464                                 if (value == null) 
465                                         throw new ArgumentNullException
466                                         ("The value specified for the property is a null reference");
467                                 
468                                 if (readOnly)
469                                         throw new InvalidOperationException
470                                         ("The current instance is read-only and a set operation was attempted");
471                                 
472                                 percentDecimalSeparator = value;
473                         }
474                 }
475
476
477                 public string PercentGroupSeparator {
478                         get {
479                                 return percentGroupSeparator;
480                         }
481                         
482                         set {
483                                 if (value == null) 
484                                         throw new ArgumentNullException
485                                         ("The value specified for the property is a null reference");
486                         
487                                 if (readOnly)
488                                         throw new InvalidOperationException
489                                         ("The current instance is read-only and a set operation was attempted");        
490                                 
491                                 percentGroupSeparator = value;
492                         }
493                 }
494
495                 public int[] PercentGroupSizes {
496                         get {
497                                 return percentGroupSizes;
498                         }
499                         
500                         set {
501                                 if (value == null || value.Length == 0) 
502                                         throw new ArgumentNullException
503                                         ("The value specified for the property is a null reference");
504                                 
505                                 if (readOnly)
506                                         throw new InvalidOperationException
507                                         ("The current instance is read-only and a set operation was attempted");
508                                 
509                                 // All elements except last need to be in range 1 - 9, last can be 0.
510                                 int last = value.Length - 1;
511
512                                 for (int i = 0; i < last; i++)
513                                         if (value[i] < 1 || value[i] > 9)
514                                                 throw new ArgumentOutOfRangeException
515                                                 ("One of the elements in the array specified is not between 1 and 9");
516
517                                 if (value[last] < 0 || value[last] > 9)
518                                         throw new ArgumentOutOfRangeException
519                                         ("Last element in the array specified is not between 0 and 9");
520                                 
521                                 percentGroupSizes = (int[]) value.Clone();
522                         }
523                 }
524
525                 public int PercentNegativePattern {
526                         get {
527                                 // See ECMA NumberFormatInfo page 8
528                                 return percentNegativePattern;
529                         }
530                         
531                         set {
532                                 if (value < 0 || value > 2) 
533                                         throw new ArgumentOutOfRangeException
534                                         ("The value specified for the property is less than 0 or greater than 15");
535                                 
536                                 if (readOnly)
537                                         throw new InvalidOperationException
538                                         ("The current instance is read-only and a set operation was attempted");
539
540                                 percentNegativePattern = value;
541                         }
542                 }
543
544                 public int PercentPositivePattern {
545                         get {
546                                 // See ECMA NumberFormatInfo page 11 
547                                 return percentPositivePattern;
548                         }
549                         
550                         set {
551                                 if (value < 0 || value > 2) 
552                                         throw new ArgumentOutOfRangeException
553                                         ("The value specified for the property is less than 0 or greater than 3");
554                                 
555                                 if (readOnly)
556                                         throw new InvalidOperationException
557                                         ("The current instance is read-only and a set operation was attempted");
558
559                                 percentPositivePattern = value;
560                         }
561                 }
562
563                 public string PercentSymbol {
564                         get {
565                                 return percentSymbol;
566                         }
567                         
568                         set {
569                                 if (value == null) 
570                                         throw new ArgumentNullException
571                                         ("The value specified for the property is a null reference");
572                         
573                                 if (readOnly)
574                                         throw new InvalidOperationException
575                                         ("The current instance is read-only and a set operation was attempted");        
576                                 
577                                 percentSymbol = value;
578                         }
579                 }
580
581                 public string PerMilleSymbol {
582                         get {
583                                 return perMilleSymbol;
584                         }
585                         
586                         set {
587                                 if (value == null) 
588                                         throw new ArgumentNullException
589                                         ("The value specified for the property is a null reference");
590                                 
591                                 if (readOnly)
592                                         throw new InvalidOperationException
593                                         ("The current instance is read-only and a set operation was attempted");
594                                 
595                                 perMilleSymbol = value;
596                         }
597                 }
598
599                 public string PositiveInfinitySymbol {
600                         get {
601                                 return positiveInfinitySymbol;
602                         }
603                         
604                         set {
605                                 if (value == null) 
606                                         throw new ArgumentNullException
607                                         ("The value specified for the property is a null reference");
608                         
609                                 if (readOnly)
610                                         throw new InvalidOperationException
611                                         ("The current instance is read-only and a set operation was attempted");        
612                                 
613                                 positiveInfinitySymbol = value;
614                         }
615                 }
616
617                 public string PositiveSign {
618                         get {
619                                 return positiveSign;
620                         }
621                         
622                         set {
623                                 if (value == null) 
624                                         throw new ArgumentNullException
625                                         ("The value specified for the property is a null reference");
626                         
627                                 if (readOnly)
628                                         throw new InvalidOperationException
629                                         ("The current instance is read-only and a set operation was attempted");        
630                                 
631                                 positiveSign = value;
632                         }
633                 }
634
635                 public object GetFormat (Type formatType) 
636                 {
637                         // LAMESPEC: ECMA says we implement IFormatProvider, but doesn't define this
638                         //
639                         // From the .NET Framework SDK
640                         //
641                         // Parameters: formatType The Type of the formatting service required. 
642                         //
643                         // Return Value: The current instance of the NumberFormatInfo class, if formatType 
644                         // is the same as the type of the current instance; otherwise, a null reference
645                         //
646                         // Remarks: This method is invoked by the Format(String, IFormatProvider) method                        
647                         // supported by the base data types when this instance is passed as the 
648                         // IFormatProvider parameter. It implements IFormatProvider.GetFormat.
649
650                         if (formatType.Equals(this)) // LAMESPEC: Should this be IsInstanceOfType?
651                                 return this;
652                         else return null;
653                 }
654                 
655                 public object Clone () 
656                 {
657                         NumberFormatInfo clone = (NumberFormatInfo) MemberwiseClone();
658                         // clone is not read only
659                         clone.readOnly = false;
660                         return clone;
661                 }
662
663                 public static NumberFormatInfo ReadOnly (NumberFormatInfo nfi)
664                 {
665                         NumberFormatInfo copy = (NumberFormatInfo)nfi.Clone();
666                         copy.readOnly = true;
667                         return copy;
668                 }                       
669         }
670 }