[Xfce4-commits] <squeeze:peter/datetime> Parse dates and times to LSQ_TYPE_DATETIME

Peter de Ridder noreply at xfce.org
Sat Oct 8 01:24:03 CEST 2011


Updating branch refs/heads/peter/datetime
         to 15c767a3557acf54ae9dd5bba7e08879aa4f5fd4 (commit)
       from bc7be8990bb2b53079703a8f6b3b70a15e8c7f5f (commit)

commit 15c767a3557acf54ae9dd5bba7e08879aa4f5fd4
Author: Peter de Ridder <peter at xfce.org>
Date:   Sat Oct 8 00:44:02 2011 +0200

    Parse dates and times to LSQ_TYPE_DATETIME

 libsqueeze/Makefile.am      |    1 +
 libsqueeze/archive-iter.c   |  106 ++++++++++++--
 libsqueeze/archive-iter.h   |    2 +-
 libsqueeze/datetime.c       |  344 +++++++++++++++++++++++++++++++++++++++++++
 libsqueeze/datetime.h       |   76 ++++++++++
 libsqueeze/libsqueeze.c     |    2 +
 libsqueeze/libsqueeze.h     |    1 +
 libsqueeze/parser.c         |   10 ++
 libsqueeze/parser.h         |    7 +
 libsqueeze/pcre-parser.c    |   39 ++++-
 libsqueeze/scanf-parser.c   |  254 ++++++++++++++++++++++++++++----
 libsqueeze/support-reader.c |    6 +
 src/archive_store.c         |   19 +++-
 src/notebook.c              |   13 +-
 14 files changed, 824 insertions(+), 56 deletions(-)

diff --git a/libsqueeze/Makefile.am b/libsqueeze/Makefile.am
index 51cc350..57432ff 100644
--- a/libsqueeze/Makefile.am
+++ b/libsqueeze/Makefile.am
@@ -7,6 +7,7 @@ libsqueeze_2_la_SOURCES =  \
 	archive-tempfs.c archive-tempfs.h \
 	command-queue.c command-queue.h \
 	command-option.c command-option.h \
+	datetime.c datetime.h \
 	internals.c internals.h \
 	libsqueeze.c libsqueeze.h \
 	libsqueeze-view.h \
diff --git a/libsqueeze/archive-iter.c b/libsqueeze/archive-iter.c
index 6288535..5b8887b 100644
--- a/libsqueeze/archive-iter.c
+++ b/libsqueeze/archive-iter.c
@@ -84,14 +84,18 @@ inline static guint
 lsq_archive_entry_get_prop_uint(const LSQArchive *, const LSQArchiveEntry *, guint);
 inline static guint64
 lsq_archive_entry_get_prop_uint64(const LSQArchive *, const LSQArchiveEntry *, guint);
+inline static const LSQDateTime *
+lsq_archive_entry_get_prop_datetime(const LSQArchive *, const LSQArchiveEntry *, guint);
 
 static void
-lsq_archive_entry_set_prop_str(const LSQArchive *, LSQArchiveEntry *, guint, const gchar *);
+lsq_archive_entry_set_prop_str(const LSQArchive *, LSQArchiveEntry *, guint, gchar *);
 static void
 lsq_archive_entry_set_prop_uint(const LSQArchive *, LSQArchiveEntry *, guint, guint);
 static void
 lsq_archive_entry_set_prop_uint64(const LSQArchive *, LSQArchiveEntry *, guint, guint64);
 static void
+lsq_archive_entry_set_prop_datetime(const LSQArchive *, LSQArchiveEntry *, guint, LSQDateTime *);
+static void
 lsq_archive_entry_set_propsv(const LSQArchive *, LSQArchiveEntry *, gpointer *);
 static void
 lsq_archive_entry_set_propsva(const LSQArchive *, LSQArchiveEntry *, va_list);
@@ -667,6 +671,11 @@ lsq_archive_iter_get_prop_value(const LSQArchiveIter *iter, guint n, GValue *val
 			g_value_set_uint64(value, lsq_archive_entry_get_prop_uint64(iter->archive, iter->entry, n));
 			break;
 		default:
+			if ( LSQ_TYPE_DATETIME == G_VALUE_TYPE(value) )
+			{
+                            g_value_set_datetime(value, lsq_archive_entry_get_prop_datetime(iter->archive, iter->entry, n));
+                            break;
+			}
 			return FALSE;
 	}
 
@@ -686,7 +695,7 @@ lsq_archive_iter_set_prop_value(LSQArchiveIter *iter, guint n, const GValue *val
 	switch(G_VALUE_TYPE(value))
 	{
 		case G_TYPE_STRING:
-			lsq_archive_entry_set_prop_str(iter->archive, iter->entry, n, g_value_get_string(value));
+			lsq_archive_entry_set_prop_str(iter->archive, iter->entry, n, g_value_dup_string(value));
 			break;
 		case G_TYPE_UINT:
 			lsq_archive_entry_set_prop_uint(iter->archive, iter->entry, n, g_value_get_uint(value));
@@ -694,11 +703,18 @@ lsq_archive_iter_set_prop_value(LSQArchiveIter *iter, guint n, const GValue *val
 		case G_TYPE_UINT64:
 			lsq_archive_entry_set_prop_uint64(iter->archive, iter->entry, n, g_value_get_uint64(value));
 			break;
+		default:
+			if ( LSQ_TYPE_DATETIME == G_VALUE_TYPE(value) )
+			{
+                            lsq_archive_entry_set_prop_datetime(iter->archive, iter->entry, n, g_value_dup_datetime(value));
+                            break;
+                        }
+                        break;
 	}
 }
 
 void
-lsq_archive_iter_set_prop(LSQArchiveIter *iter, guint n, gconstpointer value)
+lsq_archive_iter_set_prop(LSQArchiveIter *iter, guint n, gpointer value)
 {
 #ifdef DEBUG
 	g_return_if_fail(iter);
@@ -712,11 +728,18 @@ lsq_archive_iter_set_prop(LSQArchiveIter *iter, guint n, gconstpointer value)
 			lsq_archive_entry_set_prop_str(iter->archive, iter->entry, n, value);
 			break;
 		case G_TYPE_UINT:
-			lsq_archive_entry_set_prop_uint(iter->archive, iter->entry, n, *(const guint*)value);
+			lsq_archive_entry_set_prop_uint(iter->archive, iter->entry, n, *(guint*)value);
 			break;
 		case G_TYPE_UINT64:
-			lsq_archive_entry_set_prop_uint64(iter->archive, iter->entry, n, *(const guint64*)value);
+			lsq_archive_entry_set_prop_uint64(iter->archive, iter->entry, n, *(guint64*)value);
 			break;
+		default:
+			if ( LSQ_TYPE_DATETIME == lsq_archive_get_entry_property_type(iter->archive, n) )
+			{
+                            lsq_archive_entry_set_prop_datetime(iter->archive, iter->entry, n, value);
+                            break;
+                        }
+                        break;
 	}
 }
 
