GnuCash 2.4.99
gnc-glib-utils.c
00001 /********************************************************************\
00002  * gnc-glib-utils.c -- utility functions based on glib functions    *
00003  * Copyright (C) 2006 David Hampton <hampton@employees.org>         *
00004  *                                                                  *
00005  * This program is free software; you can redistribute it and/or    *
00006  * modify it under the terms of the GNU General Public License as   *
00007  * published by the Free Software Foundation; either version 2 of   *
00008  * the License, or (at your option) any later version.              *
00009  *                                                                  *
00010  * This program is distributed in the hope that it will be useful,  *
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00013  * GNU General Public License for more details.                     *
00014  *                                                                  *
00015  * You should have received a copy of the GNU General Public License*
00016  * along with this program; if not, contact:                        *
00017  *                                                                  *
00018  * Free Software Foundation           Voice:  +1-617-542-5942       *
00019  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00020  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00021  *                                                                  *
00022 \********************************************************************/
00023 
00024 #include "config.h"
00025 #include <errno.h>
00026 #include <stdio.h>
00027 #include <signal.h>
00028 #include <string.h>
00029 
00030 #include "gnc-glib-utils.h"
00031 
00032 #ifdef G_OS_WIN32
00033 #include <windows.h>
00034 #endif
00035 
00036 int
00037 safe_utf8_collate (const char * da, const char * db)
00038 {
00039     if (da && !(*da))
00040         da = NULL;
00041     if (db && !(*db))
00042         db = NULL;
00043 
00044     if (da && db)
00045         return g_utf8_collate(da, db);
00046     if (da)
00047         return 1;
00048     if (db)
00049         return -1;
00050     return 0;
00051 }
00052 
00053 /********************************************************************
00054  * The following definitions are from gutf8.c, for use by
00055  * gnc_utf8_validate().  These are all verbatim copies, except for
00056  * UNICODE_VALID() which has been modified to look for the strict
00057  * subset of UTF-8 that is valid XML text.
00058  */
00059 
00060 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
00061   if (Char < 128)                                                             \
00062     {                                                                         \
00063       Len = 1;                                                                \
00064       Mask = 0x7f;                                                            \
00065     }                                                                         \
00066   else if ((Char & 0xe0) == 0xc0)                                             \
00067     {                                                                         \
00068       Len = 2;                                                                \
00069       Mask = 0x1f;                                                            \
00070     }                                                                         \
00071   else if ((Char & 0xf0) == 0xe0)                                             \
00072     {                                                                         \
00073       Len = 3;                                                                \
00074       Mask = 0x0f;                                                            \
00075     }                                                                         \
00076   else if ((Char & 0xf8) == 0xf0)                                             \
00077     {                                                                         \
00078       Len = 4;                                                                \
00079       Mask = 0x07;                                                            \
00080     }                                                                         \
00081   else if ((Char & 0xfc) == 0xf8)                                             \
00082     {                                                                         \
00083       Len = 5;                                                                \
00084       Mask = 0x03;                                                            \
00085     }                                                                         \
00086   else if ((Char & 0xfe) == 0xfc)                                             \
00087     {                                                                         \
00088       Len = 6;                                                                \
00089       Mask = 0x01;                                                            \
00090     }                                                                         \
00091   else                                                                        \
00092     Len = -1;
00093 
00094 #define UTF8_LENGTH(Char)              \
00095   ((Char) < 0x80 ? 1 :                 \
00096    ((Char) < 0x800 ? 2 :               \
00097     ((Char) < 0x10000 ? 3 :            \
00098      ((Char) < 0x200000 ? 4 :          \
00099       ((Char) < 0x4000000 ? 5 : 6)))))
00100 
00101 
00102 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
00103   (Result) = (Chars)[0] & (Mask);                                             \
00104   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
00105     {                                                                         \
00106       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
00107         {                                                                     \
00108           (Result) = -1;                                                      \
00109           break;                                                              \
00110         }                                                                     \
00111       (Result) <<= 6;                                                         \
00112       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
00113     }
00114 
00115 #define UNICODE_VALID(Char)                   \
00116     ((Char) < 0x110000 &&                             \
00117      (((Char) & 0xFFFFF800) != 0xD800) &&             \
00118      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&          \
00119      ((Char) >= 0x20 || (Char) == 0x09 || (Char) == 0x0A || (Char) == 0x0D) && \
00120      ((Char) & 0xFFFE) != 0xFFFE)
00121 
00122 gboolean
00123 gnc_utf8_validate(const gchar  *str,
00124                   gssize        max_len,
00125                   const gchar **end)
00126 {
00127 
00128     const gchar *p;
00129 
00130     g_return_val_if_fail (str != NULL, FALSE);
00131 
00132     if (end)
00133         *end = str;
00134 
00135     p = str;
00136 
00137     while ((max_len < 0 || (p - str) < max_len) && *p)
00138     {
00139         int i, mask = 0, len;
00140         gunichar result;
00141         unsigned char c = (unsigned char) * p;
00142 
00143         UTF8_COMPUTE (c, mask, len);
00144 
00145         if (len == -1)
00146             break;
00147 
00148         /* check that the expected number of bytes exists in str */
00149         if (max_len >= 0 &&
00150                 ((max_len - (p - str)) < len))
00151             break;
00152 
00153         UTF8_GET (result, p, i, mask, len);
00154 
00155         if (UTF8_LENGTH (result) != len) /* Check for overlong UTF-8 */
00156             break;
00157 
00158         if (result == (gunichar) - 1)
00159             break;
00160 
00161         if (!UNICODE_VALID (result))
00162             break;
00163 
00164         p += len;
00165     }
00166 
00167     if (end)
00168         *end = p;
00169 
00170     /* See that we covered the entire length if a length was
00171      * passed in, or that we ended on a nul if not
00172      */
00173     if (max_len >= 0 &&
00174             p != (str + max_len))
00175         return FALSE;
00176     else if (max_len < 0 &&
00177              *p != '\0')
00178         return FALSE;
00179     else
00180         return TRUE;
00181 }
00182 
00183 void
00184 gnc_utf8_strip_invalid (gchar *str)
00185 {
00186     gchar *end;
00187     gint len;
00188 
00189     g_return_if_fail(str);
00190 
00191     if (gnc_utf8_validate(str, -1, (const gchar **)&end))
00192         return;
00193 
00194     g_warning("Invalid utf8 string: %s", str);
00195     do
00196     {
00197         len = strlen(end);
00198         memmove(end, end + 1, len);     /* shuffle the remainder one byte */
00199     }
00200     while (!gnc_utf8_validate(str, -1, (const gchar **)&end));
00201 }
00202 
00203 gchar *
00204 gnc_utf8_strip_invalid_strdup(const gchar* str)
00205 {
00206     gchar *result = g_strdup (str);
00207     gnc_utf8_strip_invalid (result);
00208     return result;
00209 }
00210 
00211 gchar *
00212 gnc_locale_from_utf8(const gchar* str)
00213 {
00214     gchar *   locale_str;
00215     gsize     bytes_written = 0;
00216     GError *  err = NULL;
00217 
00218     /* Convert from UTF-8 to the encoding used in the current locale. */
00219     locale_str = g_locale_from_utf8(str, -1, NULL, &bytes_written, &err);
00220     if (err)
00221     {
00222         g_warning("g_locale_from_utf8 failed: %s", err->message);
00223         g_error_free(err);
00224     }
00225 
00226     return locale_str;
00227 }
00228 
00229 gchar *
00230 gnc_locale_to_utf8(const gchar* str)
00231 {
00232     gchar *   utf8_str;
00233     gsize     bytes_written = 0;
00234     GError *  err = NULL;
00235 
00236     /* Convert to UTF-8 from the encoding used in the current locale. */
00237     utf8_str = g_locale_to_utf8(str, -1, NULL, &bytes_written, &err);
00238     if (err)
00239     {
00240         g_warning("g_locale_to_utf8 failed: %s", err->message);
00241         g_error_free(err);
00242     }
00243 
00244     return utf8_str;
00245 }
00246 
00247 GList*
00248 gnc_g_list_map(GList* list, GncGMapFunc fn, gpointer user_data)
00249 {
00250     GList *rtn = NULL;
00251     for (; list != NULL; list = list->next)
00252     {
00253         rtn = g_list_append(rtn, (*fn)(list->data, user_data));
00254     }
00255     return rtn;
00256 }
00257 
00258 void
00259 gnc_g_list_cut(GList **list, GList *cut_point)
00260 {
00261     if (list == NULL || *list == NULL)
00262         return;
00263 
00264     // if it's the first element.
00265     if (cut_point->prev == NULL)
00266     {
00267         *list = NULL;
00268         return;
00269     }
00270 
00271     cut_point->prev->next = NULL;
00272     cut_point->prev = NULL;
00273 }
00274 
00275 void
00276 gnc_scm_log_warn(const gchar *msg)
00277 {
00278     g_log("gnc.scm", G_LOG_LEVEL_WARNING, "%s", msg);
00279 }
00280 
00281 void
00282 gnc_scm_log_error(const gchar *msg)
00283 {
00284     g_log("gnc.scm", G_LOG_LEVEL_CRITICAL, "%s", msg);
00285 }
00286 
00287 void
00288 gnc_scm_log_msg(const gchar *msg)
00289 {
00290     g_log("gnc.scm", G_LOG_LEVEL_MESSAGE, "%s", msg);
00291 }
00292 
00293 void
00294 gnc_scm_log_debug(const gchar *msg)
00295 {
00296     g_log("gnc.scm", G_LOG_LEVEL_DEBUG, "%s", msg);
00297 }
00298 
00299 void gnc_gpid_kill(GPid pid)
00300 {
00301 #ifdef G_OS_WIN32
00302     if (!TerminateProcess((HANDLE) pid, 0))
00303     {
00304         gchar *msg = g_win32_error_message(GetLastError());
00305         g_warning("Could not kill child process: %s", msg ? msg : "(null)");
00306         g_free(msg);
00307     }
00308 #else /* !G_OS_WIN32 */
00309     if (kill(pid, SIGKILL))
00310     {
00311         g_warning("Could not kill child process: %s", g_strerror(errno));
00312     }
00313 #endif /* G_OS_WIN32 */
00314 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines