private HoconArray ParsePlusEqualAssignArray(IHoconElement owner) { // sanity check if (_tokens.Current.Type != TokenType.PlusEqualAssign) { throw HoconParserException.Create(_tokens.Current, Path, "Failed to parse Hocon field with += operator. " + $"Expected {TokenType.PlusEqualAssign}, found {{_tokens.Current.Type}} instead."); } var currentArray = new HoconArray(owner); // consume += operator token ConsumeWhitelines(); switch (_tokens.Current.Type) { case TokenType.Include: currentArray.Add(ParseInclude(currentArray)); break; case TokenType.StartOfArray: // Array inside of arrays are parsed as values because it can be value concatenated with another array. currentArray.Add(ParseValue(currentArray)); break; case TokenType.StartOfObject: currentArray.Add(ParseObject(currentArray)); break; case TokenType.LiteralValue: if (_tokens.Current.IsNonSignificant()) { ConsumeWhitelines(); } if (_tokens.Current.Type != TokenType.LiteralValue) { break; } currentArray.Add(ParseValue(currentArray)); break; case TokenType.SubstituteOptional: case TokenType.SubstituteRequired: var pointerPath = HoconPath.Parse(_tokens.Current.Value); HoconSubstitution sub = new HoconSubstitution(currentArray, pointerPath, _tokens.Current, _tokens.Current.Type == TokenType.SubstituteRequired); _substitutions.Add(sub); currentArray.Add(sub); _tokens.Next(); break; default: throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon array. Expected {TokenType.EndOfArray} but found {_tokens.Current.Type} instead."); } return(currentArray); }
/// <summary> /// Retrieves the <see cref="HoconField" /> field associated with the supplied <see cref="string" /> key. /// </summary> /// <param name="key">The <see cref="string" /> key associated with the field to retrieve.</param> /// <returns> /// The <see cref="HoconField" /> associated with the supplied key. /// </returns> /// <exception cref="ArgumentNullException">key is null</exception> /// <exception cref="KeyNotFoundException">The key does not exist in the <see cref="HoconObject" /></exception> public HoconField GetField(string key) { if (key == null) { throw new ArgumentNullException(nameof(key)); } var path = HoconPath.Parse(key); return(GetField(path)); }
/// <summary> /// Retrieves the <see cref="HoconField" /> field associated with the supplied <see cref="string" /> key. /// </summary> /// <param name="key">The <see cref="string" /> key associated with the field to retrieve.</param> /// <param name="result"> /// When this method returns, contains the <see cref="HoconField" /> /// associated with the specified key, if the key is found; /// otherwise, null. This parameter is passed uninitialized. /// </param> /// <returns> /// <c>true</c> if the <see cref="HoconObject" /> contains a field with the the specified key; otherwise, <c>false</c>. /// </returns> public bool TryGetField(string key, out HoconField result) { result = null; if (string.IsNullOrWhiteSpace(key)) { return(false); } var path = HoconPath.Parse(key); return(TryGetField(path, out result)); }
/// <summary> /// Retrieves the next value token from the tokenizer and appends it /// to the supplied element <paramref name="owner"/>. /// </summary> /// <param name="owner">The element to append the next token.</param> /// <exception cref="System.Exception">End of file reached while trying to read a value</exception> private HoconValue ParseValue(IHoconElement owner) { var value = new HoconValue(owner); var parsing = true; while (parsing) { switch (_tokens.Current.Type) { case TokenType.Include: value.Add(ParseInclude(value)); break; case TokenType.LiteralValue: // Consume leading whitespaces. if (_tokens.Current.IsNonSignificant()) { ConsumeWhitespace(); } if (_tokens.Current.Type != TokenType.LiteralValue) { break; } while (_tokens.Current.Type == TokenType.LiteralValue) { value.Add(HoconLiteral.Create(value, _tokens.Current)); _tokens.Next(); } break; case TokenType.StartOfObject: value.Add(ParseObject(value)); break; case TokenType.StartOfArray: value.Add(ParseArray(value)); break; case TokenType.SubstituteOptional: case TokenType.SubstituteRequired: var pointerPath = HoconPath.Parse(_tokens.Current.Value); HoconSubstitution sub = new HoconSubstitution(value, pointerPath, _tokens.Current, _tokens.Current.Type == TokenType.SubstituteRequired); _substitutions.Add(sub); value.Add(sub); _tokens.Next(); break; case TokenType.EndOfObject: case TokenType.EndOfArray: parsing = false; break; // comments automatically stop value parsing. case TokenType.Comment: ConsumeWhitelines(); parsing = false; break; case TokenType.EndOfLine: parsing = false; break; case TokenType.EndOfFile: case TokenType.Comma: parsing = false; break; case TokenType.PlusEqualAssign: HoconSubstitution subAssign = new HoconSubstitution(value, new HoconPath(Path), _tokens.Current, false); _substitutions.Add(subAssign); value.Add(subAssign); value.Add(ParsePlusEqualAssignArray(value)); parsing = false; break; case TokenType.Assign: ConsumeWhitelines(); break; default: throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon value. Unexpected token: `{_tokens.Current.Type}`"); } } // trim trailing whitespace if result is a literal if (value.Type == HoconType.Literal) { if (value[value.Count - 1] is HoconWhitespace) { value.RemoveAt(value.Count - 1); } } return(value); }
public static HoconPath ToHoconPath(this string path) => HoconPath.Parse(path);
/// <summary> /// Determine if a HOCON configuration element exists at the specified location /// </summary> /// <param name="path">The location to check for a configuration value.</param> /// <returns><c>true</c> if a value was found, <c>false</c> otherwise.</returns> public bool HasPath(string path) => HasPath(HoconPath.Parse(path));
/// <summary> /// Retrieves a <see cref="HoconValue"/> from a specific path. /// </summary> /// <param name="path">The path that contains the value to retrieve.</param> /// <returns>The <see cref="HoconValue"/> found at the location if one exists, otherwise <c>null</c>.</returns> public HoconValue GetValue(string path) => GetValue(HoconPath.Parse(path));
/// <summary> /// Retrieves a list of byte values from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the values to retrieve.</param> /// <returns>The list of byte values defined in the specified path.</returns> public IList <byte> GetByteList(string path) => GetByteList(HoconPath.Parse(path));
/// <summary> /// Retrieves a list of double values from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the values to retrieve.</param> /// <returns>The list of double values defined in the specified path.</returns> public IList <double> GetDoubleList(string path) => GetDoubleList(HoconPath.Parse(path));
/// <summary> /// Retrieves a long value, optionally suffixed with a 'b', from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the value to retrieve.</param> /// <returns>The long value defined in the specified path.</returns> public long?GetByteSize(string path) => GetByteSize(HoconPath.Parse(path));
/// <summary> /// Retrieves a boolean value from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the value to retrieve.</param> /// <param name="default">The default value to return if the value doesn't exist.</param> /// <returns>The boolean value defined in the specified path.</returns> public bool GetBoolean(string path, bool @default = false) => GetBoolean(HoconPath.Parse(path), @default);
/// <summary> /// Retrieves a string value from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the value to retrieve.</param> /// <param name="default">The default value to return if the value doesn't exist.</param> /// <returns>The string value defined in the specified path.</returns> public string GetString(string path, string @default = null) => GetString(HoconPath.Parse(path), @default);
public static HoconPath ToHoconPath(this string path) { return(HoconPath.Parse(path)); }
/// <summary> /// Retrieves a new configuration from the current configuration /// with the root node being the supplied path. /// </summary> /// <param name="path">The path that contains the configuration to retrieve.</param> /// <returns>A new configuration with the root node being the supplied path.</returns> public virtual Config GetConfig(string path) { return(GetConfig(HoconPath.Parse(path))); }
/// <summary> /// Retrieves the next array token from the tokenizer. /// </summary> /// <returns>An array of elements retrieved from the token.</returns> private HoconArray ParseArray(IHoconElement owner) { var currentArray = new HoconArray(owner); // consume start of array token ConsumeWhitelines(); IHoconElement lastValue = null; var parsing = true; while (parsing) { switch (_tokens.Current.Type) { case TokenType.Include: if (lastValue != null) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " + $"found `{_tokens.Current.Type}` instead."); } lastValue = ParseInclude(currentArray); break; case TokenType.StartOfArray: if (lastValue != null) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " + $"found `{_tokens.Current.Type}` instead."); } // Array inside of arrays are parsed as values because it can be value concatenated with another array. lastValue = ParseValue(currentArray); break; case TokenType.StartOfObject: if (lastValue != null) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " + $"found `{_tokens.Current.Type}` instead."); } lastValue = ParseObject(currentArray); break; case TokenType.LiteralValue: if (_tokens.Current.IsNonSignificant()) { ConsumeWhitelines(); } if (_tokens.Current.Type != TokenType.LiteralValue) { break; } if (lastValue != null) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " + $"found `{_tokens.Current.Type}` instead."); } lastValue = ParseValue(currentArray); break; case TokenType.SubstituteOptional: case TokenType.SubstituteRequired: if (lastValue != null) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " + $"found `{_tokens.Current.Type}` instead."); } var pointerPath = HoconPath.Parse(_tokens.Current.Value); HoconSubstitution sub = new HoconSubstitution(currentArray, pointerPath, _tokens.Current, _tokens.Current.Type == TokenType.SubstituteRequired); _substitutions.Add(sub); lastValue = sub; _tokens.Next(); break; case TokenType.Comment: case TokenType.EndOfLine: if (lastValue == null) { ConsumeWhitelines(); break; } switch (lastValue.Type) { case HoconType.Array: currentArray.Add(lastValue); break; default: currentArray.Add(lastValue); break; } lastValue = null; ConsumeWhitelines(); break; case TokenType.Comma: if (lastValue == null) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon array. Expected a valid value, found `{_tokens.Current.Type}` instead."); } switch (lastValue.Type) { case HoconType.Array: currentArray.Add(lastValue); break; default: currentArray.Add(lastValue); break; } lastValue = null; ConsumeWhitelines(); break; case TokenType.EndOfArray: if (lastValue != null) { switch (lastValue.Type) { case HoconType.Array: currentArray.Add(lastValue); break; default: currentArray.Add(lastValue); break; } lastValue = null; } parsing = false; break; default: throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon array. Expected {TokenType.EndOfArray} but found {_tokens.Current.Type} instead."); } } // Consume end of array token _tokens.Next(); return(currentArray); }
/// <summary> /// Retrieves a list of decimal values from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the values to retrieve.</param> /// <returns>The list of decimal values defined in the specified path.</returns> public IList <decimal> GetDecimalList(string path) => GetDecimalList(HoconPath.Parse(path));
/// <summary> /// Retrieves a list of float values from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the values to retrieve.</param> /// <returns>The list of float values defined in the specified path.</returns> public IList <float> GetFloatList(string path) => GetFloatList(HoconPath.Parse(path));
/// <summary> /// Retrieves an integer value from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the value to retrieve.</param> /// <param name="default">The default value to return if the value doesn't exist.</param> /// <returns>The integer value defined in the specified path.</returns> public int GetInt(string path, int @default = 0) => GetInt(HoconPath.Parse(path), @default);
/// <summary> /// Retrieves a list of int values from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the values to retrieve.</param> /// <returns>The list of int values defined in the specified path.</returns> public IList <int> GetIntList(string path) => GetIntList(HoconPath.Parse(path));
/// <summary> /// Retrieves a long value from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the value to retrieve.</param> /// <param name="default">The default value to return if the value doesn't exist.</param> /// <returns>The long value defined in the specified path.</returns> public long GetLong(string path, long @default = 0) => GetLong(HoconPath.Parse(path), @default);
/// <summary> /// Retrieves a list of string values from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the values to retrieve.</param> /// <returns>The list of string values defined in the specified path.</returns> public IList <string> GetStringList(string path) => GetStringList(HoconPath.Parse(path));
public byte GetByte(string path, byte @default = 0) => GetByte(HoconPath.Parse(path), @default);
/// <summary> /// Retrieves a <see cref="TimeSpan"/> value from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the value to retrieve.</param> /// <param name="default">The default value to return if the value doesn't exist.</param> /// <param name="allowInfinite"><c>true</c> if infinite timespans are allowed; otherwise <c>false</c>.</param> /// <returns>The <see cref="TimeSpan"/> value defined in the specified path.</returns> public TimeSpan GetTimeSpan(string path, TimeSpan? @default = null, bool allowInfinite = true) => GetTimeSpan(HoconPath.Parse(path), @default, allowInfinite);
/// <summary> /// Retrieves a float value from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the value to retrieve.</param> /// <param name="default">The default value to return if the value doesn't exist.</param> /// <returns>The float value defined in the specified path.</returns> public float GetFloat(string path, float @default = 0) => GetFloat(HoconPath.Parse(path), @default);
/// <summary> /// Retrieves a new configuration from the current configuration /// with the root node being the supplied path. /// </summary> /// <param name="path">The path that contains the configuration to retrieve.</param> /// <returns>A new configuration with the root node being the supplied path.</returns> public Config GetConfig(string path) => GetConfig(HoconPath.Parse(path));
/// <summary> /// Retrieves a decimal value from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the value to retrieve.</param> /// <param name="default">The default value to return if the value doesn't exist.</param> /// <returns>The decimal value defined in the specified path.</returns> public decimal GetDecimal(string path, decimal @default = 0) => GetDecimal(HoconPath.Parse(path), @default);
/// <summary> /// Retrieves a double value from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the value to retrieve.</param> /// <param name="default">The default value to return if the value doesn't exist.</param> /// <returns>The double value defined in the specified path.</returns> public double GetDouble(string path, double @default = 0) => GetDouble(HoconPath.Parse(path), @default);
/// <summary> /// Retrieves a list of boolean values from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the values to retrieve.</param> /// <returns>The list of boolean values defined in the specified path.</returns> public IList <Boolean> GetBooleanList(string path) => GetBooleanList(HoconPath.Parse(path));
/// <summary> /// Retrieves the next value token from the tokenizer and appends it /// to the supplied element <paramref name="owner" />. /// </summary> /// <param name="owner">The element to append the next token.</param> /// <exception cref="System.Exception">End of file reached while trying to read a value</exception> private HoconValue ParseValue(IHoconElement owner) { // value is lazy initialized because we don't know what kind of value we're parsing HoconValue value = null; var parsing = true; while (parsing) { switch (_tokens.Current.Type) { case TokenType.Include: var includeToken = _tokens.Current; var includeValue = ParseInclude(); switch (includeValue.Type) { case HoconType.Empty: value = new HoconEmptyValue(owner); break; case HoconType.Object: value = GetHoconValueFromParentElement(owner, TokenType.StartOfObject); value.ReParent(includeValue); break; case HoconType.Array: value = GetHoconValueFromParentElement(owner, TokenType.StartOfArray); value.ReParent(includeValue); break; default: throw HoconParserException.Create(includeToken, Path, "Include could never contain a literal type."); } break; case TokenType.LiteralValue: // Consume leading whitespaces. if (_tokens.Current.IsNonSignificant()) { _tokens.ToNextSignificant(); } if (_tokens.Current.Type != TokenType.LiteralValue) { break; } if (value == null) { value = GetHoconValueFromParentElement(owner, _tokens.Current.Type); } while (_tokens.Current.Type == TokenType.LiteralValue) { value.Add(HoconLiteral.Create(value, _tokens.Current)); _tokens.Next(); } break; case TokenType.StartOfObject: if (value == null) { value = GetHoconValueFromParentElement(owner, _tokens.Current.Type); } ParseObject(ref value); break; case TokenType.StartOfArray: if (value == null) { value = GetHoconValueFromParentElement(owner, _tokens.Current.Type); } // If this array is already initialized, we are going to overwrite it if (value.Type == HoconType.Array && value.Count > 0) { value.Clear(); } value.Add(ParseArray(value)); break; case TokenType.SubstituteOptional: case TokenType.SubstituteRequired: if (value == null) { value = new HoconValue(owner); } var pointerPath = HoconPath.Parse(_tokens.Current.Value); var sub = new HoconSubstitution(value, pointerPath, _tokens.Current, _tokens.Current.Type == TokenType.SubstituteRequired); _substitutions.Add(sub); _tokens.Next(); value.Add(sub); break; case TokenType.PlusEqualAssign: if (value == null) { value = new HoconValue(owner); } var subAssign = new HoconSubstitution(value, new HoconPath(Path), _tokens.Current, false); _substitutions.Add(subAssign); value.Add(subAssign); value.Add(ParsePlusEqualAssignArray(value)); parsing = false; break; case TokenType.EndOfObject: case TokenType.EndOfArray: parsing = false; break; case TokenType.Comment: _tokens.ToNextSignificant(); break; case TokenType.EndOfLine: parsing = false; break; case TokenType.EndOfFile: case TokenType.Comma: parsing = false; break; case TokenType.Assign: // Special case to support end of line after assign _tokens.ToNextSignificantLine(); break; default: throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon value. Unexpected token: `{_tokens.Current.Type}`"); } } if (value == null) { value = new HoconEmptyValue(owner); } // trim trailing whitespace if result is a literal if (value.Type.IsLiteral()) { if (value[value.Count - 1] is HoconWhitespace) { value.RemoveAt(value.Count - 1); } } return(value); }
/// <summary> /// Retrieves a list of objects from the specified path in the configuration. /// </summary> /// <param name="path">The path that contains the objects to retrieve.</param> /// <returns>The list of objects defined in the specified path.</returns> public IList <HoconObject> GetObjectList(string path) => GetObjectList(HoconPath.Parse(path));