@@ -972,12 +995,22 @@ lsq_archive_entry_props_free(const LSQArchive *archive, LSQArchiveEntry *entry)
 		{
 			switch ( lsq_archive_get_entry_property_type(archive, i+LSQ_ARCHIVE_PROP_USER) )
 			{
-				case ( G_TYPE_STRING ):
+				case G_TYPE_STRING:
 					/* free only strings */
 					offset = lsq_archive_get_entry_property_offset(archive, i+LSQ_ARCHIVE_PROP_USER);
 					g_free(((gchar **)props_iter)[offset]);
 					((gchar **)props_iter)[offset] = NULL;
 					break;
+
+                                default:
+                                        if ( LSQ_TYPE_DATETIME == lsq_archive_get_entry_property_type(archive, i+LSQ_ARCHIVE_PROP_USER) )
+                                        {
+                                            offset = lsq_archive_get_entry_property_offset(archive, i+LSQ_ARCHIVE_PROP_USER);
+                                            g_free(((LSQDateTime **)props_iter)[offset]);
+                                            ((LSQDateTime **)props_iter)[offset] = NULL;
+                                            break;
+                                        }
+					break;
 			}
 		}
 		g_free(entry->props);
@@ -1468,6 +1501,26 @@ lsq_archive_entry_get_prop_uint64(const LSQArchive *archive, const LSQArchiveEnt
 	return (((guint64 *)props_iter)[offset]);
 }
 
+inline static const LSQDateTime *
+lsq_archive_entry_get_prop_datetime(const LSQArchive *archive, const LSQArchiveEntry *entry, guint i)
+{
+	gpointer props_iter = entry->props;
+	guint offset;
+	if ( NULL == props_iter )
+	{
+		return NULL;
+	}
+
+	if ( LSQ_TYPE_DATETIME != lsq_archive_get_entry_property_type(archive, i) )
+	{
+		return NULL;
+	}
+
+	offset = lsq_archive_get_entry_property_offset(archive, i);
+
+	return (((LSQDateTime **)props_iter)[offset]);
+}
+
 static gpointer
 lsq_archive_entry_get_props(const LSQArchive *archive, LSQArchiveEntry *entry)
 {
@@ -1484,7 +1537,7 @@ lsq_archive_entry_get_props(const LSQArchive *archive, LSQArchiveEntry *entry)
 }
 
 static void
