|
|
@@ -0,0 +1,747 @@
|
|
|
+//
|
|
|
+// This part taken from KopiLua - https://github.com/NLua/KopiLua
|
|
|
+//
|
|
|
+// =========================================================================================================
|
|
|
+//
|
|
|
+// Kopi Lua License
|
|
|
+// ----------------
|
|
|
+// MIT License for KopiLua
|
|
|
+// Copyright (c) 2012 LoDC
|
|
|
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
|
+// associated documentation files (the "Software"), to deal in the Software without restriction,
|
|
|
+// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
+// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
|
+// subject to the following conditions:
|
|
|
+// The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
|
+// portions of the Software.
|
|
|
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
|
|
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
|
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
|
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
|
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
+// ===============================================================================
|
|
|
+// Lua License
|
|
|
+// -----------
|
|
|
+// Lua is licensed under the terms of the MIT license reproduced below.
|
|
|
+// This means that Lua is free software and can be used for both academic
|
|
|
+// and commercial purposes at absolutely no cost.
|
|
|
+// For details and rationale, see http://www.lua.org/license.html .
|
|
|
+// ===============================================================================
|
|
|
+// Copyright (C) 1994-2008 Lua.org, PUC-Rio.
|
|
|
+// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
+// of this software and associated documentation files (the "Software"), to deal
|
|
|
+// in the Software without restriction, including without limitation the rights
|
|
|
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
+// copies of the Software, and to permit persons to whom the Software is
|
|
|
+// furnished to do so, subject to the following conditions:
|
|
|
+// The above copyright notice and this permission notice shall be included in
|
|
|
+// all copies or substantial portions of the Software.
|
|
|
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
+// THE SOFTWARE.
|
|
|
+
|
|
|
+
|
|
|
+#region Usings
|
|
|
+using System;
|
|
|
+using System.IO;
|
|
|
+using System.Text;
|
|
|
+using System.Text.RegularExpressions;
|
|
|
+using System.Globalization;
|
|
|
+
|
|
|
+
|
|
|
+#endregion
|
|
|
+
|
|
|
+namespace AT.MIN
|
|
|
+{
|
|
|
+ public static class Tools
|
|
|
+ {
|
|
|
+ #region Public Methods
|
|
|
+ #region IsNumericType
|
|
|
+ /// <summary>
|
|
|
+ /// Determines whether the specified value is of numeric type.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="o">The object to check.</param>
|
|
|
+ /// <returns>
|
|
|
+ /// <c>true</c> if o is a numeric type; otherwise, <c>false</c>.
|
|
|
+ /// </returns>
|
|
|
+ public static bool IsNumericType(object o)
|
|
|
+ {
|
|
|
+ return (o is byte ||
|
|
|
+ o is sbyte ||
|
|
|
+ o is short ||
|
|
|
+ o is ushort ||
|
|
|
+ o is int ||
|
|
|
+ o is uint ||
|
|
|
+ o is long ||
|
|
|
+ o is ulong ||
|
|
|
+ o is float ||
|
|
|
+ o is double ||
|
|
|
+ o is decimal);
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ #region IsPositive
|
|
|
+ /// <summary>
|
|
|
+ /// Determines whether the specified value is positive.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="Value">The value.</param>
|
|
|
+ /// <param name="ZeroIsPositive">if set to <c>true</c> treats 0 as positive.</param>
|
|
|
+ /// <returns>
|
|
|
+ /// <c>true</c> if the specified value is positive; otherwise, <c>false</c>.
|
|
|
+ /// </returns>
|
|
|
+ public static bool IsPositive(object Value, bool ZeroIsPositive)
|
|
|
+ {
|
|
|
+ switch (Type.GetTypeCode(Value.GetType()))
|
|
|
+ {
|
|
|
+ case TypeCode.SByte:
|
|
|
+ return (ZeroIsPositive ? (sbyte)Value >= 0 : (sbyte)Value > 0);
|
|
|
+ case TypeCode.Int16:
|
|
|
+ return (ZeroIsPositive ? (short)Value >= 0 : (short)Value > 0);
|
|
|
+ case TypeCode.Int32:
|
|
|
+ return (ZeroIsPositive ? (int)Value >= 0 : (int)Value > 0);
|
|
|
+ case TypeCode.Int64:
|
|
|
+ return (ZeroIsPositive ? (long)Value >= 0 : (long)Value > 0);
|
|
|
+ case TypeCode.Single:
|
|
|
+ return (ZeroIsPositive ? (float)Value >= 0 : (float)Value > 0);
|
|
|
+ case TypeCode.Double:
|
|
|
+ return (ZeroIsPositive ? (double)Value >= 0 : (double)Value > 0);
|
|
|
+ case TypeCode.Decimal:
|
|
|
+ return (ZeroIsPositive ? (decimal)Value >= 0 : (decimal)Value > 0);
|
|
|
+ case TypeCode.Byte:
|
|
|
+ return (ZeroIsPositive ? true : (byte)Value > 0);
|
|
|
+ case TypeCode.UInt16:
|
|
|
+ return (ZeroIsPositive ? true : (ushort)Value > 0);
|
|
|
+ case TypeCode.UInt32:
|
|
|
+ return (ZeroIsPositive ? true : (uint)Value > 0);
|
|
|
+ case TypeCode.UInt64:
|
|
|
+ return (ZeroIsPositive ? true : (ulong)Value > 0);
|
|
|
+ case TypeCode.Char:
|
|
|
+ return (ZeroIsPositive ? true : (char)Value != '\0');
|
|
|
+ default:
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ #region ToUnsigned
|
|
|
+ /// <summary>
|
|
|
+ /// Converts the specified values boxed type to its correpsonding unsigned
|
|
|
+ /// type.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="Value">The value.</param>
|
|
|
+ /// <returns>A boxed numeric object whos type is unsigned.</returns>
|
|
|
+ public static object ToUnsigned(object Value)
|
|
|
+ {
|
|
|
+ switch (Type.GetTypeCode(Value.GetType()))
|
|
|
+ {
|
|
|
+ case TypeCode.SByte:
|
|
|
+ return (byte)((sbyte)Value);
|
|
|
+ case TypeCode.Int16:
|
|
|
+ return (ushort)((short)Value);
|
|
|
+ case TypeCode.Int32:
|
|
|
+ return (uint)((int)Value);
|
|
|
+ case TypeCode.Int64:
|
|
|
+ return (ulong)((long)Value);
|
|
|
+
|
|
|
+ case TypeCode.Byte:
|
|
|
+ return Value;
|
|
|
+ case TypeCode.UInt16:
|
|
|
+ return Value;
|
|
|
+ case TypeCode.UInt32:
|
|
|
+ return Value;
|
|
|
+ case TypeCode.UInt64:
|
|
|
+ return Value;
|
|
|
+
|
|
|
+ case TypeCode.Single:
|
|
|
+ return (UInt32)((float)Value);
|
|
|
+ case TypeCode.Double:
|
|
|
+ return (ulong)((double)Value);
|
|
|
+ case TypeCode.Decimal:
|
|
|
+ return (ulong)((decimal)Value);
|
|
|
+
|
|
|
+ default:
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ #region ToInteger
|
|
|
+ /// <summary>
|
|
|
+ /// Converts the specified values boxed type to its correpsonding integer
|
|
|
+ /// type.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="Value">The value.</param>
|
|
|
+ /// <returns>A boxed numeric object whos type is an integer type.</returns>
|
|
|
+ public static object ToInteger(object Value, bool Round)
|
|
|
+ {
|
|
|
+ switch (Type.GetTypeCode(Value.GetType()))
|
|
|
+ {
|
|
|
+ case TypeCode.SByte:
|
|
|
+ return Value;
|
|
|
+ case TypeCode.Int16:
|
|
|
+ return Value;
|
|
|
+ case TypeCode.Int32:
|
|
|
+ return Value;
|
|
|
+ case TypeCode.Int64:
|
|
|
+ return Value;
|
|
|
+
|
|
|
+ case TypeCode.Byte:
|
|
|
+ return Value;
|
|
|
+ case TypeCode.UInt16:
|
|
|
+ return Value;
|
|
|
+ case TypeCode.UInt32:
|
|
|
+ return Value;
|
|
|
+ case TypeCode.UInt64:
|
|
|
+ return Value;
|
|
|
+
|
|
|
+ case TypeCode.Single:
|
|
|
+ return (Round ? (int)Math.Round((float)Value) : (int)((float)Value));
|
|
|
+ case TypeCode.Double:
|
|
|
+ return (Round ? (long)Math.Round((double)Value) : (long)((double)Value));
|
|
|
+ case TypeCode.Decimal:
|
|
|
+ return (Round ? Math.Round((decimal)Value) : (decimal)Value);
|
|
|
+
|
|
|
+ default:
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ #region UnboxToLong
|
|
|
+ public static long UnboxToLong(object Value, bool Round)
|
|
|
+ {
|
|
|
+ switch (Type.GetTypeCode(Value.GetType()))
|
|
|
+ {
|
|
|
+ case TypeCode.SByte:
|
|
|
+ return (long)((sbyte)Value);
|
|
|
+ case TypeCode.Int16:
|
|
|
+ return (long)((short)Value);
|
|
|
+ case TypeCode.Int32:
|
|
|
+ return (long)((int)Value);
|
|
|
+ case TypeCode.Int64:
|
|
|
+ return (long)Value;
|
|
|
+
|
|
|
+ case TypeCode.Byte:
|
|
|
+ return (long)((byte)Value);
|
|
|
+ case TypeCode.UInt16:
|
|
|
+ return (long)((ushort)Value);
|
|
|
+ case TypeCode.UInt32:
|
|
|
+ return (long)((uint)Value);
|
|
|
+ case TypeCode.UInt64:
|
|
|
+ return (long)((ulong)Value);
|
|
|
+
|
|
|
+ case TypeCode.Single:
|
|
|
+ return (Round ? (long)Math.Round((float)Value) : (long)((float)Value));
|
|
|
+ case TypeCode.Double:
|
|
|
+ return (Round ? (long)Math.Round((double)Value) : (long)((double)Value));
|
|
|
+ case TypeCode.Decimal:
|
|
|
+ return (Round ? (long)Math.Round((decimal)Value) : (long)((decimal)Value));
|
|
|
+
|
|
|
+ default:
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ #region ReplaceMetaChars
|
|
|
+ /// <summary>
|
|
|
+ /// Replaces the string representations of meta chars with their corresponding
|
|
|
+ /// character values.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="input">The input.</param>
|
|
|
+ /// <returns>A string with all string meta chars are replaced</returns>
|
|
|
+ public static string ReplaceMetaChars(string input)
|
|
|
+ {
|
|
|
+ return Regex.Replace(input, @"(\\)(\d{3}|[^\d])?", new MatchEvaluator(ReplaceMetaCharsMatch));
|
|
|
+ }
|
|
|
+ private static string ReplaceMetaCharsMatch(Match m)
|
|
|
+ {
|
|
|
+ // convert octal quotes (like \040)
|
|
|
+ if (m.Groups[2].Length == 3)
|
|
|
+ return Convert.ToChar(Convert.ToByte(m.Groups[2].Value, 8)).ToString();
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // convert all other special meta characters
|
|
|
+ //TODO: \xhhh hex and possible dec !!
|
|
|
+ switch (m.Groups[2].Value)
|
|
|
+ {
|
|
|
+ case "0": // null
|
|
|
+ return "\0";
|
|
|
+ case "a": // alert (beep)
|
|
|
+ return "\a";
|
|
|
+ case "b": // BS
|
|
|
+ return "\b";
|
|
|
+ case "f": // FF
|
|
|
+ return "\f";
|
|
|
+ case "v": // vertical tab
|
|
|
+ return "\v";
|
|
|
+ case "r": // CR
|
|
|
+ return "\r";
|
|
|
+ case "n": // LF
|
|
|
+ return "\n";
|
|
|
+ case "t": // Tab
|
|
|
+ return "\t";
|
|
|
+ default:
|
|
|
+ // if neither an octal quote nor a special meta character
|
|
|
+ // so just remove the backslash
|
|
|
+ return m.Groups[2].Value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ #region printf
|
|
|
+ public static void printf(string Format, params object[] Parameters)
|
|
|
+ {
|
|
|
+ Console.Write(Tools.sprintf(Format, Parameters));
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ #region fprintf
|
|
|
+ public static void fprintf(TextWriter Destination, string Format, params object[] Parameters)
|
|
|
+ {
|
|
|
+ Destination.Write(Tools.sprintf(Format, Parameters));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ #endregion
|
|
|
+ #region sprintf
|
|
|
+ internal static Regex r = new Regex(@"\%(\d*\$)?([\'\#\-\+ ]*)(\d*)(?:\.(\d+))?([hl])?([dioxXucsfeEgGpn%])");
|
|
|
+ public static string sprintf(string Format, params object[] Parameters)
|
|
|
+ {
|
|
|
+ #region Variables
|
|
|
+ StringBuilder f = new StringBuilder();
|
|
|
+ //Regex r = new Regex( @"\%(\d*\$)?([\'\#\-\+ ]*)(\d*)(?:\.(\d+))?([hl])?([dioxXucsfeEgGpn%])" );
|
|
|
+ //"%[parameter][flags][width][.precision][length]type"
|
|
|
+ Match m = null;
|
|
|
+ string w = String.Empty;
|
|
|
+ int defaultParamIx = 0;
|
|
|
+ int paramIx;
|
|
|
+ object o = null;
|
|
|
+
|
|
|
+ bool flagLeft2Right = false;
|
|
|
+ bool flagAlternate = false;
|
|
|
+ bool flagPositiveSign = false;
|
|
|
+ bool flagPositiveSpace = false;
|
|
|
+ bool flagZeroPadding = false;
|
|
|
+ bool flagGroupThousands = false;
|
|
|
+
|
|
|
+ int fieldLength = 0;
|
|
|
+ int fieldPrecision = 0;
|
|
|
+ char shortLongIndicator = '\0';
|
|
|
+ char formatSpecifier = '\0';
|
|
|
+ char paddingCharacter = ' ';
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ // find all format parameters in format string
|
|
|
+ f.Append(Format);
|
|
|
+ m = r.Match(f.ToString());
|
|
|
+ while (m.Success)
|
|
|
+ {
|
|
|
+ #region parameter index
|
|
|
+ paramIx = defaultParamIx;
|
|
|
+ if (m.Groups[1] != null && m.Groups[1].Value.Length > 0)
|
|
|
+ {
|
|
|
+ string val = m.Groups[1].Value.Substring(0, m.Groups[1].Value.Length - 1);
|
|
|
+ paramIx = Convert.ToInt32(val) - 1;
|
|
|
+ };
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region format flags
|
|
|
+ // extract format flags
|
|
|
+ flagAlternate = false;
|
|
|
+ flagLeft2Right = false;
|
|
|
+ flagPositiveSign = false;
|
|
|
+ flagPositiveSpace = false;
|
|
|
+ flagZeroPadding = false;
|
|
|
+ flagGroupThousands = false;
|
|
|
+ if (m.Groups[2] != null && m.Groups[2].Value.Length > 0)
|
|
|
+ {
|
|
|
+ string flags = m.Groups[2].Value;
|
|
|
+
|
|
|
+ flagAlternate = (flags.IndexOf('#') >= 0);
|
|
|
+ flagLeft2Right = (flags.IndexOf('-') >= 0);
|
|
|
+ flagPositiveSign = (flags.IndexOf('+') >= 0);
|
|
|
+ flagPositiveSpace = (flags.IndexOf(' ') >= 0);
|
|
|
+ flagGroupThousands = (flags.IndexOf('\'') >= 0);
|
|
|
+
|
|
|
+ // positive + indicator overrides a
|
|
|
+ // positive space character
|
|
|
+ if (flagPositiveSign && flagPositiveSpace)
|
|
|
+ flagPositiveSpace = false;
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region field length
|
|
|
+ // extract field length and
|
|
|
+ // pading character
|
|
|
+ paddingCharacter = ' ';
|
|
|
+ fieldLength = int.MinValue;
|
|
|
+ if (m.Groups[3] != null && m.Groups[3].Value.Length > 0)
|
|
|
+ {
|
|
|
+ fieldLength = Convert.ToInt32(m.Groups[3].Value);
|
|
|
+ flagZeroPadding = (m.Groups[3].Value[0] == '0');
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ if (flagZeroPadding)
|
|
|
+ paddingCharacter = '0';
|
|
|
+
|
|
|
+ // left2right allignment overrides zero padding
|
|
|
+ if (flagLeft2Right && flagZeroPadding)
|
|
|
+ {
|
|
|
+ flagZeroPadding = false;
|
|
|
+ paddingCharacter = ' ';
|
|
|
+ }
|
|
|
+
|
|
|
+ #region field precision
|
|
|
+ // extract field precision
|
|
|
+ fieldPrecision = int.MinValue;
|
|
|
+ if (m.Groups[4] != null && m.Groups[4].Value.Length > 0)
|
|
|
+ fieldPrecision = Convert.ToInt32(m.Groups[4].Value);
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region short / long indicator
|
|
|
+ // extract short / long indicator
|
|
|
+ shortLongIndicator = Char.MinValue;
|
|
|
+ if (m.Groups[5] != null && m.Groups[5].Value.Length > 0)
|
|
|
+ shortLongIndicator = m.Groups[5].Value[0];
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region format specifier
|
|
|
+ // extract format
|
|
|
+ formatSpecifier = Char.MinValue;
|
|
|
+ if (m.Groups[6] != null && m.Groups[6].Value.Length > 0)
|
|
|
+ formatSpecifier = m.Groups[6].Value[0];
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ // default precision is 6 digits if none is specified except
|
|
|
+ if (fieldPrecision == int.MinValue &&
|
|
|
+ formatSpecifier != 's' &&
|
|
|
+ formatSpecifier != 'c' &&
|
|
|
+ Char.ToUpper(formatSpecifier) != 'X' &&
|
|
|
+ formatSpecifier != 'o')
|
|
|
+ fieldPrecision = 6;
|
|
|
+
|
|
|
+ #region get next value parameter
|
|
|
+ // get next value parameter and convert value parameter depending on short / long indicator
|
|
|
+ if (Parameters == null || paramIx >= Parameters.Length)
|
|
|
+ o = null;
|
|
|
+ else
|
|
|
+ {
|
|
|
+ o = Parameters[paramIx];
|
|
|
+
|
|
|
+ if (shortLongIndicator == 'h')
|
|
|
+ {
|
|
|
+ if (o is int)
|
|
|
+ o = (short)((int)o);
|
|
|
+ else if (o is long)
|
|
|
+ o = (short)((long)o);
|
|
|
+ else if (o is uint)
|
|
|
+ o = (ushort)((uint)o);
|
|
|
+ else if (o is ulong)
|
|
|
+ o = (ushort)((ulong)o);
|
|
|
+ }
|
|
|
+ else if (shortLongIndicator == 'l')
|
|
|
+ {
|
|
|
+ if (o is short)
|
|
|
+ o = (long)((short)o);
|
|
|
+ else if (o is int)
|
|
|
+ o = (long)((int)o);
|
|
|
+ else if (o is ushort)
|
|
|
+ o = (ulong)((ushort)o);
|
|
|
+ else if (o is uint)
|
|
|
+ o = (ulong)((uint)o);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ // convert value parameters to a string depending on the formatSpecifier
|
|
|
+ w = String.Empty;
|
|
|
+ switch (formatSpecifier)
|
|
|
+ {
|
|
|
+ #region % - character
|
|
|
+ case '%': // % character
|
|
|
+ w = "%";
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ #region d - integer
|
|
|
+ case 'd': // integer
|
|
|
+ w = FormatNumber((flagGroupThousands ? "n" : "d"), flagAlternate,
|
|
|
+ fieldLength, int.MinValue, flagLeft2Right,
|
|
|
+ flagPositiveSign, flagPositiveSpace,
|
|
|
+ paddingCharacter, o);
|
|
|
+ defaultParamIx++;
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ #region i - integer
|
|
|
+ case 'i': // integer
|
|
|
+ goto case 'd';
|
|
|
+ #endregion
|
|
|
+ #region o - octal integer
|
|
|
+ case 'o': // octal integer - no leading zero
|
|
|
+ w = FormatOct("o", flagAlternate,
|
|
|
+ fieldLength, int.MinValue, flagLeft2Right,
|
|
|
+ paddingCharacter, o);
|
|
|
+ defaultParamIx++;
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ #region x - hex integer
|
|
|
+ case 'x': // hex integer - no leading zero
|
|
|
+ w = FormatHex("x", flagAlternate,
|
|
|
+ fieldLength, fieldPrecision, flagLeft2Right,
|
|
|
+ paddingCharacter, o);
|
|
|
+ defaultParamIx++;
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ #region X - hex integer
|
|
|
+ case 'X': // same as x but with capital hex characters
|
|
|
+ w = FormatHex("X", flagAlternate,
|
|
|
+ fieldLength, fieldPrecision, flagLeft2Right,
|
|
|
+ paddingCharacter, o);
|
|
|
+ defaultParamIx++;
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ #region u - unsigned integer
|
|
|
+ case 'u': // unsigned integer
|
|
|
+ w = FormatNumber((flagGroupThousands ? "n" : "d"), flagAlternate,
|
|
|
+ fieldLength, int.MinValue, flagLeft2Right,
|
|
|
+ false, false,
|
|
|
+ paddingCharacter, ToUnsigned(o));
|
|
|
+ defaultParamIx++;
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ #region c - character
|
|
|
+ case 'c': // character
|
|
|
+ if (IsNumericType(o))
|
|
|
+ w = Convert.ToChar(o).ToString();
|
|
|
+ else if (o is char)
|
|
|
+ w = ((char)o).ToString();
|
|
|
+ else if (o is string && ((string)o).Length > 0)
|
|
|
+ w = ((string)o)[0].ToString();
|
|
|
+ defaultParamIx++;
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ #region s - string
|
|
|
+ case 's': // string
|
|
|
+ //string t = "{0" + ( fieldLength != int.MinValue ? "," + ( flagLeft2Right ? "-" : String.Empty ) + fieldLength.ToString() : String.Empty ) + ":s}";
|
|
|
+ w = o.ToString();
|
|
|
+ if (fieldPrecision >= 0)
|
|
|
+ w = w.Substring(0, fieldPrecision);
|
|
|
+
|
|
|
+ if (fieldLength != int.MinValue)
|
|
|
+ if (flagLeft2Right)
|
|
|
+ w = w.PadRight(fieldLength, paddingCharacter);
|
|
|
+ else
|
|
|
+ w = w.PadLeft(fieldLength, paddingCharacter);
|
|
|
+ defaultParamIx++;
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ #region f - double number
|
|
|
+ case 'f': // double
|
|
|
+ w = FormatNumber((flagGroupThousands ? "n" : "f"), flagAlternate,
|
|
|
+ fieldLength, fieldPrecision, flagLeft2Right,
|
|
|
+ flagPositiveSign, flagPositiveSpace,
|
|
|
+ paddingCharacter, o);
|
|
|
+ defaultParamIx++;
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ #region e - exponent number
|
|
|
+ case 'e': // double / exponent
|
|
|
+ w = FormatNumber("e", flagAlternate,
|
|
|
+ fieldLength, fieldPrecision, flagLeft2Right,
|
|
|
+ flagPositiveSign, flagPositiveSpace,
|
|
|
+ paddingCharacter, o);
|
|
|
+ defaultParamIx++;
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ #region E - exponent number
|
|
|
+ case 'E': // double / exponent
|
|
|
+ w = FormatNumber("E", flagAlternate,
|
|
|
+ fieldLength, fieldPrecision, flagLeft2Right,
|
|
|
+ flagPositiveSign, flagPositiveSpace,
|
|
|
+ paddingCharacter, o);
|
|
|
+ defaultParamIx++;
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ #region g - general number
|
|
|
+ case 'g': // double / exponent
|
|
|
+ w = FormatNumber("g", flagAlternate,
|
|
|
+ fieldLength, fieldPrecision, flagLeft2Right,
|
|
|
+ flagPositiveSign, flagPositiveSpace,
|
|
|
+ paddingCharacter, o);
|
|
|
+ defaultParamIx++;
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ #region G - general number
|
|
|
+ case 'G': // double / exponent
|
|
|
+ w = FormatNumber("G", flagAlternate,
|
|
|
+ fieldLength, fieldPrecision, flagLeft2Right,
|
|
|
+ flagPositiveSign, flagPositiveSpace,
|
|
|
+ paddingCharacter, o);
|
|
|
+ defaultParamIx++;
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ #region p - pointer
|
|
|
+ case 'p': // pointer
|
|
|
+ if (o is IntPtr)
|
|
|
+#if XBOX || SILVERLIGHT
|
|
|
+ w = ( (IntPtr)o ).ToString();
|
|
|
+#else
|
|
|
+ w = "0x" + ((IntPtr)o).ToString("x");
|
|
|
+#endif
|
|
|
+ defaultParamIx++;
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ #region n - number of processed chars so far
|
|
|
+ case 'n': // number of characters so far
|
|
|
+ w = FormatNumber("d", flagAlternate,
|
|
|
+ fieldLength, int.MinValue, flagLeft2Right,
|
|
|
+ flagPositiveSign, flagPositiveSpace,
|
|
|
+ paddingCharacter, m.Index);
|
|
|
+ break;
|
|
|
+ #endregion
|
|
|
+ default:
|
|
|
+ w = String.Empty;
|
|
|
+ defaultParamIx++;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // replace format parameter with parameter value
|
|
|
+ // and start searching for the next format parameter
|
|
|
+ // AFTER the position of the current inserted value
|
|
|
+ // to prohibit recursive matches if the value also
|
|
|
+ // includes a format specifier
|
|
|
+ f.Remove(m.Index, m.Length);
|
|
|
+ f.Insert(m.Index, w);
|
|
|
+ m = r.Match(f.ToString(), m.Index + w.Length);
|
|
|
+ }
|
|
|
+
|
|
|
+ return f.ToString();
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region Private Methods
|
|
|
+ #region FormatOCT
|
|
|
+ private static string FormatOct(string NativeFormat, bool Alternate,
|
|
|
+ int FieldLength, int FieldPrecision,
|
|
|
+ bool Left2Right,
|
|
|
+ char Padding, object Value)
|
|
|
+ {
|
|
|
+ string w = String.Empty;
|
|
|
+ string lengthFormat = "{0" + (FieldLength != int.MinValue ?
|
|
|
+ "," + (Left2Right ?
|
|
|
+ "-" :
|
|
|
+ String.Empty) + FieldLength.ToString() :
|
|
|
+ String.Empty) + "}";
|
|
|
+
|
|
|
+ if (IsNumericType(Value))
|
|
|
+ {
|
|
|
+ w = Convert.ToString(UnboxToLong(Value, true), 8);
|
|
|
+
|
|
|
+ if (Left2Right || Padding == ' ')
|
|
|
+ {
|
|
|
+ if (Alternate && w != "0")
|
|
|
+ w = "0" + w;
|
|
|
+ w = String.Format(lengthFormat, w);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (FieldLength != int.MinValue)
|
|
|
+ w = w.PadLeft(FieldLength - (Alternate && w != "0" ? 1 : 0), Padding);
|
|
|
+ if (Alternate && w != "0")
|
|
|
+ w = "0" + w;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return w;
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ #region FormatHEX
|
|
|
+ private static string FormatHex(string NativeFormat, bool Alternate,
|
|
|
+ int FieldLength, int FieldPrecision,
|
|
|
+ bool Left2Right,
|
|
|
+ char Padding, object Value)
|
|
|
+ {
|
|
|
+ string w = String.Empty;
|
|
|
+ string lengthFormat = "{0" + (FieldLength != int.MinValue ?
|
|
|
+ "," + (Left2Right ?
|
|
|
+ "-" :
|
|
|
+ String.Empty) + FieldLength.ToString() :
|
|
|
+ String.Empty) + "}";
|
|
|
+ string numberFormat = "{0:" + NativeFormat + (FieldPrecision != int.MinValue ?
|
|
|
+ FieldPrecision.ToString() :
|
|
|
+ String.Empty) + "}";
|
|
|
+
|
|
|
+ if (IsNumericType(Value))
|
|
|
+ {
|
|
|
+ w = String.Format(numberFormat, Value);
|
|
|
+
|
|
|
+ if (Left2Right || Padding == ' ')
|
|
|
+ {
|
|
|
+ if (Alternate)
|
|
|
+ w = (NativeFormat == "x" ? "0x" : "0X") + w;
|
|
|
+ w = String.Format(lengthFormat, w);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (FieldLength != int.MinValue)
|
|
|
+ w = w.PadLeft(FieldLength - (Alternate ? 2 : 0), Padding);
|
|
|
+ if (Alternate)
|
|
|
+ w = (NativeFormat == "x" ? "0x" : "0X") + w;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return w;
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ #region FormatNumber
|
|
|
+ private static string FormatNumber(string NativeFormat, bool Alternate,
|
|
|
+ int FieldLength, int FieldPrecision,
|
|
|
+ bool Left2Right,
|
|
|
+ bool PositiveSign, bool PositiveSpace,
|
|
|
+ char Padding, object Value)
|
|
|
+ {
|
|
|
+ string w = String.Empty;
|
|
|
+ string lengthFormat = "{0" + (FieldLength != int.MinValue ?
|
|
|
+ "," + (Left2Right ?
|
|
|
+ "-" :
|
|
|
+ String.Empty) + FieldLength.ToString() :
|
|
|
+ String.Empty) + "}";
|
|
|
+ string numberFormat = "{0:" + NativeFormat + (FieldPrecision != int.MinValue ?
|
|
|
+ FieldPrecision.ToString() :
|
|
|
+ "0") + "}";
|
|
|
+
|
|
|
+ if (IsNumericType(Value))
|
|
|
+ {
|
|
|
+ w = String.Format(CultureInfo.InvariantCulture, numberFormat, Value);
|
|
|
+
|
|
|
+ if (Left2Right || Padding == ' ')
|
|
|
+ {
|
|
|
+ if (IsPositive(Value, true))
|
|
|
+ w = (PositiveSign ?
|
|
|
+ "+" : (PositiveSpace ? " " : String.Empty)) + w;
|
|
|
+ w = String.Format(lengthFormat, w);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (w.StartsWith("-"))
|
|
|
+ w = w.Substring(1);
|
|
|
+ if (FieldLength != int.MinValue)
|
|
|
+ w = w.PadLeft(FieldLength - 1, Padding);
|
|
|
+ if (IsPositive(Value, true))
|
|
|
+ w = (PositiveSign ?
|
|
|
+ "+" : (PositiveSpace ?
|
|
|
+ " " : (FieldLength != int.MinValue ?
|
|
|
+ Padding.ToString() : String.Empty))) + w;
|
|
|
+ else
|
|
|
+ w = "-" + w;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return w;
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|