private static bool ContainsLoopsInternal(SKONObject obj, Dictionary <SKONObject, bool> contains) { if (contains.ContainsKey(obj)) { return(true); } contains.Add(obj, true); switch (obj.Type) { case SKONValueType.EMPTY: case SKONValueType.STRING: case SKONValueType.INTEGER: case SKONValueType.FLOAT: case SKONValueType.BOOLEAN: case SKONValueType.DATETIME: return(false); case SKONValueType.MAP: foreach (var key in obj.Keys) { if (ContainsLoopsInternal(obj[key], new Dictionary <SKONObject, bool>(contains))) { return(true); } } return(false); case SKONValueType.ARRAY: foreach (var element in obj.Values) { if (ContainsLoopsInternal(element, new Dictionary <SKONObject, bool>(contains))) { return(true); } } return(false); default: return(false); } }
/// <summary> /// Writes a SKONObject. /// </summary> /// <param name="obj">The object to write.</param> /// <returns>A string to write into a file.</returns> public static string Write(SKONObject obj, SKONMetadata metadata = default(SKONMetadata)) { if (obj.Type != SKONValueType.MAP) { throw new ArgumentException("SKONObject to write must be of type map!"); } if (ContainsLoops(obj)) { throw new ArgumentException("Could not write SKONObject due to recursive references!"); } //There might be something we would want to do if the versions don't match metadata.LanguageVersion = LanguageVersion; StringBuilder sb = new StringBuilder(); sb.Append($"{Metadelimit}Version: {metadata.LanguageVersion}{Metadelimit}\n"); sb.Append($"{Metadelimit}DocumentVersion: \"{metadata.DocuemntVersion}\"{Metadelimit}\n"); if (metadata.SKEMA != null && metadata.SKEMA.Length > 0) { sb.Append($"{Metadelimit}SKEMA: {metadata.SKEMA}{Metadelimit}\n"); } sb.Append('\n'); foreach (string key in obj.Keys) { sb.Append(key + ": "); sb.Append(obj[key].IsComplex ? '\n' : ' '); sb.Append(WriteObject(obj[key], 0)); } return(sb.ToString()); }
/// <summary> /// Writes a SKONObject value. /// </summary> /// <param name="obj">The object to write.</param> /// <param name="indent">The amount of indentation.</param> /// <returns>A string to write into a file.</returns> private static string WriteObject(SKONObject obj, int indent) { string indentString = string.Empty; for (int i = 0; i < indent; i++) { indentString += IndentString; } switch (obj.Type) { case ValueType.EMPTY: return("null"); case ValueType.STRING: return("\"" + obj.String + "\""); case ValueType.INTEGER: return(obj.Int.ToString()); case ValueType.DOUBLE: return(obj.Double.ToString().Replace(',', '.')); case ValueType.BOOLEAN: return(obj.Boolean.ToString().ToLower()); case ValueType.DATETIME: return((obj.DateTime ?? default(DateTime)).ToString("yyyy-MM-ddThh:mm:ss.fffzzz")); case ValueType.MAP: StringBuilder mapsb = new StringBuilder(); if (obj.Keys.Count <= 0) { mapsb.Append("{ }"); return(mapsb.ToString()); } mapsb.Append('\n' + indentString + "{\n"); foreach (string key in obj.Keys) { mapsb.Append(indentString + IndentString + $"{key}: {WriteObject(obj[key], indent + 1)},\n"); } mapsb.Append(indentString + "}"); return(mapsb.ToString()); case ValueType.ARRAY: StringBuilder arraysb = new StringBuilder(); if (obj.Length <= 0) { arraysb.Append("[ ]"); return(arraysb.ToString()); } arraysb.Append('\n' + indentString + "[\n"); for (int i = 0; i < obj.Length; i++) { arraysb.Append(indentString + IndentString + $"{WriteObject(obj[i], indent + 1)},\n"); } arraysb.Append(indentString + "]"); return(arraysb.ToString()); default: return(null); } }
/// <summary> /// Writes a SKONObject value. /// </summary> /// <param name="obj">The object to write.</param> /// <param name="indent">The amount of indentation.</param> /// <returns>A string to write into a file.</returns> private static string WriteObject(SKONObject obj, int indent) { if (obj == null) { return(string.Empty); } string indentString = string.Empty; for (int i = 0; i < indent; i++) { indentString += IndentString; } switch (obj.Type) { case SKONValueType.EMPTY: return(indentString + "null,\n"); case SKONValueType.STRING: return(indentString + "\"" + obj.String + "\",\n"); case SKONValueType.INTEGER: return(indentString + obj.Int.ToString() + ",\n"); case SKONValueType.FLOAT: return(indentString + obj.Double.Value.ToString(CultureInfo.InvariantCulture) + ",\n"); case SKONValueType.BOOLEAN: return(indentString + obj.Boolean.ToString().ToLower() + ",\n"); case SKONValueType.DATETIME: return(indentString + (obj.DateTime ?? default(DateTime)).ToString("yyyy-MM-ddThh:mm:ss.fffzzz") + ",\n"); case SKONValueType.MAP: StringBuilder mapsb = new StringBuilder(); mapsb.Append(indentString); if (obj.Keys.Count <= 0) { mapsb.Append("{ },\n"); return(mapsb.ToString()); } mapsb.Append("{\n"); foreach (string key in obj.Keys) { mapsb.Append(indentString).Append(IndentString); mapsb.Append(key).Append(":"); mapsb.Append(obj[key].IsComplex ? '\n' : ' '); mapsb.Append(WriteObject(obj[key], obj[key].IsComplex ? indent + 1 : 0)); } mapsb.Append(indentString).Append("},\n"); return(mapsb.ToString()); case SKONValueType.ARRAY: StringBuilder arraysb = new StringBuilder(); arraysb.Append(indentString); if (obj.Length <= 0) { arraysb.Append("[ ],\n"); return(arraysb.ToString()); } arraysb.Append("[\n"); for (int i = 0; i < obj.Length; i++) { arraysb.Append($"{WriteObject(obj[i], indent + 1)}"); } arraysb.Append(indentString).Append("],\n"); return(arraysb.ToString()); default: return("!!internal error!!"); } }
/// <summary> /// Writes a SKONObject to a file. This will overwrite the current content of the file. /// </summary> /// <param name="filepath">The path to the file to write to.</param> /// <param name="obj">The SKONObject to turn into a string and write to a file.</param> public static void WriteToFile(string filepath, SKONObject obj) { File.WriteAllText(filepath, Write(obj), Encoding.UTF8); }