/// <summary> /// Parse a string to long. String must not start with '0x'. /// Long can accomodate only 16 meaningful hex-decimals. /// </summary> /// <param name="str">string of hexadecimal characters [0-9a-fA-F]</param> /// <param name="value">result value</param> /// <returns>false if contains non-hex characters, or if number of meaningful hexnumbers is over 24.</returns> public static bool TryParseToULong(String str, out ulong value) { HexEnumerator stream = new HexEnumerator(str.GetEnumerator()); // Calculate hex character count int count = 0; // Calculate meaningful number characters int meaningfulDigits = 0; for (int i = 0; i < 999 && stream.MoveNext(); i++) { // Got non-hex value. if (stream.Current < 0) { value = default(ulong); return(false); } // Start calculating after first non-zero. if (meaningfulDigits > 0 || stream.Current != 0) { meaningfulDigits++; } // Total character count. count++; } // Found non-zero value. if (stream.Error) { value = default(ulong); return(false); } // Restart stream.Reset(); // Too many characters if (meaningfulDigits >= 17) { value = default(ulong); return(false); } value = 0UL; while (count > 16 && stream.MoveNext()) { // long can fit 64bit value, any non-zero over 64bits cannot be parsed. if (stream.Current != 0) { value = default(ulong); return(false); } count--; } while (count > 0 && stream.MoveNext()) { ulong hex = (ulong)stream.Current; value = value << 4 | hex; count--; } return(true); }
/// <summary> /// Parse a string to uint. String must not start with '0x'. /// UInt can accomodate only 8 meaningful hex-decimals. /// </summary> /// <param name="str">string of hexadecimal characters [0-9a-fA-F]</param> /// <param name="startIndex">character start index</param> /// <returns>value</returns> /// <exception cref="System.FormatException"></exception> public static uint ToUInt(String str, int startIndex = 0) { CharEnumerator enumr = str.GetEnumerator(); for (int i = 0; i < startIndex; i++) { if (!enumr.MoveNext()) { throw new FormatException("End of stream before startIndex."); } } HexEnumerator stream = new HexEnumerator(enumr); // Calculate hex character count int count = 0; // Calculate meaningful number characters int meaningfulDigits = 0; for (int i = 0; i < 999 && stream.MoveNext(); i++) { // Got non-hex value. if (stream.Current < 0) { throw new System.FormatException("Unexpected character in hex stream."); } // Start calculating after first non-zero. if (meaningfulDigits > 0 || stream.Current != 0) { meaningfulDigits++; } // Total character count. count++; } // Found non-zero value. if (stream.Error) { if (stream.Current < 0) { throw new System.FormatException("Unexpected character in hex stream."); } } // Restart stream.Reset(); for (int i = 0; i < startIndex; i++) { enumr.MoveNext(); } // Too many characters if (meaningfulDigits >= 9) { throw new System.FormatException("Hex value too large to fit into decimal."); } uint value = 0U; while (count > 8 && stream.MoveNext()) { // long can fit 64bit value, any non-zero over 64bits cannot be parsed. if (stream.Current != 0) { throw new System.FormatException("Hex value too large to fit into decimal."); } count--; } while (count > 0 && stream.MoveNext()) { uint hex = (uint)stream.Current; value = value << 4 | hex; count--; } return(value); }
/// <summary> /// Try to parse a string to decimal number. /// String must not start with '0x'. /// Decimal can accomodate only 24 meaningful hexnumbers. /// Although, the string can precede any number of zeroes, e.g. "0000000000000000000000000000000000000000000000000000000000000123123abff". /// </summary> /// <param name="str">string of hexadecimal characters [0-9a-fA-F]</param> /// <param name="value">result value</param> /// <returns>false if contains non-hex characters, or if number of meaningful hexnumbers is over 24.</returns> public static bool TryParseToDecimal(String str, out decimal value) { HexEnumerator stream = new HexEnumerator(str.GetEnumerator()); // Calculate hex character count int count = 0; // Calculate meaningful number characters int meaningfulDigits = 0; for (int i = 0; i < 999 && stream.MoveNext(); i++) { // Got non-hex value. if (stream.Current < 0) { value = 0; return(false); } // Start calculating after first non-zero. if (meaningfulDigits > 0 || stream.Current != 0) { meaningfulDigits++; } // Total character count. count++; } // Found non-zero value. if (stream.Error) { value = 0; return(false); } // Restart stream.Reset(); // Too many characters if (meaningfulDigits >= 25) { value = 0; return(false); } int lo = 0, mid = 0, hi = 0; while (count > 24 && stream.MoveNext()) { // decimal can fit 96bit value, any non-zero over 96bits cannot be parsed. if (stream.Current != 0) { value = 0; return(false); } count--; } while (count > 16 && stream.MoveNext()) { hi = (hi << 4) | stream.Current; count--; } while (count > 8 && stream.MoveNext()) { mid = (mid << 4) | stream.Current; count--; } while (count > 0 && stream.MoveNext()) { lo = (lo << 4) | stream.Current; count--; } value = new decimal(lo, mid, hi, false, 0); return(!stream.Error); }