[grisbi-cvs] [SCM] grisbi branch, master, updated. upstream_version_0_9_3-15-ga39ed67

Philippe Delorme nobody at users.sourceforge.net
Sat Aug 27 15:48:26 CEST 2011


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "grisbi".

The branch, master has been updated
       via  a39ed671261058a83e6d89e2e26d89f0aba793e8 (commit)
       via  061bcbab5035b3c861a8748b2eb0581702a32234 (commit)
      from  d4dc2d785dc443d8386bff7b506e6bb7ca47ac9f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a39ed671261058a83e6d89e2e26d89f0aba793e8
Author: Philippe Delorme <philippedelorme at users.sourceforge.net>
Date:   Sat Aug 27 15:38:06 2011 +0200

    Control string format of dates with regex

commit 061bcbab5035b3c861a8748b2eb0581702a32234
Author: Philippe Delorme <philippedelorme at users.sourceforge.net>
Date:   Sat Aug 27 15:34:26 2011 +0200

    Add a regex store

-----------------------------------------------------------------------

Changes:
diff --git a/src/Makefile.am b/src/Makefile.am
index beddca6..acb2dcf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -111,6 +111,7 @@ libgrisbi_la_SOURCES = \
 	gsb_reconcile_config.c	\
 	gsb_reconcile_list.c	\
 	gsb_reconcile_sort_config.c	\
+	gsb_regex.c		\
 	gsb_report.c		\
 	gsb_scheduler.c		\
 	gsb_scheduler_list.c	\
@@ -250,6 +251,7 @@ libgrisbi_la_SOURCES = \
 	gsb_reconcile_config.h	\
 	gsb_reconcile_list.h	\
 	gsb_reconcile_sort_config.h	\
+	gsb_regex.h		\
 	gsb_report.h		\
 	gsb_status.h            \
 	gsb_select_icon.h 	\