-lsq_archive_entry_set_prop_str(const LSQArchive *archive, LSQArchiveEntry *entry, guint n, const gchar *str_val)
+lsq_archive_entry_set_prop_str(const LSQArchive *archive, LSQArchiveEntry *entry, guint n, gchar *str_val)
 {
 	gpointer props_iter = lsq_archive_entry_get_props(archive, entry);
 	guint offset;
@@ -1497,7 +1550,7 @@ lsq_archive_entry_set_prop_str(const LSQArchive *archive, LSQArchiveEntry *entry
 	offset = lsq_archive_get_entry_property_offset(archive, n);
 
 	g_free(((gchar **)props_iter)[offset]);
-	((gchar **)props_iter)[offset] = g_strdup(str_val);
+	((gchar **)props_iter)[offset] = str_val; /* We take ownership */
 }
 
 static void
@@ -1533,6 +1586,23 @@ lsq_archive_entry_set_prop_uint64(const LSQArchive *archive, LSQArchiveEntry *en
 }
 
 static void
+lsq_archive_entry_set_prop_datetime(const LSQArchive *archive, LSQArchiveEntry *entry, guint n, LSQDateTime *dt_val)
+{
+	gpointer props_iter = lsq_archive_entry_get_props(archive, entry);
+	guint offset;
+
+	if ( LSQ_TYPE_DATETIME != lsq_archive_get_entry_property_type(archive, n) )
+	{
+		return;
+	}
+
+	offset = lsq_archive_get_entry_property_offset(archive, n);
+
+	g_free(((LSQDateTime **)props_iter)[offset]);
+	((LSQDateTime **)props_iter)[offset] = dt_val; /* We take ownership */
+}
+
+static void
 lsq_archive_entry_set_propsv(const LSQArchive *archive, LSQArchiveEntry *entry, gpointer *props)
 {
 	gpointer props_iter = lsq_archive_entry_get_props(archive, entry);
@@ -1547,7 +1617,7 @@ lsq_archive_entry_set_propsv(const LSQArchive *archive, LSQArchiveEntry *entry,
 			case G_TYPE_STRING:
 				g_free(((gchar **)props_iter)[offset]);
 				//(*((gchar **)props_iter)) = g_strdup((const gchar*)props[i]);
-				((gchar **)props_iter)[offset] = (gchar*)props[i];
+				((gchar **)props_iter)[offset] = (gchar*)props[i]; /* We take ownership */
 				break;
 			case G_TYPE_UINT:
 				((guint *)props_iter)[offset] = *((const guint *)props[i]);
@@ -1555,6 +1625,14 @@ lsq_archive_entry_set_propsv(const LSQArchive *archive, LSQArchiveEntry *entry,
 			case G_TYPE_UINT64:
 				((guint64 *)props_iter)[offset] = *((const guint64 *)props[i]);
 				break;
+                        default:
+                                if ( LSQ_TYPE_DATETIME == lsq_archive_get_entry_property_type(archive, i+LSQ_ARCHIVE_PROP_USER) )
+                                {
+                                    g_free(((LSQDateTime **)props_iter)[offset]);
+                                    ((LSQDateTime **)props_iter)[offset] = (LSQDateTime*)props[i]; /* We take ownership */
+                                    break;
+                                }
+				break;
 		}
 	}
 }
@@ -1573,7 +1651,7 @@ lsq_archive_entry_set_propsva(const LSQArchive *archive, LSQArchiveEntry *entry,
 		{
 			case G_TYPE_STRING:
 				g_free(((gchar **)props_iter)[offset]);
-				((gchar **)props_iter)[offset] = g_strdup(va_arg(ap, gchar*));
+				((gchar **)props_iter)[offset] = va_arg(ap, gchar*); /* We take ownership */
 				break;
 			case G_TYPE_UINT:
 				((guint *)props_iter)[offset] = va_arg(ap, guint);
@@ -1581,6 +1659,14 @@ lsq_archive_entry_set_propsva(const LSQArchive *archive, LSQArchiveEntry *entry,
 			case G_TYPE_UINT64:
 				((guint64 *)props_iter)[offset] = va_arg(ap, guint64);
 				break;
+                        default:
+                                if ( LSQ_TYPE_DATETIME == lsq_archive_get_entry_property_type(archive, i+LSQ_ARCHIVE_PROP_USER) )
+                                {
+                                    g_free(((LSQDateTime **)props_iter)[offset]);
+                                    ((LSQDateTime **)props_iter)[offset] = va_arg(ap, LSQDateTime*); /* We take ownership */
+                                    break;
+                                }
+				break;
 		}
 	}
 }
diff --git a/libsqueeze/archive-iter.h b/libsqueeze/archive-iter.h
index 3913102..4a4b105 100644
--- a/libsqueeze/archive-iter.h
+++ b/libsqueeze/archive-iter.h
@@ -50,7 +50,7 @@ LSQArchiveIter *lsq_archive_add_file(LSQArchive *archive, const gchar *path);
 LSQArchiveIter *lsq_archive_iter_add_file(LSQArchiveIter *parent, const gchar *filename);
 
 void  lsq_archive_iter_set_prop_value(LSQArchiveIter *iter, guint n, const GValue *value);
-void  lsq_archive_iter_set_prop(LSQArchiveIter *iter, guint n, gconstpointer value);
+void  lsq_archive_iter_set_prop(LSQArchiveIter *iter, guint n, gpointer value);
 void  lsq_archive_iter_set_props(LSQArchiveIter *iter, ...);
 void  lsq_archive_iter_set_propsv(LSQArchiveIter *iter, gpointer *props);
 
diff --git a/libsqueeze/datetime.c b/libsqueeze/datetime.c
new file mode 100644
index 0000000..2989a00
--- /dev/null
+++ b/libsqueeze/datetime.c
@@ -0,0 +1,344 @@
+/*
+ *  This program is free software; 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 2 of the License, or 
+ *  (at your option) any later version.
+ *
+ *  This program 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 Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+#define _XOPEN_SOURCE
+#include <time.h>
+#include <string.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <gobject/gvaluecollector.h>
+#include <gio/gio.h>
+
+#include <libxfce4util/libxfce4util.h>
+
+#include "libsqueeze.h"
+#include "support-factory.h"
+#include "support-reader.h"
+#include "archive-iter.h"
+#include "archive.h"
+
+#include "internals.h"
+
+static void
+value_init_datetime ( GValue *value )
+{
+    value->data[0].v_pointer = NULL;
+}
+
+static void
+value_free_datetime ( GValue *value )
+{
+    if ( ! ( value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS ) )
+    {
+        g_free( value->data[0].v_pointer );
+    }
+}
+
+static void
+value_copy_datetime (
+        const GValue *src_value,
+        GValue *dest_value )
+{
+    LSQDateTime *copy = NULL;
+    if ( NULL != src_value->data[0].v_pointer )
+    {
+        copy = g_new( LSQDateTime, 1 );
+        *copy = *LSQ_DATETIME(src_value->data[0].v_pointer);
+    }
+    dest_value->data[0].v_pointer = copy;
+}
+
+static gpointer
+value_peek_datetime ( const GValue *value )
+{
+    return value->data[0].v_pointer;
+}
+
+static gchar *
+value_collect_datetime (
+        GValue *value,
+        guint n_collect_values,
+        GTypeCValue *collect_values,
+        guint collect_flags )
+{
+    if ( NULL == collect_values[0].v_pointer )
+    {
+        value->data[0].v_pointer = NULL;
+    }
+    else if ( collect_flags & G_VALUE_NOCOPY_CONTENTS )
+    {
+        value->data[0].v_pointer = collect_values[0].v_pointer;
+        value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
+    }
+    else
+    {
+        LSQDateTime *copy = NULL;
+        if ( NULL != collect_values[0].v_pointer )
+        {
+            copy = g_new( LSQDateTime, 1 );
+            *copy = *LSQ_DATETIME(collect_values[0].v_pointer);
+        }
+        value->data[0].v_pointer = copy;
+    }
+
+    return NULL;
+}
+
+static gchar *
+value_lcopy_datetime (
+        const GValue *value,
+        guint n_collect_values,
+        GTypeCValue *collect_values,
+        guint collect_flags )
+{
+    LSQDateTime **dt_p = collect_values[0].v_pointer;
+
+    if ( NULL == dt_p )
+    {
+        return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
+    }
+
+    if ( NULL == value->data[0].v_pointer)
+    {
+        *dt_p = NULL;
+    }
+    else if ( collect_flags & G_VALUE_NOCOPY_CONTENTS )
+    {
+        *dt_p = value->data[0].v_pointer;
+    }
+    else
+    {
+        LSQDateTime *copy = NULL;
+        if ( NULL != value->data[0].v_pointer )
+        {
+            copy = g_new( LSQDateTime, 1 );
+            *copy = *LSQ_DATETIME(value->data[0].v_pointer);
+        }
+        *dt_p = copy;
+    }
+
+    return NULL;
+}
+
+static void
+value_datetime_to_string (
+        const GValue *src_value,
+        GValue *dest_value )
+{
+    gchar buffer[200]; /* An abitrary size to fit the time string in */
+    const LSQDateTime *dt = g_value_get_datetime( src_value );
+    if ( NULL != dt )
+    {
+        strftime( buffer, sizeof(buffer), "%c", dt );
+        g_value_set_string( dest_value, buffer );
+    }
+}
+
+GType
+lsq_datetime_get_type ( void )
+{
+    static GType type = G_TYPE_INVALID;
+
+    if ( G_UNLIKELY( G_TYPE_INVALID == type ) )
+    {
+        GTypeValueTable value_table = {
+            value_init_datetime,
+            value_free_datetime,
+            value_copy_datetime,
+            value_peek_datetime,
+            "p",
+            value_collect_datetime,
+            "p",
+            value_lcopy_datetime
+        };
+        GTypeInfo type_info = {
+            0,
+            NULL,
+            NULL,
+            NULL,
+            NULL,
+            NULL,
+            0,
+            0,
+            NULL,
+            &value_table
+        };
+        GTypeFundamentalInfo fundamental_info = { 0 };
+
+        type = g_type_register_fundamental(
+                g_type_fundamental_next(),
+                "LSQDateTime",
+                &type_info,
+                &fundamental_info,
+                0
+            );
+
+	g_value_register_transform_func(
+                type,
+                G_TYPE_STRING,
+                value_datetime_to_string
+            );
+    }
+
+    return type;
+}
+
+void
+lsq_datetime_register_type ( void )
+{
+    /* Force lsq_datetime_get_type to get called, and not optimized by G_GNUC_CONST */
+    volatile GType type;
+    type  = lsq_datetime_get_type();
+}
+
+LSQDateTime *
+lsq_datetime_new_from_string (
+        const gchar *str,
+        const gchar *format,
+        gchar **endp )
+{
+    LSQDateTime *dt;
+
+    g_return_val_if_fail( NULL != str, NULL );
+    g_return_val_if_fail( NULL != format, NULL );
+
+    /* we don't expect it to fail, so the chance of an unnecessary alloc isn't high,
+     * if it would fail most of the time, a read to stack and copy to a alloc on success would be better. */
+    dt = g_new0( LSQDateTime, 1 );
+
+    str = strptime( str, format, dt );
+
+    if ( G_UNLIKELY( NULL == str ) )
+    {
+        g_free( dt );
+        dt = NULL;
+    }
+    else if ( NULL != endp )
+    {
+        *endp = (gchar*)str;
+    }
+
+    return dt;
+}
+
+gchar *
+lsq_datetime_from_string (
+        LSQDateTime *dt,
+        const gchar *str,
+        const gchar *format )
+{
+    g_return_val_if_fail( NULL != dt, NULL );
+    g_return_val_if_fail( NULL != str, NULL );
+    g_return_val_if_fail( NULL != format, NULL );
+
+    return strptime( str, format, dt );
+}
+
+gint
+lsq_datetime_cmp (
+        const LSQDateTime *a,
+        const LSQDateTime *b )
+{
+    g_return_val_if_fail( NULL != a, 0 );
+    g_return_val_if_fail( NULL != b, 0 );
+
+    return difftime( mktime( (struct tm*)a ), mktime( (struct tm*)b ) );
+}
+
+const LSQDateTime *
+g_value_get_datetime ( const GValue *value )
+{
+    g_return_val_if_fail( G_VALUE_HOLDS_DATETIME( value ), NULL );
+
+    return value->data[0].v_pointer;
+}
+
+LSQDateTime *
+g_value_dup_datetime ( const GValue *value )
+{
+    LSQDateTime *copy = NULL;
+
+    g_return_val_if_fail( G_VALUE_HOLDS_DATETIME( value ), NULL );
+
+    if ( NULL != value->data[0].v_pointer )
+    {
+        copy = g_new( LSQDateTime, 1 );
+        *copy = *LSQ_DATETIME(value->data[0].v_pointer);
+    }
+
+    return copy;
+}
+
+void
+g_value_set_datetime (
+        GValue *value,
+        const LSQDateTime *dt )
+{
+    LSQDateTime *new_val = NULL;
+
+    g_return_if_fail( G_VALUE_HOLDS_DATETIME( value ) );
+
+    if ( NULL != dt )
+    {
+        new_val = g_new( LSQDateTime, 1 );
+        *new_val = *LSQ_DATETIME(dt);
+    }
+
+    if ( value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS )
+    {
+        value->data[1].v_uint = 0;
+    }
+    else
+    {
+        g_free( value->data[0].v_pointer );
+    }
+
+    value->data[0].v_pointer = new_val;
+}
+
+void
+g_value_set_static_datetime (
+        GValue *value,
+        const gchar *dt )
+{
+    g_return_if_fail( G_VALUE_HOLDS_STRING( value ) );
+
+    if ( ! ( value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS ) )
+    {
+        g_free (value->data[0].v_pointer);
+    }
+    value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
+    value->data[0].v_pointer = LSQ_DATETIME(dt);
+}
+
+void
+g_value_take_datetime (
+        GValue *value,
+        LSQDateTime *dt )
+{
+    g_return_if_fail( G_VALUE_HOLDS_STRING( value ) );
+
+    if ( value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) 
+    {
+        value->data[1].v_uint = 0;
+    }
+    else
+    {
+        g_free( value->data[0].v_pointer );
+    }
+    value->data[0].v_pointer = dt;
+}
+
diff --git a/libsqueeze/datetime.h b/libsqueeze/datetime.h
new file mode 100644
index 0000000..8ade25e
--- /dev/null
+++ b/libsqueeze/datetime.h
@@ -0,0 +1,76 @@
+/*
+ *
+ *  This program is free software; 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 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 Library General Public License for more details.
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software 
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+ */
+
+#ifndef __LIBSQUEEZE_DATETIME_H__
+#define __LIBSQUEEZE_DATETIME_H__ 
+G_BEGIN_DECLS
+
+
+#define LSQ_TYPE_DATETIME lsq_datetime_get_type()
+#define LSQ_DATETIME(p) ((LSQDateTime*)(p))
+
+#define G_VALUE_HOLDS_DATETIME(value) (G_TYPE_CHECK_VALUE_TYPE((value), LSQ_TYPE_DATETIME))
+
+typedef struct tm LSQDateTime;
+
+GType
+lsq_datetime_get_type ( void ) G_GNUC_CONST;
+
+void
+lsq_datetime_register_type ( void );
+
+LSQDateTime *
+lsq_datetime_new_from_string (
+        const gchar *,
+        const gchar *,
+        gchar ** );
+
+gchar *
+lsq_datetime_from_string (
+        LSQDateTime *,
+        const gchar *,
+        const gchar * );
+
+gint
+lsq_datetime_cmp (
+        const LSQDateTime *,
+        const LSQDateTime * );
+
+const LSQDateTime *
+g_value_get_datetime ( const GValue * );
+
+LSQDateTime *
+g_value_dup_datetime ( const GValue * );
+
+void
+g_value_set_datetime (
+        GValue *,
+        const LSQDateTime * );
+
+void
+g_value_set_static_datetime (
+        GValue *,
+        const gchar * );
+
+void
+g_value_take_datetime (
+        GValue *,
+        LSQDateTime * );
+
+
+G_END_DECLS
+
+#endif /* __LIBSQUEEZE_DATETIME_H__ */
diff --git a/libsqueeze/libsqueeze.c b/libsqueeze/libsqueeze.c
index 2dd2105..a62aef0 100644
--- a/libsqueeze/libsqueeze.c
+++ b/libsqueeze/libsqueeze.c
@@ -74,6 +74,8 @@ lsq_init(void)
   const gchar* const* system_dirs = g_get_system_data_dirs ();
   const gchar* user_dir = g_get_user_data_dir ();
 
