private string IntPrecision(string str, FormatStringPart part) { if (str.Equals("0") && part.precision == 0) { return(""); } else if (str.Length < part.precision) { return(new string('0', (part.precision ?? 1) - str.Length) + str); } else { return(str); } }
/// <summary> /// Creates a new formatter with or without the default formatters (used by the printf functions). /// </summary> /// <param name="format">The format string</param> /// <param name="useDefaultFormatters">Load the default formatters or not</param> public FormatObject(string format, bool useDefaultFormatters) { //State machine to parse the format string //Surprisingly, the regexp version is not really shorter: //Parsing the string is easier, but extracting the results is longer List <FormatStringPart> parts = new List <FormatStringPart>(); List <string> staticParts = new List <string>(); StringBuilder staticPart = new StringBuilder(); //Static mode: not in a % block, Format mode: in a % block ParseMode mode = ParseMode.Static; FormatStringPart part = null; FormatStep step = FormatStep.Flags; StringBuilder tempBuffer = null; for (int i = 0; i < format.Length; ++i) { char c = format[i]; if (mode == ParseMode.Static) { //If if (c == '%') { mode = ParseMode.Format; step = FormatStep.Flags; } else { staticPart.Append(c); } } else { //For the terminology (flags, specifiers etc.) look up any printf documentation. switch (step) { case FormatStep.Flags: if (c == '%') { staticPart.Append('%'); mode = ParseMode.Static; continue; } if (part == null) { part = new FormatStringPart(); } if (c == '-') { part.LeftAlign = true; } else if (c == '+') { part.ForcePlus = true; } else if (c == ' ') { part.BlankIfPlus = true; } else if (c == '#') { part.HashMark = true; } else if (c == '0') { part.PadWithZero = true; } else { step = FormatStep.Width; goto case FormatStep.Width; } break; case FormatStep.Width: if (tempBuffer != null) { if (c >= '0' && c <= '9') { tempBuffer.Append(c); } else { part.width = int.Parse(tempBuffer.ToString()); tempBuffer = null; step = FormatStep.PrecisionStart; goto case FormatStep.PrecisionStart; } } else if (c == '*') { part.width = -1; argCount++; } else if (c >= '0' && c <= '9') { tempBuffer = new StringBuilder(); tempBuffer.Append(c); } else { step = FormatStep.PrecisionStart; goto case FormatStep.PrecisionStart; } break; case FormatStep.PrecisionStart: if (c != '.') { step = FormatStep.Length; goto case FormatStep.Length; } else { step = FormatStep.Precision; } break; case FormatStep.Precision: if (tempBuffer != null) { if (c >= '0' && c <= '9') { tempBuffer.Append(c); } else { part.precision = int.Parse(tempBuffer.ToString()); tempBuffer = null; step = FormatStep.Length; goto case FormatStep.Length; } } else if (c == '*') { part.precision = -1; argCount++; } else if (c >= '0' && c <= '9') { tempBuffer = new StringBuilder(); tempBuffer.Append(c); } else { part.precision = 0; step = FormatStep.Length; goto case FormatStep.Length; } break; case FormatStep.Length: if ("hlL".IndexOf(c) != -1) { part.length = c; step = FormatStep.Specifier; } else { step = FormatStep.Specifier; goto case FormatStep.Specifier; } break; case FormatStep.Specifier: argCount++; part.specifier = c; staticParts.Add(staticPart.ToString()); staticPart = new StringBuilder(); parts.Add(part); part = null; mode = ParseMode.Static; break; } } } if (mode == ParseMode.Format) { throw new ArgumentException("Invalid format string", "format"); } staticParts.Add(staticPart.ToString()); this.parts = parts.ToArray(); this.staticParts = staticParts.ToArray(); if (useDefaultFormatters) { LoadDefaultFormatters(); } }