gnc-gkeyfile-utils.c

Go to the documentation of this file.
00001 /*
00002  * gnc-gkeyfile-utils.c -- utility functions for working
00003  *              with GKeyFile data structures from GLib
00004  * Copyright (C) 2005 David Hampton <hampton@employees.org>
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License as
00008  * published by the Free Software Foundation; either version 2 of
00009  * the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, contact:
00018  *
00019  * Free Software Foundation           Voice:  +1-617-542-5942
00020  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
00021  * Boston, MA  02110-1301,  USA       gnu@gnu.org
00022  */
00023 
00037 #include "config.h"
00038 
00039 #include <glib.h>
00040 #include <glib/gi18n.h>
00041 #include <glib/gstdio.h>
00042 #include <string.h>
00043 #include <errno.h>
00044 #include <fcntl.h>
00045 #include <unistd.h>
00046 
00047 #include "gnc-gkeyfile-utils.h"
00048 
00049 #ifndef HAVE_GLIB_2_12
00050 /**********************************************************************
00051  *
00052  * The following functions are copied verbatim from the GLIB 2.12
00053  * source code.  If more glib 2.12 functions are included into
00054  * gnucash,then they should all be consolidated in a lib/glib212
00055  * directory.
00056  *
00057  **********************************************************************/
00058 static gchar *
00059 _g_utf8_make_valid (const gchar *name)
00060 {
00061   GString *string;
00062   const gchar *remainder, *invalid;
00063   gint remaining_bytes, valid_bytes;
00064   
00065   string = NULL;
00066   remainder = name;
00067   remaining_bytes = strlen (name);
00068   
00069   while (remaining_bytes != 0) 
00070     {
00071       if (g_utf8_validate (remainder, remaining_bytes, &invalid)) 
00072         break;
00073       valid_bytes = invalid - remainder;
00074     
00075       if (string == NULL) 
00076         string = g_string_sized_new (remaining_bytes);
00077 
00078       g_string_append_len (string, remainder, valid_bytes);
00079       /* append U+FFFD REPLACEMENT CHARACTER */
00080       g_string_append (string, "\357\277\275");
00081       
00082       remaining_bytes -= valid_bytes + 1;
00083       remainder = invalid + 1;
00084     }
00085   
00086   if (string == NULL)
00087     return g_strdup (name);
00088   
00089   g_string_append (string, remainder);
00090 
00091   g_assert (g_utf8_validate (string->str, -1, NULL));
00092   
00093   return g_string_free (string, FALSE);
00094 }
00095 
00096 static gdouble
00097 g_key_file_parse_value_as_double  (GKeyFile     *key_file,
00098                                    const gchar  *value,
00099                                    GError      **error)
00100 {
00101   gchar *end_of_valid_d;
00102   gdouble double_value = 0;
00103 
00104   double_value = g_ascii_strtod (value, &end_of_valid_d);
00105 
00106   if (*end_of_valid_d != '\0' || end_of_valid_d == value)
00107     {
00108       gchar *value_utf8 = _g_utf8_make_valid (value);
00109       g_set_error (error, G_KEY_FILE_ERROR,
00110                    G_KEY_FILE_ERROR_INVALID_VALUE,
00111                    _("Value '%s' cannot be interpreted "
00112                      "as a float number."), 
00113                    value_utf8);
00114       g_free (value_utf8);
00115     }
00116 
00117   return double_value;
00118 }
00119 
00120 gdouble
00121 g_key_file_get_double (GKeyFile *key_file, const gchar *group_name,
00122                        const gchar *key, GError **error)
00123 {
00124   GError *key_file_error;
00125   gchar *value;
00126   gdouble double_value;
00127 
00128   g_return_val_if_fail (key_file != NULL, -1);
00129   g_return_val_if_fail (group_name != NULL, -1);
00130   g_return_val_if_fail (key != NULL, -1);
00131 
00132   key_file_error = NULL;
00133 
00134   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
00135 
00136   if (key_file_error)
00137     {
00138       g_propagate_error (error, key_file_error);
00139       return 0;
00140     }
00141 
00142   double_value = g_key_file_parse_value_as_double (key_file, value,
00143                                                   &key_file_error);
00144   g_free (value);
00145 
00146   if (key_file_error)
00147     {
00148       if (g_error_matches (key_file_error,
00149                            G_KEY_FILE_ERROR,
00150                            G_KEY_FILE_ERROR_INVALID_VALUE))
00151         {
00152           g_set_error (error, G_KEY_FILE_ERROR,
00153                        G_KEY_FILE_ERROR_INVALID_VALUE,
00154                        _("Key file contains key '%s' in group '%s' "
00155                          "which has a value that cannot be interpreted."), key,
00156                        group_name);
00157           g_error_free (key_file_error);
00158         }
00159       else
00160         g_propagate_error (error, key_file_error);
00161     }
00162 
00163   return double_value;
00164 }
00165 
00166 void
00167 g_key_file_set_double  (GKeyFile    *key_file,
00168                         const gchar *group_name,
00169                         const gchar *key,
00170                         gdouble      value)
00171 {
00172   gchar result[G_ASCII_DTOSTR_BUF_SIZE];
00173 
00174   g_return_if_fail (key_file != NULL);
00175 
00176   g_ascii_dtostr (result, sizeof (result), value);
00177   g_key_file_set_value (key_file, group_name, key, result);
00178 }
00179 
00180 gdouble*
00181 g_key_file_get_double_list (GKeyFile *key_file,
00182                             const gchar *group_name,
00183                             const gchar *key,
00184                             gsize *length,
00185                             GError **error)
00186 {
00187   GError *key_file_error = NULL;
00188   gchar **values;
00189   gdouble *double_values;
00190   gsize i, num_doubles;
00191 
00192   g_return_val_if_fail (key_file != NULL, NULL);
00193   g_return_val_if_fail (group_name != NULL, NULL);
00194   g_return_val_if_fail (key != NULL, NULL);
00195 
00196   values = g_key_file_get_string_list (key_file, group_name, key,
00197                                        &num_doubles, &key_file_error);
00198 
00199   if (key_file_error)
00200     g_propagate_error (error, key_file_error);
00201 
00202   if (!values)
00203     return NULL;
00204 
00205   double_values = g_new0 (gdouble, num_doubles);
00206 
00207   for (i = 0; i < num_doubles; i++)
00208     {
00209       double_values[i] = g_key_file_parse_value_as_double (key_file,
00210                                                            values[i],
00211                                                            &key_file_error);
00212 
00213       if (key_file_error)
00214         {
00215           g_propagate_error (error, key_file_error);
00216           g_strfreev (values);
00217           g_free (double_values);
00218 
00219           return NULL;
00220         }
00221     }
00222   g_strfreev (values);
00223 
00224   if (length)
00225     *length = num_doubles;
00226 
00227   return double_values;
00228 }
00229 
00230 void
00231 g_key_file_set_double_list (GKeyFile     *key_file,
00232                             const gchar  *group_name,
00233                             const gchar  *key,
00234                             gdouble       list[],
00235                             gsize         length)
00236 {
00237   GString *values;
00238   gsize i;
00239 
00240   g_return_if_fail (key_file != NULL);
00241   g_return_if_fail (list != NULL);
00242 
00243   values = g_string_sized_new (length * 16);
00244   for (i = 0; i < length; i++)
00245     {
00246       gchar result[G_ASCII_DTOSTR_BUF_SIZE];
00247 
00248       g_ascii_dtostr( result, sizeof (result), list[i] );
00249 
00250       g_string_append (values, result);
00251       g_string_append_c (values, ';');
00252     }
00253 
00254   g_key_file_set_value (key_file, group_name, key, values->str);
00255   g_string_free (values, TRUE);
00256 }
00257 /**********************************************************************
00258  *
00259  *                     End of copied functions.
00260  *
00261  **********************************************************************/
00262 #endif
00263 
00264 
00265 GKeyFile *
00266 gnc_key_file_load_from_file (const gchar *filename,
00267                              gboolean ignore_error,
00268                              gboolean return_empty_struct,
00269                              GError **caller_error)
00270 {
00271   GKeyFile *key_file;
00272   GError *error = NULL;
00273 
00274   g_return_val_if_fail(filename != NULL, NULL);
00275 
00276   if (!g_file_test(filename, G_FILE_TEST_EXISTS))
00277     return NULL;
00278 
00279   key_file = g_key_file_new();
00280   if (!key_file)
00281     return NULL;
00282 
00283   if (g_key_file_load_from_file(key_file, filename, G_KEY_FILE_NONE, &error))
00284     return key_file;
00285 
00286   /* An error occurred */
00287   if (!return_empty_struct) {
00288     g_key_file_free(key_file);
00289     key_file = NULL;
00290   }
00291 
00292   if (!ignore_error)
00293     g_warning("Unable to read file %s: %s\n", filename, error->message);
00294   g_propagate_error(caller_error, error);
00295   return key_file;
00296 }
00297 
00298 
00299 gboolean
00300 gnc_key_file_save_to_file (const gchar *filename,
00301                            GKeyFile *key_file,
00302                            GError **error)
00303 {
00304   gchar *contents;
00305   gint fd;
00306   extern int errno;
00307   gint length;
00308   ssize_t written;
00309   gboolean success = TRUE;
00310 
00311   g_return_val_if_fail(filename != NULL, FALSE);
00312   g_return_val_if_fail(key_file != NULL, FALSE);
00313   if (error)
00314     g_return_val_if_fail(*error == NULL, FALSE);
00315 
00316   contents = g_key_file_to_data(key_file, NULL, NULL);
00317   length = strlen(contents);
00318   fd = g_open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
00319   if (fd == -1) {
00320     if (error) {
00321       *error = g_error_new(G_FILE_ERROR, g_file_error_from_errno(errno), 
00322                            "Cannot open file %s: %s", filename,
00323                            strerror(errno));
00324     } else {
00325       g_critical("Cannot open file %s: %s\n", filename, strerror(errno));
00326     }
00327     g_free(contents);
00328     return FALSE;
00329   }
00330 
00331   written = write(fd, contents, length);
00332   if (written == -1 ) {
00333     success = FALSE;
00334     if (error) {
00335       *error = g_error_new(G_FILE_ERROR, g_file_error_from_errno(errno), 
00336                            "Cannot write to file %s: %s", filename,
00337                            strerror(errno));
00338     } else {
00339       g_critical("Cannot write to file %s: %s\n", filename, strerror(errno));
00340     }
00341     close(fd);
00342   } else if (written != length) {
00343     success = FALSE;
00344     if (error) {
00345       *error = g_error_new(G_FILE_ERROR, g_file_error_from_errno(errno), 
00346                            "File %s truncated (provided %d, written %d)",
00347                            filename, length, (int)written);
00348     } else {
00349       g_critical("File %s truncated (provided %d, written %d)",
00350               filename, length, (int)written);
00351     }
00352     /* Ignore any error */
00353     close(fd);
00354   } else if (close(fd) == -1) {
00355     if (error) {
00356       *error = g_error_new(G_FILE_ERROR, g_file_error_from_errno(errno), 
00357                            "Close failed for file %s: %s", filename,
00358                            strerror(errno));
00359     } else {
00360       g_warning("Close failed for file %s: %s", filename, strerror(errno));
00361     }
00362   }
00363   g_free(contents);
00364   return success;
00365 }
00366 

Generated on Mon Sep 8 05:04:00 2008 for GnuCash by  doxygen 1.5.2