/// <summary> /// Creates a parser to parse configuration path. /// </summary> /// <param name="configPath">The file to parse</param> public ServerConfigurationParser(string configPath) { this.configPath = configPath; DefinedSections["__global__"] = new ConfigSection(); DefinedConstants["FHTTPVERSION"] = new ConfigVariable() { DataType = ConfigVariableDataType.Integer, Name = "FHTTPVERSION", Value = 1 }; }
/// <summary> /// Checks if a given variable is given a null value. /// </summary> /// <param name="path">The path to use.</param> /// <returns></returns> public bool IsNull(string path) { ConfigVariable v = GetVariable(path); if ((v == null) || (v.DataType != ConfigVariableDataType.Null)) { return(false); } return(v.Value.GetType().IsAssignableFrom(typeof(ConfigNullValue))); }
/// <summary> /// Returns a boolean from the specified path. Default value is false if not found. /// </summary> /// <param name="path">The path to use.</param> /// <returns></returns> public bool GetBool(string path) { ConfigVariable v = GetVariable(path); if ((v == null) || (v.DataType != ConfigVariableDataType.Boolean)) { return(false); } return((bool)v.Value); }
/// <summary> /// Returns a string from the specified path. /// </summary> /// <param name="path">The path to use.</param> /// <returns></returns> public string GetString(string path) { ConfigVariable v = GetVariable(path); if ((v == null) || (v.DataType != ConfigVariableDataType.String)) { return(""); } return((string)v.Value); }
/// <summary> /// Returns an integer from the specified path. /// </summary> /// <param name="path">The path to use.</param> /// <returns></returns> public int GetInteger(string path) { ConfigVariable v = GetVariable(path); if ((v == null) || (v.DataType != ConfigVariableDataType.Integer)) { return(-1); } return((int)v.Value); }
/// <summary> /// Defines a constant variable. /// </summary> /// <param name="name">The name of the constant to define</param> /// <param name="dataType">The data type to use</param> /// <param name="value">The value of the constant</param> /// <exception cref="ConstantAlreadyDefinedException"></exception> public void DefineConstant(string name, ConfigVariableDataType dataType, object value, int trackingLineNumber = -1) { CheckIdentifier(name, trackingLineNumber); if (DefinedConstants.ContainsKey(name)) { throw new ConstantAlreadyDefinedException(name, trackingLineNumber); } DefinedConstants[name] = new ConfigVariable() { Name = name, DataType = dataType, Value = value }; }
/// <summary> /// Adds a variable to the specified section. /// </summary> /// <param name="variable">The variable object to add.</param> /// <param name="section">The section to add the variable to (leave empty for global section).</param> /// <exception cref="SectionNotFoundException"></exception> /// <exception cref="InvalidIdentifierNameException"></exception> public void AddVariable(ConfigVariable variable, string section = "") { CheckIdentifier(variable.Name); if (section == "") { DefinedSections["__global__"].Variables[variable.Name] = variable; } else { if (!DefinedSections.ContainsKey("__global__." + section)) { throw new SectionNotFoundException(section); } DefinedSections["__global__." + section].Variables[variable.Name] = variable; } }
/// <summary> /// Defines a variable with the specified name and value. If the variable already exists, it will be overwritten. /// </summary> /// <param name="name">The name of the variable.</param> /// <param name="value">The value of the variable. Only primitive types are supported, others are converted using ToString().</param> /// <param name="section">The section to place the variable in. Must be a valid section or a SectionNotFoundException will be thrown.</param> /// <exception cref="SectionNotFoundException"></exception> public void DefineVariable(string name, object value, string section = "") { ConfigVariable cv = new ConfigVariable() { Name = name }; var valueType = value.GetType(); if (valueType.IsAssignableFrom(typeof(string))) { cv.DataType = ConfigVariableDataType.String; } else if (valueType.IsAssignableFrom(typeof(int))) { cv.DataType = ConfigVariableDataType.Integer; } else if (valueType.IsAssignableFrom(typeof(bool))) { cv.DataType = ConfigVariableDataType.Boolean; } else if (valueType == null) { cv.DataType = ConfigVariableDataType.Null; } else { cv.DataType = ConfigVariableDataType.Unknown; } switch (cv.DataType) { default: cv.Value = value; break; case ConfigVariableDataType.Null: cv.Value = new ConfigNullValue(); break; case ConfigVariableDataType.Unknown: cv.DataType = ConfigVariableDataType.String; cv.Value = value.ToString(); break; } AddVariable(cv, section); }
/// <summary> /// Parse and evaluate text. /// </summary> /// <param name="data">The lines to parse</param> /// <param name="ctx">The context to run under (global is __global__)</param> private void _Parse(string[] data, string ctx = "__global__") { foreach (var rl in data) { lineNumber++; var ln = rl.Trim(); if (ln == "") { continue; } else if (ln.StartsWith("//")) { continue; } foreach (var c in DefinedConstants) { if (currentReadMode != ConfigReadMode.MultiLineComment) { ln = ln.Replace("$" + c.Key + "$", c.Value.Value.ToString()); } } foreach (var c in DefinedSections[ctx].Variables) { if (currentReadMode != ConfigReadMode.MultiLineComment) { ln = ln.Replace("$" + c.Key + "$", c.Value.Value.ToString()); } } switch (currentReadMode) { default: //What read mode is this?! break; case ConfigReadMode.Normal: if (ln.StartsWith("/*")) { currentReadMode = ConfigReadMode.MultiLineComment; continue; } else if (ln.StartsWith("const ")) { // DEBUG only Console.WriteLine("Found const, lets parse it"); var v = ParseVar(ln.Substring(6).Trim()); DefineConstant(v.Name, v.DataType, v.Value, lineNumber); } else if (ln.StartsWith("section ")) { string sname = ln.Split(' ')[1].Trim(); if (sname.Contains(".")) { throw new InvalidIdentifierNameException(lineNumber, sname); } currentReadMode = ConfigReadMode.SectionDef; currentSName = sname; blockDepth = 1; continue; } else if (ln.StartsWith("include ")) { if (!ln.Contains("\"")) { continue; } string fileName = ln.Split('"')[1].Trim(); if (!Path.IsPathRooted(fileName)) { fileName = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(configPath)), fileName); } if (!File.Exists(fileName)) { throw new IncludeNotFoundException(fileName, lineNumber); } var p = new ServerConfigurationParser(fileName); p.DefinedConstants = DefinedConstants; p.DefinedSections = DefinedSections; p.Parse(ctx); } else if (ln.Contains(" ")) //Probably a property { ConfigVariable var = ParseVar(ln.Trim()); DefinedSections[ctx].Variables[var.Name] = var; } break; case ConfigReadMode.SectionDef: if (ln.EndsWith("{")) { blockDepth++; } else if (ln.EndsWith("}")) { blockDepth--; } if (blockDepth == 0) //Finished searching section { var ctxedName = ctx + "." + currentSName; DefinedSections[ctxedName] = new ConfigSection(); currentReadMode = ConfigReadMode.Normal; var p = new ServerConfigurationParser(null); p.DefinedConstants = DefinedConstants; p.DefinedSections = DefinedSections; p.lineNumber = lineNumber; p.configPath = configPath; p._Parse(currentSectionBody.ToArray(), ctxedName); currentSName = ""; currentSectionBody.Clear(); continue; } currentSectionBody.Add(ln); break; case ConfigReadMode.MultiLineComment: if (ln.EndsWith("*/")) { currentReadMode = ConfigReadMode.Normal; continue; } break; } } }