diff --git a/src/gsb_regex.c b/src/gsb_regex.c
new file mode 100644
index 0000000..72fe084
--- /dev/null
+++ b/src/gsb_regex.c
@@ -0,0 +1,140 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*     Copyright (C)    2000-2008 Cédric Auger (cedric at grisbi.org)            */
+/*          2003-2009 Benjamin Drieu (bdrieu at april.org)                       */
+/*          2008-2011 Pierre Biava (grisbi at pierre.biava.name)                 */
+/*          http://www.grisbi.org                                             */
+/*                                                                            */
+/*  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 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 */
+/*                                                                            */
+/* ************************************************************************** */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+ /*START_INCLUDE*/
+#include "gsb_regex.h"
+/*END_INCLUDE*/
+
+/*START_STATIC*/
+static GHashTable *regex_store = NULL;
+/*END_STATIC*/
+
+/*START_EXTERN*/
+/*END_EXTERN*/
+
+
+
+/**
+ * Initialize the hash map which is used to store 
+ * compile GRegex during the whole exeuction of Grisbi.
+ *
+ * This function is called on Grisbi startup and each time 
+ * of a new file is opened.
+ *
+ * \return void
+ */
+void gsb_regex_init_variables ( void )
+{
+    if ( regex_store )
+    {
+        g_hash_table_destroy ( regex_store );
+        regex_store = NULL;
+    }
+
+    regex_store = g_hash_table_new_full ( g_str_hash,
+                                          g_str_equal,
+                                          (GDestroyNotify) g_free,
+                                          (GDestroyNotify) g_regex_unref );
+}
+
+
+/**
+ * Add a new regex to the map.
+ *
+ * \param key the key to retrieve the regex
+ * \param pattern the pattern of the GRegex
+ * \param compile_options options passed to g_regex_new, can be NULL
+ * \param match_options options passed to g_regex_new, can be NULL
+ *
+ * \return Pointer value on success, NULL otherwise
+ */
+GRegex *gsb_regex_insert ( const gchar *key,
+                            const gchar *pattern,
+                            GRegexCompileFlags compile_options,
+                            GRegexMatchFlags match_options )
+{
+    GRegex *regex;
+    GError *error = NULL;
+
+    if ( ! regex_store )
+        return NULL;
+
+    if ( ! key || ! strlen ( key ) 
+         || ! pattern || ! strlen ( pattern ) )
+        return NULL;
+
+    regex = g_regex_new ( pattern, compile_options, match_options, &error );
+    if ( ! regex )
+    {
+        g_print ( _("Unable to compile regex: %s\n"), error -> message);
+        g_error_free ( error );
+        return NULL;
+    }
+
+    g_hash_table_insert ( regex_store, 
+                          (gpointer) g_strdup ( key ), 
+                          regex );
+
+    return regex;
+}
+
+
+/**
+ * Get a GRegex stored in the map.
+ *
+ * \param key
+ *
+ * \return Pointer on the regex, NULL if it can't be found
+ */
+GRegex *gsb_regex_lookup ( const gchar *key )
+{
+    return g_hash_table_lookup ( regex_store, key );
+}
+
+
+/**
+ * Destroy the hash map. Free keys and values properly.
+ *
+ * This function is called once on Grisbi shutdown.
+ *
+ * \return void
+ */
+void gsb_regex_destroy ( void )
+{
+    if ( regex_store )
+        g_hash_table_destroy ( regex_store );
+}
+
+
+
+/* Local Variables: */
+/* c-basic-offset: 4 */
+/* End: */
diff --git a/src/gsb_regex.h b/src/gsb_regex.h
new file mode 100644
index 0000000..7037d6e
--- /dev/null
+++ b/src/gsb_regex.h
@@ -0,0 +1,20 @@
+#ifndef _GSB_REGEX_H
+#define _GSB_REGEX_H (1)
+
+#include <glib.h>
+
+
+/* START_INCLUDE_H */
+/* END_INCLUDE_H */
+
+
+/* START_DECLARATION */
+void gsb_regex_init_variables ( void );
+void gsb_regex_destroy ( void );
+GRegex *gsb_regex_lookup ( const gchar * );
+GRegex *gsb_regex_insert ( const gchar *, const gchar *,
+                           GRegexCompileFlags, GRegexMatchFlags );
+/* END_DECLARATION */
+
+
+#endif
diff --git a/src/traitement_variables.c b/src/traitement_variables.c
index 0efcb46..1d3cc73 100644
--- a/src/traitement_variables.c
+++ b/src/traitement_variables.c
@@ -68,6 +68,7 @@
 #include "gsb_fyear.h"
 #include "gsb_locale.h"
 #include "gsb_real.h"
+#include "gsb_regex.h"
 #include "gsb_report.h"
 #include "gsb_scheduler_list.h"
 #include "gsb_select_icon.h"
@@ -188,6 +189,7 @@ void init_variables ( void )
     gsb_currency_init_variables ();
     gsb_fyear_init_variables ();
     gsb_report_init_variables ();
+    gsb_regex_init_variables ();
 
     gsb_data_print_config_init ();
 
@@ -323,6 +325,7 @@ void free_variables ( void )
 {
     gsb_data_print_config_free ();
     gsb_gui_navigation_free_pages_list ( );
+    gsb_regex_destroy ( );
 }
 
 
diff --git a/src/utils_dates.c b/src/utils_dates.c
index 16bcc7e..5ec5217 100644
--- a/src/utils_dates.c
+++ b/src/utils_dates.c
@@ -39,20 +39,28 @@
 #include "dialog.h"
 #include "gsb_calendar_entry.h"
 #include "gsb_form_widget.h"
+#include "gsb_regex.h"
 #include "utils_str.h"
 #include "erreur.h"
 /*END_INCLUDE*/
 
 /*START_STATIC*/
-static gchar **split_unique_datefield ( gchar * string, gchar **date_tokens );
+/* format pour les dates */
+static gchar *format = NULL;
 /*END_STATIC*/
 
-
 /*START_EXTERN*/
 /*END_EXTERN*/
 
-/* format pour les dates */
-static gchar *format = NULL;
+
+/* date regex:
+ * 1 or 2 digits + 
+ * optional ( optional separator + 2 digits + 
+ *            optional ( optional separator + 2 or 4 digits ) )
+ */
+#define DATE_STRING_REGEX       "^(\\d{1,2})(?:[-/.:]?(\\d{1,2})(?:[-/.:]?(\\d{2}(?:\\d{2})?))?)?$"
+#define DATE_STRING_KEY         "date_string"
+
 
 /* save of the last date entried */
 static gchar *last_date = NULL;
