Tools.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. //
  2. // This part taken from KopiLua - https://github.com/NLua/KopiLua
  3. //
  4. // =========================================================================================================
  5. //
  6. // Kopi Lua License
  7. // ----------------
  8. // MIT License for KopiLua
  9. // Copyright (c) 2012 LoDC
  10. // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
  11. // associated documentation files (the "Software"), to deal in the Software without restriction,
  12. // including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13. // and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
  14. // subject to the following conditions:
  15. // The above copyright notice and this permission notice shall be included in all copies or substantial
  16. // portions of the Software.
  17. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  18. // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  19. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  20. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  21. // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. // ===============================================================================
  23. // Lua License
  24. // -----------
  25. // Lua is licensed under the terms of the MIT license reproduced below.
  26. // This means that Lua is free software and can be used for both academic
  27. // and commercial purposes at absolutely no cost.
  28. // For details and rationale, see http://www.lua.org/license.html .
  29. // ===============================================================================
  30. // Copyright (C) 1994-2008 Lua.org, PUC-Rio.
  31. // Permission is hereby granted, free of charge, to any person obtaining a copy
  32. // of this software and associated documentation files (the "Software"), to deal
  33. // in the Software without restriction, including without limitation the rights
  34. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  35. // copies of the Software, and to permit persons to whom the Software is
  36. // furnished to do so, subject to the following conditions:
  37. // The above copyright notice and this permission notice shall be included in
  38. // all copies or substantial portions of the Software.
  39. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  40. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  41. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  42. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  43. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  44. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  45. // THE SOFTWARE.
  46. #region Usings
  47. using System;
  48. using System.IO;
  49. using System.Text;
  50. using System.Text.RegularExpressions;
  51. using System.Globalization;
  52. #endregion
  53. namespace MoonSharp.Interpreter.Interop.LuaStateInterop
  54. {
  55. internal static class Tools
  56. {
  57. #region Public Methods
  58. #region IsNumericType
  59. /// <summary>
  60. /// Determines whether the specified value is of numeric type.
  61. /// </summary>
  62. /// <param name="o">The object to check.</param>
  63. /// <returns>
  64. /// <c>true</c> if o is a numeric type; otherwise, <c>false</c>.
  65. /// </returns>
  66. public static bool IsNumericType(object o)
  67. {
  68. return (o is byte ||
  69. o is sbyte ||
  70. o is short ||
  71. o is ushort ||
  72. o is int ||
  73. o is uint ||
  74. o is long ||
  75. o is ulong ||
  76. o is float ||
  77. o is double ||
  78. o is decimal);
  79. }
  80. #endregion
  81. #region IsPositive
  82. /// <summary>
  83. /// Determines whether the specified value is positive.
  84. /// </summary>
  85. /// <param name="Value">The value.</param>
  86. /// <param name="ZeroIsPositive">if set to <c>true</c> treats 0 as positive.</param>
  87. /// <returns>
  88. /// <c>true</c> if the specified value is positive; otherwise, <c>false</c>.
  89. /// </returns>
  90. public static bool IsPositive(object Value, bool ZeroIsPositive)
  91. {
  92. switch (Type.GetTypeCode(Value.GetType()))
  93. {
  94. case TypeCode.SByte:
  95. return (ZeroIsPositive ? (sbyte)Value >= 0 : (sbyte)Value > 0);
  96. case TypeCode.Int16:
  97. return (ZeroIsPositive ? (short)Value >= 0 : (short)Value > 0);
  98. case TypeCode.Int32:
  99. return (ZeroIsPositive ? (int)Value >= 0 : (int)Value > 0);
  100. case TypeCode.Int64:
  101. return (ZeroIsPositive ? (long)Value >= 0 : (long)Value > 0);
  102. case TypeCode.Single:
  103. return (ZeroIsPositive ? (float)Value >= 0 : (float)Value > 0);
  104. case TypeCode.Double:
  105. return (ZeroIsPositive ? (double)Value >= 0 : (double)Value > 0);
  106. case TypeCode.Decimal:
  107. return (ZeroIsPositive ? (decimal)Value >= 0 : (decimal)Value > 0);
  108. case TypeCode.Byte:
  109. return (ZeroIsPositive ? true : (byte)Value > 0);
  110. case TypeCode.UInt16:
  111. return (ZeroIsPositive ? true : (ushort)Value > 0);
  112. case TypeCode.UInt32:
  113. return (ZeroIsPositive ? true : (uint)Value > 0);
  114. case TypeCode.UInt64:
  115. return (ZeroIsPositive ? true : (ulong)Value > 0);
  116. case TypeCode.Char:
  117. return (ZeroIsPositive ? true : (char)Value != '\0');
  118. default:
  119. return false;
  120. }
  121. }
  122. #endregion
  123. #region ToUnsigned
  124. /// <summary>
  125. /// Converts the specified values boxed type to its correpsonding unsigned
  126. /// type.
  127. /// </summary>
  128. /// <param name="Value">The value.</param>
  129. /// <returns>A boxed numeric object whos type is unsigned.</returns>
  130. public static object ToUnsigned(object Value)
  131. {
  132. switch (Type.GetTypeCode(Value.GetType()))
  133. {
  134. case TypeCode.SByte:
  135. return (byte)((sbyte)Value);
  136. case TypeCode.Int16:
  137. return (ushort)((short)Value);
  138. case TypeCode.Int32:
  139. return (uint)((int)Value);
  140. case TypeCode.Int64:
  141. return (ulong)((long)Value);
  142. case TypeCode.Byte:
  143. return Value;
  144. case TypeCode.UInt16:
  145. return Value;
  146. case TypeCode.UInt32:
  147. return Value;
  148. case TypeCode.UInt64:
  149. return Value;
  150. case TypeCode.Single:
  151. return (UInt32)((float)Value);
  152. case TypeCode.Double:
  153. return (ulong)((double)Value);
  154. case TypeCode.Decimal:
  155. return (ulong)((decimal)Value);
  156. default:
  157. return null;
  158. }
  159. }
  160. #endregion
  161. #region ToInteger
  162. /// <summary>
  163. /// Converts the specified values boxed type to its correpsonding integer
  164. /// type.
  165. /// </summary>
  166. /// <param name="Value">The value.</param>
  167. /// <param name="Round">if set to <c>true</c> [round].</param>
  168. /// <returns>
  169. /// A boxed numeric object whos type is an integer type.
  170. /// </returns>
  171. public static object ToInteger(object Value, bool Round)
  172. {
  173. switch (Type.GetTypeCode(Value.GetType()))
  174. {
  175. case TypeCode.SByte:
  176. return Value;
  177. case TypeCode.Int16:
  178. return Value;
  179. case TypeCode.Int32:
  180. return Value;
  181. case TypeCode.Int64:
  182. return Value;
  183. case TypeCode.Byte:
  184. return Value;
  185. case TypeCode.UInt16:
  186. return Value;
  187. case TypeCode.UInt32:
  188. return Value;
  189. case TypeCode.UInt64:
  190. return Value;
  191. case TypeCode.Single:
  192. return (Round ? (int)Math.Round((float)Value) : (int)((float)Value));
  193. case TypeCode.Double:
  194. return (Round ? (long)Math.Round((double)Value) : (long)((double)Value));
  195. case TypeCode.Decimal:
  196. return (Round ? Math.Round((decimal)Value) : (decimal)Value);
  197. default:
  198. return null;
  199. }
  200. }
  201. #endregion
  202. #region UnboxToLong
  203. public static long UnboxToLong(object Value, bool Round)
  204. {
  205. switch (Type.GetTypeCode(Value.GetType()))
  206. {
  207. case TypeCode.SByte:
  208. return (long)((sbyte)Value);
  209. case TypeCode.Int16:
  210. return (long)((short)Value);
  211. case TypeCode.Int32:
  212. return (long)((int)Value);
  213. case TypeCode.Int64:
  214. return (long)Value;
  215. case TypeCode.Byte:
  216. return (long)((byte)Value);
  217. case TypeCode.UInt16:
  218. return (long)((ushort)Value);
  219. case TypeCode.UInt32:
  220. return (long)((uint)Value);
  221. case TypeCode.UInt64:
  222. return (long)((ulong)Value);
  223. case TypeCode.Single:
  224. return (Round ? (long)Math.Round((float)Value) : (long)((float)Value));
  225. case TypeCode.Double:
  226. return (Round ? (long)Math.Round((double)Value) : (long)((double)Value));
  227. case TypeCode.Decimal:
  228. return (Round ? (long)Math.Round((decimal)Value) : (long)((decimal)Value));
  229. default:
  230. return 0;
  231. }
  232. }
  233. #endregion
  234. #region ReplaceMetaChars
  235. /// <summary>
  236. /// Replaces the string representations of meta chars with their corresponding
  237. /// character values.
  238. /// </summary>
  239. /// <param name="input">The input.</param>
  240. /// <returns>A string with all string meta chars are replaced</returns>
  241. public static string ReplaceMetaChars(string input)
  242. {
  243. return Regex.Replace(input, @"(\\)(\d{3}|[^\d])?", new MatchEvaluator(ReplaceMetaCharsMatch));
  244. }
  245. private static string ReplaceMetaCharsMatch(Match m)
  246. {
  247. // convert octal quotes (like \040)
  248. if (m.Groups[2].Length == 3)
  249. return Convert.ToChar(Convert.ToByte(m.Groups[2].Value, 8)).ToString();
  250. else
  251. {
  252. // convert all other special meta characters
  253. //TODO: \xhhh hex and possible dec !!
  254. switch (m.Groups[2].Value)
  255. {
  256. case "0": // null
  257. return "\0";
  258. case "a": // alert (beep)
  259. return "\a";
  260. case "b": // BS
  261. return "\b";
  262. case "f": // FF
  263. return "\f";
  264. case "v": // vertical tab
  265. return "\v";
  266. case "r": // CR
  267. return "\r";
  268. case "n": // LF
  269. return "\n";
  270. case "t": // Tab
  271. return "\t";
  272. default:
  273. // if neither an octal quote nor a special meta character
  274. // so just remove the backslash
  275. return m.Groups[2].Value;
  276. }
  277. }
  278. }
  279. #endregion
  280. #region printf
  281. public static void printf(string Format, params object[] Parameters)
  282. {
  283. Console.Write(Tools.sprintf(Format, Parameters));
  284. }
  285. #endregion
  286. #region fprintf
  287. public static void fprintf(TextWriter Destination, string Format, params object[] Parameters)
  288. {
  289. Destination.Write(Tools.sprintf(Format, Parameters));
  290. }
  291. #endregion
  292. #region sprintf
  293. internal static Regex r = new Regex(@"\%(\d*\$)?([\'\#\-\+ ]*)(\d*)(?:\.(\d+))?([hl])?([dioxXucsfeEgGpn%])");
  294. public static string sprintf(string Format, params object[] Parameters)
  295. {
  296. #region Variables
  297. StringBuilder f = new StringBuilder();
  298. //Regex r = new Regex( @"\%(\d*\$)?([\'\#\-\+ ]*)(\d*)(?:\.(\d+))?([hl])?([dioxXucsfeEgGpn%])" );
  299. //"%[parameter][flags][width][.precision][length]type"
  300. Match m = null;
  301. string w = String.Empty;
  302. int defaultParamIx = 0;
  303. int paramIx;
  304. object o = null;
  305. bool flagLeft2Right = false;
  306. bool flagAlternate = false;
  307. bool flagPositiveSign = false;
  308. bool flagPositiveSpace = false;
  309. bool flagZeroPadding = false;
  310. bool flagGroupThousands = false;
  311. int fieldLength = 0;
  312. int fieldPrecision = 0;
  313. char shortLongIndicator = '\0';
  314. char formatSpecifier = '\0';
  315. char paddingCharacter = ' ';
  316. #endregion
  317. // find all format parameters in format string
  318. f.Append(Format);
  319. m = r.Match(f.ToString());
  320. while (m.Success)
  321. {
  322. #region parameter index
  323. paramIx = defaultParamIx;
  324. if (m.Groups[1] != null && m.Groups[1].Value.Length > 0)
  325. {
  326. string val = m.Groups[1].Value.Substring(0, m.Groups[1].Value.Length - 1);
  327. paramIx = Convert.ToInt32(val) - 1;
  328. };
  329. #endregion
  330. #region format flags
  331. // extract format flags
  332. flagAlternate = false;
  333. flagLeft2Right = false;
  334. flagPositiveSign = false;
  335. flagPositiveSpace = false;
  336. flagZeroPadding = false;
  337. flagGroupThousands = false;
  338. if (m.Groups[2] != null && m.Groups[2].Value.Length > 0)
  339. {
  340. string flags = m.Groups[2].Value;
  341. flagAlternate = (flags.IndexOf('#') >= 0);
  342. flagLeft2Right = (flags.IndexOf('-') >= 0);
  343. flagPositiveSign = (flags.IndexOf('+') >= 0);
  344. flagPositiveSpace = (flags.IndexOf(' ') >= 0);
  345. flagGroupThousands = (flags.IndexOf('\'') >= 0);
  346. // positive + indicator overrides a
  347. // positive space character
  348. if (flagPositiveSign && flagPositiveSpace)
  349. flagPositiveSpace = false;
  350. }
  351. #endregion
  352. #region field length
  353. // extract field length and
  354. // pading character
  355. paddingCharacter = ' ';
  356. fieldLength = int.MinValue;
  357. if (m.Groups[3] != null && m.Groups[3].Value.Length > 0)
  358. {
  359. fieldLength = Convert.ToInt32(m.Groups[3].Value);
  360. flagZeroPadding = (m.Groups[3].Value[0] == '0');
  361. }
  362. #endregion
  363. if (flagZeroPadding)
  364. paddingCharacter = '0';
  365. // left2right allignment overrides zero padding
  366. if (flagLeft2Right && flagZeroPadding)
  367. {
  368. flagZeroPadding = false;
  369. paddingCharacter = ' ';
  370. }
  371. #region field precision
  372. // extract field precision
  373. fieldPrecision = int.MinValue;
  374. if (m.Groups[4] != null && m.Groups[4].Value.Length > 0)
  375. fieldPrecision = Convert.ToInt32(m.Groups[4].Value);
  376. #endregion
  377. #region short / long indicator
  378. // extract short / long indicator
  379. shortLongIndicator = Char.MinValue;
  380. if (m.Groups[5] != null && m.Groups[5].Value.Length > 0)
  381. shortLongIndicator = m.Groups[5].Value[0];
  382. #endregion
  383. #region format specifier
  384. // extract format
  385. formatSpecifier = Char.MinValue;
  386. if (m.Groups[6] != null && m.Groups[6].Value.Length > 0)
  387. formatSpecifier = m.Groups[6].Value[0];
  388. #endregion
  389. // default precision is 6 digits if none is specified except
  390. if (fieldPrecision == int.MinValue &&
  391. formatSpecifier != 's' &&
  392. formatSpecifier != 'c' &&
  393. Char.ToUpper(formatSpecifier) != 'X' &&
  394. formatSpecifier != 'o')
  395. fieldPrecision = 6;
  396. #region get next value parameter
  397. // get next value parameter and convert value parameter depending on short / long indicator
  398. if (Parameters == null || paramIx >= Parameters.Length)
  399. o = null;
  400. else
  401. {
  402. o = Parameters[paramIx];
  403. if (shortLongIndicator == 'h')
  404. {
  405. if (o is int)
  406. o = (short)((int)o);
  407. else if (o is long)
  408. o = (short)((long)o);
  409. else if (o is uint)
  410. o = (ushort)((uint)o);
  411. else if (o is ulong)
  412. o = (ushort)((ulong)o);
  413. }
  414. else if (shortLongIndicator == 'l')
  415. {
  416. if (o is short)
  417. o = (long)((short)o);
  418. else if (o is int)
  419. o = (long)((int)o);
  420. else if (o is ushort)
  421. o = (ulong)((ushort)o);
  422. else if (o is uint)
  423. o = (ulong)((uint)o);
  424. }
  425. }
  426. #endregion
  427. // convert value parameters to a string depending on the formatSpecifier
  428. w = String.Empty;
  429. switch (formatSpecifier)
  430. {
  431. #region % - character
  432. case '%': // % character
  433. w = "%";
  434. break;
  435. #endregion
  436. #region d - integer
  437. case 'd': // integer
  438. w = FormatNumber((flagGroupThousands ? "n" : "d"), flagAlternate,
  439. fieldLength, int.MinValue, flagLeft2Right,
  440. flagPositiveSign, flagPositiveSpace,
  441. paddingCharacter, o);
  442. defaultParamIx++;
  443. break;
  444. #endregion
  445. #region i - integer
  446. case 'i': // integer
  447. goto case 'd';
  448. #endregion
  449. #region o - octal integer
  450. case 'o': // octal integer - no leading zero
  451. w = FormatOct("o", flagAlternate,
  452. fieldLength, int.MinValue, flagLeft2Right,
  453. paddingCharacter, o);
  454. defaultParamIx++;
  455. break;
  456. #endregion
  457. #region x - hex integer
  458. case 'x': // hex integer - no leading zero
  459. w = FormatHex("x", flagAlternate,
  460. fieldLength, fieldPrecision, flagLeft2Right,
  461. paddingCharacter, o);
  462. defaultParamIx++;
  463. break;
  464. #endregion
  465. #region X - hex integer
  466. case 'X': // same as x but with capital hex characters
  467. w = FormatHex("X", flagAlternate,
  468. fieldLength, fieldPrecision, flagLeft2Right,
  469. paddingCharacter, o);
  470. defaultParamIx++;
  471. break;
  472. #endregion
  473. #region u - unsigned integer
  474. case 'u': // unsigned integer
  475. w = FormatNumber((flagGroupThousands ? "n" : "d"), flagAlternate,
  476. fieldLength, int.MinValue, flagLeft2Right,
  477. false, false,
  478. paddingCharacter, ToUnsigned(o));
  479. defaultParamIx++;
  480. break;
  481. #endregion
  482. #region c - character
  483. case 'c': // character
  484. if (IsNumericType(o))
  485. w = Convert.ToChar(o).ToString();
  486. else if (o is char)
  487. w = ((char)o).ToString();
  488. else if (o is string && ((string)o).Length > 0)
  489. w = ((string)o)[0].ToString();
  490. defaultParamIx++;
  491. break;
  492. #endregion
  493. #region s - string
  494. case 's': // string
  495. //string t = "{0" + ( fieldLength != int.MinValue ? "," + ( flagLeft2Right ? "-" : String.Empty ) + fieldLength.ToString() : String.Empty ) + ":s}";
  496. w = o.ToString();
  497. if (fieldPrecision >= 0)
  498. w = w.Substring(0, fieldPrecision);
  499. if (fieldLength != int.MinValue)
  500. if (flagLeft2Right)
  501. w = w.PadRight(fieldLength, paddingCharacter);
  502. else
  503. w = w.PadLeft(fieldLength, paddingCharacter);
  504. defaultParamIx++;
  505. break;
  506. #endregion
  507. #region f - double number
  508. case 'f': // double
  509. w = FormatNumber((flagGroupThousands ? "n" : "f"), flagAlternate,
  510. fieldLength, fieldPrecision, flagLeft2Right,
  511. flagPositiveSign, flagPositiveSpace,
  512. paddingCharacter, o);
  513. defaultParamIx++;
  514. break;
  515. #endregion
  516. #region e - exponent number
  517. case 'e': // double / exponent
  518. w = FormatNumber("e", flagAlternate,
  519. fieldLength, fieldPrecision, flagLeft2Right,
  520. flagPositiveSign, flagPositiveSpace,
  521. paddingCharacter, o);
  522. defaultParamIx++;
  523. break;
  524. #endregion
  525. #region E - exponent number
  526. case 'E': // double / exponent
  527. w = FormatNumber("E", flagAlternate,
  528. fieldLength, fieldPrecision, flagLeft2Right,
  529. flagPositiveSign, flagPositiveSpace,
  530. paddingCharacter, o);
  531. defaultParamIx++;
  532. break;
  533. #endregion
  534. #region g - general number
  535. case 'g': // double / exponent
  536. w = FormatNumber("g", flagAlternate,
  537. fieldLength, fieldPrecision, flagLeft2Right,
  538. flagPositiveSign, flagPositiveSpace,
  539. paddingCharacter, o);
  540. defaultParamIx++;
  541. break;
  542. #endregion
  543. #region G - general number
  544. case 'G': // double / exponent
  545. w = FormatNumber("G", flagAlternate,
  546. fieldLength, fieldPrecision, flagLeft2Right,
  547. flagPositiveSign, flagPositiveSpace,
  548. paddingCharacter, o);
  549. defaultParamIx++;
  550. break;
  551. #endregion
  552. #region p - pointer
  553. case 'p': // pointer
  554. if (o is IntPtr)
  555. #if XBOX || SILVERLIGHT
  556. w = ( (IntPtr)o ).ToString();
  557. #else
  558. w = "0x" + ((IntPtr)o).ToString("x");
  559. #endif
  560. defaultParamIx++;
  561. break;
  562. #endregion
  563. #region n - number of processed chars so far
  564. case 'n': // number of characters so far
  565. w = FormatNumber("d", flagAlternate,
  566. fieldLength, int.MinValue, flagLeft2Right,
  567. flagPositiveSign, flagPositiveSpace,
  568. paddingCharacter, m.Index);
  569. break;
  570. #endregion
  571. default:
  572. w = String.Empty;
  573. defaultParamIx++;
  574. break;
  575. }
  576. // replace format parameter with parameter value
  577. // and start searching for the next format parameter
  578. // AFTER the position of the current inserted value
  579. // to prohibit recursive matches if the value also
  580. // includes a format specifier
  581. f.Remove(m.Index, m.Length);
  582. f.Insert(m.Index, w);
  583. m = r.Match(f.ToString(), m.Index + w.Length);
  584. }
  585. return f.ToString();
  586. }
  587. #endregion
  588. #endregion
  589. #region Private Methods
  590. #region FormatOCT
  591. private static string FormatOct(string NativeFormat, bool Alternate,
  592. int FieldLength, int FieldPrecision,
  593. bool Left2Right,
  594. char Padding, object Value)
  595. {
  596. string w = String.Empty;
  597. string lengthFormat = "{0" + (FieldLength != int.MinValue ?
  598. "," + (Left2Right ?
  599. "-" :
  600. String.Empty) + FieldLength.ToString() :
  601. String.Empty) + "}";
  602. if (IsNumericType(Value))
  603. {
  604. w = Convert.ToString(UnboxToLong(Value, true), 8);
  605. if (Left2Right || Padding == ' ')
  606. {
  607. if (Alternate && w != "0")
  608. w = "0" + w;
  609. w = String.Format(lengthFormat, w);
  610. }
  611. else
  612. {
  613. if (FieldLength != int.MinValue)
  614. w = w.PadLeft(FieldLength - (Alternate && w != "0" ? 1 : 0), Padding);
  615. if (Alternate && w != "0")
  616. w = "0" + w;
  617. }
  618. }
  619. return w;
  620. }
  621. #endregion
  622. #region FormatHEX
  623. private static string FormatHex(string NativeFormat, bool Alternate,
  624. int FieldLength, int FieldPrecision,
  625. bool Left2Right,
  626. char Padding, object Value)
  627. {
  628. string w = String.Empty;
  629. string lengthFormat = "{0" + (FieldLength != int.MinValue ?
  630. "," + (Left2Right ?
  631. "-" :
  632. String.Empty) + FieldLength.ToString() :
  633. String.Empty) + "}";
  634. string numberFormat = "{0:" + NativeFormat + (FieldPrecision != int.MinValue ?
  635. FieldPrecision.ToString() :
  636. String.Empty) + "}";
  637. if (IsNumericType(Value))
  638. {
  639. w = String.Format(numberFormat, Value);
  640. if (Left2Right || Padding == ' ')
  641. {
  642. if (Alternate)
  643. w = (NativeFormat == "x" ? "0x" : "0X") + w;
  644. w = String.Format(lengthFormat, w);
  645. }
  646. else
  647. {
  648. if (FieldLength != int.MinValue)
  649. w = w.PadLeft(FieldLength - (Alternate ? 2 : 0), Padding);
  650. if (Alternate)
  651. w = (NativeFormat == "x" ? "0x" : "0X") + w;
  652. }
  653. }
  654. return w;
  655. }
  656. #endregion
  657. #region FormatNumber
  658. private static string FormatNumber(string NativeFormat, bool Alternate,
  659. int FieldLength, int FieldPrecision,
  660. bool Left2Right,
  661. bool PositiveSign, bool PositiveSpace,
  662. char Padding, object Value)
  663. {
  664. string w = String.Empty;
  665. string lengthFormat = "{0" + (FieldLength != int.MinValue ?
  666. "," + (Left2Right ?
  667. "-" :
  668. String.Empty) + FieldLength.ToString() :
  669. String.Empty) + "}";
  670. string numberFormat = "{0:" + NativeFormat + (FieldPrecision != int.MinValue ?
  671. FieldPrecision.ToString() :
  672. "0") + "}";
  673. if (IsNumericType(Value))
  674. {
  675. w = String.Format(CultureInfo.InvariantCulture, numberFormat, Value);
  676. if (Left2Right || Padding == ' ')
  677. {
  678. if (IsPositive(Value, true))
  679. w = (PositiveSign ?
  680. "+" : (PositiveSpace ? " " : String.Empty)) + w;
  681. w = String.Format(lengthFormat, w);
  682. }
  683. else
  684. {
  685. if (w.StartsWith("-"))
  686. w = w.Substring(1);
  687. if (FieldLength != int.MinValue)
  688. if (PositiveSign) // xan - change here
  689. w = w.PadLeft(FieldLength-1, Padding);
  690. else
  691. w = w.PadLeft(FieldLength, Padding);
  692. if (IsPositive(Value, true))
  693. w = (PositiveSign ?
  694. "+" : "") + w; // xan - change here
  695. else
  696. w = "-" + w;
  697. }
  698. }
  699. return w;
  700. }
  701. #endregion
  702. #endregion
  703. }
  704. }