namespace HeuristicLab.Problems.ProgramSynthesis { using System; using System.Diagnostics; using System.Globalization; using System.Text; public static class StringBuilderExtension { // These digits are here in a static array to support hex with simple, easily-understandable code. // Since A-Z don't sit next to 0-9 in the ascii table. private static readonly char[] MsDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; //private static readonly ulong MsDefaultDecimalPlaces = 5; //< Matches standard .NET formatting dp's private const char MsDefaultPadChar = '0'; //! Convert a given unsigned integer value to a string and concatenate onto the stringbuilder. Any base value allowed. public static StringBuilder Concat( this StringBuilder stringBuilder, ulong ulongVal, ulong padAmount, char padChar, ulong baseVal) { Debug.Assert((baseVal > 0) && (baseVal <= 16)); // Calculate length of integer when written out ulong length = 0; var lengthCalc = ulongVal; do { lengthCalc /= baseVal; length++; } while (lengthCalc > 0); // Pad out space for writing. stringBuilder.Append(padChar, (int)Math.Max(padAmount, length)); var strpos = stringBuilder.Length; // We're writing backwards, one character at a time. while (length > 0) { strpos--; // Lookup from static char array, to cover hex values too stringBuilder[strpos] = MsDigits[ulongVal % baseVal]; ulongVal /= baseVal; length--; } return stringBuilder; } //! Convert a given unsigned integer value to a string and concatenate onto the stringbuilder. Assume no padding and base ten. public static StringBuilder Concat(this StringBuilder stringBuilder, ulong ulongVal) { stringBuilder.Concat(ulongVal, 0, MsDefaultPadChar, 10); return stringBuilder; } //! Convert a given unsigned integer value to a string and concatenate onto the stringbuilder. Assume base ten. public static StringBuilder Concat(this StringBuilder stringBuilder, ulong ulongVal, ulong padAmount) { stringBuilder.Concat(ulongVal, padAmount, MsDefaultPadChar, 10); return stringBuilder; } //! Convert a given unsigned integer value to a string and concatenate onto the stringbuilder. Assume base ten. public static StringBuilder Concat( this StringBuilder stringBuilder, ulong ulongVal, ulong padAmount, char padChar) { stringBuilder.Concat(ulongVal, padAmount, padChar, 10); return stringBuilder; } //! Convert a given signed integer value to a string and concatenate onto the stringbuilder. Any base value allowed. public static StringBuilder Concat( this StringBuilder stringBuilder, long longVal, ulong padAmount, char padChar, ulong baseVal) { Debug.Assert((baseVal > 0) && (baseVal <= 16)); // Deal with negative numbers if (longVal < 0) { stringBuilder.Append('-'); var ulongVal = ulong.MaxValue - (ulong)longVal + 1; //< This is to deal with Int64.MinValue stringBuilder.Concat(ulongVal, padAmount, padChar, baseVal); } else { stringBuilder.Concat((ulong)longVal, padAmount, padChar, baseVal); } return stringBuilder; } //! Convert a given signed integer value to a string and concatenate onto the stringbuilder. Assume no padding and base ten. public static StringBuilder Concat(this StringBuilder stringBuilder, long longVal) { stringBuilder.Concat(longVal, 0, MsDefaultPadChar, 10); return stringBuilder; } //! Convert a given signed integer value to a string and concatenate onto the stringbuilder. Assume base ten. public static StringBuilder Concat(this StringBuilder stringBuilder, long longVal, ulong padAmount) { stringBuilder.Concat(longVal, padAmount, MsDefaultPadChar, 10); return stringBuilder; } //! Convert a given signed integer value to a string and concatenate onto the stringbuilder. Assume base ten. public static StringBuilder Concat( this StringBuilder stringBuilder, long longVal, ulong padAmount, char padChar) { stringBuilder.Concat(longVal, padAmount, padChar, 10); return stringBuilder; } //! Convert a given signed integer value to a string and concatenate onto the stringbuilder. Any base value allowed. public static StringBuilder Concat( this StringBuilder stringBuilder, int intVal, ulong padAmount, char padChar, ulong baseVal) { Debug.Assert((baseVal > 0) && (baseVal <= 16)); // Deal with negative numbers if (intVal < 0) { stringBuilder.Append('-'); var ulongVal = ulong.MaxValue - (ulong)intVal + 1; //< This is to deal with Int32.MinValue stringBuilder.Concat(ulongVal, padAmount, padChar, baseVal); } else { stringBuilder.Concat((ulong)intVal, padAmount, padChar, baseVal); } return stringBuilder; } //! Convert a given signed integer value to a string and concatenate onto the stringbuilder. Assume no padding and base ten. public static StringBuilder Concat(this StringBuilder stringBuilder, int intVal) { stringBuilder.Concat(intVal, 0, MsDefaultPadChar, 10); return stringBuilder; } //! Convert a given signed integer value to a string and concatenate onto the stringbuilder. Assume base ten. public static StringBuilder Concat(this StringBuilder stringBuilder, int intVal, ulong padAmount) { stringBuilder.Concat(intVal, padAmount, MsDefaultPadChar, 10); return stringBuilder; } //! Convert a given signed integer value to a string and concatenate onto the stringbuilder. Assume base ten. public static StringBuilder Concat(this StringBuilder stringBuilder, int intVal, ulong padAmount, char padChar) { stringBuilder.Concat(intVal, padAmount, padChar, 10); return stringBuilder; } //! Convert a given double value to a string and concatenate onto the stringbuilder public static StringBuilder Concat( this StringBuilder stringBuilder, double doubleVal, uint decimalPlaces, uint padAmount, char padChar, CultureInfo culturInfo = null) { culturInfo = culturInfo ?? CultureInfo.CurrentCulture; if (decimalPlaces == 0) { // No decimal places, just round up and print it as an int // Agh, Math.Floor() just works on doubles/decimals. Don't want to cast! Let's do this the old-fashioned way. int intVal; if (doubleVal >= 0.0d) intVal = (int)(doubleVal + 0.5d); else intVal = (int)(doubleVal - 0.5d); stringBuilder.Concat(intVal, padAmount, padChar, 10); } else { var intPart = (int)doubleVal; // First part is easy, just cast to an integer stringBuilder.Concat(intPart, padAmount, padChar, 10); // Decimal point var numberDecimalSeparator = Convert.ToChar(culturInfo.NumberFormat.NumberDecimalSeparator); stringBuilder.Append(numberDecimalSeparator); // Work out remainder we need to print after the d.p. var remainder = Math.Abs(doubleVal - intPart); // Multiply up to become an int that we can print do { remainder *= 10; decimalPlaces--; } while (remainder > (int)remainder && decimalPlaces > 0); // Round up. It's guaranteed to be a positive number, so no extra work required here. remainder += 0.5d; // All done, print that as an int! stringBuilder.Concat((ulong)remainder, 0, '0', 10); } return stringBuilder; } //! Convert a given double value to a string and concatenate onto the stringbuilder. Assumes five decimal places, and no padding. public static StringBuilder Concat(this StringBuilder stringBuilder, double doubleVal, CultureInfo culturInfo = null) { culturInfo = culturInfo ?? CultureInfo.CurrentCulture; stringBuilder.Concat(doubleVal, (uint)culturInfo.NumberFormat.NumberDecimalDigits, 0, MsDefaultPadChar, culturInfo); return stringBuilder; } //! Convert a given double value to a string and concatenate onto the stringbuilder. Assumes no padding. public static StringBuilder Concat(this StringBuilder stringBuilder, double doubleVal, uint decimalPlaces, CultureInfo culturInfo = null) { stringBuilder.Concat(doubleVal, decimalPlaces, 0, MsDefaultPadChar, culturInfo); return stringBuilder; } //! Convert a given double value to a string and concatenate onto the stringbuilder. public static StringBuilder Concat( this StringBuilder stringBuilder, double doubleVal, uint decimalPlaces, uint padAmount, CultureInfo culturInfo = null) { stringBuilder.Concat(doubleVal, decimalPlaces, padAmount, MsDefaultPadChar, culturInfo); return stringBuilder; } } }