@@ -294,54 +302,6 @@ gboolean gsb_date_check_entry ( GtkWidget *entry )
     return ( TRUE );
 }
 
-/**
- * try to split a compact date into an understanding date
- * ie 01042000 to 01/04/2000
- *
- * \param string
- * \param date_tokens
- *
- * \return NULL if not a date
- */
-gchar **split_unique_datefield ( gchar *string, gchar **date_tokens )
-{
-    gchar **return_tab;
-    gint size;
-    gchar *max;
-    gint i = 0;
-    gint num_fields = 0;
-
-    num_fields = g_strv_length ( date_tokens );
-    return_tab = g_new ( gchar *, num_fields + 1 );
-    size = strlen ( string );
-    max = string + size;
-
-    /* size 1 could be used for example if we write 1 to set 01/mm/yyyy */
-    if ( size != 1 && size != 2 && size != 4 && size != 6 && size != 8 )
-    {
-        return NULL;
-    }
-
-    for ( i = 0 ; date_tokens [ i ] && string < max; i ++ )
-    {
-        if ( size != 8 || strcmp ( date_tokens [ i ], "Y" ) != 0 )
-        {
-            return_tab [ i ] = g_strndup ( string, 2 );
-            string += 2;
-        }
-        else
-        {
-            return_tab [ i ] = g_strndup ( string, 4 );
-            string += 4;
-        }
-    }
-
-    return_tab [ i ] = NULL;
-
-    return return_tab;
-}
-
-
 
 /**
  * Create and try to return a GDate from a string representation of a date.
@@ -355,160 +315,95 @@ gchar **split_unique_datefield ( gchar *string, gchar **date_tokens )
 GDate *gsb_parse_date_string ( const gchar *date_string )
 {
     GDate *date;
-    gchar *string;
-    gchar *string_ptr;
-    gchar **tab_date;
+    GRegex *date_regex;
     gchar **date_tokens;
-    gint num_tokens = 3;
-    gint num_fields = 0;
-    gint i;
-    gint j;
+    gchar **tab_date;
+    int num_tokens, num_fields;
+    int i, j;
 
     if ( !date_string || !strlen ( date_string ) )
         return NULL;
 
-    /* Keep the const gchar in that function */
-    string = g_strdup ( date_string );
-
-    /* And keep a pointer to free memory later */
-    string_ptr = string;
-
     /* récupère le format des champs date */
     date_tokens = g_strsplit ( format + 1, "/%", 3 );
 
-    /* delete space char */
-    g_strstrip ( string );
-
-    /* replace all separators by . */
-    g_strcanon ( string, "0123456789", '.' );
-
-    /* remove the . at the beginning and ending of the string */
-    while ( * string == '.' && * string ) string ++;
-    while ( string [ strlen ( string ) - 1 ] == '.' && strlen ( string ) ) 
-        string [ strlen ( string )  - 1 ] = '\0';
-
-    /* remove if there are some .. */
-    tab_date = g_strsplit ( string, "..", 0 );
-    g_free ( string_ptr );
-    string = g_strjoinv ( ".", tab_date );
-    string_ptr = string;
-    g_strfreev ( tab_date );
-
-    /* split the parts of the date */
-    tab_date = g_strsplit_set ( string, ".", 0 );
-
-    /* From here, string is no more used */
-    g_free ( string_ptr );
-    string = string_ptr = NULL;
-
-    num_fields = g_strv_length ( tab_date );
-
-    if ( num_fields == 0 )
-    {
-        g_strfreev ( tab_date );
-        return NULL;
-    }
-    else if ( num_fields == 1 )
+    /* get the regex from the store */
+    date_regex = gsb_regex_lookup ( DATE_STRING_KEY );
+    if ( ! date_regex )
     {
-        /* there is only 1 field in the date, try to split the number
-         * (ie 01042000 gives 01/04/2000) */
-        gchar **new_tab_date;
-
-        new_tab_date = split_unique_datefield ( tab_date [0], date_tokens );
-
-        g_strfreev ( tab_date );
-
-        if ( ! new_tab_date )
-            return NULL;
-        else
+        /* only for the first call */
+        devel_debug ( DATE_STRING_KEY );
+        date_regex = gsb_regex_insert ( DATE_STRING_KEY, DATE_STRING_REGEX, 0, 0 );
+        if ( ! date_regex )
         {
-            tab_date = new_tab_date;
-            num_fields = g_strv_length ( tab_date );
+            /* big problem */
+            alert_debug ( DATE_STRING_KEY );
+            return NULL;
         }
     }
 
