Updating branch refs/heads/master to 15c767a3557acf54ae9dd5bba7e08879aa4f5fd4 (commit) from bc7be8990bb2b53079703a8f6b3b70a15e8c7f5f (commit)
commit 15c767a3557acf54ae9dd5bba7e08879aa4f5fd4 Author: Peter de Ridder <pe...@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); _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org https://mail.xfce.org/mailman/listinfo/xfce4-commits