private void ScalarToYaml(YamlScalar node, string pres, Context c) { var s = node.Value; // If tag can be resolved from the content, or tag is !!str, // no need to explicitly specify it. var auto_tag = YamlNode.ShorthandTag(AutoTagResolver.Resolve(s)); var tag = TagToYaml(node, auto_tag); if (tag != "" && tag != "!!str") { Write(tag + " "); } if (IsValidPlainText(s, c) && !(node.ShorthandTag() == "!!str" && auto_tag != null && !node.Properties.ContainsKey("plainText"))) { // one line plain style Write(s); if (c != Context.NoBreak) { WriteLine(); } } else { if (ForbiddenChars.IsMatch(s) || OneLine.IsMatch(s) || (config.ExplicitlyPreserveLineBreaks && GetPropertyOrNull(node, "Don'tCareLineBreaks") == null)) { // double quoted Write(DoubleQuotedString.Quote(s, pres, c)); if (c != Context.NoBreak) { WriteLine(); } } else { // Literal style if (s[s.Length - 1] == '\n' || s[s.Length - 1] == '\r') { WriteLine("|+2"); } else { WriteLine("|-2"); s += "\r\n"; // guard } var press = pres + " "; for (int p = 0; p < s.Length;) { var m = UntilBreak.Match(s, p); // does not fail because of the guard Write(pres + s.Substring(p, m.Length)); p += m.Length; } } } }
public bool Encode(object obj, out YamlScalar node) { node = null; YamlTagResolutionRule rule; if (!TypeToRule.TryGetValue(obj.GetType(), out rule)) { return(false); } node = new YamlScalar(rule.Tag, rule.Encode(obj)); return(true); }
private AYamlValue Include(string filePath) { var sourceFile = Path.Combine(Path.GetDirectoryName(SourceFilename), filePath); // read include contents string contents = null; try { contents = File.ReadAllText(sourceFile); } catch (FileNotFoundException) { LogError($"could not find '{sourceFile}'"); } catch (IOException) { LogError($"invalid !Include value '{sourceFile}'"); } catch (ArgumentException) { LogError($"invalid !Include value '{sourceFile}'"); } AYamlValue result = new YamlScalar(new Scalar("<BAD>")); if (contents != null) { // check if YAML conversion is required if (Path.GetExtension(sourceFile).ToLowerInvariant() != ".yml") { return(new YamlScalar(new Scalar(contents))); } InSourceFile(sourceFile, () => { try { var includeStream = YamlParser.Parse(contents); result = Preprocess(includeStream.Documents.First()).Values.First(); } catch (YamlDotNet.Core.YamlException e) { LogError($"parsing error near {e.Message}", e); } catch (Exception e) { LogError($"parse error: {e.Message}", e); } }); } return(result); }
/// <summary> /// Decode <paramref name="node"/> and returns actual value in C# object. /// </summary> /// <param name="node">Node to be decoded.</param> /// <param name="obj">Decoded value.</param> /// <returns>True if decoded successfully.</returns> public bool Decode(YamlScalar node, out object obj) { obj = null; if (node.Tag == null || node.Value == null) { return(false); } var tag = YamlNode.ExpandTag(node.Tag); if (!types.ContainsKey(tag)) { return(false); } foreach (var rule in types[tag]) { var m = rule.Pattern.Match(node.Value); if (m.Success) { obj = rule.Decode(m); return(true); } } return(false); }
object ScalarToObject(YamlScalar node, Type type) { if (type == null) { throw new FormatException("Could not find a type '{0}'.".DoFormat(node.Tag)); } // To accommodate the !!int and !!float encoding, all "_"s in integer and floating point values // are simply neglected. if (type == typeof(byte) || type == typeof(sbyte) || type == typeof(short) || type == typeof(ushort) || type == typeof(int) || type == typeof(uint) || type == typeof(long) || type == typeof(ulong) || type == typeof(float) || type == typeof(decimal)) { return(config.TypeConverter.ConvertFromString(node.Value.Replace("_", ""), type)); } if (type.IsEnum || type.IsPrimitive || type == typeof(char) || type == typeof(bool) || type == typeof(string) || EasyTypeConverter.IsTypeConverterSpecified(type)) { return(config.TypeConverter.ConvertFromString(node.Value, type)); } if (type.IsArray) { // Split dimension from base64 strings var s = node.Value; var regex = new Regex(@" *\[([0-9 ,]+)\][\r\n]+((.+|[\r\n])+)"); int[] dimension; byte[] binary; var elementSize = Marshal.SizeOf(type.GetElementType()); if (type.GetArrayRank() == 1) { binary = System.Convert.FromBase64CharArray(s.ToCharArray(), 0, s.Length); var arrayLength = binary.Length / elementSize; dimension = new int[] { arrayLength }; } else { var m = regex.Match(s); if (!m.Success) { throw new FormatException("Irregal binary array"); } // Create array from dimension dimension = m.Groups[1].Value.Split(',').Select(n => Convert.ToInt32(n)).ToArray(); if (type.GetArrayRank() != dimension.Length) { throw new FormatException("Irregal binary array"); } // Fill values s = m.Groups[2].Value; binary = System.Convert.FromBase64CharArray(s.ToCharArray(), 0, s.Length); } var paramType = dimension.Select(n => typeof(int) /* n.GetType() */).ToArray(); var array = (Array)type.GetConstructor(paramType).Invoke(dimension.Cast <object>().ToArray()); if (binary.Length != array.Length * elementSize) { throw new FormatException("Irregal binary: data size does not match to array dimension"); } int j = 0; for (int i = 0; i < array.Length; i++) { var p = Marshal.UnsafeAddrOfPinnedArrayElement(array, i); Marshal.Copy(binary, j, p, elementSize); j += elementSize; } return(array); } if (node.Value == "") { return(config.Activator.Activate(type)); } else { return(TypeDescriptor.GetConverter(type).ConvertFromString(node.Value)); } }
public void MergeKey() { var map = new YamlMapping("existing", "value"); var mergeKey = new YamlScalar("!!merge", "<<"); map.Add(mergeKey, new YamlMapping("existing", "new value")); map.OnLoaded(); Assert.AreEqual(1, map.Count); Assert.IsTrue(map.ContainsKey("existing")); Assert.AreEqual((YamlNode)"value", map["existing"]); map.Add(mergeKey, new YamlMapping("not existing", "new value")); map.OnLoaded(); Assert.AreEqual(2, map.Count); Assert.IsTrue(map.ContainsKey("existing")); Assert.AreEqual((YamlNode)"value", map["existing"]); Assert.IsTrue(map.ContainsKey("not existing")); Assert.AreEqual((YamlNode)"new value", map["not existing"]); map.Add(mergeKey, new YamlMapping("key1", "value1", 2, 2, 3.0, 3.0)); map.OnLoaded(); Assert.AreEqual(5, map.Count); Assert.IsTrue(map.ContainsKey("existing")); Assert.AreEqual((YamlNode)"value", map["existing"]); Assert.IsTrue(map.ContainsKey("not existing")); Assert.AreEqual((YamlNode)"new value", map["not existing"]); Assert.IsTrue(map.ContainsKey(2)); Assert.AreEqual((YamlNode)2, map[2]); Assert.IsTrue(map.ContainsKey(3.0)); Assert.AreEqual((YamlNode)3.0, map[3.0]); map = new YamlMapping( "existing", "value", mergeKey, new YamlMapping("not existing", "new value")); map.OnLoaded(); Assert.AreEqual(2, map.Count); Assert.IsTrue(map.ContainsKey("existing")); Assert.AreEqual((YamlNode)"value", map["existing"]); Assert.IsTrue(map.ContainsKey("not existing")); Assert.AreEqual((YamlNode)"new value", map["not existing"]); map = (YamlMapping)YamlNode.FromYaml( "key1: value1\r\n" + "key2: value2\r\n" + "<<: \r\n" + " key2: value2 modified\r\n" + " key3: value3\r\n" + " <<: \r\n" + " key4: value4\r\n" + " <<: value5\r\n" + "key6: <<\r\n")[0]; Assert.AreEqual( "%YAML 1.2\r\n" + "---\r\n" + "<<: value5\r\n" + "key6: <<\r\n" + "key3: value3\r\n" + "key2: value2\r\n" + "key4: value4\r\n" + "key1: value1\r\n" + "...\r\n", map.ToYaml() ); Assert.IsTrue(map.ContainsKey(mergeKey)); Assert.AreEqual(mergeKey, map["key6"]); map.Remove(mergeKey); map.Add(mergeKey, map); // recursive map.OnLoaded(); Assert.AreEqual( // nothing has been changed "%YAML 1.2\r\n" + "---\r\n" + "key6: <<\r\n" + "key3: value3\r\n" + "key2: value2\r\n" + "key4: value4\r\n" + "key1: value1\r\n" + "...\r\n", map.ToYaml() ); }
object ScalarToObject(YamlScalar node, Type type) { if ( type == null ) throw new FormatException("Could not find a type '{0}'.".DoFormat(node.Tag)); // 1) Give a chance to deserialize through a IYamlSerializable interface var serializable = config.Serializable.FindSerializable(context, null, type); if (serializable != null) { return serializable.Deserialize(context, node, type); } // 2) Give a chance to IYamlTypeConverter var hasTypeConverter = config.TypeConverter.IsTypeConverterSpecified(context, type); var nodeValue = node.Value; // To accommodate the !!int and !!float encoding, all "_"s in integer and floating point values // are simply neglected. if (type == typeof (byte) || type == typeof (sbyte) || type == typeof (short) || type == typeof (ushort) || type == typeof (int) || type == typeof (uint) || type == typeof (long) || type == typeof (ulong) || type == typeof (float) || type == typeof (decimal)) { nodeValue = nodeValue.Replace("_", string.Empty); return config.TypeConverter.ConvertFromString(context, nodeValue, type); } // 変換結果が見かけ上他の型に見える可能性がある場合を優先的に変換 // 予想通りの型が見つからなければエラーになる条件でもある if ( type.IsEnum || type.IsPrimitive || type == typeof(char) || type == typeof(bool) || type == typeof(string) || hasTypeConverter ) return config.TypeConverter.ConvertFromString(context, nodeValue, type); // 3) If an array of bytes, try to deserialize it directly in base64 if (type.IsArray) { // Split dimension from base64 strings var s = node.Value; var regex = new Regex(@" *\[([0-9 ,]+)\][\r\n]+((.+|[\r\n])+)"); int[] dimension; byte[] binary; if (type.GetElementType() != typeof (byte) || type.GetArrayRank() != 1) { throw new FormatException("Expecting single dimension byte[] array"); } return System.Convert.FromBase64CharArray(s.ToCharArray(), 0, s.Length); } // 4) If value is empty, try to activate the object through Activator. if ( node.Value == string.Empty ) { return config.Activator.Activate(type); } // Else throw an exception throw new FormatException(string.Format("Unable to deserialize yaml node [{0}]", node)); }
object ScalarToObject(YamlScalar node, Type type) { if (type == null) { throw new FormatException("Could not find a type '{0}'.".DoFormat(node.Tag)); } // 1) Give a chance to deserialize through a IYamlSerializable interface var serializable = config.Serializable.FindSerializable(context, null, type); if (serializable != null) { return(serializable.Deserialize(context, node, type)); } // 2) Give a chance to IYamlTypeConverter var hasTypeConverter = config.TypeConverter.IsTypeConverterSpecified(context, type); var nodeValue = node.Value; // To accommodate the !!int and !!float encoding, all "_"s in integer and floating point values // are simply neglected. if (type == typeof(byte) || type == typeof(sbyte) || type == typeof(short) || type == typeof(ushort) || type == typeof(int) || type == typeof(uint) || type == typeof(long) || type == typeof(ulong) || type == typeof(float) || type == typeof(decimal)) { nodeValue = nodeValue.Replace("_", string.Empty); return(config.TypeConverter.ConvertFromString(context, nodeValue, type)); } // 変換結果が見かけ上他の型に見える可能性がある場合を優先的に変換 // 予想通りの型が見つからなければエラーになる条件でもある if (type.IsEnum || type.IsPrimitive || type == typeof(char) || type == typeof(bool) || type == typeof(string) || hasTypeConverter) { return(config.TypeConverter.ConvertFromString(context, nodeValue, type)); } // 3) If an array of bytes, try to deserialize it directly in base64 if (type.IsArray) { // Split dimension from base64 strings var s = node.Value; var regex = new Regex(@" *\[([0-9 ,]+)\][\r\n]+((.+|[\r\n])+)"); int[] dimension; byte[] binary; if (type.GetElementType() != typeof(byte) || type.GetArrayRank() != 1) { throw new FormatException("Expecting single dimension byte[] array"); } return(System.Convert.FromBase64CharArray(s.ToCharArray(), 0, s.Length)); } // 4) If value is empty, try to activate the object through Activator. if (node.Value == string.Empty) { return(config.Activator.Activate(type)); } // Else throw an exception throw new FormatException(string.Format("Unable to deserialize yaml node [{0}]", node)); }