/// <summary> /// Parse a template. /// </summary> /// <param name="template">Template to be parsed.</param> /// <exception cref="ArgumentNullException">When <paramref name="template"/> is null.</exception> /// <returns>Template, never null</returns> public static Template Parse(string template) { if (template == null) { throw new ArgumentNullException(nameof(template)); } bool isPositional = true; List <Literal> literals = new List <Literal>(); List <Hole> holes = new List <Hole>(); TemplateEnumerator templateEnumerator = new TemplateEnumerator(template); while (templateEnumerator.MoveNext()) { if (templateEnumerator.Current.Literal.Skip == 0) { literals.Add(templateEnumerator.Current.Literal); } else { literals.Add(templateEnumerator.Current.Literal); holes.Add(templateEnumerator.Current.Hole); if (templateEnumerator.Current.Hole.Index == -1) { isPositional = false; } } } Debug.Assert(holes.Count == literals.Count(x => x.Skip > 0)); return(new Template(template, isPositional, literals, holes)); }
/// <summary> /// Create MessageTemplateParameter from <paramref name="parameters"/> /// </summary> /// <param name="message"></param> /// <param name="parameters"></param> /// <returns></returns> private IList <MessageTemplateParameter> CreateParameters(string message, object[] parameters) { try { List <MessageTemplateParameter> templateParameters = new List <MessageTemplateParameter>(parameters.Length); int holeIndex = 0; TemplateEnumerator templateEnumerator = new TemplateEnumerator(message); while (templateEnumerator.MoveNext()) { if (templateEnumerator.Current.Literal.Skip != 0) { var hole = templateEnumerator.Current.Hole; if (hole.Index == -1) { templateParameters.Add(new MessageTemplateParameter(hole.Name, parameters[holeIndex++], hole.Format, hole.CaptureType)); } else { templateParameters.Add(new MessageTemplateParameter(hole.Name, parameters[hole.Index], hole.Format, hole.CaptureType)); } } } return(templateParameters); } catch (Exception ex) { InternalLogger.Warn(ex, "Error when parsing a message."); return(Internal.ArrayHelper.Empty <MessageTemplateParameter>()); } }
/// <summary> /// Create MessageTemplateParameter from <paramref name="parameters"/> /// </summary> /// <param name="template"></param> /// <param name="parameters"></param> /// <param name="isPositional"></param> /// <param name="isValidTemplate"></param> /// <returns></returns> private static IList <MessageTemplateParameter> ParseMessageTemplate(string template, object[] parameters, out bool isPositional, out bool isValidTemplate) { isPositional = true; isValidTemplate = true; List <MessageTemplateParameter> templateParameters = new List <MessageTemplateParameter>(parameters.Length); try { short holeIndex = 0; TemplateEnumerator templateEnumerator = new TemplateEnumerator(template); while (templateEnumerator.MoveNext()) { if (templateEnumerator.Current.Literal.Skip != 0) { var hole = templateEnumerator.Current.Hole; if (hole.Index != -1 && isPositional) { holeIndex++; var value = GetHoleValueSafe(parameters, hole.Index); templateParameters.Add(new MessageTemplateParameter(hole.Name, value, hole.Format, hole.CaptureType)); } else { if (isPositional) { isPositional = false; if (holeIndex != 0) { // rewind and try again templateEnumerator = new TemplateEnumerator(template); holeIndex = 0; templateParameters.Clear(); continue; } } var value = GetHoleValueSafe(parameters, holeIndex); templateParameters.Add(new MessageTemplateParameter(hole.Name, value, hole.Format, hole.CaptureType)); holeIndex++; } } } if (templateParameters.Count != parameters.Length) { isValidTemplate = false; } return(templateParameters); } catch (Exception ex) { isValidTemplate = false; InternalLogger.Warn(ex, "Error when parsing a message."); return(templateParameters); } }
/// <summary> /// Render a template to a string. /// </summary> /// <param name="template">The template.</param> /// <param name="formatProvider">Culture.</param> /// <param name="parameters">Parameters for the holes.</param> /// <param name="forceTemplateRenderer">Do not fallback to StringBuilder.Format for positional templates.</param> /// <param name="sb">The String Builder destination.</param> /// <param name="messageTemplateParameters">Parameters for the holes.</param> public static void Render(this string template, IFormatProvider formatProvider, object[] parameters, bool forceTemplateRenderer, StringBuilder sb, out IList <MessageTemplateParameter> messageTemplateParameters) { int pos = 0; int holeIndex = 0; messageTemplateParameters = null; TemplateEnumerator holeEnumerator = new TemplateEnumerator(template); while (holeEnumerator.MoveNext()) { var literal = holeEnumerator.Current.Literal; if (holeIndex == 0 && !forceTemplateRenderer && sb.Length == 0 && literal.Skip != 0 && holeEnumerator.Current.Hole.Index != -1) { // Not a template sb.AppendFormat(formatProvider, template, parameters); return; } sb.Append(template, pos, literal.Print); pos += literal.Print; if (literal.Skip == 0) { pos++; } else { pos += literal.Skip; var hole = holeEnumerator.Current.Hole; if (hole.Index != -1) { RenderHole(sb, hole, formatProvider, parameters[hole.Index], true); } else { var holeParameter = parameters[holeIndex]; if (messageTemplateParameters == null) { messageTemplateParameters = new MessageTemplateParameter[parameters.Length]; } messageTemplateParameters[holeIndex++] = new MessageTemplateParameter(hole.Name, holeParameter, hole.Format, hole.CaptureType); RenderHole(sb, hole, formatProvider, holeParameter); } } } if (messageTemplateParameters != null && holeIndex != messageTemplateParameters.Count) { var truncateParameters = new MessageTemplateParameter[holeIndex]; for (int i = 0; i < truncateParameters.Length; ++i) { truncateParameters[i] = messageTemplateParameters[i]; } messageTemplateParameters = truncateParameters; } }
/// <summary> /// Render a template to a string. /// </summary> /// <param name="template">The template.</param> /// <param name="formatProvider">Culture.</param> /// <param name="parameters">Parameters for the holes.</param> /// <param name="forceTemplateRenderer">Do not fallback to StringBuilder.Format for positional templates.</param> /// <param name="sb">The String Builder destination.</param> /// <param name="messageTemplateParameters">Parameters for the holes.</param> public static void Render(this string template, IFormatProvider formatProvider, object[] parameters, bool forceTemplateRenderer, StringBuilder sb, out IList <MessageTemplateParameter> messageTemplateParameters) { int pos = 0; int holeIndex = 0; int holeStartPosition = 0; messageTemplateParameters = null; int originalLength = sb.Length; TemplateEnumerator templateEnumerator = new TemplateEnumerator(template); while (templateEnumerator.MoveNext()) { if (holeIndex == 0 && !forceTemplateRenderer && templateEnumerator.Current.MaybePositionalTemplate && sb.Length == originalLength) { // Not a structured template sb.AppendFormat(formatProvider, template, parameters); return; } var literal = templateEnumerator.Current.Literal; sb.Append(template, pos, literal.Print); pos += literal.Print; if (literal.Skip == 0) { pos++; } else { pos += literal.Skip; var hole = templateEnumerator.Current.Hole; if (hole.Alignment != 0) { holeStartPosition = sb.Length; } if (hole.Index != -1 && messageTemplateParameters == null) { holeIndex++; RenderHole(sb, hole, formatProvider, parameters[hole.Index], true); } else { var holeParameter = parameters[holeIndex]; if (messageTemplateParameters == null) { messageTemplateParameters = new MessageTemplateParameter[parameters.Length]; if (holeIndex != 0) { // rewind and try again templateEnumerator = new TemplateEnumerator(template); sb.Length = originalLength; holeIndex = 0; pos = 0; continue; } } messageTemplateParameters[holeIndex++] = new MessageTemplateParameter(hole.Name, holeParameter, hole.Format, hole.CaptureType); RenderHole(sb, hole, formatProvider, holeParameter); } if (hole.Alignment != 0) { RenderPadding(sb, hole.Alignment, holeStartPosition); } } } if (messageTemplateParameters != null && holeIndex != messageTemplateParameters.Count) { var truncateParameters = new MessageTemplateParameter[holeIndex]; for (int i = 0; i < truncateParameters.Length; ++i) { truncateParameters[i] = messageTemplateParameters[i]; } messageTemplateParameters = truncateParameters; } }