NumberFormatInfo.cs 18 KB

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