diff --git a/README.md b/README.md index 7482569..9e55139 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ load a single document. ```vala var path = "./config/main.yml"; // uncomment to enable debug - // Pluie.Yaml.Scanner.DEBUG = true; + // Pluie.Yaml.DEBUG = true; var loader = new Yaml.Loader (path /* , displayFile, displayNode */); if ((done = loader.done)) { Yaml.Node root = loader.get_nodes (); @@ -136,7 +136,7 @@ load a single document. ### finder -**lib-yaml** provide a `Yaml.Finder` to easily retriew a particular yaml node. +**pluie-yaml** provide a `Yaml.Finder` to easily retriew a particular yaml node. Search path definition has two mode. The default mode is `Yaml.FIND_MODE.DOT` - child mapping node are separated by dot @@ -270,13 +270,65 @@ on vala side : ```vala ... - Yaml.Example obj = (Yaml.Example) Yaml.Object.from_node (root.first ()); + var obj = (Yaml.Example) Yaml.Builder.from_node (root.first ()); of.echo("obj.type_int : %d".printf (o.type_int)); obj.type_object.method_a () ``` ![pluie-yaml-tag](https://www.meta-tech.academy/img/libyaml-tag-ex.png) +### Builder + +**pluie-yaml** has automatic mechanisms to build Yaml.Object instances (and derived classes) +and set basics types properties, enum properties and based Yaml.Object properties. + +Other types like struct or native GLib.Object (Gee.ArrayList for example) properties need some stuff in order to populate instances appropriately +We cannot do introspection on Structure's properties, so you need to implement a method which will do the job. + +First at all you need to register in the static construct, (properties) types that need some glue for instanciation. + +```vala +public class Example : Yaml.Object +{ + static construct + { + Yaml.Object.register.add_type (typeof (Example), typeof (ExampleStruct)); + Yaml.Object.register.add_type (typeof (Example), typeof (Gee.ArrayList)); + } + ... +``` + +Secondly you must override the `Yaml.Object populate_by_type (Glib.Typem Yaml.Node node)` original method. +`populate_by_type` is called by the Yaml.Builder only if the type property is prealably registered. + +Example of implementation from `src/vala/Pluie/Yaml.Example.vala` : + +``` + public override void populate_by_type(GLib.Type type, Yaml.Node node) + { + switch (type) { + case typeof (Yaml.ExampleStruct) : + this.type_struct = ExampleStruct.from_yaml_node (node); + break; + case typeof (Gee.ArrayList) : + this.type_gee_al = new Gee.ArrayList (); + if (!node.empty ()) { + foreach (var child in node) { + this.type_gee_al.add(child.data); + } + } + break; + } + } +``` + + +for more details see : +* `src/vala/Pluie/Yaml.Example.vala` +* `src/vala/Pluie/Yaml.ExampleChild.vala` +* `src/vala/Pluie/Yaml.ExampleStruct.vala` +* `samples/yaml-tag.vala` + code from samples/yaml-tag.vala : ![pluie-yaml-tag](https://www.meta-tech.academy/img/libyaml-tag-code.png) diff --git a/meson.build b/meson.build index 99ac1dd..bcddb39 100644 --- a/meson.build +++ b/meson.build @@ -64,21 +64,24 @@ sources = [ 'src/vala/Pluie/Yaml.global.vala', 'src/vala/Pluie/Yaml.AbstractChild.vala', 'src/vala/Pluie/Yaml.AbstractNode.vala', + 'src/vala/Pluie/Yaml.Builder.vala', 'src/vala/Pluie/Yaml.Collection.vala', 'src/vala/Pluie/Yaml.Config.vala', 'src/vala/Pluie/Yaml.Event.vala', 'src/vala/Pluie/Yaml.Example.vala', + 'src/vala/Pluie/Yaml.ExampleChild.vala', + 'src/vala/Pluie/Yaml.ExampleStruct.vala', 'src/vala/Pluie/Yaml.Finder.vala', 'src/vala/Pluie/Yaml.Loader.vala', 'src/vala/Pluie/Yaml.Mapping.vala', 'src/vala/Pluie/Yaml.Node.vala', 'src/vala/Pluie/Yaml.Object.vala', 'src/vala/Pluie/Yaml.Processor.vala', + 'src/vala/Pluie/Yaml.Register.vala', 'src/vala/Pluie/Yaml.Root.vala', 'src/vala/Pluie/Yaml.Scalar.vala', 'src/vala/Pluie/Yaml.Scanner.vala', 'src/vala/Pluie/Yaml.Sequence.vala', - 'src/vala/Pluie/Yaml.SubExample.vala', 'src/vala/Pluie/Yaml.Tag.vala', 'src/c/yaml.c' ] diff --git a/resources/tag.yml b/resources/tag.yml index 9928736..f1c2758 100644 --- a/resources/tag.yml +++ b/resources/tag.yml @@ -1,5 +1,4 @@ %YAML 1.2 -%TAG !yaml! tag:yaml.org,2002: %TAG !v! tag:pluie.org,2018:vala/ --- !v!Pluie.Yaml.Example test1 : @@ -12,12 +11,21 @@ type_uint : !v!uint 62005 type_float : !v!float 42.36 type_double : !v!double 95542123.4579512128 - type_enum : !v!Pluie.Yaml.NODE_TYPE SCALAR - !v!Pluie.Yaml.SubExample type_object : + type_enum : scalar # or int + type_object : toto : totovalue1 tata : tatavalue1 titi : 123 tutu : 1 + type_struct : + red : !v!uint8 214 + green : !v!uint8 78 + blue : 153 + !v!Gee.ArrayList type_gee_al : + - ab_1 + - ab_2 + - ab_3 + - ab_4 !v!Pluie.Yaml.Example test2 : myname : test2object @@ -29,7 +37,8 @@ type_uint : 63005 type_float : 5.28 type_double : 9.28 - !v!Pluie.Yaml.SubExample type_object : + type_enum : PLUIE_YAML_NODE_TYPE_SCALAR + !v!Pluie.Yaml.ExampleChild type_object : toto : totovalue2 tata : tatavalue2 titi : !v!int 456 diff --git a/samples/json-loader.vala b/samples/json-loader.vala index 18dc639..3ad7960 100644 --- a/samples/json-loader.vala +++ b/samples/json-loader.vala @@ -39,7 +39,7 @@ int main (string[] args) var done = false; of.title ("Pluie Yaml Library", Pluie.Yaml.VERSION, "a-sansara"); - Pluie.Yaml.Scanner.DEBUG = false; + Pluie.Yaml.DEBUG = false; var loader = new Yaml.Loader (path, true, true); if ((done = loader.done)) { var root = loader.get_nodes (); diff --git a/samples/yaml-config.vala b/samples/yaml-config.vala index d9aa34c..9a0d910 100644 --- a/samples/yaml-config.vala +++ b/samples/yaml-config.vala @@ -39,7 +39,7 @@ int main (string[] args) var done = false; of.title ("Pluie Yaml Library", Pluie.Yaml.VERSION, "a-sansara"); - Pluie.Yaml.Scanner.DEBUG = false; + Pluie.Yaml.DEBUG = false; var config = new Yaml.Config (path, true); var spath = "bo.host{0}"; var root = config.root_node (); diff --git a/samples/yaml-finder.vala b/samples/yaml-finder.vala index 8d08c66..1baf630 100644 --- a/samples/yaml-finder.vala +++ b/samples/yaml-finder.vala @@ -39,7 +39,7 @@ int main (string[] args) var done = false; of.title ("Pluie Yaml Library", Pluie.Yaml.VERSION, "a-sansara"); -//~ Pluie.Yaml.Scanner.DEBUG = false; +//~ Pluie.Yaml.DEBUG = false; var loader = new Yaml.Loader (path, true); if ((done = loader.done)) { Yaml.Node root = loader.get_nodes (); diff --git a/samples/yaml-imports.vala b/samples/yaml-imports.vala index 8257f61..aed12cb 100644 --- a/samples/yaml-imports.vala +++ b/samples/yaml-imports.vala @@ -40,7 +40,7 @@ int main (string[] args) of.title ("Pluie Yaml Library", Pluie.Yaml.VERSION, "a-sansara"); - Pluie.Yaml.Scanner.DEBUG = false; + Pluie.Yaml.DEBUG = false; var config = new Yaml.Config (path, true); var spath = "^imports"; var node = config.get (spath); diff --git a/samples/yaml-loader.vala b/samples/yaml-loader.vala index 0c0f22e..08db77a 100644 --- a/samples/yaml-loader.vala +++ b/samples/yaml-loader.vala @@ -39,7 +39,7 @@ int main (string[] args) var done = false; of.title ("Pluie Yaml Library", Pluie.Yaml.VERSION, "a-sansara"); - Pluie.Yaml.Scanner.DEBUG = false; + Pluie.Yaml.DEBUG = false; var loader = new Yaml.Loader (path, true, true); if ((done = loader.done)) { var root = loader.get_nodes (); diff --git a/samples/yaml-tag.vala b/samples/yaml-tag.vala index 20cbb1e..196c433 100644 --- a/samples/yaml-tag.vala +++ b/samples/yaml-tag.vala @@ -39,7 +39,7 @@ int main (string[] args) var done = false; of.title ("Pluie Yaml Library", Pluie.Yaml.VERSION, "a-sansara"); - Pluie.Yaml.Scanner.DEBUG = false; + Pluie.Yaml.DEBUG = false; Yaml.Object? obj = null; var config = new Yaml.Config (path, true); var root = config.root_node (); @@ -50,7 +50,7 @@ int main (string[] args) 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) { + if ((obj = Yaml.Builder.from_node (node)) != null) { list[node.name] = obj; } else { @@ -69,14 +69,22 @@ int main (string[] args) of.keyval("type_char" , "%c" .printf(o.type_char)); of.keyval("type_string", "%s" .printf(o.type_string)); of.keyval("type_uchar" , "%u" .printf(o.type_uchar)); + of.keyval("type_uint" , "%u" .printf(o.type_uint)); of.keyval("type_float" , "%f" .printf(o.type_float)); of.keyval("type_double", "%f" .printf(o.type_double)); + of.keyval("type_struct", "%s" .printf(o.type_struct.to_string ())); of.keyval("type_object", "%s" .printf(o.type_object.get_type ().name ())); - of.keyval(" toto (string)", "%s" .printf(o.type_object.toto)); - of.keyval(" tapa (string)", "%s" .printf(o.type_object.tata)); - of.keyval(" titi (int)" , "%d" .printf(o.type_object.titi)); - of.keyval(" tutu (bool)" , "%s" .printf(o.type_object.tutu.to_string ())); + of.keyval(" toto" , "%s (string)" .printf(o.type_object.toto)); + of.keyval(" tapa" , "%s (string)" .printf(o.type_object.tata)); + of.keyval(" titi" , "%d (int)" .printf(o.type_object.titi)); + of.keyval(" tutu" , "%s (bool)" .printf(o.type_object.tutu.to_string ())); o.type_object.method_a (); + if (o.type_gee_al != null) { + of.keyval("type_gee_al", "(%s)" .printf(o.type_gee_al.get_type ().name ())); + foreach (string v in o.type_gee_al) { + of.echo(" - item : %s".printf (v)); + } + } } } diff --git a/samples/yaml-traversing.vala b/samples/yaml-traversing.vala index 28772af..df311ad 100644 --- a/samples/yaml-traversing.vala +++ b/samples/yaml-traversing.vala @@ -39,7 +39,7 @@ int main (string[] args) var done = false; of.title ("Pluie Yaml Library", Pluie.Yaml.VERSION, "a-sansara"); - Pluie.Yaml.Scanner.DEBUG = false; + Pluie.Yaml.DEBUG = false; var config = new Yaml.Config (path, true); var node = config.root_node (); if ((done = node != null)) { diff --git a/src/vala/Pluie/Yaml.AbstractNode.vala b/src/vala/Pluie/Yaml.AbstractNode.vala index 2f925fd..cef5791 100644 --- a/src/vala/Pluie/Yaml.AbstractNode.vala +++ b/src/vala/Pluie/Yaml.AbstractNode.vala @@ -101,7 +101,5 @@ public abstract class Pluie.Yaml.AbstractNode : GLib.Object { return ""; } - - } diff --git a/src/vala/Pluie/Yaml.Builder.vala b/src/vala/Pluie/Yaml.Builder.vala new file mode 100644 index 0000000..9b8e0ef --- /dev/null +++ b/src/vala/Pluie/Yaml.Builder.vala @@ -0,0 +1,259 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * @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; + +/** + * a Yaml.Builder class helping to build vala Yaml.Object from Yaml.Node + */ +public class Pluie.Yaml.Builder +{ + /** + * + */ + private static GLib.Module? p_module; + + /** + * + */ + private static unowned GLib.Module p_open_module () + { + if (p_module == null) { + p_module = GLib.Module.open (null, 0); + } + return p_module; + } + + /** + * + */ + public static GLib.Type? type_from_string (string name) + { + 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; + } + + /** + * 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 { + 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, Type otype = GLib.Type.INVALID) + { + Yaml.Object? obj = null; + try { + Type type = node.tag != null ? type_from_tag (node.tag.value) : otype; + if (type != Type.INVALID) { + Yaml.dbg_action ("vala type founded", "%s (%s)".printf (type.name (), type.to_string ())); + if (type.is_object ()) { + obj = (Yaml.Object) GLib.Object.new (type); + if (node!= null && !node.empty ()) { + GLib.ParamSpec? def = null; + Yaml.Node? scalar = null; + foreach (var child in node) { + if ((def = obj.get_class ().find_property (child.name)) != null) { + Yaml.dbg ("== prop [%s] type is : %s".printf (child.name, def.value_type.name ())); + if (child.ntype.is_single_pair () && (scalar = child.first ()) != null) { + set_from_scalar (ref obj, def.name, def.value_type, scalar.data); + } + else if (child.ntype.is_collection ()) { + set_from_collection (ref obj, type, child, def.value_type); + } + } + else { + of.warn ("property %s not found".printf (child.name)); + } + } + } + } + } + if (obj == null) { + of.warn ("searched type not found : %s".printf (type.name ())); + } + } + catch (GLib.Error e) { + of.warn (e.message); + } + obj.yaml_init (); + return obj; + } + + /** + * + */ + public static void set_from_collection (ref Yaml.Object obj, GLib.Type parentType, Yaml.Node node, GLib.Type type) + { + if (type.is_a (typeof (Yaml.Object))) { + obj.set (node.name, Yaml.Builder.from_node(node, type)); + } + else if (Yaml.Object.register.is_registered_type(parentType, type)) { + Yaml.dbg ("%s is a registered type".printf (type.name ())); + obj.populate_by_type (type, node); + } + else { + Dbg.error ("%s is not registered and cannot be populated".printf (type.name ()), Log.METHOD, Log.LINE); + } + } + + /** + * + */ + public static void set_from_scalar (ref Yaml.Object obj, string name, GLib.Type type, string data) + { + GLib.Value v = GLib.Value(type); + Yaml.dbg_action ("Auto setting property value %s".printf (of.c (ECHO.MICROTIME).s (type.name ())), name); + Yaml.dbg (data); + if (type.is_a(Type.ENUM)) + set_enum_value (ref v, type, data); + else + set_basic_type_value(ref v, type, data); + obj.set_property(name, v); + } + + /** + * + */ + public static void set_basic_type_value (ref Value v, GLib.Type type, string data) + { + switch (type) + { + case Type.STRING : + v.set_string(data); + break; + case Type.CHAR : + v.set_schar((int8)data.data[0]); + break; + case Type.UCHAR : + v.set_uchar((uint8)data.data[0]); + break; + case Type.BOOLEAN : + v.set_boolean (data == "1" || data.down () == "true"); + break; + case Type.INT : + v.set_int(int.parse(data)); + break; + case Type.UINT : + v.set_uint((uint)long.parse(data)); + break; + case Type.LONG : + case Type.INT64 : + v.set_long((long)int64.parse(data)); + break; + case Type.ULONG : + case Type.UINT64 : + v.set_ulong((ulong)uint64.parse(data)); + break; + case Type.FLOAT : + v.set_float((float)double.parse(data)); + break; + case Type.DOUBLE : + v.set_double(double.parse(data)); + break; + } + } + + /** + * + */ + public static void set_enum_value (ref Value v, GLib.Type type, string data) + { + EnumClass kenum = (EnumClass) type.class_ref(); + unowned EnumValue? enumval = kenum.get_value_by_name(data); + if (enumval == null) { + enumval = kenum.get_value_by_nick(data.down()); + int64 e = 0; + if(enumval == null) { + if(!int64.try_parse(data, out e)) { + Dbg.error ("invalid enum value %s".printf(data), Log.METHOD, Log.LINE); + } + else enumval = kenum.get_value((int)e); + } + } + v.set_enum(enumval.value); +//~ of.echo ("enumValue : %d".printf (enumval.value)); + } + +} diff --git a/src/vala/Pluie/Yaml.Config.vala b/src/vala/Pluie/Yaml.Config.vala index e448338..895da0c 100644 --- a/src/vala/Pluie/Yaml.Config.vala +++ b/src/vala/Pluie/Yaml.Config.vala @@ -144,9 +144,7 @@ public class Pluie.Yaml.Config subnode.parent = null; n.add(subnode); } -//~ root.add (n); } -//~ root.update_level(); } /** @@ -175,7 +173,7 @@ public class Pluie.Yaml.Config foreach (var v in this.varmap.entries) { if (v.key != "path") { this.paths[key] = val.replace ("^%s^".printf (v.key), v.value); - if (Yaml.Scanner.DEBUG) of.keyval (key, this.paths[key]); + Yaml.dbg_keyval (key, this.paths[key]); } } } diff --git a/src/vala/Pluie/Yaml.Example.vala b/src/vala/Pluie/Yaml.Example.vala index b9b9fba..109c221 100644 --- a/src/vala/Pluie/Yaml.Example.vala +++ b/src/vala/Pluie/Yaml.Example.vala @@ -26,39 +26,49 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +using GLib; +using Gee; +using Pluie; /** * a test class to implements yamlize - */ public class Pluie.Yaml.Example : Yaml.Object { - public string myname { get; set; } - public string type_string { get; set; } - public int type_int { get; set; } - public uint type_uint { get; set; } - public float type_float { get; set; } - public double type_double { get; set; } - public char type_char { get; set; } - public uchar type_uchar { get; set; } - public unichar type_unichar { get; set; } - public short type_short { get; set; } - public ushort type_ushort { get; set; } - public long type_long { get; set; } - public ulong type_ulong { get; set; } - public size_t type_size_t { get; set; } - public ssize_t type_ssize_t { get; set; } - public int8 type_int8 { get; set; } - public uint8 type_uint8 { get; set; } - public int16 type_int16 { get; set; } - public uint16 type_uint16 { get; set; } - public int32 type_int32 { get; set; } - public uint32 type_uint32 { get; set; } - public int64 type_int64 { get; set; } - public uint64 type_uint64 { get; set; } - public bool type_bool { get; set; } - public Yaml.SubExample type_object { get; set; } - public Yaml.NODE_TYPE type_enum { get; set; } + public string myname { get; set; } + public string type_string { get; set; } + public int type_int { get; set; } + public uint type_uint { get; set; } + public float type_float { get; set; } + public double type_double { get; set; } + public char type_char { get; set; } + public uchar type_uchar { get; set; } + public unichar type_unichar { get; set; } + public short type_short { get; set; } + public ushort type_ushort { get; set; } + public long type_long { get; set; } + public ulong type_ulong { get; set; } + public size_t type_size_t { get; set; } + public ssize_t type_ssize_t { get; set; } + public int8 type_int8 { get; set; } + public uint8 type_uint8 { get; set; } + public int16 type_int16 { get; set; } + public uint16 type_uint16 { get; set; } + public int32 type_int32 { get; set; } + public uint32 type_uint32 { get; set; } + public int64 type_int64 { get; set; } + public uint64 type_uint64 { get; set; } + public bool type_bool { get; set; } + public Yaml.ExampleChild type_object { get; set; } + public Yaml.NODE_TYPE type_enum { get; set; } + public Yaml.ExampleStruct type_struct { get; set; } + public Gee.ArrayList type_gee_al { get; set; } + + static construct + { + Yaml.Object.register.add_type (typeof (Yaml.Example), typeof (Yaml.ExampleStruct)); + Yaml.Object.register.add_type (typeof (Yaml.Example), typeof (Gee.ArrayList)); + } /** * @@ -69,4 +79,27 @@ public class Pluie.Yaml.Example : Yaml.Object Dbg.msg ("Yaml.Object %s (%s) instantiated".printf (this.myname, this.type_from_self ()), Log.LINE, Log.FILE); } + /** + * + */ + public override void populate_by_type(GLib.Type type, Yaml.Node node) + { + try { + if (type == typeof (Yaml.ExampleStruct)) { + this.type_struct = ExampleStruct.from_yaml_node (node); + } + else if (type == typeof (Gee.ArrayList)) { + this.type_gee_al = new Gee.ArrayList (); + if (!node.empty ()) { + foreach (var child in node) { + this.type_gee_al.add(child.data); + } + } + } + } + catch (GLib.Error e) { + Dbg.error(e.message, Log.METHOD, Log.LINE); + } + } + } diff --git a/src/vala/Pluie/Yaml.SubExample.vala b/src/vala/Pluie/Yaml.ExampleChild.vala similarity index 96% rename from src/vala/Pluie/Yaml.SubExample.vala rename to src/vala/Pluie/Yaml.ExampleChild.vala index 3de037b..4e5e464 100644 --- a/src/vala/Pluie/Yaml.SubExample.vala +++ b/src/vala/Pluie/Yaml.ExampleChild.vala @@ -29,9 +29,8 @@ /** * a test class to implements yamlize - */ -public class Pluie.Yaml.SubExample : Yaml.Object +public class Pluie.Yaml.ExampleChild : Yaml.Object { public string toto { get; set; } public string tata { get; set; } diff --git a/samples/yaml-tag2.vala b/src/vala/Pluie/Yaml.ExampleStruct.vala similarity index 59% rename from samples/yaml-tag2.vala rename to src/vala/Pluie/Yaml.ExampleStruct.vala index a35587f..7b8f47d 100644 --- a/samples/yaml-tag2.vala +++ b/src/vala/Pluie/Yaml.ExampleStruct.vala @@ -27,28 +27,32 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -using GLib; -using Gee; -using Pluie; - -int main (string[] args) +public struct Pluie.Yaml.ExampleStruct { - 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 = true; - 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 - obj = Yaml.Object.from_node (root.first()); - - of.rs (done); - of.echo (); - return (int) done; - + public uint red; + public uint green; + public uint blue; + public static ExampleStruct from_yaml_node (Yaml.Node node) + { + var s = ExampleStruct (); + foreach (var child in node) { + var v = child.val (typeof (uint)); + switch (child.name) { + case "red" : + s.red = v.get_uint (); + break; + case "green" : + s.green = v.get_uint (); + break; + case "blue" : + s.blue = v.get_uint (); + break; + } + } + return s; + } + public string to_string () + { + return "%s(red:%u,green:%u,blue:%u)".printf ((typeof (ExampleStruct)).name (), this.red, this.green, this.blue); + } } diff --git a/src/vala/Pluie/Yaml.Mapping.vala b/src/vala/Pluie/Yaml.Mapping.vala index a4a6381..6a1036a 100644 --- a/src/vala/Pluie/Yaml.Mapping.vala +++ b/src/vala/Pluie/Yaml.Mapping.vala @@ -143,8 +143,12 @@ public class Pluie.Yaml.Mapping : Yaml.Node return clone; } + /** + * + */ public Gee.ArrayList? child_names () { return this.keys; } + } diff --git a/src/vala/Pluie/Yaml.Node.vala b/src/vala/Pluie/Yaml.Node.vala index a1766e0..7fcb69a 100644 --- a/src/vala/Pluie/Yaml.Node.vala +++ b/src/vala/Pluie/Yaml.Node.vala @@ -251,6 +251,17 @@ public class Pluie.Yaml.Node : Yaml.AbstractChild, Pluie.Yaml.Collection return new Yaml.Node (null, this.ntype, name); } + /** + * + */ + public GLib.Value val (GLib.Type type) + { + var v = GLib.Value(type); + if (this.ntype.is_single_pair ()) { + Yaml.Builder.set_basic_type_value (ref v, type, this.first ().data); + } + return v; + } /** * display childs diff --git a/src/vala/Pluie/Yaml.Object.vala b/src/vala/Pluie/Yaml.Object.vala index f74ba2f..42c6ab1 100644 --- a/src/vala/Pluie/Yaml.Object.vala +++ b/src/vala/Pluie/Yaml.Object.vala @@ -37,7 +37,15 @@ public abstract class Pluie.Yaml.Object : GLib.Object /** * */ - private static GLib.Module? p_module; + public static Yaml.Register register { get; private set; } + + /** + * + */ + static construct + { + register = new Yaml.Register(); + } /** * @@ -47,53 +55,6 @@ public abstract class Pluie.Yaml.Object : GLib.Object Dbg.msg ("Yaml.Object (%s) instantiated".printf (this.type_from_self ()), Log.LINE, Log.FILE); } - /** - * - */ - private static unowned GLib.Module p_open_module () - { - if (p_module == null) { - p_module = GLib.Module.open (null, 0); - } - return p_module; - } - - /** - * - */ - public static GLib.Type? type_from_string (string name) - { - 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 */ @@ -102,149 +63,13 @@ public abstract class Pluie.Yaml.Object : GLib.Object 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 { - 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) + public virtual void populate_by_type(GLib.Type type, 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? scalar = null; - foreach (var child in node) { - if ((def = obj.get_class ().find_property (child.name)) != null) { - if (child.ntype.is_single_pair ()) { - if ((scalar = child.first ()) != null) { - obj.set_from_scalar (def.name, def.value_type, scalar); - } - } - else if (child.ntype.is_mapping ()) { - obj.set (child.name, from_node(child)); - } - } - } - } - } - else { - of.echo ("searched type : %s".printf (type.to_string ())); - } - } - } - catch (GLib.Error e) { - of.warn (e.message); - } - obj.yaml_init (); - return obj; - } - - /** - * - */ - public void set_from_scalar (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); - } - if (type.is_a(Type.ENUM)) { - this.set_enum_value (ref v, type, data); - } - else { - switch (type) - { - case Type.STRING : - v.set_string(data); - break; - case Type.CHAR : - v.set_schar((int8)data.data[0]); - break; - case Type.UCHAR : - v.set_uchar((uint8)data.data[0]); - break; - case Type.BOOLEAN : - v.set_boolean (data == "1" || data.down () == "true"); - break; - case Type.INT : - v.set_int(int.parse(data)); - break; - case Type.UINT : - v.set_uint((uint)long.parse(data)); - break; - case Type.LONG : - case Type.INT64 : - v.set_long((long)int64.parse(data)); - break; - case Type.ULONG : - case Type.UINT64 : - v.set_ulong((ulong)uint64.parse(data)); - break; - case Type.FLOAT : - v.set_float((float)double.parse(data)); - break; - case Type.DOUBLE : - v.set_double(double.parse(data)); - break; - } - } - this.set_property(name, v); - } - - /** - * - */ - public void set_enum_value (ref Value v, GLib.Type type, string data) - { - EnumClass eclass = (EnumClass) type.class_ref(); - unowned EnumValue? evalue = eclass.get_value_by_name(data); - if (evalue == null) { - evalue = eclass.get_value_by_nick(data.down()); - int64 e = 0; - if(evalue == null) { - if(!int64.try_parse(data, out e)) { - Dbg.error ("invalid enum value %s".printf(data), Log.METHOD, Log.LINE); - } - } - e = evalue.value; - v.set_enum((int)e); + if (type.is_a (typeof (Yaml.Object))) { + this.set (node.name, Yaml.Builder.from_node(node, type)); } } } diff --git a/src/vala/Pluie/Yaml.Processor.vala b/src/vala/Pluie/Yaml.Processor.vala index d1614aa..1a3e579 100644 --- a/src/vala/Pluie/Yaml.Processor.vala +++ b/src/vala/Pluie/Yaml.Processor.vala @@ -158,10 +158,8 @@ public class Pluie.Yaml.Processor */ public bool run () { - if (Yaml.Scanner.DEBUG) { - this.read (); - of.action ("Processing events"); - } + if (Yaml.DEBUG) this.read (); + Yaml.dbg_action ("Processing events"); this.reset (); for (var has_next = this.iterator.next (); has_next; has_next = this.iterator.next ()) { this.event = this.iterator.get (); @@ -180,7 +178,9 @@ public class Pluie.Yaml.Processor this.on_entry (); } if (this.beginFlowSeq && this.event.evtype.is_scalar ()) { - this.on_scalar (true); + if (!this.change) { + this.on_scalar (true); + } this.beginFlowSeq = false; } if (this.event.evtype.is_key () && (this.event = this.get_value_key_event ()) != null) { @@ -264,8 +264,7 @@ public class Pluie.Yaml.Processor */ private void on_tag_directive () { - if (Yaml.Scanner.DEBUG) - of.action ("on_tag_directive %s".printf (this.event.data["handle"]), this.event.data["prefix"]); + Yaml.dbg_action ("on_tag_directive %s".printf (this.event.data["handle"]), this.event.data["prefix"]); this.root.tag_directives[this.event.data["handle"]] = this.event.data["prefix"]; } @@ -309,8 +308,7 @@ public class Pluie.Yaml.Processor private void on_tag (bool onKey = false) { if (this.event.evtype.is_tag ()) { - if (Yaml.Scanner.DEBUG) - of.keyval ("tag %s".printf (this.event.data["handle"]), this.event.data["suffix"]); + Yaml.dbg_keyval ("tag %s".printf (this.event.data["handle"]), this.event.data["suffix"]); if (this.root.tag_directives.has_key (this.event.data["handle"])) { var tag = new Yaml.Tag (this.event.data["suffix"], this.event.data["handle"].replace("!", "")); if (onKey) @@ -444,12 +442,12 @@ public class Pluie.Yaml.Processor private void on_update () { if (this.node != null) { - if (Yaml.Scanner.DEBUG) of.echo (this.node.name); + Yaml.dbg (this.node.name); } if (this.change) { - if (Yaml.Scanner.DEBUG) of.action ("on change", this.node.name); + Yaml.dbg_action ("on change", this.node.name != null ? this.node.name : this.node.data); if (this.keyTag != null) { - if (Yaml.Scanner.DEBUG) of.action ("setting tag", this.keyTag.@value); + Yaml.dbg_action ("setting tag", this.keyTag.@value); this.node.tag = this.keyTag; } else if (this.valueTag != null) { diff --git a/src/vala/Pluie/Yaml.Register.vala b/src/vala/Pluie/Yaml.Register.vala new file mode 100644 index 0000000..964f046 --- /dev/null +++ b/src/vala/Pluie/Yaml.Register.vala @@ -0,0 +1,93 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * @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 Pluie; +using Gee; + +/** + * a class registering type which could be populated + */ +public class Pluie.Yaml.Register : GLib.Object +{ + /** + * + */ + public static Gee.HashMap> reg { get; internal set; } + + /** + * + */ + static construct { + Yaml.Register.reg = new Gee.HashMap> (); + } + + /** + * + */ + private Gee.ArrayList init_type_list () + { + return new Gee.ArrayList (); + } + + /** + * + */ + public Gee.ArrayList? get_type_list (GLib.Type type) + { + return reg.get (type); + } + + /** + * + */ + public bool add_type (GLib.Type type, GLib.Type addedType) + { + if (!this.is_registered (type)) { + reg.set (type, this.init_type_list ()); + } + return reg.get (type).add (addedType); + } + + /** + * + */ + public bool is_registered (GLib.Type type) + { + return reg.has_key (type); + } + + /** + * + */ + public bool is_registered_type (GLib.Type type, GLib.Type checktype) + { + return this.is_registered (type) && reg.get (type).contains (checktype); + } +} diff --git a/src/vala/Pluie/Yaml.Scanner.vala b/src/vala/Pluie/Yaml.Scanner.vala index 124b8ed..16ab85b 100644 --- a/src/vala/Pluie/Yaml.Scanner.vala +++ b/src/vala/Pluie/Yaml.Scanner.vala @@ -37,7 +37,6 @@ extern void yaml_parse_file(string srcPath, string destPath); */ public class Pluie.Yaml.Scanner { - public static bool DEBUG = false; /** * Regex pattern use to find EVENT */ @@ -143,14 +142,14 @@ public class Pluie.Yaml.Scanner this.before_run (path); this.processor = new Yaml.Processor (); this.done = false; - if (Pluie.Yaml.Scanner.DEBUG) of.action ("Scanning events", path); + Yaml.dbg_action ("Scanning events", path); while (this.reader.readable) { this.scan_event (this.reader.read ()); } this.done = true; - if (Pluie.Yaml.Scanner.DEBUG) of.state (this.done); + Yaml.dbg_state (this.done); this.done = this.done && this.processor.run (); - if (Pluie.Yaml.Scanner.DEBUG) of.state (this.done); + Yaml.dbg_state (this.done); Dbg.out (Log.METHOD, "done:%d".printf ((int)done), Log.LINE, Log.FILE); return this.done; } diff --git a/src/vala/Pluie/Yaml.Tag.vala b/src/vala/Pluie/Yaml.Tag.vala index 81429a0..5133d55 100644 --- a/src/vala/Pluie/Yaml.Tag.vala +++ b/src/vala/Pluie/Yaml.Tag.vala @@ -31,9 +31,8 @@ using Gee; /** * a test class to implements yamlize - */ -public class Pluie.Yaml.Tag : GLib.Object +public class Pluie.Yaml.Tag { public string handle { get; internal set; } public string @value { get; internal set; } diff --git a/src/vala/Pluie/Yaml.global.vala b/src/vala/Pluie/Yaml.global.vala index 84e865e..cad9059 100644 --- a/src/vala/Pluie/Yaml.global.vala +++ b/src/vala/Pluie/Yaml.global.vala @@ -31,6 +31,8 @@ namespace Pluie { namespace Yaml { + public static bool DEBUG = false; + public static bool DBG_SHOW_INDENT = true; public static bool DBG_SHOW_PARENT = false; public static bool DBG_SHOW_UUID = true; @@ -40,6 +42,38 @@ namespace Pluie public static bool DBG_SHOW_TAG = true; public static bool DBG_SHOW_TYPE = true; + /** + * + */ + public static void dbg_action (string msg, string? val = null) + { + if (Pluie.Yaml.DEBUG) of.action (msg, val); + } + + /** + * + */ + public static void dbg_keyval (string key, string val) + { + if (Pluie.Yaml.DEBUG) of.keyval (key, val); + } + + /** + * + */ + public static void dbg_state (bool done) + { + if (Pluie.Yaml.DEBUG) of.state (done); + } + + /** + * + */ + public static void dbg (string? msg = null) + { + if (Pluie.Yaml.DEBUG && msg != null) of.echo (msg); + } + /** * ParseError */