353 lines
11 KiB
Vala
353 lines
11 KiB
Vala
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*
|
|
* @software : pluie-yaml <https://git.pluie.org/pluie/lib-yaml>
|
|
* @version : 0.5
|
|
* @type : library
|
|
* @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 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 <http://www.gnu.org/licenses/>.
|
|
*
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*/
|
|
|
|
using GLib;
|
|
using Gee;
|
|
using Pluie;
|
|
extern void yaml_parse_file(string srcPath, string destPath);
|
|
|
|
/**
|
|
* a Yaml scanner class dealing with libyaml to generate a list of Yaml.Event
|
|
*/
|
|
public class Pluie.Yaml.Scanner
|
|
{
|
|
/**
|
|
* Regex pattern use to find EVENT
|
|
*/
|
|
const string REG_EVENT = "^([0-9]+), ([0-9]+)(.*)$";
|
|
/**
|
|
* Regex pattern use to find EVENT VERSION
|
|
*/
|
|
const string REG_VERSION = "^, ([0-9]+), ([0-9]+)$";
|
|
/**
|
|
* Regex pattern use to find EVENT TAG
|
|
*/
|
|
const string REG_TAG = "^, \"([^\"]*)\", \"([^\"]*)\"$";
|
|
/**
|
|
* Regex pattern use to find EVENT ERROR
|
|
*/
|
|
const string REG_ERROR = "^, \"([^\"]*)\"$";
|
|
/**
|
|
* Regex pattern use to find EVENT SCALAR
|
|
*/
|
|
const string REG_SCALAR = "^, ([0-9]+), \"(.*)\"$";
|
|
/**
|
|
* Regex pattern use to find EVENT ANCHOR
|
|
*/
|
|
const string REG_ANCHOR = "^, \"([^\"]*)\"$";
|
|
/**
|
|
* Regex pattern use to find EVENT ALIAS
|
|
*/
|
|
const string REG_ALIAS = "^, \"([^\"]*)\"$";
|
|
|
|
/**
|
|
* enum linked to MatchInfo REG_EVENT
|
|
*/
|
|
enum MIEVT { NONE, LINE, TYPE, DATA }
|
|
/**
|
|
* enum linked to MatchInfo REG_VERSION
|
|
*/
|
|
enum MIEVT_VERSION { NONE, MAJOR, MINOR }
|
|
/**
|
|
* enum linked to MatchInfo REG_SCALAR
|
|
*/
|
|
enum MIEVT_SCALAR { NONE, STYLE, DATA }
|
|
/**
|
|
* enum linked to MatchInfo REG_TAG
|
|
*/
|
|
enum MIEVT_TAG { NONE, HANDLE, SUFFIX }
|
|
/**
|
|
* enum linked to MatchInfo REG_ANCHOR
|
|
*/
|
|
enum MIEVT_ANCHOR { NONE, ID }
|
|
/**
|
|
* enum linked to MatchInfo REG_ERROR
|
|
*/
|
|
enum MIEVT_ERROR { NONE, DATA }
|
|
|
|
/**
|
|
* indicate if file has been sucessfully scanned
|
|
*/
|
|
public bool done { get; internal set; }
|
|
|
|
/**
|
|
* Reader used to load content yaml file
|
|
*/
|
|
Io.Reader reader;
|
|
|
|
/**
|
|
* Yaml Processor used to process events
|
|
*/
|
|
Yaml.Processor processor { get; internal set; }
|
|
|
|
/**
|
|
* @param path the path of file to scan
|
|
*/
|
|
public Scanner (string path)
|
|
{
|
|
var destPath = Path.build_filename (Environment.get_tmp_dir (), Path.get_basename(path));
|
|
yaml_parse_file(path, destPath);
|
|
this.reader = new Io.Reader (destPath);
|
|
}
|
|
|
|
/**
|
|
* return resulting Yaml root node
|
|
*/
|
|
public Yaml.Node? get_nodes ()
|
|
{
|
|
return this.processor.root;
|
|
}
|
|
|
|
/**
|
|
* return error Yaml Event
|
|
*/
|
|
public Yaml.Event? get_error_event ()
|
|
{
|
|
return this.processor.error_event;
|
|
}
|
|
|
|
/**
|
|
* scan specifiyed file generated throught yaml.c
|
|
* @param path optional file path to scan
|
|
*/
|
|
public bool run (string? path = null)
|
|
{
|
|
Dbg.in (Log.METHOD, "path:'%s'".printf (path), Log.LINE, Log.FILE);
|
|
this.before_run (path);
|
|
this.processor = new Yaml.Processor ();
|
|
this.done = false;
|
|
Yaml.dbg_action ("Scanning events", path);
|
|
while (this.reader.readable) {
|
|
this.scan_event (this.reader.read ());
|
|
}
|
|
this.done = true;
|
|
Yaml.dbg_state (this.done);
|
|
this.done = this.done && this.processor.run ();
|
|
Yaml.dbg_state (this.done);
|
|
Dbg.out (Log.METHOD, "done:%d".printf ((int)done), Log.LINE, Log.FILE);
|
|
return this.done;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
private void before_run (string? path)
|
|
{
|
|
if (path != null && this.reader.path != path) {
|
|
this.reader.load (path);
|
|
}
|
|
else {
|
|
this.reader.rewind(new Io.StreamLineMark(0, 0));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* register event version
|
|
* @param evtdata the current data event
|
|
* @param line the current line
|
|
* @throws GLib.RegexError
|
|
*/
|
|
private void register_event_version(string evtdata, int line) throws GLib.RegexError
|
|
{
|
|
MatchInfo mi = null;
|
|
Regex reg = new Regex (REG_VERSION);
|
|
HashMap<string, string>? data = null;
|
|
if (reg.match (evtdata, 0, out mi)) {
|
|
data = new HashMap<string, string>();
|
|
data.set("major", mi.fetch (MIEVT_VERSION.MAJOR));
|
|
data.set("minor", mi.fetch (MIEVT_VERSION.MINOR));
|
|
}
|
|
this.processor.events.add(new Yaml.Event(EVT.VERSION_DIRECTIVE, line, null, data));
|
|
}
|
|
|
|
/**
|
|
* register event tag
|
|
* @param evtdata the current data event
|
|
* @param line the current line
|
|
* @throws GLib.RegexError
|
|
*/
|
|
private void register_event_tag_directive(string evtdata, int line) throws GLib.RegexError
|
|
{
|
|
MatchInfo mi = null;
|
|
Regex reg = new Regex (REG_TAG);
|
|
HashMap<string, string>? data = null;
|
|
if (reg.match (evtdata, 0, out mi)) {
|
|
data = new HashMap<string, string>();
|
|
data.set("handle", mi.fetch (MIEVT_TAG.HANDLE));
|
|
data.set("prefix", mi.fetch (MIEVT_TAG.SUFFIX));
|
|
}
|
|
this.processor.events.add(new Yaml.Event(EVT.TAG_DIRECTIVE, line, null, data));
|
|
}
|
|
|
|
/**
|
|
* register event tag
|
|
* @param evtdata the current data event
|
|
* @param line the current line
|
|
* @throws GLib.RegexError
|
|
*/
|
|
private void register_event_tag(string evtdata, int line) throws GLib.RegexError
|
|
{
|
|
MatchInfo mi = null;
|
|
Regex reg = new Regex (REG_TAG);
|
|
HashMap<string, string>? data = null;
|
|
if (reg.match (evtdata, 0, out mi)) {
|
|
data = new HashMap<string, string>();
|
|
data.set("handle", mi.fetch (MIEVT_TAG.HANDLE));
|
|
data.set("suffix", mi.fetch (MIEVT_TAG.SUFFIX));
|
|
}
|
|
this.processor.events.add(new Yaml.Event(EVT.TAG, line, null, data));
|
|
}
|
|
|
|
/**
|
|
* register event version
|
|
* @param evtdata the current data event
|
|
* @param line the current line
|
|
* @throws GLib.RegexError
|
|
*/
|
|
private void register_event_error(string evtdata, int line) throws GLib.RegexError
|
|
{
|
|
MatchInfo mi = null;
|
|
Regex reg = new Regex (REG_ERROR);
|
|
HashMap<string, string>? data = null;
|
|
if (reg.match (evtdata, 0, out mi)) {
|
|
data = new HashMap<string, string>();
|
|
data.set("error", mi.fetch (MIEVT_ERROR.DATA));
|
|
}
|
|
this.processor.events.add(new Yaml.Event(EVT.NONE, line, null, data));
|
|
}
|
|
|
|
/**
|
|
* register event scalar
|
|
* @param evtdata the current data event
|
|
* @param line the current line
|
|
* @throws GLib.RegexError
|
|
*/
|
|
private void register_event_scalar(string evtdata, int line) throws GLib.RegexError
|
|
{
|
|
MatchInfo mi = null;
|
|
Regex reg = new Regex (REG_SCALAR);
|
|
HashMap<string, string>? data = null;
|
|
int? style = null;
|
|
if (reg.match (evtdata, 0, out mi)) {
|
|
style = int.parse(mi.fetch (MIEVT_SCALAR.STYLE));
|
|
data = new HashMap<string, string>();
|
|
data.set("data", mi.fetch (MIEVT_SCALAR.DATA));
|
|
}
|
|
this.processor.events.add(new Yaml.Event(EVT.SCALAR, line, style, data));
|
|
}
|
|
|
|
/**
|
|
* register event anchor
|
|
* @param evtdata the current data event
|
|
* @param line the current line
|
|
* @throws GLib.RegexError
|
|
*/
|
|
private void register_event_anchor(string evtdata, int line) throws GLib.RegexError
|
|
{
|
|
MatchInfo mi = null;
|
|
Regex reg = new Regex (REG_ANCHOR);
|
|
HashMap<string, string>? data = null;
|
|
if (reg.match (evtdata, 0, out mi)) {
|
|
data = new HashMap<string, string>();
|
|
data.set("id", mi.fetch (MIEVT_ANCHOR.ID));
|
|
}
|
|
this.processor.events.add(new Yaml.Event(EVT.ANCHOR, line, null, data));
|
|
}
|
|
|
|
/**
|
|
* register event alias
|
|
* @param evtdata the current data event
|
|
* @param line the current line
|
|
* @throws GLib.RegexError
|
|
*/
|
|
private void register_event_alias(string evtdata, int line) throws GLib.RegexError
|
|
{
|
|
MatchInfo mi = null;
|
|
Regex reg = new Regex (REG_ALIAS);
|
|
HashMap<string, string>? data = null;
|
|
if (reg.match (evtdata, 0, out mi)) {
|
|
data = new HashMap<string, string>();
|
|
data.set("id", mi.fetch (MIEVT_ANCHOR.ID));
|
|
}
|
|
this.processor.events.add(new Yaml.Event(EVT.ALIAS, line, null, data));
|
|
}
|
|
|
|
/**
|
|
* scan specifiyed line
|
|
* @param data the current line
|
|
*/
|
|
private void scan_event (string? data = null)
|
|
{
|
|
Dbg.in (Log.METHOD, null, Log.LINE, Log.FILE);
|
|
if (data == null) {
|
|
return;
|
|
}
|
|
try {
|
|
MatchInfo mi = null;
|
|
Regex reg = new Regex (REG_EVENT);
|
|
if (reg.match (data, 0, out mi)) {
|
|
int line = int.parse(mi.fetch (MIEVT.LINE));
|
|
int type = int.parse(mi.fetch (MIEVT.TYPE));
|
|
string evtdata = mi.fetch (MIEVT.DATA);
|
|
switch(type) {
|
|
case EVT.SCALAR :
|
|
this.register_event_scalar (evtdata, line);
|
|
break;
|
|
case EVT.ANCHOR :
|
|
this.register_event_anchor (evtdata, line);
|
|
break;
|
|
case EVT.ALIAS :
|
|
this.register_event_alias (evtdata, line);
|
|
break;
|
|
case EVT.TAG :
|
|
this.register_event_tag (evtdata, line);
|
|
break;
|
|
case EVT.TAG_DIRECTIVE :
|
|
this.register_event_tag_directive (evtdata, line);
|
|
break;
|
|
case EVT.VERSION_DIRECTIVE :
|
|
this.register_event_version (evtdata, line);
|
|
break;
|
|
case EVT.NONE :
|
|
this.register_event_error (evtdata, line);
|
|
break;
|
|
default :
|
|
this.processor.events.add(new Yaml.Event ((Yaml.EVT) type, line, null, null));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
catch (GLib.RegexError e) {
|
|
Dbg.error (e.message, Log.METHOD, Log.LINE, Log.FILE);
|
|
}
|
|
Dbg.out (Log.METHOD, null, Log.LINE, Log.FILE);
|
|
}
|
|
}
|