From 3de39868e62066447f92797d2767f7bf6e125c9d Mon Sep 17 00:00:00 2001 From: a-Sansara Date: Fri, 10 Aug 2018 02:12:08 +0200 Subject: [PATCH] suite tag impl --- README.md | 4 +- meson.build | 5 +- resources/tag.yml | 2 + samples/yaml-tag.vala | 79 +++++++++++++ samples/yamlize.vala | 98 ---------------- src/vala/Pluie/Yaml.Object.vala | 178 ++++++++++++++++++++++------- src/vala/Pluie/Yaml.Processor.vala | 14 ++- 7 files changed, 231 insertions(+), 149 deletions(-) create mode 100644 samples/yaml-tag.vala delete mode 100644 samples/yamlize.vala diff --git a/README.md b/README.md index 6dafa8a..56e07d8 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ GNU GPL v3 ## Prerequisites -`valac meson ninja glib gee gobject pluie-echo` +`valac meson ninja libyaml glib gobject gmodule gee pluie-echo` see https://git.pluie.org/pluie/libpluie-echo in order to install pluie-echo-0.2 pkg @@ -42,7 +42,7 @@ sudo ninja install -C build ## Compilation ``` -valac --pkg gee-0.8 --pkg pluie-echo-0.2 --pkg pluie-yaml-0.4 main.vala +valac --pkg pluie-echo-0.2 --pkg pluie-yaml-0.4 main.vala ``` you can use `./build.sh` to rebuild/install the **pluie-yaml** lib and compile samples files diff --git a/meson.build b/meson.build index 3f34509..d029313 100644 --- a/meson.build +++ b/meson.build @@ -31,6 +31,7 @@ project('libpluie-yaml', 'vala', 'c') cc = meson.get_compiler('c') dep_glib = dependency('glib-2.0') dep_gobject = dependency('gobject-2.0') +dep_gmodule = dependency('gmodule-2.0') dep_gio = dependency('gio-2.0') dep_gee = dependency('gee-0.8') dep_echo = dependency('pluie-echo-0.2') @@ -92,7 +93,7 @@ libpluie_yaml = library( sources, vala_header : 'pluie_yaml.h', vala_vapi : 'pluie-yaml-' +version+'.vapi', - dependencies : [dep_glib, dep_gobject, dep_gio, dep_gee, dep_echo, dep_m, dep_yaml], + dependencies : [dep_glib, dep_gobject, dep_gmodule, dep_gio, dep_gee, dep_echo, dep_m, dep_yaml], install : true, install_dir : [get_option('libdir'), incdir, true] ) @@ -100,7 +101,7 @@ libpluie_yaml = library( pkgconfig = import('pkgconfig') pkgconfig.generate( libraries : libpluie_yaml, - requires : 'glib-2.0 gobject-2.0 gio-2.0 gee-0.8 pluie-echo-0.2', + requires : 'glib-2.0 gmodule-2.0 gobject-2.0 gio-2.0 gee-0.8 pluie-echo-0.2', variables : 'datarootdir='+join_paths('${prefix}', get_option('datadir'))+'\ndatadir='+join_paths('${datarootdir}', 'pluie'), version : version, name : 'libpluie-yaml', diff --git a/resources/tag.yml b/resources/tag.yml index c69c87f..980355d 100644 --- a/resources/tag.yml +++ b/resources/tag.yml @@ -7,9 +7,11 @@ type_int : !vala!int 3306 type_bool : !vala!bool false type_char : !vala!char c + type_string : !vala!string mystring1 !vala!Pluie.Yaml.Example test2 : type_int : !vala!int 3306 type_bool : !vala!bool true type_char : !vala!char g + type_string : !vala!string mystring2 diff --git a/samples/yaml-tag.vala b/samples/yaml-tag.vala new file mode 100644 index 0000000..c3ea197 --- /dev/null +++ b/samples/yaml-tag.vala @@ -0,0 +1,79 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * @software : lib-yaml + * @version : 0.4 + * @date : 2018 + * @licence : GPLv3.0 + * @author : a-Sansara <[dev]at[pluie]dot[org]> + * @copyright : pluie.org + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * This file is part of lib-yaml. + * + * lib-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. + * + * lib-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 lib-yaml. If not, see . + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + */ + +using GLib; +using Gee; +using Pluie; + +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.Scanner.DEBUG = false; + Yaml.Object? obj = null; + var config = new Yaml.Config (path, true); + var root = config.root_node (); + root.display_childs (); + // define a map with base Yaml.Object type rather than target type + Gee.HashMap list = new Gee.HashMap (); + if ((done = root != null)) { + foreach (var node in root) { + of.action ("Yaml.Object from node", node.name); + of.echo (node.to_string (false)); + if ((obj = Yaml.Object.from_node (node)) != null) { + list[node.name] = obj; + } + else { + of.error ("cannot set Yaml.Object from node : %s".printf (node.name), true); + } + node = node.next_sibling (); + } + } + of.echo (""); + // hard code + Yaml.Example? o = new Pluie.Yaml.Example (); + foreach (var entry in list.entries) { + of.action ("Getting Hard coded values for Yaml.Object %s".printf (of.c (ECHO.MICROTIME).s (o.type_from_self ())), entry.key); + if ((o = entry.value as Yaml.Example)!=null) { + of.keyval("type_int" , "%d".printf(o.type_int)); + of.keyval("type_bool" , "%s".printf(o.type_bool.to_string ())); + of.keyval("type_char" , "%c".printf(o.type_char)); + of.keyval("type_string", "%s".printf(o.type_string)); + } + } + + of.rs (done); + of.echo (); + return (int) done; + +} diff --git a/samples/yamlize.vala b/samples/yamlize.vala deleted file mode 100644 index 49b58c4..0000000 --- a/samples/yamlize.vala +++ /dev/null @@ -1,98 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * @software : lib-yaml - * @version : 0.4 - * @date : 2018 - * @licence : GPLv3.0 - * @author : a-Sansara <[dev]at[pluie]dot[org]> - * @copyright : pluie.org - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * This file is part of lib-yaml. - * - * lib-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. - * - * lib-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 lib-yaml. If not, see . - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ - -using GLib; -using Gee; -using Pluie; - -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.Scanner.DEBUG = false; - var config = new Yaml.Config (path, true); - var root = config.root_node (); - root.display_childs (); - // define a map with base Yaml.Object - Gee.HashMap list = new Gee.HashMap (); - // require to register type; - Yaml.Example? obj = new Pluie.Yaml.Example (); - if ((done = root != null)) { - foreach (var node in root) { - of.action ("Yamlize Yaml.Example", node.name); - of.echo (node.to_string ()); - if (node.tag != null) { - of.action ("tag value", node.tag.value); - var type = Yaml.Object.type_from_name (node.tag.value); - if (type != null && type.is_object ()) { - of.echo ("type founded : %s".printf (type.to_string ())); - -//~ of.echo ("======"); -//~ of.action ("Auto Instanciate object as Yaml.Object", type.name ()); -//~ var o = (Yaml.Object) GLib.Object.new (type); -//~ if (o != null) { -//~ of.action ("Yamlize Yaml.Object", type.name ()); -//~ of.state (o.yamlize (node)); -//~ of.action ("Hardcode casting as", type.name ()); -//~ var so = o as Yaml.Example; -//~ of.action ("Hardcode Getting values object", type.name ()); -//~ of.keyval("type_int" , "%d".printf(so.type_int)); -//~ of.keyval("type_bool", "%s".printf(so.type_bool.to_string ())); -//~ of.keyval("type_char", "%c".printf(so.type_char)); -//~ of.echo ("======"); -//~ } - list[node.name] = (Pluie.Yaml.Object) GLib.Object.new (type); - of.state (list[node.name].yamlize (node)); - } - else { - of.warn ("type %s not found, you probably need to instanciate it first".printf (node.tag.value)); - } - } - node = node.next_sibling (); - } - } - - foreach (var entry in list.entries) { - of.action ("Getting values", entry.key); - if ((obj = entry.value as Yaml.Example)!=null) { - 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.rs (done); - of.echo (); - return (int) done; - -} diff --git a/src/vala/Pluie/Yaml.Object.vala b/src/vala/Pluie/Yaml.Object.vala index c82854d..909ce30 100644 --- a/src/vala/Pluie/Yaml.Object.vala +++ b/src/vala/Pluie/Yaml.Object.vala @@ -31,67 +31,163 @@ using Gee; /** * a test class to implements yamlize - */ public abstract class Pluie.Yaml.Object : GLib.Object { + private static GLib.Module? p_module; - public static string type_name (string name) + /** + * + */ + private static unowned GLib.Module p_open_module () { - return name.replace(".", ""); - } - - public static GLib.Type? type_from_name (string name) - { - GLib.Type? type = Type.from_name (type_name (name)); - return type; - } - - public string get_type_name () - { - return Type.from_instance (this).name (); + if (p_module == null) { + p_module = GLib.Module.open (null, 0); + } + return p_module; } /** * */ - public bool yamlize (Yaml.Node node) + public static GLib.Type? type_from_string (string name) { - bool done = false; + GLib.Type? type = Type.from_name (name.replace(".", "")); + return type; + } + + /** + * retriew GLib.Type related to specified vala name + * @param name a valid vala identifier name + */ + public static Type type_from_vala (string name) + { + void * s; + p_open_module (); + if (!p_module.symbol (resolve_c_name(@"$(name).get_type"), out s)) { + of.error ("cannot resolve type %s (not found)".printf (name)); + } + return ((dlgType) s)(); + } + + /** + * retiew GLib.Type related to specified tag value. + * Type may not be registered yet + */ + public static Type? type_from_tag (string tagValue) + { + var type = type_from_string (tagValue); + if(type != null && type == Type.INVALID) { + type = type_from_vala (tagValue); + } + return type; + } + + /** + * retiew GLib.Type related to instance + */ + public string type_from_self () + { + return Type.from_instance (this).name (); + } + + /** + * retriew corresponding c name related to specified vala name + * @param name a valid vala identifier name + */ + public static string resolve_c_name (string name) + { + string? str = null; + MatchInfo? mi = null; + StringBuilder sb = new StringBuilder (); + bool begin = true; try { - if (node!= null && !node.empty ()) { - Iterator it = node.iterator (); - foreach (var child in node) { - of.action ("yamlize ", child.to_string ()); - var pspec = this.get_class ().find_property (child.name); - if (pspec != null) { - if (child.first ().tag != null) { - of.keyval ("found tag", child.first ().tag.@value); -//~ of.keyval ("value is `%s`", child.first ().data); - switch (child.first ().tag.@value) { - case "char" : - this.set (child.name, child.first ().data[0]); - break; - case "bool" : - this.set (child.name, bool.parse(child.first ().data.down ())); - break; - case "int" : - this.set (child.name, int.parse(child.first ().data)); - break; + var reg = new Regex ("([^.]*).?"); + for (reg.match (name, 0, out mi) ; mi.matches () ; mi.next ()) { + if ((str = mi.fetch (1)) != null && str.length > 0) { + if (!begin) sb.append_unichar ('_'); + else begin = false; + sb.append_unichar (str[0].tolower ()); + sb.append (str.substring(1)); + } + } + } + catch (GLib.RegexError e) { + of.error (e.message, true); + } + return !begin ? sb.str : name; + } + + [CCode (has_target = false)] + private delegate Type dlgType(); + + /** + * + */ + public static Yaml.Object? from_node (Yaml.Node node) + { + Yaml.Object? obj = null; + try { + if (node.tag != null) { + if (Yaml.Scanner.DEBUG) of.action ("tag value", node.tag.value); + Type? type = type_from_tag (node.tag.value); + if (type != null && type.is_object ()) { + if (Yaml.Scanner.DEBUG) of.echo ("object type founded : %s".printf (type.to_string ())); + obj = (Yaml.Object) GLib.Object.new (type); + if (node!= null && !node.empty ()) { + GLib.ParamSpec? def = null; + Yaml.Node? snode = null; + foreach (var child in node) { + if ((def = obj.get_class ().find_property (child.name)) != null) { + if ((snode = child.first ()) != null) { + if (snode.tag != null) { + obj.set_by_basic_type (def.name, def.value_type, snode); + } + else { + obj.set (child.name, snode.data); + } + } } } - else { - this.set (child.name, child.first ().data); - } } } + else { + of.echo ("searched type : %s".printf (type.to_string ())); + } } } catch (GLib.Error e) { of.warn (e.message); - done = false; } - done = true; - return done; + return obj; + } + + /** + * + */ + public void set_by_basic_type (string name, GLib.Type type, Yaml.Node node) + { + GLib.Value v = GLib.Value(type); + var data = node.data; + if (Yaml.Scanner.DEBUG) { + of.action("Auto setting property value %s".printf (of.c (ECHO.MICROTIME).s (type.name ())), name); + of.echo (data); + } + switch (type) + { + case Type.STRING : + v.set_string(data); + break; + case Type.CHAR : + v.set_schar((int8)data.data[0]); + break; + case Type.BOOLEAN : + v.set_boolean (bool.parse(data.down ())); + break; + case Type.INT : + v.set_int(int.parse(data)); + break; + } + this.set_property(name, v); } } diff --git a/src/vala/Pluie/Yaml.Processor.vala b/src/vala/Pluie/Yaml.Processor.vala index 438e7f1..15df154 100644 --- a/src/vala/Pluie/Yaml.Processor.vala +++ b/src/vala/Pluie/Yaml.Processor.vala @@ -271,7 +271,8 @@ public class Pluie.Yaml.Processor */ private void on_tag_directive () { - of.action ("on_tag_directive %s".printf (this.event.data["handle"]), this.event.data["prefix"]); + if (Yaml.Scanner.DEBUG) + of.action ("on_tag_directive %s".printf (this.event.data["handle"]), this.event.data["prefix"]); this.tags[this.event.data["handle"]] = this.event.data["prefix"]; } @@ -315,8 +316,9 @@ public class Pluie.Yaml.Processor private void on_tag (bool onKey = false) { if (this.event.evtype.is_tag ()) { - of.keyval ("tag %s".printf (this.event.data["handle"]), this.event.data["suffix"]); - if (this.tags.contains (this.event.data["handle"])) { + if (Yaml.Scanner.DEBUG) + of.keyval ("tag %s".printf (this.event.data["handle"]), this.event.data["suffix"]); + if (this.tags.has_key (this.event.data["handle"])) { var tag = new Yaml.Tag (this.event.data["suffix"], this.tags[this.event.data["handle"]]); if (onKey) this.keyTag = tag; @@ -449,12 +451,12 @@ public class Pluie.Yaml.Processor private void on_update () { if (this.node != null) { - of.echo (this.node.name); + if (Yaml.Scanner.DEBUG) of.echo (this.node.name); } if (this.change) { - of.action ("on change", this.node.name); + if (Yaml.Scanner.DEBUG) of.action ("on change", this.node.name); if (this.keyTag != null) { - of.action ("setting tag", this.keyTag.@value); + if (Yaml.Scanner.DEBUG) of.action ("setting tag", this.keyTag.@value); this.node.tag = this.keyTag; } else if (this.valueTag != null) {