//#define COSMOSDEBUG using System; using Cosmos.Debug.Kernel; namespace Cosmos.Common { public static class StringHelper { private static Debugger mDebugger = new Debugger("Common", "StringHelper"); internal enum StringComparisonResultEnum { Less = -1, Equal = 0, Greater = 1 } public static string GetNumberString(uint aValue) { mDebugger.SendInternal("StringHelper.GetNumberString(uint)"); string[] xChars = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; string xResult = string.Empty; if (aValue == 0) { xResult = "0"; } else { uint xValue = aValue; while (xValue > 0) { uint xValue2 = xValue % 10; xResult = string.Concat(xChars[xValue2], xResult); xValue /= 10; } } return xResult; } public static string GetNumberString(int aValue) { mDebugger.SendInternal("StringHelper.GetNumberString(int)"); string[] xChars = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; string xResult = string.Empty; if (aValue == 0) { xResult = "0"; } else { int xValue = aValue; if (aValue < 0) { xValue *= -1; } while (xValue > 0) { int xValue2 = xValue % 10; xResult = string.Concat(xChars[xValue2], xResult); xValue /= 10; } } if (aValue < 0) { xResult = string.Concat("-", xResult); } return xResult; } public static string GetNumberString(ulong aValue) { mDebugger.SendInternal("StringHelper.GetNumberString(ulong)"); string[] xChars = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; string xResult = string.Empty; if (aValue == 0) { xResult = "0"; mDebugger.SendInternal("xResult ="); mDebugger.SendInternal(xResult); } else { ulong xValue = aValue; mDebugger.SendInternal("xValue ="); mDebugger.SendInternal(xValue); while (xValue > 0) { ulong xValue2 = xValue % 10; mDebugger.SendInternal("xValue2 ="); mDebugger.SendInternal(xValue2); xResult = string.Concat(xChars[xValue2], xResult); mDebugger.SendInternal("xResult ="); mDebugger.SendInternal(xResult); xValue /= 10; mDebugger.SendInternal("xValue ="); mDebugger.SendInternal(xValue); } } mDebugger.SendInternal("xResult ="); mDebugger.SendInternal(xResult); return xResult; } public static string GetNumberString(long aValue) { mDebugger.SendInternal("StringHelper.GetNumberString(long)"); string[] xChars = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; string xResult = string.Empty; long xValue = aValue; if (aValue == 0) { xResult = "0"; mDebugger.SendInternal("xResult ="); mDebugger.SendInternal(xResult); } else { if (aValue < 0) { xValue *= -1; } mDebugger.SendInternal("xValue ="); mDebugger.SendInternal(xValue); while (xValue > 0) { long xValue2 = xValue % 10; mDebugger.SendInternal("xValue2 ="); mDebugger.SendInternal(xValue2); xResult = string.Concat(xChars[xValue2], xResult); mDebugger.SendInternal("xResult ="); mDebugger.SendInternal(xResult); xValue /= 10; mDebugger.SendInternal("xValue ="); mDebugger.SendInternal(xValue); } } if (aValue < 0) { xResult = string.Concat("-", xResult); } mDebugger.SendInternal("xResult ="); mDebugger.SendInternal(xResult); return xResult; } /* * This implementation could only print values which integer part is < ULONG_MAX, the only solution would have been to use BigInteger but then * I'd have an analogous problem: to plug BigInteger.ToString() and I don't know how many other things. * We will retain this code for now it is OK for debug purposes and big value should be printed in scientific notation to be readable anyway... */ public static string GetNumberString(float aValue) { mDebugger.SendInternal("StringHelper.GetNumberString(float)"); var singleBytes = BitConverter.GetBytes(aValue); int hexVal = BitConverter.ToInt32(singleBytes, 0); /* Let's extract the parts that compose our single: sign, exponent and mantissa */ bool isNeg = (hexVal >> 31) != 0; int exp = ((hexVal >> 23) & 0xFF); ulong mantissa = (ulong)(hexVal & 0x7FFFFF); ulong intPart = 0, fracPart = 0; /* First we handle the special cases INF, NaN, 0 and denormalized float */ switch (exp) { /* * INF or NaN? */ case 0xFF: if (mantissa == 0) { if (isNeg) return "-∞"; else return "∞"; } else /* It could exist -NaN but this is always printed as NaN */ return "NaN"; /* 0 or denormalized float? */ case 0x00: if (mantissa == 0) return "0"; /* Denormalized float have always exp -126 */ else exp = -126; break; /* Normalized float the exponent is unbiased and the implicit leading one is placed in the mantissa */ default: exp -= 127; mantissa |= 0x800000; break; } if (exp >= 23) { intPart = mantissa << (exp - 23); } else if (exp >= 0) { intPart = mantissa >> (23 - exp); fracPart = (mantissa << (exp + 1)) & 0xFFFFFF; } else { fracPart = (mantissa & 0xFFFFFF) >> (-(exp + 1)); } string result = ""; if (isNeg) { result += "-"; } result += intPart.ToString(); int usedDigits = intPart.ToString().Length; if (fracPart == 0) { return result; } result += "."; if (usedDigits >= 7) { usedDigits = 6; } for (int m = usedDigits; m < 7; m++) { fracPart = (fracPart << 3) + (fracPart << 1); char p = (char)((fracPart >> 24) + '0'); result += p; fracPart &= 0xFFFFFF; } fracPart = (fracPart << 3) + (fracPart << 1); char remain = (char)((fracPart >> 24) + '0'); if ((remain > '5') && (result[result.Length - 1] > '0')) { char[] answer = result.ToCharArray(); int digitPos = answer.Length - 1; char digit = result[digitPos]; answer[digitPos] = (char)(digit + 1); while (answer[digitPos] > '9') { answer[digitPos] = '0'; digitPos--; digit = result[digitPos]; if (digit == '.') { digitPos--; digit = result[digitPos]; } answer[digitPos] = (char)(digit + 1); } result = new string(answer); } while (result[result.Length - 1] == '0') { result = result.Substring(0, result.Length - 1); } return result; } /* * This implementation could only print values which integer part is < ULONG_MAX, the only solution would have been to use BigInteger but then * I'd have an analogous problem: to plug BigInteger.ToString() and I don't know how many other things. * We will retain this code for now it is OK for debug purposes and big value should be printed in scientific notation to be readable anyway... */ public static string GetNumberString(double aValue) { mDebugger.SendInternal("StringHelper.GetNumberString(double)"); mDebugger.SendInternal("aValue = "); mDebugger.SendInternal(aValue); long hexVal = BitConverter.DoubleToInt64Bits(aValue); mDebugger.SendInternal("hexVal = "); mDebugger.SendInternal(hexVal); /* Let's extract the parts that compose our double: sign, exponent and mantissa */ bool isNeg = (hexVal >> 63) != 0; int exp = (int)((hexVal >> 52) & 0x07FF); ulong mantissa = (ulong)(hexVal & 0x0FFFFFFFFFFFFF); mDebugger.SendInternal("isNeg = "); mDebugger.SendInternal(isNeg.ToString()); mDebugger.SendInternal("exp = "); mDebugger.SendInternal(exp); mDebugger.SendInternal("mantissa = "); mDebugger.SendInternal(mantissa); ulong intPart = 0, fracPart = 0; if (double.IsPositiveInfinity(aValue)) { return "∞"; } else if (double.IsNegativeInfinity(aValue)) { return "-∞"; } else if (double.IsNaN(aValue)) { return "NaN"; } /* First we handle the special cases INF, NaN, 0 and denormalized float */ switch (exp) { /* 0 or denormalized double? */ case 0x0000: if (mantissa == 0) return "0"; /* Denormalized float have always exp -1022 */ else exp = -1022; break; /* Normalized double the exponent is unbiased and the implicit leading one is placed in the mantissa */ default: exp -= 1023; mantissa |= 0x10000000000000; break; } if (exp >= 52) { intPart = mantissa << (exp - 52); } else if (exp >= 0) { intPart = mantissa >> (52 - exp); fracPart = (mantissa << (exp + 1)) & 0x1FFFFFFFFFFFFF; } else { fracPart = (mantissa & 0x1FFFFFFFFFFFFF) >> (-(exp + 1)); } string result = ""; if (isNeg) { result += "-"; } result += intPart.ToString(); int usedDigits = result.Length; if (fracPart == 0) { return result; } result += "."; if (usedDigits >= 15) { usedDigits = 14; } for (int m = usedDigits; m < 15; m++) { fracPart = (fracPart << 3) + (fracPart << 1); char p = (char)(((fracPart >> 53) & 0xFF) + '0'); result += p; fracPart &= 0x1FFFFFFFFFFFFF; } fracPart = (fracPart << 3) + (fracPart << 1); char remain = (char)((fracPart >> 53) + '0'); if ((remain > '5') && (result[result.Length - 1] > '0')) { char[] answer = result.ToCharArray(); int digitPos = answer.Length - 1; char digit = result[digitPos]; answer[digitPos] = (char)(digit + 1); while (answer[digitPos] > '9') { answer[digitPos] = '0'; digitPos--; digit = result[digitPos]; if (digit == '.') { digitPos--; digit = result[digitPos]; } answer[digitPos] = (char)(digit + 1); } result = new string(answer); } while (result[result.Length - 1] == '0') { result = result.Substring(0, result.Length - 1); } return result; } public static int GetStringToNumber(string aString) { bool xIsNegative = false; int xNumber = 0; if (!string.IsNullOrWhiteSpace(aString)) { char[] xCharArray = aString.ToCharArray(); for (int i = 0; i < xCharArray.Length; i++) { if (char.IsDigit(xCharArray[i])) { int xValue = xCharArray[i] - '0'; int xMax = xCharArray.Length - 1; for (int j = 0; j < xMax - i; i++) { xValue *= 10; } xNumber += xValue; } else if (xCharArray[i] == '-') { xIsNegative = true; } else if (xCharArray[i] == '.') { break; } else { throw new FormatException("The string parameter is not a number and is invalid."); } } } if (xIsNegative) { xNumber *= -1; } return xNumber; } public static int Compare(string aString1, int aIndex1, string aString2, int aIndex2, int aLength1, int aLength2) { if (aString1.Length < aString2.Length) { return (int)StringComparisonResultEnum.Less; } if (aString1.Length > aString2.Length) { return (int)StringComparisonResultEnum.Greater; } for (int i = aString1.Length; i < aString1.Length; i++) { if (aString1[i] < aString2[i]) { return (int)StringComparisonResultEnum.Equal; } if (aString1[i] > aString2[i]) { return (int)StringComparisonResultEnum.Greater; } } return (int)StringComparisonResultEnum.Equal; } } }