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     len = strlen(end);
00197     memmove(end, end+1, len);   /* shuffle the remainder one byte */
00198   } while (!gnc_utf8_validate(str, -1, (const gchar **)&end));
00199 }
00200 
00201 gchar *
00202 gnc_utf8_strip_invalid_strdup(const gchar* str)
00203 {
00204   gchar *result = g_strdup (str);
00205   gnc_utf8_strip_invalid (result);
00206   return result;
00207 }
00208 
00209 gchar *
00210 gnc_locale_from_utf8(const gchar* str)
00211 {
00212   gchar *   locale_str;
00213   gsize     bytes_written = 0;
00214   GError *  err = NULL;
00215 
00216   /* Convert from UTF-8 to the encoding used in the current locale. */
00217   locale_str = g_locale_from_utf8(str, -1, NULL, &bytes_written, &err);
00218   if (err) {
00219     g_warning("g_locale_from_utf8 failed: %s", err->message);
00220     g_error_free(err);
00221   }
00222 
00223   return locale_str;
00224 }
00225 
00226 gchar *
00227 gnc_locale_to_utf8(const gchar* str)
00228 {
00229   gchar *   utf8_str;
00230   gsize     bytes_written = 0;
00231   GError *  err = NULL;
00232 
00233   /* Convert to UTF-8 from the encoding used in the current locale. */
00234   utf8_str = g_locale_to_utf8(str, -1, NULL, &bytes_written, &err);
00235   if (err) {
00236     g_warning("g_locale_to_utf8 failed: %s", err->message);
00237     g_error_free(err);
00238   }
00239 
00240   return utf8_str;
00241 }
00242 
00243 GList*
00244 gnc_g_list_map(GList* list, GncGMapFunc fn, gpointer user_data)
00245 {
00246   GList *rtn = NULL;
00247   for (; list != NULL; list = list->next)
00248   {
00249     rtn = g_list_append(rtn, (*fn)(list->data, user_data));
00250   }
00251   return rtn;
00252 }
00253 
00254 void
00255 gnc_g_list_cut(GList **list, GList *cut_point)
00256 {
00257   if (list == NULL || *list == NULL)
00258     return;
00259 
00260   // if it's the first element.
00261   if (cut_point->prev == NULL)
00262   {
00263     *list = NULL;
00264     return;
00265   }
00266 
00267   cut_point->prev->next = NULL;
00268   cut_point->prev = NULL;
00269 }
00270 
00271 void
00272 gnc_scm_log_warn(const gchar *msg)
00273 {
00274     g_log("gnc.scm", G_LOG_LEVEL_WARNING, "%s", msg);
00275 }
00276 
00277 void
00278 gnc_scm_log_error(const gchar *msg)
00279 {
00280     g_log("gnc.scm", G_LOG_LEVEL_CRITICAL, "%s", msg);
00281 }
00282 
00283 void
00284 gnc_scm_log_msg(const gchar *msg)
00285 {
00286     g_log("gnc.scm", G_LOG_LEVEL_MESSAGE, "%s", msg);
00287 }
00288 
00289 void
00290 gnc_scm_log_debug(const gchar *msg)
00291 {
00292     g_log("gnc.scm", G_LOG_LEVEL_DEBUG, "%s", msg);
00293 }
00294 
00295 void gnc_gpid_kill(GPid pid)
00296 {
00297 #ifdef G_OS_WIN32
00298     if (!TerminateProcess((HANDLE) pid, 0)) {
00299         gchar *msg = g_win32_error_message(GetLastError());
00300         g_warning("Could not kill child process: %s", msg ? msg : "(null)");
00301         g_free(msg);
00302     }
00303 #else /* !G_OS_WIN32 */
00304     if (kill(pid, SIGKILL)) {
00305         g_warning("Could not kill child process: %s", g_strerror(errno));
00306     }
00307 #endif /* G_OS_WIN32 */
00308 }

Generated on Sun Sep 7 05:07:15 2008 for GnuCash by  doxygen 1.5.2