+  lsq_datetime_register_type();
+
   support_factory_list = NULL;
 
   lsq_opened_archive_list = NULL;
diff --git a/libsqueeze/libsqueeze.h b/libsqueeze/libsqueeze.h
index e86ed79..965e054 100644
--- a/libsqueeze/libsqueeze.h
+++ b/libsqueeze/libsqueeze.h
@@ -24,6 +24,7 @@
 #include <libsqueeze/archive-iter-pool.h>
 #include <libsqueeze/archive.h>
 #include <libsqueeze/archive-iter.h>
+#include <libsqueeze/datetime.h>
 
 #include <libsqueeze/libsqueeze-view.h>
 
diff --git a/libsqueeze/parser.c b/libsqueeze/parser.c
index 3a3e92c..ca2578f 100644
--- a/libsqueeze/parser.c
+++ b/libsqueeze/parser.c
@@ -103,6 +103,7 @@ lsq_storage_group_has_type (
 static void
 lsq_parser_init ( LSQParser *self )
 {
+    self->datetime_format = g_strdup( "%c" );
 }
 
 static void
@@ -120,6 +121,7 @@ lsq_parser_class_init ( LSQParserClass *klass )
     lsq_storage_group_add(G_TYPE_UINT, sizeof(guint));
     lsq_storage_group_add(G_TYPE_UINT64, sizeof(guint64));
     lsq_storage_group_add(G_TYPE_ULONG, sizeof(gulong));
+    lsq_storage_group_add(LSQ_TYPE_DATETIME, sizeof(LSQDateTime*));
 }
 
 LSQParserContext*
