From 2b11962eb65e039c7c4c6aec1d65cfde74db826b Mon Sep 17 00:00:00 2001 From: a-sansara Date: Fri, 24 Aug 2018 14:11:19 +0200 Subject: [PATCH] add Yaml.serialize & Yaml.deserialize --- meson.build | 2 + samples/yaml-dump.vala | 2 +- samples/yaml-serialize.vala | 113 ++++++++++++++++++++++++ src/vala/Pluie/Io.InputChunkStream.vala | 79 +++++++++++++++++ src/vala/Pluie/Io.Reader.vala | 14 +++ src/vala/Pluie/Io.Writter.vala | 95 ++++++++++++++++++++ src/vala/Pluie/Yaml.AbstractNode.vala | 6 +- src/vala/Pluie/Yaml.Config.vala | 4 +- src/vala/Pluie/Yaml.Dumper.vala | 38 ++++---- src/vala/Pluie/Yaml.Register.vala | 1 + src/vala/Pluie/Yaml.global.vala | 66 ++++++++++++++ 11 files changed, 391 insertions(+), 29 deletions(-) create mode 100644 samples/yaml-serialize.vala create mode 100644 src/vala/Pluie/Io.InputChunkStream.vala create mode 100644 src/vala/Pluie/Io.Writter.vala diff --git a/meson.build b/meson.build index ca04b94..345daba 100644 --- a/meson.build +++ b/meson.build @@ -61,7 +61,9 @@ configure_file( sources = [ 'build/install.vala', 'src/vala/Pluie/Io.Reader.vala', + 'src/vala/Pluie/Io.InputChunkStream.vala', 'src/vala/Pluie/Io.StreamLineMark.vala', + 'src/vala/Pluie/Io.Writter.vala', 'src/vala/Pluie/Yaml.global.vala', 'src/vala/Pluie/Yaml.AbstractChild.vala', 'src/vala/Pluie/Yaml.AbstractNode.vala', diff --git a/samples/yaml-dump.vala b/samples/yaml-dump.vala index f62bb5f..44e3355 100644 --- a/samples/yaml-dump.vala +++ b/samples/yaml-dump.vala @@ -64,7 +64,7 @@ int main (string[] args) // sum of the bytes of 'text' that already have been written to the stream written += dos.write (data[written:data.length]); } - of.echo ("write %lld bytes in `%s`".printf ((long) written, genpath)); + of.echo ("write %ld bytes in `%s`".printf ((long) written, genpath)); Yaml.Dumper.show_yaml_string (root, true, true, true); } catch (Error e) { stderr.printf ("%s\n", e.message); diff --git a/samples/yaml-serialize.vala b/samples/yaml-serialize.vala new file mode 100644 index 0000000..8d6b853 --- /dev/null +++ b/samples/yaml-serialize.vala @@ -0,0 +1,113 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * @software : pluie-yaml + * @version : 0.5 + * @type : library + * @date : 2018 + * @licence : GPLv3.0 + * @author : a-Sansara <[dev]at[pluie]dot[org]> + * @copyright : pluie.org + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * This file is part of pluie-yaml. + * + * pluie-yaml is free software (free as in speech) : you can redistribute it + * and/or modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * pluie-yaml is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with pluie-yaml. If not, see . + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ + +using GLib; +using Gee; +using Pluie; + +public void test_object(Yaml.Example obj) +{ + of.action ("Test Object", obj.yaml_name); + obj.type_object.method_a (); + if (obj.type_gee_al != null) { + of.keyval("yaml_name" , "%s" .printf(obj.yaml_name)); + of.keyval("type_int" , "%d" .printf(obj.type_int)); + of.keyval("type_bool" , "%s" .printf(obj.type_bool.to_string ())); + of.keyval("type_char" , "%c" .printf(obj.type_char)); + of.keyval("type_string" , "%s" .printf(obj.type_string)); + of.keyval("type_uchar" , "%u" .printf(obj.type_uchar)); + of.keyval("type_uint" , "%u" .printf(obj.type_uint)); + of.keyval("type_float" , "%f" .printf(obj.type_float)); + of.keyval("type_double" , "%f" .printf(obj.type_double)); + of.keyval("type_struct" , "%s" .printf(obj.type_struct.to_string ())); + of.keyval("type_enum" , "%d (%s)" .printf(obj.type_enum, obj.type_enum.infos())); + of.keyval("type_gee_al", "(%s<%s>)" .printf(obj.type_gee_al.get_type ().name (), obj.type_gee_al.element_type.name ())); + foreach (var v in obj.type_gee_al) { + of.echo(" - item : %g".printf (v)); + } + of.keyval("type_object", "(%s)" .printf(obj.type_object.get_type ().name ())); + of.keyval(" toto" , "%s (string)" .printf(obj.type_object.toto)); + of.keyval(" tapa" , "%s (string)" .printf(obj.type_object.tata)); + of.keyval(" titi" , "%d (int)" .printf(obj.type_object.titi)); + of.keyval(" tutu" , "%s (bool)" .printf(obj.type_object.tutu.to_string ())); + obj.type_object.method_a (); + + of.keyval("type_gee_alobject", "(%s<%s>)" .printf(obj.type_gee_alobject.get_type ().name (), obj.type_gee_alobject.element_type.name ())); + foreach (var child in obj.type_gee_alobject) { + of.echo(" == entry (%s) ==".printf(child.get_type ().name ())); + of.keyval(" toto" , "%s (string)" .printf(child.toto)); + of.keyval(" tapa" , "%s (string)" .printf(child.tata)); + of.keyval(" titi" , "%d (int)" .printf(child.titi)); + of.keyval(" tutu" , "%s (bool)" .printf(child.tutu.to_string ())); + child.method_a (); + } + } +} + +int main (string[] args) +{ + Echo.init(false); + + var path = Yaml.DATA_PATH + "/tag.yml"; + var done = false; + + of.title ("Pluie Yaml Library", Pluie.Yaml.VERSION, "a-sansara"); + Pluie.Yaml.DEBUG = false; + var config = new Yaml.Config (path, true); + var root = config.root_node (); + if ((done = root != null)) { + root.display_childs (); + + of.action ("Yaml build first child", root.first ().name); + Yaml.Example obj = (Yaml.Example) Yaml.Builder.from_node (root.first ()); + obj = (Yaml.Example) Yaml.Builder.from_node (root.first ()); + test_object (obj); + + of.action ("Serialize", obj.yaml_name); + uint8[] zdata = Yaml.serialize (obj); + of.echo ("zdata size : %ld".printf (zdata.length)); + for (var i = 0; i < zdata.length; i++) { + print ("%02x", zdata[i]); + } + of.echo (""); + of.action ("Deserialize zdata from", obj.yaml_name); + message ("*"); + root = Yaml.deserialize (zdata); + message ("*"); + root.display_childs (); + of.action ("Yaml build first child", obj.yaml_name); + obj = (Yaml.Example) Yaml.Builder.from_node (root.first ()); + message ("*"); + test_object (obj); + + } + + return (int) done; +} diff --git a/src/vala/Pluie/Io.InputChunkStream.vala b/src/vala/Pluie/Io.InputChunkStream.vala new file mode 100644 index 0000000..d9f2a8b --- /dev/null +++ b/src/vala/Pluie/Io.InputChunkStream.vala @@ -0,0 +1,79 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * @software : pluie-yaml + * @version : 0.5 + * @type : library + * @date : 2018 + * @licence : GPLv3.0 + * @author : a-Sansara <[dev]at[pluie]dot[org]> + * @copyright : pluie.org + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * This file is part of pluie-yaml. + * + * pluie-yaml is free software (free as in speech) : you can redistribute it + * and/or modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * pluie-yaml is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with pluie-yaml. If not, see . + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ + +using GLib; +class Pluie.Io.InputChunkStream : Object +{ + protected ulong chunk_index; + protected uint8 chunk_size; + protected uint8 buffer_size; + protected uint8[] buffer; + protected FileStream fs; + + public InputChunkStream (string path, uint8 chunk_size) + { + this.chunk_size = chunk_size; + this.buffer = new uint8[this.chunk_size]; + this.fs = FileStream.open (path, "r"); + this.chunk_index = 0; + } + public bool eof () + { + bool stop = this.fs.eof (); + if (stop) { + this.buffer = null; + } + return stop; + } + public unowned uint8[] read () + { + if (!this.eof ()) { + this.buffer_size = (uint8) this.fs.read (this.buffer); + this.chunk_index++; + } + return this.buffer; + } + public unowned uint8 get_buffer_size () + { + return this.buffer_size; + } + public unowned uint8[] get_buffer () + { + return this.buffer; + } + public ulong get_chunk_index () + { + return this.chunk_index-1; + } + public uint8 get_chunk_size () + { + return this.chunk_size; + } +} diff --git a/src/vala/Pluie/Io.Reader.vala b/src/vala/Pluie/Io.Reader.vala index ad46add..1a65e4e 100644 --- a/src/vala/Pluie/Io.Reader.vala +++ b/src/vala/Pluie/Io.Reader.vala @@ -142,4 +142,18 @@ public class Pluie.Io.Reader return this.readable; } + /** + * + */ + public string? get_contents () + { + string? read = null; + try { + FileUtils.get_contents (this.path, out read); + } + catch(GLib.Error e) { + of.error (e.message); + } + return read; + } } diff --git a/src/vala/Pluie/Io.Writter.vala b/src/vala/Pluie/Io.Writter.vala new file mode 100644 index 0000000..fe33f53 --- /dev/null +++ b/src/vala/Pluie/Io.Writter.vala @@ -0,0 +1,95 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * @software : pluie-yaml + * @version : 0.5 + * @type : library + * @date : 2018 + * @licence : GPLv3.0 + * @author : a-Sansara <[dev]at[pluie]dot[org]> + * @copyright : pluie.org + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * This file is part of pluie-yaml. + * + * pluie-yaml is free software (free as in speech) : you can redistribute it + * and/or modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * pluie-yaml is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with pluie-yaml. If not, see . + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ + +using GLib; +using Gee; +using Pluie; + +/** + * basic writer + */ +public class Pluie.Io.Writter +{ + /** + * current file path + */ + public string path { get; internal set; } + /** + * + */ + public File file { get; internal set; } + /** + * stream used to read the file + */ + DataOutputStream stream; + + /** + * construct a reader + * by adding {@link Io.StreamLineMark} + * @param path the path to load + */ + public Writter (string path) + { + this.path = path; + this.file = File.new_for_path (path); + try { + this.stream = new DataOutputStream(file.create (FileCreateFlags.NONE)); + if (!file.query_exists ()) { + of.error ("cannot create file '%s'".printf (path)); + } + } + catch (GLib.Error e) { + of.error (e.message); + } + } + + /** + * read current stream by line + * @param mark a mark used to operate possible future rewind + * @return current readed line + */ + public bool write (uint8[] data) + { + bool done = false; + try { + long written = 0; + while (written < data.length) { + // sum of the bytes that already have been written to the stream + written += stream.write (data[written:data.length]); + } + done = written == data.length; + } + catch (GLib.Error e) { + of.error (e.message); + } + return done; + } + +} diff --git a/src/vala/Pluie/Yaml.AbstractNode.vala b/src/vala/Pluie/Yaml.AbstractNode.vala index 54077d2..6f402a0 100644 --- a/src/vala/Pluie/Yaml.AbstractNode.vala +++ b/src/vala/Pluie/Yaml.AbstractNode.vala @@ -110,8 +110,7 @@ public abstract class Pluie.Yaml.AbstractNode : GLib.Object int indent = Yaml.Dumper.DEFAULT_INDENT, bool show_doc = Yaml.Dumper.SHOW_DOC, bool show_tags = Yaml.Dumper.SHOW_TAGS, - bool show_fullkeys = Yaml.Dumper.SHOW_FULL_KEYS, - bool show_colors = Yaml.Dumper.SHOW_COLORS + bool show_fullkeys = Yaml.Dumper.SHOW_FULL_KEYS ) { return Yaml.Dumper.dump ( @@ -119,8 +118,7 @@ public abstract class Pluie.Yaml.AbstractNode : GLib.Object indent, show_doc, show_tags, - show_fullkeys, - show_colors + show_fullkeys ); } } diff --git a/src/vala/Pluie/Yaml.Config.vala b/src/vala/Pluie/Yaml.Config.vala index 178e0d1..1b7392d 100644 --- a/src/vala/Pluie/Yaml.Config.vala +++ b/src/vala/Pluie/Yaml.Config.vala @@ -101,9 +101,9 @@ public class Pluie.Yaml.Config /** * */ - public Yaml.Node root_node () + public Yaml.Root root_node () { - return this.finder.context; + return this.finder.context as Yaml.Root; } /** diff --git a/src/vala/Pluie/Yaml.Dumper.vala b/src/vala/Pluie/Yaml.Dumper.vala index c04d8e7..96cda49 100644 --- a/src/vala/Pluie/Yaml.Dumper.vala +++ b/src/vala/Pluie/Yaml.Dumper.vala @@ -56,11 +56,11 @@ public class Pluie.Yaml.Dumper /** * */ - public static bool SHOW_COLORS { get; internal set; default = false; } + static bool SHOW_COLOR { get; internal set; default = false; } /** * */ - public static bool SHOW_LINE { get; internal set; default = false; } + static bool SHOW_LINE { get; internal set; default = false; } /** * */ @@ -86,16 +86,11 @@ public class Pluie.Yaml.Dumper bool show_fullkeys = Yaml.Dumper.SHOW_FULL_KEYS ) { - bool prev1 = SHOW_LINE; - bool prev2 = SHOW_COLORS; - bool prev3 = SHOW_TAGS; SHOW_LINE = show_line; - SHOW_COLORS = show_color; - SHOW_TAGS = show_tags; - string yaml = dump (node, indent, show_doc, show_tags, show_fullkeys, show_color); - SHOW_LINE = prev1; - SHOW_COLORS = prev2; - SHOW_TAGS = prev3; + SHOW_COLOR = show_color; + string yaml = dump (node, indent, show_doc, show_tags, show_fullkeys); + SHOW_LINE = false; + SHOW_COLOR = false; of.action ("Yaml string representation for", node!= null ? node.name : "null"); print ("%s%s%s", "\n", yaml, "\n"); } @@ -108,8 +103,7 @@ public class Pluie.Yaml.Dumper int indent = Yaml.Dumper.DEFAULT_INDENT, bool show_doc = Yaml.Dumper.SHOW_DOC, bool show_tags = Yaml.Dumper.SHOW_TAGS, - bool show_fullkeys = Yaml.Dumper.SHOW_FULL_KEYS, - bool show_colors = Yaml.Dumper.SHOW_COLORS + bool show_fullkeys = Yaml.Dumper.SHOW_FULL_KEYS ) { var yaml = new StringBuilder(""); @@ -118,7 +112,7 @@ public class Pluie.Yaml.Dumper line = 0; yaml_root (ref yaml, node as Yaml.Root, show_doc); foreach (var child in node) { - yaml.append (Yaml.Dumper.dump (child, indent, show_doc, show_tags, show_fullkeys, show_colors)); + yaml.append (Yaml.Dumper.dump (child, indent, show_doc, show_tags, show_fullkeys)); } } else if (node.ntype.is_single_pair ()) { @@ -128,7 +122,7 @@ public class Pluie.Yaml.Dumper else if (node.ntype.is_collection ()) { yaml_key (ref yaml, node, indent, show_tags); foreach (var child in node) { - yaml.append (Yaml.Dumper.dump (child, indent, show_doc, show_tags, show_fullkeys, show_colors)); + yaml.append (Yaml.Dumper.dump (child, indent, show_doc, show_tags, show_fullkeys)); } } else if (node.ntype.is_scalar ()) { @@ -156,12 +150,12 @@ public class Pluie.Yaml.Dumper private static void yaml_tag (ref StringBuilder yaml, Yaml.Node node, bool show_tags) { if (node.tag != null && show_tags) { - if (SHOW_COLORS) yaml.append (of.c (ECHO.COMMAND).to_string ()); + if (SHOW_COLOR) yaml.append (of.c (ECHO.COMMAND).to_string ()); yaml.append ("!%s!%s".printf ( node.tag.handle, node.tag.value )); - yaml.append ("%s ".printf (SHOW_COLORS ? Color.off () : "")); + yaml.append ("%s ".printf (SHOW_COLOR ? Color.off () : "")); } } @@ -193,7 +187,7 @@ public class Pluie.Yaml.Dumper else if (!node.is_first ()) { yaml_indent (ref yaml, node, indent, true); } - if (node.parent != null && node.parent.ntype.is_sequence ()) yaml.append (!SHOW_COLORS ? "- " : of.c (ECHO.DATE).s ("- ")); + if (node.parent != null && node.parent.ntype.is_sequence ()) yaml.append (!SHOW_COLOR ? "- " : of.c (ECHO.DATE).s ("- ")); if (wrapseq) { if (Yaml.DEBUG) of.warn ("node %s wrapseq ? %s".printf (node.name, wrapseq.to_string ())); } @@ -205,8 +199,8 @@ public class Pluie.Yaml.Dumper } len = (!show_tags || (node.tag == null && !node.ntype.is_collection ()) && len > 0) ? len +1 - node.name.length : 0; yaml.append("%s%s%s".printf( - !SHOW_COLORS ? @"%s%$(len)s ".printf (node.name, " ") : of.c (node.ntype.is_collection() ? ECHO.TIME : ECHO.OPTION).s(@"%s%$(len)s".printf (node.name, " ")), - !SHOW_COLORS ? ":" : of.c (ECHO.DATE).s(":"), + !SHOW_COLOR ? @"%s%$(len)s ".printf (node.name, " ") : of.c (node.ntype.is_collection() ? ECHO.TIME : ECHO.OPTION).s(@"%s%$(len)s".printf (node.name, " ")), + !SHOW_COLOR ? ":" : of.c (ECHO.DATE).s(":"), node.ntype.is_collection () ? "\n" : " " )); } @@ -218,10 +212,10 @@ public class Pluie.Yaml.Dumper private static void yaml_scalar (ref StringBuilder yaml, Yaml.Node node, int indent, bool show_tags) { if (!(node.parent !=null && node.parent.ntype.is_single_pair ())) yaml_indent (ref yaml, node, indent); - if (node.parent != null && node.parent.ntype.is_sequence ()) yaml.append (!SHOW_COLORS ? "- " : of.c (ECHO.DATE).s ("- ")); + if (node.parent != null && node.parent.ntype.is_sequence ()) yaml.append (!SHOW_COLOR ? "- " : of.c (ECHO.DATE).s ("- ")); yaml_tag (ref yaml, node, show_tags); yaml.append ("%s\n".printf ( - !SHOW_COLORS ? node.data : of.c (ECHO.OPTION_SEP).s (node.data) + !SHOW_COLOR ? node.data : of.c (ECHO.OPTION_SEP).s (node.data) )); } } diff --git a/src/vala/Pluie/Yaml.Register.vala b/src/vala/Pluie/Yaml.Register.vala index e9fe32d..551cb10 100644 --- a/src/vala/Pluie/Yaml.Register.vala +++ b/src/vala/Pluie/Yaml.Register.vala @@ -116,6 +116,7 @@ public class Pluie.Yaml.Register /** * add one or multiple namespace for tag resolution + * namespace value ar same as in vala source code (so with dot separator) * @param name a namespace to register */ public static bool add_namespace (string name, ...) diff --git a/src/vala/Pluie/Yaml.global.vala b/src/vala/Pluie/Yaml.global.vala index bf6b74a..fd94e07 100644 --- a/src/vala/Pluie/Yaml.global.vala +++ b/src/vala/Pluie/Yaml.global.vala @@ -87,6 +87,72 @@ namespace Pluie MAPPING_NOT_SINGLE_PAIR } + private const ZlibCompressorFormat ZFORMAT = ZlibCompressorFormat.GZIP; + + /** + * + */ + private void convert (File source, File dest, Converter converter) throws Error { + var src_stream = source.read (); + var dst_stream = dest.replace (null, false, 0); + var conv_stream = new ConverterOutputStream (dst_stream, converter); + // 'splice' pumps all data from an InputStream to an OutputStream + conv_stream.splice (src_stream, 0); + } + + /** + * + */ + public static uint8[] serialize (GLib.Object? obj) + { + Array a = new Array (); + if (obj != null) { + var node = obj.get_type ().is_a (typeof (Yaml.Node)) ? obj as Yaml.Node : Yaml.Builder.to_node (obj); + if (node != null) { + var content = node.to_yaml_string (); + var date = new GLib.DateTime.now_local ().format ("%s"); + var path = Path.build_filename (Environment.get_tmp_dir (), "pluie-yaml-%s-%s.source".printf (date, node.uuid)); + var writter = new Io.Writter (path); + if (writter.write (content.data)) { + try { + var gzfile = File.new_for_path (path + ".gz"); + convert (writter.file, gzfile, new ZlibCompressor (ZFORMAT)); + var reader = new Io.InputChunkStream(path + ".gz", 80); + while (!reader.eof ()) { + var b = reader.read (); + a.append_vals (b, reader.get_buffer_size ()); + } + } + catch (GLib.Error e) { + of.error (e.message); + } + } + } + } + return a.data; + } + + /** + * + */ + public static Yaml.Root deserialize (uint8[] zdata) + { + Yaml.Root? obj = null; + if (zdata.length > 0) { + var date = new GLib.DateTime.now_local ().format ("%s"); + var path = Path.build_filename (Environment.get_tmp_dir (), "pluie-yaml-%s.gz".printf (date)); + var dpath = Path.build_filename (Environment.get_tmp_dir (), "pluie-yaml-%s.source".printf (date)); + var writter = new Io.Writter (path); + if (writter.write (zdata)) { + var file = File.new_for_path (dpath); + convert (writter.file, file, new ZlibDecompressor (ZFORMAT)); + var config = new Yaml.Config (dpath); + obj = config.root_node (); + } + } + return obj; + } + /** * haxadecimal sequence */