00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00053
00054
00055
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
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
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
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
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