NumberFormatInfo.cs 17 KB

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