Drafted code to load log entries
[gregoa/zavai.git] / src / log.vala
index 1534b04400910df803a7b80824b92b5f660121b1..607fffe24fe9b0105957e8310a32e19170b8c392 100644 (file)
@@ -58,13 +58,14 @@ public class LogEntry : Waypoint
 
     public LogEntry()
     {
-        Object();
+        base();
     }
 
     public void write(FileStream outfd)
     {
         outfd.printf("   <wpt lat=\"%f\" lon=\"%f\">\n", lat, lon);
         writeInside(outfd);
+        outfd.printf("   <name>%s</name>\n", Markup.escape_text(msg));
         outfd.puts("   </wpt>\n");
     }
 }
@@ -73,7 +74,7 @@ public class TrackEntry : Waypoint
 {
     public TrackEntry()
     {
-        Object();
+        base();
     }
 
     public void write(FileStream outfd)
@@ -87,15 +88,15 @@ public class TrackEntry : Waypoint
 
 public class Log : Object
 {
-    public uint id;
     public string tag;
+    public string title;
     public List<LogEntry> entries;
     public List<TrackEntry> track;
 
-    public Log(uint id, string tag)
+    public Log(string tag, string title)
     {
-        this.id = id;
         this.tag = tag;
+        this.title = title;
         entries = null;
         track = null;
     }
@@ -107,6 +108,11 @@ public class Log : Object
         entries.append(entry);
     }
 
+    public void add_trackpoint()
+    {
+        track.append(new TrackEntry());
+    }
+
     public void save()
     {
         if (entries == null) return;
@@ -125,8 +131,6 @@ public class Log : Object
         for (int i = 1; FileUtils.test(pathname, FileTest.EXISTS); ++i)
             pathname = "%s-%d.gpx".printf(basename, i);
 
-stderr.printf("WRITING TO %s\n", pathname);
-
         // Write out
         var outfd = FileStream.open(pathname, "w");
         if (outfd == null)
@@ -165,99 +169,174 @@ stderr.printf("WRITING TO %s\n", pathname);
         outfd.puts("     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
         outfd.puts("     xmlns=\"http://www.topografix.com/GPX/1/0\"\n");
         outfd.puts("     xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">\n");
+        outfd.puts("  <metadata>\n");
+        outfd.printf("    <name>%s</name>\n", Markup.escape_text(title));
+        outfd.puts("  </metadata>\n");
         if (track != null) writeTrack(outfd);
         if (entries != null) writeEntries(outfd);
         outfd.puts(" </gpx>\n");
     }
 }
 
+enum LogParserState {
+    NONE,
+    METADATA,
+    TRACK,
+    WPT,
+}
+
+class LogParser: Object
+{
+    const MarkupParser parser = { // It's a structure, not an object
+        start,// when an element opens
+        end,  // when an element closes
+        text, // when text is found
+        null, // when comments are found
+        null  // when errors occur
+    };
+
+    MarkupParseContext context = null;
+    public Log result = null;
+    LogParserState state = LogParserState.NONE;
+    string cur_text = "";
+
+    construct
+    {
+        context = new MarkupParseContext(
+            parser, // the structure with the callbacks
+            0,      // MarkupParseFlags
+            this,   // extra argument for the callbacks, methods in this case
+            destroy // when the parsing ends
+        );
+    }
+
+    void destroy()
+    {
+        cur_text = "";
+    }
+
+    public bool parse(string content, ssize_t len = -1) throws MarkupError
+    {
+        return context.parse(content, len);
+    }
+
+
+        /*
+        outfd.puts("  <metadata>\n");
+        outfd.printf("    <name>%s</name>\n", Markup.escape_text(title));
+        outfd.puts("  </metadata>\n");
+        if (track != null) writeTrack(outfd);
+        if (entries != null) writeEntries(outfd);
+        outfd.puts(" </gpx>\n");
+        */
+
+
+    void start (MarkupParseContext context, string name,
+                string[] attr_names, string[] attr_values) throws MarkupError
+    {
+        if (name == "gpx")
+        {
+            state = LogParserState.NONE;
+            result = new Log("TODO:TAG", "TODO:TITLE");
+        } else if (name == "metadata") {
+            state = LogParserState.METADATA;
+        } else if (name == "wpt") {
+            state = LogParserState.WPT;
+        } else if (name == "trkseg") {
+            state = LogParserState.TRACK;
+        }
+        cur_text = "";
+    }
+
+    void end (MarkupParseContext context, string name) throws MarkupError
+    {
+        if (name == "state")
+            if (state == LogParserState.METADATA)
+                result.title = cur_text;
+    }
+
+    void text (MarkupParseContext context,
+               string text, size_t text_len) throws MarkupError
+    {
+        cur_text += text;
+    }
+}
+
 public class Logger : Resource, Object
 {
     protected List<Log> logs;
-    protected uint seq;
 
     public Logger()
     {
         logs = null;
-        seq = 0;
-
         zavai.registry.register(this);
     }
 
-    protected uint gen_seq()
+    protected void start_trace()
     {
-        // Increase avoiding 0 on rollover
-        while (true)
-        {
-            if (++seq == 0) ++seq;
-            bool found = false;
-            for (weak List<Log> i = logs; i != null; i = i.next)
-            {
-                if (i.data.id == seq)
-                {
-                    found = true;
-                    break;
-                }
-            }
-            if (!found) break;
-        }
-        return seq;
+        gps.gps.pos_changed += on_pos_changed;
+    }
+
+    protected void end_trace()
+    {
+        gps.gps.pos_changed -= on_pos_changed;
     }
 
-    protected weak Log? find(uint id)
+    protected void on_pos_changed()
     {
         for (weak List<Log> i = logs; i != null; i = i.next)
-            if (i.data.id == id)
-                return i.data;
-        return null;
+            i.data.add_trackpoint();
     }
 
-    protected Log? pop(uint id)
+    protected void pop(Log log)
     {
         for (weak List<Log> i = logs; i != null; i = i.next)
-            if (i.data.id == id)
-            {
-                Log res = i.data;
+            if (i.data == log)
                 logs.delete_link(i);
-                return res;
-            }
-        return null;
     }
 
-    public uint start(string tag)
+    public Log start(string tag, string title)
     {
-        uint id = gen_seq();
-        logs.append(new Log(id, tag));
-        return id;
+        bool was_empty = (logs == null);
+        Log res = new Log(tag, title);
+        logs.append(res);
+        if (was_empty) start_trace();
+        return res;
     }
 
-    public void add(uint id, string msg)
+    public void end(Log log)
     {
-        Log log = find(id);
-        if (log == null) return;
-        log.add(msg);
+        pop(log);
+        log.save();
+        if (logs == null) end_trace();
     }
 
-    public void end(uint id)
+    public Log load(string fname)
     {
-        Log log = pop(id);
-        log.save();
+        string contents;
+        size_t length;
+        FileUtils.get_contents(fname, out contents, out length);
+        LogParser parser = new LogParser();
+        parser.parse(contents, (ssize_t)length);
+        return parser.result;
     }
 
     public void instant(string tag, string msg)
     {
-        var log = new Log(0, tag);
+        var log = new Log(tag, msg);
         log.add(msg);
         log.save();
     }
 
     public void shutdown()
     {
+        bool had_logs = (logs != null);
         while (logs != null)
         {
-            var log = pop(logs.data.id);
-            log.save();
+            logs.data.save();
+            logs.delete_link(logs);
         }
+        if (had_logs) end_trace();
     }
 }