*/
#define G_IMPLEMENT_INLINES 1
#define __G_UTILS_C__
-#include "glib.h"
+#include "gutils.h"
+
+#include "gfileutils.h"
+#include "ghash.h"
+#include "gslist.h"
#include "gprintfint.h"
+#include "gthread.h"
#include "gthreadprivate.h"
+#include "gtestutils.h"
+#include "gunicode.h"
+#include "gstrfuncs.h"
+#include "garray.h"
#include "glibintl.h"
-#include "galias.h"
+
+#ifdef G_PLATFORM_WIN32
+#include "garray.h"
+#include "gconvert.h"
+#include "gwin32.h"
+#endif
#ifdef MAXPATHLEN
#define G_PATH_LENGTH MAXPATHLEN
* g_path_get_basename() allocates new memory for the returned string, unlike
* this function which returns a pointer into the argument.
**/
-G_CONST_RETURN gchar*
+const gchar *
g_basename (const gchar *file_name)
{
register gchar *base;
* g_path_is_absolute:
* @file_name: a file name.
*
- * Returns %TRUE if the given @file_name is an absolute file name,
- * i.e. it contains a full path from the root directory such as "/usr/local"
- * on UNIX or "C:\windows" on Windows systems.
+ * Returns %TRUE if the given @file_name is an absolute file name.
+ * Note that this is a somewhat vague concept on Windows.
*
- * Returns: %TRUE if @file_name is an absolute path.
+ * On POSIX systems, an absolute file name is well-defined. It always
+ * starts from the single root directory. For example "/usr/local".
+ *
+ * On Windows, the concepts of current drive and drive-specific
+ * current directory introduce vagueness. This function interprets as
+ * an absolute file name one that either begins with a directory
+ * separator such as "\Users\tml" or begins with the root on a drive,
+ * for example "C:\Windows". The first case also includes UNC paths
+ * such as "\\myserver\docs\foo". In all cases, either slashes or
+ * backslashes are accepted.
+ *
+ * Note that a file name relative to the current drive root does not
+ * truly specify a file uniquely over time and across processes, as
+ * the current drive is a per-process value and can be changed.
+ *
+ * File names relative the current directory on some specific drive,
+ * such as "D:foo/bar", are not interpreted as absolute by this
+ * function, but they obviously are not relative to the normal current
+ * directory as returned by getcwd() or g_get_current_dir()
+ * either. Such paths should be avoided, or need to be handled using
+ * Windows-specific code.
+ *
+ * Returns: %TRUE if @file_name is absolute.
*/
gboolean
g_path_is_absolute (const gchar *file_name)
*
* Returns: a pointer into @file_name after the root component.
*/
-G_CONST_RETURN gchar*
+const gchar *
g_path_skip_root (const gchar *file_name)
{
g_return_val_if_fail (file_name != NULL, NULL);
* overwritten by the next call to g_getenv(), g_setenv() or
* g_unsetenv().
**/
-G_CONST_RETURN gchar*
+const gchar *
g_getenv (const gchar *variable)
{
#ifndef G_OS_WIN32
#endif
}
+/**
+ * g_get_environ:
+ *
+ * Gets the list of environment variables for the current process. The
+ * list is %NULL terminated and each item in the list is of the form
+ * 'NAME=VALUE'.
+ *
+ * This is equivalent to direct access to the 'environ' global variable,
+ * except portable.
+ *
+ * The return value is freshly allocated and it should be freed with
+ * g_strfreev() when it is no longer needed.
+ *
+ * Returns: the list of environment variables
+ *
+ * Since: 2.28
+ */
+gchar **
+g_get_environ (void)
+{
+#ifndef G_OS_WIN32
+ return g_strdupv (environ);
+#else
+ gunichar2 *strings;
+ gchar **result;
+ gint i, n;
+
+ strings = GetEnvironmentStringsW ();
+ for (n = 0; strings[n]; n += wcslen (strings + n) + 1);
+ result = g_new (char *, n + 1);
+ for (i = 0; strings[i]; i += wcslen (strings + i) + 1)
+ result[i] = g_utf16_to_utf8 (strings + i, -1, NULL, NULL, NULL);
+ FreeEnvironmentStringsW (strings);
+ result[i] = NULL;
+
+ return result;
+#endif
+}
+
G_LOCK_DEFINE_STATIC (g_utils_global);
static gchar *g_tmp_dir = NULL;
gchar hostname[100];
g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
- if (!g_tmp_dir)
+ if (g_tmp_dir == NULL || *g_tmp_dir == '\0')
g_tmp_dir = g_strdup (g_getenv ("TMP"));
- if (!g_tmp_dir)
+ if (g_tmp_dir == NULL || *g_tmp_dir == '\0')
g_tmp_dir = g_strdup (g_getenv ("TEMP"));
#ifdef G_OS_WIN32
- if (!g_tmp_dir)
+ if (g_tmp_dir == NULL || *g_tmp_dir == '\0')
g_tmp_dir = get_windows_directory_root ();
#else
#ifdef P_tmpdir
- if (!g_tmp_dir)
+ if (g_tmp_dir == NULL || *g_tmp_dir == '\0')
{
gsize k;
g_tmp_dir = g_strdup (P_tmpdir);
}
#endif
- if (!g_tmp_dir)
+ if (g_tmp_dir == NULL || *g_tmp_dir == '\0')
{
g_tmp_dir = g_strdup ("/tmp");
}
*
* Returns: the user name of the current user.
*/
-G_CONST_RETURN gchar*
+const gchar *
g_get_user_name (void)
{
g_get_any_init_locked ();
*
* Returns: the user's real name.
*/
-G_CONST_RETURN gchar*
+const gchar *
g_get_real_name (void)
{
g_get_any_init_locked ();
*
* Returns: the current user's home directory
*/
-G_CONST_RETURN gchar*
+const gchar *
g_get_home_dir (void)
{
g_get_any_init_locked ();
* <envar>TMP</envar>, and <envar>TEMP</envar> in that order. If none
* of those are defined "/tmp" is returned on UNIX and "C:\" on Windows.
* The encoding of the returned string is system-defined. On Windows,
- * it is always UTF-8. The return value is never %NULL.
+ * it is always UTF-8. The return value is never %NULL or the empty string.
*
* Returns: the directory to use for temporary files.
*/
-G_CONST_RETURN gchar*
+const gchar *
g_get_tmp_dir (void)
{
g_get_any_init_locked ();
*
* Since: 2.2
**/
-G_CONST_RETURN gchar*
+const gchar *
g_get_application_name (void)
{
gchar* retval;
* XDG Base Directory Specification</ulink>.
* In this case the directory retrieved will be XDG_DATA_HOME.
*
- * On Windows is the virtual folder that represents the My Documents
- * desktop item. See documentation for CSIDL_PERSONAL.
+ * On Windows this is the folder to use for local (as opposed to
+ * roaming) application data. See documentation for
+ * CSIDL_LOCAL_APPDATA. Note that on Windows it thus is the same as
+ * what g_get_user_config_dir() returns.
*
* Return value: a string owned by GLib that must not be modified
* or freed.
* Since: 2.6
**/
-G_CONST_RETURN gchar*
+const gchar *
g_get_user_data_dir (void)
{
gchar *data_dir;
if (!g_user_data_dir)
{
#ifdef G_OS_WIN32
- data_dir = get_special_folder (CSIDL_PERSONAL);
+ data_dir = get_special_folder (CSIDL_LOCAL_APPDATA);
#else
data_dir = (gchar *) g_getenv ("XDG_DATA_HOME");
if (!g_user_config_dir)
{
#ifdef G_OS_WIN32
- config_dir = get_special_folder (CSIDL_APPDATA);
+ config_dir = get_special_folder (CSIDL_LOCAL_APPDATA);
#else
config_dir = (gchar *) g_getenv ("XDG_CONFIG_HOME");
* XDG Base Directory Specification</ulink>.
* In this case the directory retrieved will be XDG_CONFIG_HOME.
*
- * On Windows is the directory that serves as a common repository for
- * application-specific data. A typical path is
- * C:\Documents and Settings\username\Application. See documentation for
- * CSIDL_APPDATA.
+ * On Windows this is the folder to use for local (as opposed to
+ * roaming) application data. See documentation for
+ * CSIDL_LOCAL_APPDATA. Note that on Windows it thus is the same as
+ * what g_get_user_data_dir() returns.
*
* Return value: a string owned by GLib that must not be modified
* or freed.
* Since: 2.6
**/
-G_CONST_RETURN gchar*
+const gchar *
g_get_user_config_dir (void)
{
G_LOCK (g_utils_global);
* or freed.
* Since: 2.6
**/
-G_CONST_RETURN gchar*
+const gchar *
g_get_user_cache_dir (void)
{
gchar *cache_dir;
return cache_dir;
}
+/**
+ * g_get_user_runtime_dir:
+ *
+ * Returns a directory that is unique to the current user on the local
+ * system.
+ *
+ * On UNIX platforms this is determined using the mechanisms described in
+ * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
+ * XDG Base Directory Specification</ulink>. This is the directory
+ * specified in the <envar>XDG_RUNTIME_DIR</envar> environment variable.
+ * In the case that this variable is not set, GLib will issue a warning
+ * message to stderr and return the value of g_get_user_cache_dir().
+ *
+ * On Windows this is the folder to use for local (as opposed to
+ * roaming) application data. See documentation for
+ * CSIDL_LOCAL_APPDATA. Note that on Windows it thus is the same as
+ * what g_get_user_config_dir() returns.
+ *
+ * Returns: a string owned by GLib that must not be modified or freed.
+ *
+ * Since: 2.28
+ **/
+const gchar *
+g_get_user_runtime_dir (void)
+{
+#ifndef G_OS_WIN32
+ static const gchar *runtime_dir;
+ static gsize initialised;
+
+ if (g_once_init_enter (&initialised))
+ {
+ runtime_dir = g_strdup (getenv ("XDG_RUNTIME_DIR"));
+
+ if (runtime_dir == NULL)
+ g_warning ("XDG_RUNTIME_DIR variable not set. "
+ "Falling back to XDG cache dir.");
+
+ g_once_init_leave (&initialised, 1);
+ }
+
+ if (runtime_dir)
+ return runtime_dir;
+
+ /* Both fallback for UNIX and the default
+ * in Windows: use the user cache directory.
+ */
+#endif
+
+ return g_get_user_cache_dir ();
+}
+
#ifdef HAVE_CARBON
static gchar *
HANDLE hToken,
PWSTR *ppszPath);
t_SHGetKnownFolderPath p_SHGetKnownFolderPath;
+
static const GUID FOLDERID_Downloads =
{ 0x374de290, 0x123f, 0x4565, { 0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b } };
static const GUID FOLDERID_Public =
{ 0xDFDF76A2, 0xC82A, 0x4D63, { 0x90, 0x6A, 0x56, 0x44, 0xAC, 0x45, 0x73, 0x85 } };
+
wchar_t *wcp;
- p_SHGetKnownFolderPath = (t_SHGetKnownFolderPath) GetProcAddress (LoadLibrary ("shell32.dll"),
+ p_SHGetKnownFolderPath = (t_SHGetKnownFolderPath) GetProcAddress (GetModuleHandle ("shell32.dll"),
"SHGetKnownFolderPath");
g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] = get_special_folder (CSIDL_DESKTOPDIRECTORY);
{
wcp = NULL;
(*p_SHGetKnownFolderPath) (&FOLDERID_Downloads, 0, NULL, &wcp);
- g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL);
- if (g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] == NULL)
- g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (CSIDL_DESKTOPDIRECTORY);
- CoTaskMemFree (wcp);
+ if (wcp)
+ {
+ g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL);
+ if (g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] == NULL)
+ g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (CSIDL_DESKTOPDIRECTORY);
+ CoTaskMemFree (wcp);
+ }
+ else
+ g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (CSIDL_DESKTOPDIRECTORY);
}
g_user_special_dirs[G_USER_DIRECTORY_MUSIC] = get_special_folder (CSIDL_MYMUSIC);
{
wcp = NULL;
(*p_SHGetKnownFolderPath) (&FOLDERID_Public, 0, NULL, &wcp);
- g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL);
- if (g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] == NULL)
- g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (CSIDL_COMMON_DOCUMENTS);
- CoTaskMemFree (wcp);
+ if (wcp)
+ {
+ g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL);
+ if (g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] == NULL)
+ g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (CSIDL_COMMON_DOCUMENTS);
+ CoTaskMemFree (wcp);
+ }
+ else
+ g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (CSIDL_COMMON_DOCUMENTS);
}
g_user_special_dirs[G_USER_DIRECTORY_TEMPLATES] = get_special_folder (CSIDL_TEMPLATES);
*
* Since: 2.14
*/
-G_CONST_RETURN gchar *
+const gchar *
g_get_user_special_dir (GUserDirectory directory)
{
g_return_val_if_fail (directory >= G_USER_DIRECTORY_DESKTOP &&
if (!beenhere)
{
p_GetModuleHandleExA =
- (t_GetModuleHandleExA) GetProcAddress (LoadLibrary ("kernel32.dll"),
+ (t_GetModuleHandleExA) GetProcAddress (GetModuleHandle ("kernel32.dll"),
"GetModuleHandleExA");
beenhere = TRUE;
}
return retval;
}
-G_CONST_RETURN gchar * G_CONST_RETURN *
+const gchar * const *
g_win32_get_system_data_dirs_for_module (void (*address_of_function)())
{
GArray *data_dirs;
if (retval != NULL)
{
G_UNLOCK (g_utils_global);
- return (G_CONST_RETURN gchar * G_CONST_RETURN *) retval;
+ return (const gchar * const *) retval;
}
}
}
G_UNLOCK (g_utils_global);
}
- return (G_CONST_RETURN gchar * G_CONST_RETURN *) retval;
+ return (const gchar * const *) retval;
}
#endif
* not be modified or freed.
* Since: 2.6
**/
-G_CONST_RETURN gchar * G_CONST_RETURN *
+const gchar * const *
g_get_system_data_dirs (void)
{
gchar **data_dir_vector;
G_UNLOCK (g_utils_global);
- return (G_CONST_RETURN gchar * G_CONST_RETURN *) data_dir_vector;
+ return (const gchar * const *) data_dir_vector;
}
/**
* not be modified or freed.
* Since: 2.6
**/
-G_CONST_RETURN gchar * G_CONST_RETURN *
+const gchar * const *
g_get_system_config_dirs (void)
{
gchar *conf_dirs, **conf_dir_vector;
conf_dir_vector = g_system_config_dirs;
G_UNLOCK (g_utils_global);
- return (G_CONST_RETURN gchar * G_CONST_RETURN *) conf_dir_vector;
+ return (const gchar * const *) conf_dir_vector;
}
#ifndef G_OS_WIN32
* but it is big, ugly, and complicated, so I'm reluctant
* to do so when this should handle 99% of the time...
*/
-GSList *
-_g_compute_locale_variants (const gchar *locale)
+static void
+append_locale_variants (GPtrArray *array,
+ const gchar *locale)
{
- GSList *retval = NULL;
-
gchar *language = NULL;
gchar *territory = NULL;
gchar *codeset = NULL;
gchar *modifier = NULL;
guint mask;
- guint i;
+ guint i, j;
- g_return_val_if_fail (locale != NULL, NULL);
+ g_return_if_fail (locale != NULL);
mask = explode_locale (locale, &language, &territory, &codeset, &modifier);
/* Iterate through all possible combinations, from least attractive
* to most attractive.
*/
- for (i = 0; i <= mask; i++)
- if ((i & ~mask) == 0)
- {
- gchar *val = g_strconcat (language,
- (i & COMPONENT_TERRITORY) ? territory : "",
- (i & COMPONENT_CODESET) ? codeset : "",
- (i & COMPONENT_MODIFIER) ? modifier : "",
- NULL);
- retval = g_slist_prepend (retval, val);
- }
+ for (j = 0; j <= mask; ++j)
+ {
+ i = mask - j;
+
+ if ((i & ~mask) == 0)
+ {
+ gchar *val = g_strconcat (language,
+ (i & COMPONENT_TERRITORY) ? territory : "",
+ (i & COMPONENT_CODESET) ? codeset : "",
+ (i & COMPONENT_MODIFIER) ? modifier : "",
+ NULL);
+ g_ptr_array_add (array, val);
+ }
+ }
g_free (language);
if (mask & COMPONENT_CODESET)
g_free (territory);
if (mask & COMPONENT_MODIFIER)
g_free (modifier);
+}
- return retval;
+/**
+ * g_get_locale_variants:
+ * @locale: a locale identifier
+ *
+ * Returns a list of derived variants of @locale, which can be used to
+ * e.g. construct locale-dependent filenames or search paths. The returned
+ * list is sorted from most desirable to least desirable.
+ * This function handles territory, charset and extra locale modifiers.
+ *
+ * For example, if @locale is "fr_BE", then the returned list
+ * is "fr_BE", "fr".
+ *
+ * If you need the list of variants for the <emphasis>current locale</emphasis>,
+ * use g_get_language_names().
+ *
+ * Returns: (transfer full) (array zero-terminated="1") (element-type utf8): a newly
+ * allocated array of newly allocated strings with the locale variants. Free with
+ * g_strfreev().
+ *
+ * Since: 2.28
+ */
+gchar **
+g_get_locale_variants (const gchar *locale)
+{
+ GPtrArray *array;
+
+ g_return_val_if_fail (locale != NULL, NULL);
+
+ array = g_ptr_array_sized_new (8);
+ append_locale_variants (array, locale);
+ g_ptr_array_add (array, NULL);
+
+ return (gchar **) g_ptr_array_free (array, FALSE);
}
/* The following is (partly) taken from the gettext package.
*
* Since: 2.6
**/
-G_CONST_RETURN gchar * G_CONST_RETURN *
+const gchar * const *
g_get_language_names (void)
{
static GStaticPrivate cache_private = G_STATIC_PRIVATE_INIT;
if (!(cache->languages && strcmp (cache->languages, value) == 0))
{
- gchar **languages;
+ GPtrArray *array;
gchar **alist, **a;
- GSList *list, *l;
- gint i;
g_free (cache->languages);
g_strfreev (cache->language_names);
cache->languages = g_strdup (value);
+ array = g_ptr_array_sized_new (8);
+
alist = g_strsplit (value, ":", 0);
- list = NULL;
for (a = alist; *a; a++)
- {
- gchar *b = unalias_lang (*a);
- list = g_slist_concat (list, _g_compute_locale_variants (b));
- }
+ append_locale_variants (array, unalias_lang (*a));
g_strfreev (alist);
- list = g_slist_append (list, g_strdup ("C"));
-
- cache->language_names = languages = g_new (gchar *, g_slist_length (list) + 1);
- for (l = list, i = 0; l; l = l->next, i++)
- languages[i] = l->data;
- languages[i] = NULL;
+ g_ptr_array_add (array, g_strdup ("C"));
+ g_ptr_array_add (array, NULL);
- g_slist_free (list);
+ cache->language_names = (gchar **) g_ptr_array_free (array, FALSE);
}
- return (G_CONST_RETURN gchar * G_CONST_RETURN *) cache->language_names;
+ return (const gchar * const *) cache->language_names;
}
/**
* have to use system codepage as bindtextdomain() doesn't have a
* UTF-8 interface.
*/
-static gchar *
+gchar *
_glib_get_locale_dir (void)
{
gchar *install_dir = NULL, *locale_dir;
#endif /* G_OS_WIN32 */
-/**
- * glib_gettext:
- * @str: The string to be translated
- *
- * Returns the translated string from the glib translations.
- * This is an internal function and should only be used by
- * the internals of glib (such as libgio).
- *
- * Returns: the transation of @str to the current locale
- */
-G_CONST_RETURN gchar *
-glib_gettext (const gchar *str)
+static void
+ensure_gettext_initialized(void)
{
static gboolean _glib_gettext_initialized = FALSE;
# endif
_glib_gettext_initialized = TRUE;
}
-
+}
+
+/**
+ * glib_gettext:
+ * @str: The string to be translated
+ *
+ * Returns the translated string from the glib translations.
+ * This is an internal function and should only be used by
+ * the internals of glib (such as libgio).
+ *
+ * Returns: the transation of @str to the current locale
+ */
+const gchar *
+glib_gettext (const gchar *str)
+{
+ ensure_gettext_initialized();
+
return g_dgettext (GETTEXT_PACKAGE, str);
}
+/**
+ * glib_pgettext:
+ * @msgctxtid: a combined message context and message id, separated
+ * by a \004 character
+ * @msgidoffset: the offset of the message id in @msgctxid
+ *
+ * This function is a variant of glib_gettext() which supports
+ * a disambiguating message context. See g_dpgettext() for full
+ * details.
+ *
+ * This is an internal function and should only be used by
+ * the internals of glib (such as libgio).
+ *
+ * Returns: the transation of @str to the current locale
+ */
+const gchar *
+glib_pgettext(const gchar *msgctxtid,
+ gsize msgidoffset)
+{
+ ensure_gettext_initialized();
+
+ return g_dpgettext (GETTEXT_PACKAGE, msgctxtid, msgidoffset);
+}
+
#if defined (G_OS_WIN32) && !defined (_WIN64)
/* Binary compatibility versions. Not for newly compiled code. */
#undef g_getenv
-G_CONST_RETURN gchar*
+const gchar *
g_getenv (const gchar *variable)
{
gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
#undef g_get_user_name
-G_CONST_RETURN gchar*
+const gchar *
g_get_user_name (void)
{
g_get_any_init_locked ();
#undef g_get_real_name
-G_CONST_RETURN gchar*
+const gchar *
g_get_real_name (void)
{
g_get_any_init_locked ();
#undef g_get_home_dir
-G_CONST_RETURN gchar*
+const gchar *
g_get_home_dir (void)
{
g_get_any_init_locked ();
#undef g_get_tmp_dir
-G_CONST_RETURN gchar*
+const gchar *
g_get_tmp_dir (void)
{
g_get_any_init_locked ();
}
#endif
-
-#define __G_UTILS_C__
-#include "galiasdef.c"