public void Merge(HoconObject other) { var thisItems = Items; var otherItems = other.Items; foreach (var otherItem in otherItems) { if (thisItems.ContainsKey(otherItem.Key)) { //other key was present in this object. //if we have a value, just ignore the other value, unless it is an object var thisItem = thisItems[otherItem.Key]; //if both values are objects, merge them if (thisItem.IsObject() && otherItem.Value.IsObject()) { thisItem.GetObject().Merge(otherItem.Value.GetObject()); } } else { //other key was not present in this object, just copy it over Items.Add(otherItem.Key, otherItem.Value); } } }
public virtual void Merge(HoconObject other) { var keys = other.Keys.ToArray(); foreach (var key in keys) { var quotedKey = $"\"{key}\""; if (!ContainsKey(key)) { base[key] = other[quotedKey]; continue; } var thisItem = this[quotedKey]; var otherItem = other[quotedKey].Value; if (thisItem.Type == HoconType.Object && otherItem.Type == HoconType.Object) { thisItem.GetObject().Merge(otherItem.GetObject()); } else { thisItem.SetValue(otherItem); } } }
public void FallbackMerge(HoconObject other) { foreach (var kvp in other) { var path = kvp.Value.Path; if (!TryGetValue(path, out _)) { var currentObject = this; HoconField newField = null; foreach (var key in path) { newField = currentObject.GetOrCreateKey(key); if (newField.Type == HoconType.Empty) { var emptyValue = new HoconValue(newField); emptyValue.Add(new HoconObject(emptyValue)); newField.SetValue(emptyValue); } currentObject = newField.GetObject(); } newField.SetValue(kvp.Value.Value); } else { if (kvp.Value.Type == HoconType.Object) { FallbackMerge(kvp.Value.GetObject()); } } } }
public virtual bool TryGetObject(out HoconObject result) { result = null; if (Type != HoconType.Object) { return(false); } var objects = this .Where(value => value.Type == HoconType.Object) .Select(value => value.GetObject()).ToList(); switch (objects.Count) { case 0: break; case 1: result = objects[0]; break; default: result = new HoconMergedObject(this, objects); break; } return(true); }
public override void Merge(HoconObject other) { var parent = (HoconValue)Parent; parent.Add(other); Objects.Add(other); base.Merge(other); }
/// <inheritdoc /> public IHoconElement Clone(IHoconElement newParent) { var clone = new HoconObject(newParent); foreach (var kvp in this) { clone.SetField(kvp.Key, kvp.Value.Clone(clone) as HoconField); } return(clone); }
/// <summary> /// Retrieves the merged <see cref="HoconObject" /> backing 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 backing <see cref="HoconObject" /> /// of 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 <see cref="HoconField" /> field with the the specified key /// and the <see cref="HoconField.Type" /> is of type <see cref="HoconType.Object" />; otherwise, <c>false</c>. /// </returns> public bool TryGetObject(string key, out HoconObject result) { result = null; if (!TryGetField(key, out var field)) { return(false); } result = field.GetObject(); return(true); }
/// <summary> /// Wraps this <see cref="HoconValue" /> into a new <see cref="HoconObject" /> at the specified key. /// </summary> /// <param name="key">The key designated to be the new root element.</param> /// <returns>A new HOCON root.</returns> /// <remarks> /// Immutable. Performs a deep copy on this <see cref="HoconValue" /> first. /// </remarks> public HoconRoot AtKey(string key) { var value = new HoconValue(null); var obj = new HoconObject(value); var field = new HoconField(key, obj); field.SetValue(Clone(field) as HoconValue); obj.Add(key, field); value.Add(obj); return(new HoconRoot(value)); }
public HoconField(string key, HoconObject parent) { if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException(nameof(key)); } Path = new HoconPath(parent.Path) { key }; Parent = parent; }
internal void EnsureFieldIsObject() { if (Type == HoconType.Object) { return; } var v = new HoconValue(this); var o = new HoconObject(v); v.Add(o); _internalValues.Add(v); }
private HoconField ParseField(HoconObject owner) { // sanity check if (_tokens.Current.Type != TokenType.LiteralValue) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon field. Expected start of field {TokenType.LiteralValue}, " + $"found {_tokens.Current.Type} instead."); } var pathDelta = ParseKey(); if (_tokens.Current.IsNonSignificant()) { ConsumeWhitelines(); } // sanity check if (_tokens.Current.Type != TokenType.Assign && _tokens.Current.Type != TokenType.StartOfObject && _tokens.Current.Type != TokenType.PlusEqualAssign) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon field. Expected {TokenType.Assign}, {TokenType.StartOfObject} " + $"or {TokenType.PlusEqualAssign}, found {{_tokens.Current.Type}} instead."); } // sanity check if (pathDelta == null || pathDelta.Count == 0) { throw HoconParserException.Create(_tokens.Current, Path, "Failed to parse Hocon field. ParseField() was called with null or empty path"); } List <HoconField> childInPath = owner.TraversePath(pathDelta); Path.AddRange(pathDelta); HoconField currentField = childInPath[childInPath.Count - 1]; var parsedValue = ParseValue(currentField); foreach (var removedSub in currentField.SetValue(parsedValue)) { _substitutions.Remove(removedSub); } Path.RemoveRange(Path.Count - pathDelta.Count, pathDelta.Count); return(childInPath[0]); }
public virtual void Merge(HoconObject other) { var keys = other.Keys.ToArray(); foreach (var key in keys) { if (ContainsKey(key)) { var thisItem = this[key]; var otherItem = other[key]; if (thisItem.Type == HoconType.Object && otherItem.Type == HoconType.Object) { thisItem.GetObject().Merge(otherItem.GetObject()); continue; } } this[key] = other[key]; } }
private void ParseField(HoconObject owner) { // sanity check if (_tokens.Current.IsNonSignificant() || _tokens.Current.Type != TokenType.LiteralValue) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon field. Expected start of field {TokenType.LiteralValue}, " + $"found {_tokens.Current.Type} instead."); } var relativePath = ParseKey(); if (_tokens.Current.Type == TokenType.EndOfLine) { _tokens.ToNextSignificantLine(); } // sanity check if (_tokens.Current.Type != TokenType.Assign && _tokens.Current.Type != TokenType.StartOfObject && _tokens.Current.Type != TokenType.PlusEqualAssign) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon field. Expected {TokenType.Assign}, {TokenType.StartOfObject} " + $"or {TokenType.PlusEqualAssign}, found {_tokens.Current.Type} instead."); } // sanity check if (relativePath == null || relativePath.Count == 0) { throw HoconParserException.Create(_tokens.Current, Path, "Failed to parse Hocon field. Null or empty path"); } Path.AddRange(relativePath); var currentField = owner.TraversePath(relativePath); currentField.SetValue(ParseValue(currentField)); Path.RemoveRange(Path.Count - relativePath.Count, relativePath.Count); }
/// <summary> /// Retrieves an object 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 HoconObject GetObject(string path, HoconObject @default = null) => GetObject(HoconPath.Parse(path), @default);
// The owner in this context can be either an object or an array. private void ParseObject(ref HoconValue owner) { if (owner == null) { throw HoconParserException.Create(_tokens.Current, Path, "ParseObject called with null parent."); } // Sanity check if (_tokens.Current.Type != TokenType.StartOfObject) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon object. Expected `{TokenType.StartOfObject}`, found `{_tokens.Current.Type}` instead."); } // Consume curly bracket _tokens.ToNextSignificant(); var hoconObject = owner.GetObject(); if (hoconObject == null) { hoconObject = new HoconObject(owner); owner.Add(hoconObject); } var valueWasParsed = false; var parsing = true; while (parsing) { switch (_tokens.Current.Type) { case TokenType.Include: if (valueWasParsed) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon object. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}`, " + $"found `{_tokens.Current.Type}` instead."); } owner.ReParent(ParseInclude()); valueWasParsed = true; break; case TokenType.LiteralValue: if (_tokens.Current.IsNonSignificant()) { _tokens.ToNextSignificant(); } if (_tokens.Current.Type != TokenType.LiteralValue) { break; } if (valueWasParsed) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon object. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}`, " + $"found `{_tokens.Current.Type}` instead."); } ParseField(hoconObject); valueWasParsed = true; break; case TokenType.Comment: case TokenType.EndOfLine: valueWasParsed = false; _tokens.ToNextSignificantLine(); break; case TokenType.Comma: if (!valueWasParsed) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon object. Expected `{TokenType.Assign}` or `{TokenType.StartOfObject}`, " + $"found `{_tokens.Current.Type}` instead."); } valueWasParsed = false; _tokens.ToNextSignificant(); break; case TokenType.EndOfObject: valueWasParsed = false; parsing = false; break; case TokenType.EndOfFile: throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon object. Expected {TokenType.EndOfObject} but found {_tokens.Current.Type} instead."); default: throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon object. Unexpected token `{_tokens.Current.Type}`."); } } // Consume the closing curly bracket. _tokens.ToNextSignificant(); }
public override void Merge(HoconObject other) { ((HoconField)Parent).Value.Add(other.Clone(((HoconField)Parent).Value)); base.Merge(other); }
// The owner in this context can be either an object or an array. private HoconObject ParseObject(IHoconElement owner) { var hoconObject = new HoconObject(owner); if (_tokens.Current.Type != TokenType.StartOfObject && _tokens.Current.Type != TokenType.LiteralValue && _tokens.Current.Type != TokenType.Include) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon object. Expected `{TokenType.StartOfObject}` or `{TokenType.LiteralValue}, " + $"found `{_tokens.Current.Type}` instead."); } var headless = true; if (_tokens.Current.Type == TokenType.StartOfObject) { headless = false; 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 object. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}`, " + $"found `{_tokens.Current.Type}` instead."); } lastValue = ParseInclude(hoconObject); break; case TokenType.LiteralValue: if (_tokens.Current.IsNonSignificant()) { ConsumeWhitespace(); } if (_tokens.Current.Type != TokenType.LiteralValue) { break; } if (lastValue != null) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon object. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}`, " + $"found `{_tokens.Current.Type}` instead."); } lastValue = ParseField(hoconObject); break; // TODO: can an object be declared floating without being assigned to a field? //case TokenType.StartOfObject: case TokenType.Comment: case TokenType.EndOfLine: switch (lastValue) { case null: ConsumeWhitelines(); break; case HoconField _: break; default: ((HoconValue)hoconObject.Parent).Add(lastValue.GetObject()); break; } lastValue = null; ConsumeWhitelines(); break; case TokenType.Comma: switch (lastValue) { case null: throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon object. Expected `{TokenType.Assign}` or `{TokenType.StartOfObject}`, " + $"found `{_tokens.Current.Type}` instead."); case HoconField _: break; default: ((HoconValue)hoconObject.Parent).Add(lastValue.GetObject()); break; } lastValue = null; ConsumeWhitelines(); break; case TokenType.EndOfObject: case TokenType.EndOfFile: if (headless && _tokens.Current.Type != TokenType.EndOfFile) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon object. Expected {TokenType.EndOfFile} but found {_tokens.Current.Type} instead."); } if (!headless && _tokens.Current.Type != TokenType.EndOfObject) { throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon object. Expected {TokenType.EndOfObject} but found {_tokens.Current.Type} instead."); } switch (lastValue) { case null: break; case HoconField _: break; default: ((HoconValue)hoconObject.Parent).Add(lastValue.GetObject()); break; } lastValue = null; parsing = false; break; default: throw HoconParserException.Create(_tokens.Current, Path, $"Failed to parse Hocon object. Unexpected token `{_tokens.Current.Type}`."); } } if (_tokens.Current.Type == TokenType.EndOfObject) { _tokens.Next(); } return(hoconObject); }
static HoconObject() { var value = new HoconValue(null); _empty = new HoconObject(value); }
/// <inheritdoc cref="GetObject(string,HoconObject)"/> public HoconObject GetObject(HoconPath path, HoconObject @default = null) { var value = GetNode(path); return(value == null ? @default : value.GetObject()); }
private void ParseObject(HoconValue owner, bool root, string currentPath) { try { PushDiagnostics("{"); if (owner.IsObject()) { //the value of this KVP is already an object } else { //the value of this KVP is not an object, thus, we should add a new owner.NewValue(new HoconObject()); } HoconObject currentObject = owner.GetObject(); while (!_reader.EoF) { Token t = _reader.PullNext(); switch (t.Type) { case TokenType.Include: var included = _includeCallback(t.Value); var substitutions = included.Substitutions; foreach (var substitution in substitutions) { //fixup the substitution, add the current path as a prefix to the substitution path substitution.Path = currentPath + "." + substitution.Path; } _substitutions.AddRange(substitutions); var otherObj = included.Value.GetObject(); owner.GetObject().Merge(otherObj); break; case TokenType.EoF: if (!string.IsNullOrEmpty(currentPath)) { throw new HoconParserException(string.Format("Expected end of object but found EoF {0}", GetDiagnosticsStackTrace())); } break; case TokenType.Key: HoconValue value = currentObject.GetOrCreateKey(t.Value); var nextPath = currentPath == "" ? t.Value : currentPath + "." + t.Value; ParseKeyContent(value, nextPath); if (!root) { return; } break; case TokenType.ObjectEnd: return; } } } finally { PopDiagnostics(); } }