|
GnuCash 2.4.99
|
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 }
1.7.4