internal static LayoutRenderer[] CompileLayout(ConfigurationItemFactory configurationItemFactory, SimpleStringReader sr, bool isNested, out string text) { var result = new List<LayoutRenderer>(); var literalBuf = new StringBuilder(); int ch; int p0 = sr.Position; while ((ch = sr.Peek()) != -1) { if (isNested && (ch == '}' || ch == ':')) { break; } sr.Read(); if (ch == '$' && sr.Peek() == '{') { if (literalBuf.Length > 0) { result.Add(new LiteralLayoutRenderer(literalBuf.ToString())); literalBuf.Length = 0; } LayoutRenderer newLayoutRenderer = ParseLayoutRenderer(configurationItemFactory, sr); if (CanBeConvertedToLiteral(newLayoutRenderer)) { newLayoutRenderer = ConvertToLiteral(newLayoutRenderer); } // layout renderer result.Add(newLayoutRenderer); } else { literalBuf.Append((char)ch); } } if (literalBuf.Length > 0) { result.Add(new LiteralLayoutRenderer(literalBuf.ToString())); literalBuf.Length = 0; } int p1 = sr.Position; MergeLiterals(result); text = sr.Substring(p0, p1); return result.ToArray(); }
/// <summary> /// Initializes a new instance of the <see cref="ConditionTokenizer"/> class. /// </summary> /// <param name="stringReader">The string reader.</param> public ConditionTokenizer(SimpleStringReader stringReader) { this.stringReader = stringReader; this.TokenType = ConditionTokenType.BeginningOfInput; this.GetNextToken(); }
private static LayoutRenderer ParseLayoutRenderer(ConfigurationItemFactory configurationItemFactory, SimpleStringReader sr) { int ch = sr.Read(); Debug.Assert(ch == '{', "'{' expected in layout specification"); string name = ParseLayoutRendererName(sr); LayoutRenderer lr = configurationItemFactory.LayoutRenderers.CreateInstance(name); var wrappers = new Dictionary<Type, LayoutRenderer>(); var orderedWrappers = new List<LayoutRenderer>(); ch = sr.Read(); while (ch != -1 && ch != '}') { string parameterName = ParseParameterName(sr).Trim(); if (sr.Peek() == '=') { sr.Read(); // skip the '=' PropertyInfo pi; LayoutRenderer parameterTarget = lr; if (!PropertyHelper.TryGetPropertyInfo(lr, parameterName, out pi)) { Type wrapperType; if (configurationItemFactory.AmbientProperties.TryGetDefinition(parameterName, out wrapperType)) { LayoutRenderer wrapperRenderer; if (!wrappers.TryGetValue(wrapperType, out wrapperRenderer)) { wrapperRenderer = configurationItemFactory.AmbientProperties.CreateInstance(parameterName); wrappers[wrapperType] = wrapperRenderer; orderedWrappers.Add(wrapperRenderer); } if (!PropertyHelper.TryGetPropertyInfo(wrapperRenderer, parameterName, out pi)) { pi = null; } else { parameterTarget = wrapperRenderer; } } } if (pi == null) { ParseParameterValue(sr); } else { if (typeof(Layout).IsAssignableFrom(pi.PropertyType)) { var nestedLayout = new SimpleLayout(); string txt; LayoutRenderer[] renderers = CompileLayout(configurationItemFactory, sr, true, out txt); nestedLayout.SetRenderers(renderers, txt); pi.SetValue(parameterTarget, nestedLayout, null); } else if (typeof(ConditionExpression).IsAssignableFrom(pi.PropertyType)) { var conditionExpression = ConditionParser.ParseExpression(sr, configurationItemFactory); pi.SetValue(parameterTarget, conditionExpression, null); } else { string value = ParseParameterValue(sr); PropertyHelper.SetPropertyFromString(parameterTarget, parameterName, value, configurationItemFactory); } } } else { // what we've just read is not a parameterName, but a value // assign it to a default property (denoted by empty string) PropertyInfo pi; if (PropertyHelper.TryGetPropertyInfo(lr, string.Empty, out pi)) { if (typeof(SimpleLayout) == pi.PropertyType) { pi.SetValue(lr, new SimpleLayout(parameterName), null); } else { string value = parameterName; PropertyHelper.SetPropertyFromString(lr, pi.Name, value, configurationItemFactory); } } else { InternalLogger.Warn("{0} has no default property", lr.GetType().FullName); } } ch = sr.Read(); } lr = ApplyWrappers(configurationItemFactory, lr, orderedWrappers); return lr; }
private static string ParseParameterValue(SimpleStringReader sr) { int ch; var nameBuf = new StringBuilder(); while ((ch = sr.Peek()) != -1) { if (ch == ':' || ch == '}') { break; } // Code in this condition was replaced // to support escape codes e.g. '\r' '\n' '\u003a', // which can not be used directly as they are used as tokens by the parser // All escape codes listed in the following link were included // in addition to "\{", "\}", "\:" which are NLog specific: // http://blogs.msdn.com/b/csharpfaq/archive/2004/03/12/what-character-escape-sequences-are-available.aspx if (ch == '\\') { // skip the backslash sr.Read(); var nextChar = (char)sr.Peek(); switch (nextChar) { case ':': sr.Read(); nameBuf.Append(':'); break; case '{': sr.Read(); nameBuf.Append('{'); break; case '}': sr.Read(); nameBuf.Append('}'); break; case '\'': sr.Read(); nameBuf.Append('\''); break; case '"': sr.Read(); nameBuf.Append('"'); break; case '\\': sr.Read(); nameBuf.Append('\\'); break; case '0': sr.Read(); nameBuf.Append('\0'); break; case 'a': sr.Read(); nameBuf.Append('\a'); break; case 'b': sr.Read(); nameBuf.Append('\b'); break; case 'f': sr.Read(); nameBuf.Append('\f'); break; case 'n': sr.Read(); nameBuf.Append('\n'); break; case 'r': sr.Read(); nameBuf.Append('\r'); break; case 't': sr.Read(); nameBuf.Append('\t'); break; case 'u': sr.Read(); var uChar = GetUnicode(sr, 4); // 4 digits nameBuf.Append(uChar); break; case 'U': sr.Read(); var UChar = GetUnicode(sr, 8); // 8 digits nameBuf.Append(UChar); break; case 'x': sr.Read(); var xChar = GetUnicode(sr, 4); // 1-4 digits nameBuf.Append(xChar); break; case 'v': sr.Read(); nameBuf.Append('\v'); break; } continue; } nameBuf.Append((char)ch); sr.Read(); } return nameBuf.ToString(); }
private static char GetUnicode(SimpleStringReader sr, int maxDigits) { int code = 0; for (int cnt = 0; cnt < maxDigits; cnt++) { var digitCode = sr.Peek(); if (digitCode >= (int)'0' && digitCode <= (int)'9') digitCode = digitCode - (int)'0'; else if (digitCode >= (int)'a' && digitCode <= (int)'f') digitCode = digitCode - (int)'a' + 10; else if (digitCode >= (int)'A' && digitCode <= (int)'F') digitCode = digitCode - (int)'A' + 10; else break; sr.Read(); code = code * 16 + digitCode; } return (char)code; }
private static string ParseLayoutRendererName(SimpleStringReader sr) { int ch; var nameBuf = new StringBuilder(); while ((ch = sr.Peek()) != -1) { if (ch == ':' || ch == '}') { break; } nameBuf.Append((char)ch); sr.Read(); } return nameBuf.ToString(); }
private static string ParseParameterName(SimpleStringReader sr) { int ch; int nestLevel = 0; var nameBuf = new StringBuilder(); while ((ch = sr.Peek()) != -1) { if ((ch == '=' || ch == '}' || ch == ':') && nestLevel == 0) { break; } if (ch == '$') { sr.Read(); nameBuf.Append('$'); if (sr.Peek() == '{') { nameBuf.Append('{'); nestLevel++; sr.Read(); } continue; } if (ch == '}') { nestLevel--; } if (ch == '\\') { // skip the backslash sr.Read(); // append next character nameBuf.Append((char)sr.Read()); continue; } nameBuf.Append((char)ch); sr.Read(); } return nameBuf.ToString(); }
/// <summary> /// Initializes a new instance of the <see cref="ConditionParser"/> class. /// </summary> /// <param name="stringReader">The string reader.</param> /// <param name="configurationItemFactory">Instance of <see cref="ConfigurationItemFactory"/> used to resolve references to condition methods and layout renderers.</param> private ConditionParser(SimpleStringReader stringReader, ConfigurationItemFactory configurationItemFactory) { this.configurationItemFactory = configurationItemFactory; this.tokenizer = new ConditionTokenizer(stringReader); }
/// <summary> /// Parses the specified condition string and turns it into /// <see cref="ConditionExpression"/> tree. /// </summary> /// <param name="stringReader">The string reader.</param> /// <param name="configurationItemFactories">Instance of <see cref="ConfigurationItemFactory"/> used to resolve references to condition methods and layout renderers.</param> /// <returns> /// The root of the expression syntax tree which can be used to get the value of the condition in a specified context. /// </returns> internal static ConditionExpression ParseExpression(SimpleStringReader stringReader, ConfigurationItemFactory configurationItemFactories) { var parser = new ConditionParser(stringReader, configurationItemFactories); ConditionExpression expression = parser.ParseExpression(); return expression; }
internal static LayoutRenderer[] CompileLayout(ConfigurationItemFactory configurationItemFactory, SimpleStringReader sr, bool isNested, out string text) { var result = new List<LayoutRenderer>(); var literalBuf = new StringBuilder(); int ch; int p0 = sr.Position; while ((ch = sr.Peek()) != -1) { if (isNested) { //possible escape char `\` if (ch == '\\') { sr.Read(); var nextChar = sr.Peek(); //escape chars if (nextChar == '}' || nextChar == ':') { //read next char and append sr.Read(); literalBuf.Append((char)nextChar); } else { //dont treat \ as escape char and just read it literalBuf.Append('\\'); } continue; } if (ch == '}' || ch == ':') { //end of innerlayout. // `}` is when double nested inner layout. // `:` when single nested layout break; } } sr.Read(); //detect `${` (new layout-renderer) if (ch == '$' && sr.Peek() == '{') { //stach already found layout-renderer. if (literalBuf.Length > 0) { result.Add(new LiteralLayoutRenderer(literalBuf.ToString())); literalBuf.Length = 0; } LayoutRenderer newLayoutRenderer = ParseLayoutRenderer(configurationItemFactory, sr); if (CanBeConvertedToLiteral(newLayoutRenderer)) { newLayoutRenderer = ConvertToLiteral(newLayoutRenderer); } // layout renderer result.Add(newLayoutRenderer); } else { literalBuf.Append((char)ch); } } if (literalBuf.Length > 0) { result.Add(new LiteralLayoutRenderer(literalBuf.ToString())); literalBuf.Length = 0; } int p1 = sr.Position; MergeLiterals(result); text = sr.Substring(p0, p1); return result.ToArray(); }
internal static LayoutRenderer[] CompileLayout(ConfigurationItemFactory configurationItemFactory, SimpleStringReader sr, bool isNested, out string text) { var result = new List<LayoutRenderer>(); var literalBuf = new StringBuilder(); int ch; int p0 = sr.Position; while ((ch = sr.Peek()) != -1) { if (isNested) { //escape char? Then allow }, : and \ if (ch == '\\') { sr.Read(); var nextChar = sr.Peek(); //char that can be escaped. if (nextChar == '}' || nextChar == ':' || nextChar == '\\') { //read next char and append sr.Read(); literalBuf.Append((char)nextChar); } else { //dont read next char and just append the slash literalBuf.Append('\\'); } continue; } if (ch == '}' || ch == ':') { break; } } sr.Read(); if (ch == '$' && sr.Peek() == '{') { if (literalBuf.Length > 0) { result.Add(new LiteralLayoutRenderer(literalBuf.ToString())); literalBuf.Length = 0; } LayoutRenderer newLayoutRenderer = ParseLayoutRenderer(configurationItemFactory, sr); if (CanBeConvertedToLiteral(newLayoutRenderer)) { newLayoutRenderer = ConvertToLiteral(newLayoutRenderer); } // layout renderer result.Add(newLayoutRenderer); } else { literalBuf.Append((char)ch); } } if (literalBuf.Length > 0) { result.Add(new LiteralLayoutRenderer(literalBuf.ToString())); literalBuf.Length = 0; } int p1 = sr.Position; MergeLiterals(result); text = sr.Substring(p0, p1); return result.ToArray(); }
private static string ParseParameterValue(SimpleStringReader sr) { int ch; var nameBuf = new StringBuilder(); while ((ch = sr.Peek()) != -1) { if (ch == ':' || ch == '}') { break; } if (ch == '\\') { // skip the backslash sr.Read(); // append next character nameBuf.Append((char)sr.Read()); continue; } nameBuf.Append((char)ch); sr.Read(); } return nameBuf.ToString(); }