+    if ( ! g_regex_match ( date_regex, date_string, 0, NULL ) )
+        return NULL;
+
+    tab_date = g_regex_split ( date_regex, date_string, 0 );
+
     /* Initialize date */
     date = gdate_today ();
 
-    for ( i = 0, j = 0 ; i < num_tokens && j < num_fields ; i ++ )
+    num_tokens = g_strv_length ( date_tokens );
+    num_fields = g_strv_length ( tab_date ) - 1;
+    for ( i = 0, j = 1;
+          i < num_tokens && j < num_fields;
+          i ++, j ++ )
     {
-        gint nvalue = atoi ( tab_date [ j ] );
+        gint nvalue = atoi ( tab_date[j] );
 
-        switch ( date_tokens [ i ][0] )
+        switch ( date_tokens[i][0] )
         {
             case 'm':
-            if ( g_date_valid_month ( nvalue ) )
-            {
+                if ( ! g_date_valid_month ( nvalue ) )
+                    goto invalid;
                 g_date_set_month ( date, nvalue );
-                j++;
-            }
-            else
-            {
-                g_date_free ( date );
-                g_strfreev ( tab_date );
-                return NULL;
-            }
-            break;
+                break;
+
             case 'd':
-            if ( g_date_valid_day ( nvalue ) )
-            {
+                if ( ! g_date_valid_day ( nvalue ) )
+                    goto invalid;
                 g_date_set_day ( date, nvalue );
-                j++;
-            }
-            else
-            {
-                g_date_free ( date );
-                g_strfreev ( tab_date );
-                return NULL;
-            }
-            break;
+                break;
+
             case 'y':
             case 'Y':
-            if ( strlen ( tab_date [ j ] ) == 2
-                 ||
-                 strlen (tab_date[j] ) == 1)
-            {
-                if ( nvalue < 60 )
+                if ( strlen ( tab_date[j] ) == 2
+                        || strlen ( tab_date[j] ) == 1 )
                 {
-                nvalue += 2000;
+                    if ( nvalue < 60 )
+                        nvalue += 2000;
+                    else
+                        nvalue += 1900;
                 }
-                else
-                {
-                nvalue += 1900;
-                }
-            }
-            if ( g_date_valid_year ( nvalue ) && num_fields >= 3 )
-            {
+                if ( ! g_date_valid_year ( nvalue ) && num_fields >= 3 )
+                    goto invalid;
                 g_date_set_year ( date, nvalue );
-                j++;
-            }
-            else
-            {
-                g_date_free ( date );
-                g_strfreev ( tab_date );
-                return NULL;
-            }
-            break;
+                break;
+
             default:
                 g_printerr ( ">> Unknown format '%s'\n", date_tokens [ i ] );
-                g_date_free ( date );
-                g_strfreev ( tab_date );
-                return NULL;
-            break;
+                goto invalid;
         }
     }
-    /* comment for random crash. Memory allocation problem in split_unique_datefield () */
-    g_strfreev ( tab_date );
 
     /* need here to check if the date is valid, else an error occurs when
      * write for example only 31, and the current month has only 30 days... */
-    if ( !g_date_valid ( date ) )
-    {
-        g_date_free ( date );
-        return NULL;
-    }
-    else
-        return date;
+    if ( ! g_date_valid ( date ) )
+        goto invalid;
+
+    return date;
+
+invalid:
+    g_date_free ( date );
+    g_strfreev ( tab_date );
+    return NULL;
 }
 
 


hooks/post-receive
-- 
grisbi


More information about the cvs mailing list