@@ -229,3 +231,11 @@ lsq_parser_get_properties_size ( LSQParser *parser )
     return parser->properties_size;
 }
 
+void
+lsq_parser_set_datetime_format (
+        LSQParser *parser,
+        const gchar *format )
+{
+    g_free( parser->datetime_format );
+    parser->datetime_format = g_strdup( format );
+}
diff --git a/libsqueeze/parser.h b/libsqueeze/parser.h
index b3c0301..8d8a283 100644
--- a/libsqueeze/parser.h
+++ b/libsqueeze/parser.h
@@ -56,6 +56,8 @@ struct _LSQParser
     GType *property_types;
     guint *property_offset;
     guint properties_size;
+
+    gchar *datetime_format;
 };
 
 
@@ -112,6 +114,11 @@ lsq_parser_get_property_offset (
 guint
 lsq_parser_get_properties_size ( LSQParser * );
 
+void
+lsq_parser_set_datetime_format (
+        LSQParser *,
+        const gchar * );
+
 G_END_DECLS
 
 #endif /* __LIBSQUEEZE_PARSER_H__ */
diff --git a/libsqueeze/pcre-parser.c b/libsqueeze/pcre-parser.c
index 46f4edc..2853f5c 100644
--- a/libsqueeze/pcre-parser.c
+++ b/libsqueeze/pcre-parser.c
@@ -36,7 +36,7 @@ typedef struct _type_parser type_parser;
 typedef struct _LSQPcreParserContext LSQPcreParserContext;
 typedef struct _LSQPcreParserContextClass LSQPcreParserContextClass;
 
-typedef void (*LSQParseFunc)( gchar*, guint, LSQArchiveIter*, guint );
+typedef void (*LSQParseFunc)( gchar*, guint, LSQArchiveIter*, guint, LSQPcreParser* );
 
 struct _type_parser
 {
@@ -132,28 +132,28 @@ lsq_pcre_parser_new ( const gchar *parser_string, gchar **parser_types )
 }
 
 #define DEF_PARSE_NUM(func, base, type) \
-static void parse_##func(gchar *str, guint lng, LSQArchiveIter *iter, guint n) {  \
+static void parse_##func(gchar *str, guint lng, LSQArchiveIter *iter, guint n, LSQPcreParser *parser) {  \
     type val; \
     val = g_ascii_strtoll( str, NULL, base ); \
     lsq_archive_iter_set_prop( iter, n, &val ); \
 }
 
 #define DEF_PARSE_FLOAT(func, type)  \
-static void parse_##func(gchar *str, guint lng, LSQArchiveIter *iter, guint n) {  \
+static void parse_##func(gchar *str, guint lng, LSQArchiveIter *iter, guint n, LSQPcreParser *parser) {  \
     type  val;  \
     val = g_ascii_strtod(str, NULL);  \
     lsq_archive_iter_set_prop( iter, n, &val ); \
 }
 
 #define DEF_PARSE_UNS(func, base, type) \
-static void parse_##func(gchar *str, guint lng, LSQArchiveIter *iter, guint n) {  \
+static void parse_##func(gchar *str, guint lng, LSQArchiveIter *iter, guint n, LSQPcreParser *parser) {  \
     type val; \
     val = g_ascii_strtoull( str, NULL, base ); \
     lsq_archive_iter_set_prop( iter, n, &val ); \
 }
 
 static void
