/// <summary> /// Applies a patch, given in TML format, to this Token tree. /// </summary> /// <param name="source">A TML representation of the patch to apply.</param> /// <remarks>Patch syntax is somewhat based on JSON PATCH, RFC 6902.</remarks> public void Patch(string source) { var patch = new Token(); patch.Tokenize(source); foreach (var token in patch.Tokens) { var path = token.Text; if (token.Name == "add") { if (path == "-") { Tokens.AddRange(token.Tokens); } else if (path.EndsWith("/-")) { var target = Path(path.Substring(0, path.Length - 2)); if (target != null) { target.Tokens.AddRange(token.Tokens); } } { var target = Path(path); if (target != null) { Tokens.InsertRange(Tokens.IndexOf(target) + 1, token.Tokens); } } } else if (token.Name == "remove") { var target = Path(path); if (target != null) { if (path.LastIndexOf('/') == -1) { Tokens.Remove(target); } else { var oneUp = Path(path.Substring(0, path.LastIndexOf('/'))); oneUp.Tokens.Remove(target); } } } else if (token.Name == "replace") { var target = Path(path); if (target != null) { if (path.LastIndexOf('/') == -1) { Tokens[Tokens.IndexOf(target)] = token.Tokens[0]; } else { var oneUp = Path(path.Substring(0, path.LastIndexOf('/'))); oneUp.Tokens[oneUp.Tokens.IndexOf(target)] = token.Tokens[0]; } } } else if (token.Name == "set") { var target = Path(path); if (target != null) { var val = token.GetToken("value"); var txt = token.GetToken("text"); if (val != null) { target.Value = val.Value; } if (txt != null) { target.Text = txt.Text; } } } } }