add Yaml.Builder, provide mechanism to populate structure and other GLib.Object derived type

This commit is contained in:
a-Sansara 2018-08-18 23:01:07 +02:00
parent 68d2c026d4
commit e4c554df3d
24 changed files with 608 additions and 282 deletions

View File

@ -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<string> ();
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)

View File

@ -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'
]

View File

@ -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

View File

@ -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 ();

View File

@ -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 ();

View File

@ -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 ();

View File

@ -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);

View File

@ -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 ();

View File

@ -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));
}
}
}
}

View File

@ -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)) {

View File

@ -101,7 +101,5 @@ public abstract class Pluie.Yaml.AbstractNode : GLib.Object
{
return "";
}
}

View File

@ -0,0 +1,259 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* @software : lib-yaml <https://git.pluie.org/pluie/lib-yaml>
* @version : 0.4
* @date : 2018
* @licence : GPLv3.0 <http://www.gnu.org/licenses/>
* @author : a-Sansara <[dev]at[pluie]dot[org]>
* @copyright : pluie.org <http://www.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 <http://www.gnu.org/licenses/>.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
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));
}
}

View File

@ -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]);
}
}
}

View File

@ -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<string> 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<string> ();
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);
}
}
}

View File

@ -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; }

View File

@ -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);
}
}

View File

@ -143,8 +143,12 @@ public class Pluie.Yaml.Mapping : Yaml.Node
return clone;
}
/**
*
*/
public Gee.ArrayList<string>? child_names ()
{
return this.keys;
}
}

View File

@ -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

View File

@ -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));
}
}
}

View File

@ -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) {

View File

@ -0,0 +1,93 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* @software : lib-yaml <https://git.pluie.org/pluie/lib-yaml>
* @version : 0.4
* @date : 2018
* @licence : GPLv3.0 <http://www.gnu.org/licenses/>
* @author : a-Sansara <[dev]at[pluie]dot[org]>
* @copyright : pluie.org <http://www.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 <http://www.gnu.org/licenses/>.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
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<Type, Gee.ArrayList<GLib.Type>> reg { get; internal set; }
/**
*
*/
static construct {
Yaml.Register.reg = new Gee.HashMap<Type, Gee.ArrayList<GLib.Type>> ();
}
/**
*
*/
private Gee.ArrayList<GLib.Type> init_type_list ()
{
return new Gee.ArrayList<GLib.Type> ();
}
/**
*
*/
public Gee.ArrayList<GLib.Type>? 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);
}
}

View File

@ -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;
}

View File

@ -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; }

View File

@ -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
*/