-parse_char( gchar *str, guint lng, LSQArchiveIter *iter, guint n )
+parse_char( gchar *str, guint lng, LSQArchiveIter *iter, guint n, LSQPcreParser *parser )
 {
     gchar val;
 
@@ -177,7 +177,7 @@ DEF_PARSE_UNS(octal32, 010, gulong)
 DEF_PARSE_UNS(octal64, 010, guint64)
 
 static void
-parse_string( gchar *str, guint lng, LSQArchiveIter *iter, guint n )
+parse_string( gchar *str, guint lng, LSQArchiveIter *iter, guint n, LSQPcreParser *parser )
 {
     gchar *val;
 
@@ -185,8 +185,26 @@ parse_string( gchar *str, guint lng, LSQArchiveIter *iter, guint n )
     val = g_strndup( str, lng );
 
     lsq_archive_iter_set_prop( iter, n, val );
+}
+
+static void
+parse_datetime( gchar *str, guint lng, LSQArchiveIter *iter, guint n, LSQPcreParser *parser )
+{
+    LSQDateTime *val;
+
+#ifdef DO_EXSTENSIVE_CHECKING
+    gchar *end;
+    val = lsq_datetime_new_from_string( str, LSQ_PARSER(parser)->datetime_format, *end);
+    if ( val && ( end - str ) > lng )
+    {
+        g_free( val );
+        val = NULL;
+    }
+#else
+    val = lsq_datetime_new_from_string( str, LSQ_PARSER(parser)->datetime_format, NULL);
+#endif
 
-    g_free( val );
+    lsq_archive_iter_set_prop( iter, n, val );
 }
 
 DEF_PARSE_UNS(unsigned, 10, guint)
@@ -380,6 +398,11 @@ build_parser ( LSQPcreParser *parser, const gchar *parser_string, gchar **parser
                 type = G_TYPE_STRING;
                 break;
 
+            case 't':   /* DateTime */
+                type_iter->function = parse_datetime;
+                type = LSQ_TYPE_DATETIME;
+                break;
+
             case 'u':   /* Unsigned integer */
                 switch(size_flag)
                 {
@@ -536,7 +559,7 @@ lsq_pcre_parser_parse ( LSQPcreParser *parser, LSQPcreParserContext *ctx )
             end = ovector[( index_ * 2 ) + 1];
 
             /* Parse the subfield */
-            parser->types_list[i].function( line + start, end - start, iter, LSQ_ARCHIVE_PROP_USER +  i );
+            parser->types_list[i].function( line + start, end - start, iter, LSQ_ARCHIVE_PROP_USER +  i, parser );
         }
 
         lsq_archive_iter_unref( iter );
diff --git a/libsqueeze/scanf-parser.c b/libsqueeze/scanf-parser.c
index 462dca1..6c80a2a 100644
--- a/libsqueeze/scanf-parser.c
+++ b/libsqueeze/scanf-parser.c
@@ -35,7 +35,7 @@ typedef struct _parse_part parse_part;
 typedef struct _LSQScanfParserContext LSQScanfParserContext;
 typedef struct _LSQScanfParserContextClass LSQScanfParserContextClass;
 
-typedef guint (*LSQParseFunc)(gchar*, guint, parse_part*, LSQScanfParserContext*);
+typedef guint (*LSQParseFunc)(gchar*, guint, parse_part*, LSQScanfParserContext*, LSQScanfParser*);
 
 struct _parse_part
 {
@@ -147,7 +147,8 @@ skip_byte (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     if ( 1 > lng )
     {
@@ -162,7 +163,8 @@ skip_word (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     if ( 2 > lng )
     {
@@ -177,7 +179,8 @@ skip_dword (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     if ( 4 > lng )
     {
@@ -192,7 +195,8 @@ skip_qword (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     if ( 8 > lng )
     {
@@ -207,7 +211,8 @@ skip_char (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     const gchar *ptr;
     const gchar *delim;
@@ -245,7 +250,8 @@ skip_decimal (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     gchar *ptr;
 #ifdef DO_EXSTENSIVE_CHECKING
@@ -270,7 +276,14 @@ skip_decimal (
         return ptr - str;
     }
 
-    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr );
+    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr )
+    {
+        --lng;
+        if ( 0 == lng )
+        {
+            return 0;
+        }
+    }
 
     ptr = g_strstr_len(ptr, lng, delim);
 
@@ -295,7 +308,8 @@ skip_floatingpoint (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     gchar *ptr;
 #ifdef DO_EXSTENSIVE_CHECKING
@@ -320,7 +334,14 @@ skip_floatingpoint (
         return ptr - str;
     }
 
-    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr );
+    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr )
+    {
+        --lng;
+        if ( 0 == lng )
+        {
+            return 0;
+        }
+    }
 
     ptr = g_strstr_len(ptr, lng, delim);
 
@@ -344,7 +365,8 @@ skip_octal (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx ,
+        LSQScanfParser *parser)
 {
     gchar *ptr;
 #ifdef DO_EXSTENSIVE_CHECKING
@@ -369,7 +391,14 @@ skip_octal (
         return ptr - str;
     }
 
-    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr );
+    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr )
+    {
+        --lng;
+        if ( 0 == lng )
+        {
+            return 0;
+        }
+    }
 
     ptr = g_strstr_len(ptr, lng, delim);
 
@@ -394,7 +423,8 @@ skip_string (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     gchar *ptr;
     const gchar *delim;
@@ -416,7 +446,14 @@ skip_string (
         return 0;
     }
 
-    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr );
+    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr )
+    {
+        --lng;
+        if ( 0 == lng )
+        {
+            return 0;
+        }
+    }
 
     ptr = g_strstr_len ( ptr, lng, delim );
 
@@ -429,11 +466,64 @@ skip_string (
 }
 
 static guint
+skip_datetime (
+        gchar *str,
+        guint lng,
+        parse_part *part,
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
+{
+    gchar *ptr;
+    gchar *cur;
+    const gchar *delim;
+    LSQDateTime val;
+
+    if ( 0 == lng )
+    {
+        return 0;
+    }
+
+    delim = part->delimiter;
+    if ( ( NULL == delim ) && ( NULL == part->next ) )
+    {
+        delim = "\n";
+    }
+
+    for ( cur = str; g_ascii_isspace( *cur ); ++cur )
+    {
+    }
+
+    ptr = lsq_datetime_from_string(&val, cur, LSQ_PARSER(parser)->datetime_format);
+    if ( NULL == ptr )
+    {
+        return 0;
+    }
+
+    if ( ( ptr - str ) > lng )
+    {
+        return 0;
+    }
+
+    if ( '\0' == delim[0] )
+    {
+        lng -= ptr - str;
+        ptr = g_strstr_len( ptr, lng, delim );
+        if ( NULL == ptr )
+        {
+            return 0;
+        }
+    }
+
+    return ptr - str;
+}
+
+static guint
 skip_unsigned (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     gchar *ptr;
 #ifdef DO_EXSTENSIVE_CHECKING
@@ -458,7 +548,16 @@ skip_unsigned (
         return ptr - str;
     }
 
-    ptr = g_strstr_len ( str, lng, delim );
+    for ( ptr = str; g_ascii_isspace(*ptr); ++ptr )
+    {
+        --lng;
+        if ( 0 == lng )
+        {
+            return 0;
+        }
+    }
+
+    ptr = g_strstr_len(ptr, lng, delim);
 
     if ( NULL == ptr )
     {
@@ -482,7 +581,8 @@ skip_hexadecimal (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     gchar *ptr;
 #ifdef DO_EXSTENSIVE_CHECKING
@@ -507,7 +607,16 @@ skip_hexadecimal (
         return ptr - str;
     }
 
-    ptr = g_strstr_len ( str, lng, delim );
+    for ( ptr = str; g_ascii_isspace(*ptr); ++ptr )
+    {
+        --lng;
+        if ( 0 == lng )
+        {
+            return 0;
+        }
+    }
+
+    ptr = g_strstr_len(ptr, lng, delim);
 
     if ( NULL == ptr )
     {
@@ -527,7 +636,7 @@ skip_hexadecimal (
 
 /*{{{ parse functions*/
 #define DEF_PARSE_BIN(func, bytes, type, ptype, pname)    \
-static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx) { \
+static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx, LSQScanfParser *parser) { \
     type    val;    \
     ptype *pval;    \
     if(bytes > lng) return 0; \
@@ -539,7 +648,7 @@ static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParse
 }
 
 #define DEF_PARSE_NUM(func, base, type, ptype, pname) \
-static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx) {    \
+static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx, LSQScanfParser *parser) {    \
     gchar *ptr;     \
     gchar *ptr2;    \
     type    val;    \
@@ -555,7 +664,7 @@ static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParse
         *pval = val;    \
         return ptr - str; \
     } \
-    for(ptr = str; g_ascii_isspace(*ptr); ++ptr);     \
+    for(ptr = str; g_ascii_isspace(*ptr); ++ptr) --lng; \
     ptr = g_strstr_len(ptr, lng, delim);    \
     if(NULL == ptr) return 0;   \
     val = g_ascii_strtoll(str, &ptr2, base);    \
@@ -565,7 +674,7 @@ static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParse
 }
 
 #define DEF_PARSE_FLOAT(func, type, pname)    \
-static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx) {    \
+static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx, LSQScanfParser *parser) {    \
     gchar *ptr;     \
     gchar *ptr2;    \
     type    val;    \
@@ -581,7 +690,7 @@ static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParse
         *pval = val;    \
         return ptr - str; \
     } \
-    for(ptr = str; g_ascii_isspace(*ptr); ++ptr);     \
+    for(ptr = str; g_ascii_isspace(*ptr); ++ptr) --lng; \
     ptr = g_strstr_len(ptr, lng, delim);    \
     if(NULL == ptr) return 0;   \
     val = g_ascii_strtod(str, &ptr2); \
@@ -591,7 +700,7 @@ static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParse
 }
 
 #define DEF_PARSE_UNS(func, base, type, ptype, pname) \
-static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx) {    \
+static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx, LSQScanfParser *parser) {    \
     gchar *ptr;     \
     gchar *ptr2;    \
     type    val;    \
@@ -607,7 +716,7 @@ static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParse
         *pval = val;    \
         return ptr - str; \
     } \
-    for(ptr = str; g_ascii_isspace(*ptr); ++ptr);     \
+    for(ptr = str; g_ascii_isspace(*ptr); ++ptr) --lng; \
     ptr = g_strstr_len(ptr, lng, delim);    \
     if(NULL == ptr) return 0;   \
     val = g_ascii_strtoull(str, &ptr2, base);    \
@@ -626,7 +735,8 @@ parse_char (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+	LSQScanfParser *parser )
 {
     const gchar *ptr;
     gchar val;
@@ -688,7 +798,8 @@ parse_string (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+	LSQScanfParser *parser )
 {
     gchar *ptr;
     gchar *cur;
@@ -704,7 +815,14 @@ parse_string (
     if ( '\0' == delim[0] )
         return 0;
 
-    for ( cur = str; g_ascii_isspace( *cur ); ++cur );
+    for ( cur = str; g_ascii_isspace( *cur ); ++cur )
+    {
+        --lng;
+        if ( 0 == lng )
+        {
+            return 0;
+        }
+    }
 
     ptr = g_strstr_len(cur, lng, delim);
 
@@ -716,6 +834,60 @@ parse_string (
     return ptr - str;
 }
 
+static guint
+parse_datetime (
+        gchar *str,
+        guint lng,
+        parse_part *part,
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
+{
+    gchar *ptr;
+    gchar *cur;
+    const gchar *delim;
+    LSQDateTime *val;
+
+    if ( 0 == lng )
+    {
+        return 0;
+    }
+
+    delim = part->delimiter;
+    if ( ( NULL == delim ) && ( NULL == part->next ) )
+    {
+        delim = "\n";
+    }
+
+    for ( cur = str; g_ascii_isspace( *cur ); ++cur)
+    {
+    }
+
+    val = lsq_datetime_new_from_string( cur, LSQ_PARSER(parser)->datetime_format, &ptr );
+    if ( NULL == val )
+        return 0;
+
+    if ( ( ptr - str ) > lng )
+    {
+        g_free( val );
+        return 0;
+    }
+
+    ctx->props_store[ part->index_ ] = val;
+
+    if ( '\0' == delim[0] )
+    {
+        lng -= ptr - str;
+        ptr = g_strstr_len ( ptr, lng, delim );
+        if ( NULL == ptr )
+        {
+            g_free( val );
+            return 0;
+        }
+    }
+
+    return ptr - str;
+}
+
 DEF_PARSE_UNS(unsigned, 10, guint, guint, u)
 DEF_PARSE_UNS(unsigned16, 10, gushort, guint, u)
 DEF_PARSE_UNS(unsigned32, 10, gulong, gulong, ul)
@@ -731,7 +903,8 @@ parse_filename (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+	LSQScanfParser *parser )
 {
     gchar *ptr;
     const gchar *delim;
@@ -1124,7 +1297,7 @@ build_parser (
                     }
                 break;
                 /*}}}*/
-                /*{{{ floating point %d*/
+                /*{{{ floating point %f*/
                 case 'f':
                     g_return_if_fail( SIZE_NORMAL == size_flag || SIZE_LONGLONG == size_flag );
                     part->next = g_new0(parse_part, 1);
@@ -1208,6 +1381,25 @@ build_parser (
                     }
                 break;
                 /*}}}*/
+                /*{{{ datetime %t*/
+                case 't':
+                    g_return_if_fail(!size_flag);
+                    part->next = g_new0(parse_part, 1);
+                    part = part->next;
+                    part->width = width_flag;
+                    if(skip_flag)
+                    {
+                        part->function = skip_datetime;
+                    }
+                    else
+                    {
+                        part_count++;
+                        part->index_ = index_;
+                        part->function = parse_datetime;
+                        lsq_parser_set_property_type(LSQ_PARSER(parser), index_, LSQ_TYPE_DATETIME);
+                    }
+                break;
+                /*}}}*/
                 /*{{{ unsigned decimal %u*/
                 case 'u':
                     part->next = g_new0(parse_part, 1);
@@ -1327,7 +1519,7 @@ lsq_scanf_parser_parse (
         //parse
         if ( NULL != part->function )
         {
-            size = part->function(ptr, lng, part, ctx);
+            size = part->function(ptr, lng, part, ctx, parser);
             if ( 0 == size )
             {
                 //no match
diff --git a/libsqueeze/support-reader.c b/libsqueeze/support-reader.c
index 5032ec7..7430f62 100644
--- a/libsqueeze/support-reader.c
+++ b/libsqueeze/support-reader.c
@@ -138,6 +138,7 @@ lsq_support_reader_parse_file(const gchar *filename)
 	LSQParser *parser = NULL;
 	const gchar *parser_string;
 	const gchar *parser_regex;
+	const gchar *parser_datetime;
 	gchar **_mime_types;
 #ifdef HAVE_PCRE
 	gchar **regex_types;
@@ -202,6 +203,7 @@ lsq_support_reader_parse_file(const gchar *filename)
 	column_names = xfce_rc_read_list_entry(rc, "X-Squeeze-Headers", ";");
 	parser_string = xfce_rc_read_entry(rc, "X-Squeeze-Parse", NULL);
 	parser_regex = xfce_rc_read_entry(rc, "X-Squeeze-Parse-Regex", NULL);
+	parser_datetime = xfce_rc_read_entry(rc, "X-Squeeze-Parse-DateTime", NULL);
 
 	if (NULL != parser_string)
 	{
@@ -215,6 +217,10 @@ lsq_support_reader_parse_file(const gchar *filename)
 	    g_strfreev( regex_types );
 	}
 #endif
+        if ( NULL != parser_datetime )
+        {
+            lsq_parser_set_datetime_format( parser, parser_datetime );
+        }
 
 	_mime_types = mime_types;
 	for(i = 0; _mime_types[i]; ++i)
diff --git a/src/archive_store.c b/src/archive_store.c
index 8faed2e..56787f6 100644
--- a/src/archive_store.c
+++ b/src/archive_store.c
@@ -867,7 +867,7 @@ sq_archive_entry_compare(SQArchiveStore *store, LSQArchiveIter *a, LSQArchiveIte
 		case G_TYPE_STRING:
 			if(g_value_get_string(&prop_a) == NULL)
 			{
-				retval = -1;
+				retval = ( NULL == g_value_get_string( &prop_b ) ) ? 0 : -1;
 				break;
 			}
 			if(g_value_get_string(&prop_b) == NULL)
@@ -891,6 +891,23 @@ sq_archive_entry_compare(SQArchiveStore *store, LSQArchiveIter *a, LSQArchiveIte
 		case G_TYPE_UINT:
 			retval = g_value_get_uint(&prop_a) - g_value_get_uint(&prop_b);
 			break;
+		default:
+			if ( LSQ_TYPE_DATETIME == lsq_archive_get_entry_property_type(archive, column) )
+                        {
+                            if(g_value_get_datetime(&prop_a) == NULL)
+                            {
+                                retval = ( NULL == g_value_get_datetime( &prop_b ) ) ? 0 : -1;
+                                break;
+                            }
+                            if(g_value_get_datetime(&prop_b) == NULL)
+                            {
+                                retval = 1;
+                                break;
+                            }
+                            retval = lsq_datetime_cmp( g_value_get_datetime(&prop_a), g_value_get_datetime(&prop_b) );
+                            break;
+                        }
+			break;
 	}
 	g_value_unset(&prop_a);
 	g_value_unset(&prop_b);
diff --git a/src/notebook.c b/src/notebook.c
index de09a7c..2de6571 100644
--- a/src/notebook.c
+++ b/src/notebook.c
@@ -729,6 +729,14 @@ sq_notebook_treeview_reset_columns(LSQArchive *archive, GtkTreeView *treeview)
 		{
 			switch(lsq_archive_get_entry_property_type(archive, x))
 			{
+                                default:
+                                        if ( LSQ_TYPE_DATETIME != lsq_archive_get_entry_property_type(archive, x) )
+                                        {
+#ifdef DEBUG
+                                            g_debug("Should not be reached");
+#endif
+                                            continue;
+                                        }
         case(G_TYPE_CHAR):
 				case(G_TYPE_DOUBLE):
 				case(G_TYPE_FLOAT):
@@ -742,11 +750,6 @@ sq_notebook_treeview_reset_columns(LSQArchive *archive, GtkTreeView *treeview)
 					renderer = gtk_cell_renderer_text_new();
 					column = gtk_tree_view_column_new_with_attributes(lsq_archive_get_entry_property_name(archive, x), renderer, "text", x+SQ_ARCHIVE_STORE_EXTRA_PROP_COUNT, NULL);
 					break;
-        default:
-#ifdef DEBUG
-          g_debug("Should not be reached");
-#endif
-          continue;
 			}
 			gtk_tree_view_column_set_resizable(column, TRUE);
 			gtk_tree_view_column_set_sort_column_id(column, x+SQ_ARCHIVE_STORE_EXTRA_PROP_COUNT);


More information about the Xfce4-commits mailing list