📄 gutils.c
字号:
/* GLIB - Library of useful routines for C programming * Copyright (C) 1995-1998 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GLib Team and others 1997-2000. See the AUTHORS * file for a list of people on the GLib Team. See the ChangeLog * files for a list of changes. These files are distributed with * GLib at ftp://ftp.gtk.org/pub/gtk/. *//* * MT safe for the unix part, FIXME: make the win32 part MT safe as well. */#ifdef HAVE_CONFIG_H#include "glibconfig.h"#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <pwd.h>#include <stdarg.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <errno.h>#ifdef HAVE_PWD_H#include <pwd.h>#endif#include <sys/types.h>#ifdef HAVE_SYS_PARAM_H#include <sys/param.h>#endif/* implement gutils's inline functions */#define G_IMPLEMENT_INLINES 1#define __G_UTILS_C__#include "glib.h"#ifdef MAXPATHLEN#define G_PATH_LENGTH MAXPATHLEN#elif defined (PATH_MAX)#define G_PATH_LENGTH PATH_MAX#elif defined (_PC_PATH_MAX)#define G_PATH_LENGTH sysconf(_PC_PATH_MAX)#else #define G_PATH_LENGTH 2048#endif#ifdef G_PLATFORM_WIN32# define STRICT /* Strict typing, please */# include <windows.h># undef STRICT# include <lmcons.h> /* For UNLEN */# include <ctype.h>#endif /* G_PLATFORM_WIN32 */#ifdef G_OS_WIN32# include <direct.h>#endif#ifdef HAVE_CODESET#include <langinfo.h>#endif#ifdef HAVE_BIND_TEXTDOMAIN_CODESET#include <libintl.h>#endifconst guint glib_major_version = GLIB_MAJOR_VERSION;const guint glib_minor_version = GLIB_MINOR_VERSION;const guint glib_micro_version = GLIB_MICRO_VERSION;const guint glib_interface_age = GLIB_INTERFACE_AGE;const guint glib_binary_age = GLIB_BINARY_AGE;#if !defined (HAVE_MEMMOVE) && !defined (HAVE_WORKING_BCOPY)void g_memmove (gpointer dest, gconstpointer src, gulong len){ gchar* destptr = dest; const gchar* srcptr = src; if (src + len < dest || dest + len < src) { bcopy (src, dest, len); return; } else if (dest <= src) { while (len--) *(destptr++) = *(srcptr++); } else { destptr += len; srcptr += len; while (len--) *(--destptr) = *(--srcptr); }}#endif /* !HAVE_MEMMOVE && !HAVE_WORKING_BCOPY */voidg_atexit (GVoidFunc func){ gint result; const gchar *error = NULL; /* keep this in sync with glib.h */#ifdef G_NATIVE_ATEXIT result = ATEXIT (func); if (result) error = g_strerror (errno);#elif defined (HAVE_ATEXIT)# ifdef NeXT /* @#%@! NeXTStep */ result = !atexit ((void (*)(void)) func); if (result) error = g_strerror (errno);# else result = atexit ((void (*)(void)) func); if (result) error = g_strerror (errno);# endif /* NeXT */#elif defined (HAVE_ON_EXIT) result = on_exit ((void (*)(int, void *)) func, NULL); if (result) error = g_strerror (errno);#else result = 0; error = "no implementation";#endif /* G_NATIVE_ATEXIT */ if (error) g_error ("Could not register atexit() function: %s", error);}/* Based on execvp() from GNU Libc. * Some of this code is cut-and-pasted into gspawn.c */static gchar*my_strchrnul (const gchar *str, gchar c){ gchar *p = (gchar*)str; while (*p && (*p != c)) ++p; return p;}#ifdef G_OS_WIN32gchar *inner_find_program_in_path (const gchar *program);gchar*g_find_program_in_path (const gchar *program){ const gchar *last_dot = strrchr (program, '.'); if (last_dot == NULL || strchr (last_dot, '\\') != NULL) { const gint program_length = strlen (program); const gchar *pathext = getenv ("PATHEXT"); const gchar *p; gchar *decorated_program; gchar *retval; if (pathext == NULL) pathext = ".com;.exe;.bat"; p = pathext; do { pathext = p; p = my_strchrnul (pathext, ';'); decorated_program = g_malloc (program_length + (p-pathext) + 1); memcpy (decorated_program, program, program_length); memcpy (decorated_program+program_length, pathext, p-pathext); decorated_program [program_length + (p-pathext)] = '\0'; retval = inner_find_program_in_path (decorated_program); g_free (decorated_program); if (retval != NULL) return retval; } while (*p++ != '\0'); return NULL; } else return inner_find_program_in_path (program);}#define g_find_program_in_path inner_find_program_in_path#endif/** * g_find_program_in_path: * @program: a program name * * Locates the first executable named @program in the user's path, in the * same way that execvp() would locate it. Returns an allocated string * with the absolute path name, or NULL if the program is not found in * the path. If @program is already an absolute path, returns a copy of * @program if @program exists and is executable, and NULL otherwise. * * On Windows, if @program does not have a file type suffix, tries to * append the suffixes in the PATHEXT environment variable (if that * doesn't exists, the suffixes .com, .exe, and .bat) in turn, and * then look for the resulting file name in the same way as * CreateProcess() would. This means first in the directory where the * program was loaded from, then in the current directory, then in the * Windows 32-bit system directory, then in the Windows directory, and * finally in the directories in the PATH environment variable. If * the program is found, the return value contains the full name * including the type suffix. * * Return value: absolute path, or NULL **/gchar*g_find_program_in_path (const gchar *program){ const gchar *path, *p; gchar *name, *freeme;#ifdef G_OS_WIN32 gchar *path_tmp;#endif size_t len; size_t pathlen; g_return_val_if_fail (program != NULL, NULL); /* If it is an absolute path, or a relative path including subdirectories, * don't look in PATH. */ if (g_path_is_absolute (program) || strchr (program, G_DIR_SEPARATOR) != NULL) { if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE)) return g_strdup (program); else return NULL; } path = g_getenv ("PATH");#ifdef G_OS_UNIX if (path == NULL) { /* There is no `PATH' in the environment. The default * search path in GNU libc is the current directory followed by * the path `confstr' returns for `_CS_PATH'. */ /* In GLib we put . last, for security, and don't use the * unportable confstr(); UNIX98 does not actually specify * what to search if PATH is unset. POSIX may, dunno. */ path = "/bin:/usr/bin:."; }#else { gchar *tmp; gchar moddir[MAXPATHLEN], sysdir[MAXPATHLEN], windir[MAXPATHLEN]; GetModuleFileName (NULL, moddir, sizeof (moddir)); tmp = g_path_get_dirname (moddir); GetSystemDirectory (sysdir, sizeof (sysdir)); GetWindowsDirectory (windir, sizeof (windir)); path_tmp = g_strconcat (tmp, ";.;", sysdir, ";", windir, (path != NULL ? ";" : NULL), (path != NULL ? path : NULL), NULL); g_free (tmp); path = path_tmp; }#endif len = strlen (program) + 1; pathlen = strlen (path); freeme = name = g_malloc (pathlen + len + 1); /* Copy the file name at the top, including '\0' */ memcpy (name + pathlen + 1, program, len); name = name + pathlen; /* And add the slash before the filename */ *name = G_DIR_SEPARATOR; p = path; do { char *startp; path = p; p = my_strchrnul (path, G_SEARCHPATH_SEPARATOR); if (p == path) /* Two adjacent colons, or a colon at the beginning or the end * of `PATH' means to search the current directory. */ startp = name + 1; else startp = memcpy (name - (p - path), path, p - path); if (g_file_test (startp, G_FILE_TEST_IS_EXECUTABLE)) { gchar *ret; ret = g_strdup (startp); g_free (freeme);#ifdef G_OS_WIN32 g_free (path_tmp);#endif return ret; } } while (*p++ != '\0'); g_free (freeme);#ifdef G_OS_WIN32 g_free (path_tmp);#endif return NULL;}gintg_snprintf (gchar *str, gulong n, gchar const *fmt, ...){ va_list args; gint retval; va_start (args, fmt); retval = g_vsnprintf (str, n, fmt, args); va_end (args); return retval;}gintg_vsnprintf (gchar *str, gulong n, gchar const *fmt, va_list args){#ifdef HAVE_VSNPRINTF_C99 g_return_val_if_fail (n == 0 || str != NULL, 0); g_return_val_if_fail (fmt != NULL, 0); return vsnprintf (str, n, fmt, args);#else /* !HAVE_VSNPRINTF_C99 */ gchar *printed; gint retval; g_return_val_if_fail (n == 0 || str != NULL, 0); g_return_val_if_fail (fmt != NULL, 0); printed = g_strdup_vprintf (fmt, args); retval = strlen (printed); if (n > 0) { strncpy (str, printed, n - 1); str[n-1] = '\0'; } g_free (printed); return retval;#endif /* !HAVE_VSNPRINTF_C99 */}guint g_parse_debug_string (const gchar *string, const GDebugKey *keys, guint nkeys){ guint i; guint result = 0; g_return_val_if_fail (string != NULL, 0); if (!g_ascii_strcasecmp (string, "all")) { for (i=0; i<nkeys; i++) result |= keys[i].value; } else { const gchar *p = string; const gchar *q; gboolean done = FALSE; while (*p && !done) { q = strchr (p, ':'); if (!q) { q = p + strlen(p); done = TRUE; } for (i=0; i<nkeys; i++) if (g_ascii_strncasecmp(keys[i].key, p, q - p) == 0 && keys[i].key[q - p] == '\0') result |= keys[i].value; p = q + 1; } } return result;}G_CONST_RETURN gchar*g_basename (const gchar *file_name){ register gchar *base; g_return_val_if_fail (file_name != NULL, NULL); base = strrchr (file_name, G_DIR_SEPARATOR); if (base) return base + 1;#ifdef G_OS_WIN32 if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':') return (gchar*) file_name + 2;#endif /* G_OS_WIN32 */ return (gchar*) file_name;}gchar*g_path_get_basename (const gchar *file_name){ register gssize base; register gssize last_nonslash; gsize len; gchar *retval; g_return_val_if_fail (file_name != NULL, NULL); if (file_name[0] == '\0') /* empty string */ return g_strdup ("."); last_nonslash = strlen (file_name) - 1; while (last_nonslash >= 0 && file_name [last_nonslash] == G_DIR_SEPARATOR) last_nonslash--; if (last_nonslash == -1) /* string only containing slashes */ return g_strdup (G_DIR_SEPARATOR_S);#ifdef G_OS_WIN32 if (last_nonslash == 1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':') /* string only containing slashes and a drive */ return g_strdup (G_DIR_SEPARATOR_S);#endif /* G_OS_WIN32 */ base = last_nonslash; while (base >=0 && file_name [base] != G_DIR_SEPARATOR) base--;#ifdef G_OS_WIN32 if (base == -1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':') base = 1;#endif /* G_OS_WIN32 */ len = last_nonslash - base; retval = g_malloc (len + 1); memcpy (retval, file_name + base + 1, len); retval [len] = '\0'; return retval;}gbooleang_path_is_absolute (const gchar *file_name){ g_return_val_if_fail (file_name != NULL, FALSE); if (file_name[0] == G_DIR_SEPARATOR#ifdef G_OS_WIN32 || file_name[0] == '/'#endif ) return TRUE;#ifdef G_OS_WIN32 /* Recognize drive letter on native Windows */ if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && (file_name[2] == G_DIR_SEPARATOR || file_name[2] == '/')) return TRUE;#endif /* G_OS_WIN32 */ return FALSE;}G_CONST_RETURN gchar*g_path_skip_root (const gchar *file_name){ g_return_val_if_fail (file_name != NULL, NULL); #ifdef G_PLATFORM_WIN32 /* Skip \\server\share (Win32) or //server/share (Cygwin) */ if (file_name[0] == G_DIR_SEPARATOR && file_name[1] == G_DIR_SEPARATOR && file_name[2]) { gchar *p; if ((p = strchr (file_name + 2, G_DIR_SEPARATOR)) > file_name + 2 && p[1]) { file_name = p + 1; while (file_name[0] && file_name[0] != G_DIR_SEPARATOR) file_name++; /* Possibly skip a backslash after the share name */ if (file_name[0] == G_DIR_SEPARATOR) file_name++; return (gchar *)file_name; } }#endif /* Skip initial slashes */ if (file_name[0] == G_DIR_SEPARATOR) { while (file_name[0] == G_DIR_SEPARATOR) file_name++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -