From: Matthias Clasen Date: Mon, 17 Oct 2011 05:30:31 +0000 (-0400) Subject: Reshuffle some functions between gutils and gfileutils X-Git-Tag: 2.31.0~33 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=67bf0083db329d02ad2e99a8f4586ebfdcba1dd2;p=platform%2Fupstream%2Fglib.git Reshuffle some functions between gutils and gfileutils Move filename-related functions to gfileutils, and move size formatting functions to gutils. --- diff --git a/glib/gfileutils.c b/glib/gfileutils.c index 3f45a73..f5c8db2 100644 --- a/glib/gfileutils.c +++ b/glib/gfileutils.c @@ -2048,263 +2048,6 @@ g_build_filename (const gchar *first_element, return str; } -#define KILOBYTE_FACTOR (G_GOFFSET_CONSTANT (1000)) -#define MEGABYTE_FACTOR (KILOBYTE_FACTOR * KILOBYTE_FACTOR) -#define GIGABYTE_FACTOR (MEGABYTE_FACTOR * KILOBYTE_FACTOR) -#define TERABYTE_FACTOR (GIGABYTE_FACTOR * KILOBYTE_FACTOR) -#define PETABYTE_FACTOR (TERABYTE_FACTOR * KILOBYTE_FACTOR) -#define EXABYTE_FACTOR (PETABYTE_FACTOR * KILOBYTE_FACTOR) - -#define KIBIBYTE_FACTOR (G_GOFFSET_CONSTANT (1024)) -#define MEBIBYTE_FACTOR (KIBIBYTE_FACTOR * KIBIBYTE_FACTOR) -#define GIBIBYTE_FACTOR (MEBIBYTE_FACTOR * KIBIBYTE_FACTOR) -#define TEBIBYTE_FACTOR (GIBIBYTE_FACTOR * KIBIBYTE_FACTOR) -#define PEBIBYTE_FACTOR (TEBIBYTE_FACTOR * KIBIBYTE_FACTOR) -#define EXBIBYTE_FACTOR (PEBIBYTE_FACTOR * KIBIBYTE_FACTOR) - -/** - * g_format_size: - * @size: a size in bytes - * - * Formats a size (for example the size of a file) into a human readable - * string. Sizes are rounded to the nearest size prefix (kB, MB, GB) - * and are displayed rounded to the nearest tenth. E.g. the file size - * 3292528 bytes will be converted into the string "3.2 MB". - * - * The prefix units base is 1000 (i.e. 1 kB is 1000 bytes). - * - * This string should be freed with g_free() when not needed any longer. - * - * See g_format_size_full() for more options about how the size might be - * formatted. - * - * Returns: a newly-allocated formatted string containing a human readable - * file size. - * - * Since: 2.30 - **/ -gchar * -g_format_size (guint64 size) -{ - return g_format_size_full (size, G_FORMAT_SIZE_DEFAULT); -} - -/** - * g_format_size_full: - * @size: a size in bytes - * @flags: #GFormatSizeFlags to modify the output - * - * Formats a size. - * - * This function is similar to g_format_size() but allows for flags that - * modify the output. See #GFormatSizeFlags. - * - * Returns: a newly-allocated formatted string containing a human - * readable file size. - * - * Since: 2.30 - **/ -/** - * GFormatSizeFlags: - * @G_FORMAT_SIZE_DEFAULT: behave the same as g_format_size() - * @G_FORMAT_SIZE_LONG_FORMAT: include the exact number of bytes as part - * of the returned string. For example, - * "45.6 kB (45,612 bytes)". - * @G_FORMAT_SIZE_IEC_UNITS: use IEC (base 1024) units with "KiB"-style - * suffixes. IEC units should only be used - * for reporting things with a strong "power - * of 2" basis, like RAM sizes or RAID stripe - * sizes. Network and storage sizes should - * be reported in the normal SI units. - * - * Flags to modify the format of the string returned by - * g_format_size_full(). - **/ -gchar * -g_format_size_full (guint64 size, - GFormatSizeFlags flags) -{ - GString *string; - - string = g_string_new (NULL); - - if (flags & G_FORMAT_SIZE_IEC_UNITS) - { - if (size < KIBIBYTE_FACTOR) - { - g_string_printf (string, - g_dngettext(GETTEXT_PACKAGE, "%u byte", "%u bytes", (guint) size), - (guint) size); - flags &= ~G_FORMAT_SIZE_LONG_FORMAT; - } - - else if (size < MEBIBYTE_FACTOR) - g_string_printf (string, _("%.1f KiB"), (gdouble) size / (gdouble) KIBIBYTE_FACTOR); - - else if (size < GIBIBYTE_FACTOR) - g_string_printf (string, _("%.1f MiB"), (gdouble) size / (gdouble) MEBIBYTE_FACTOR); - - else if (size < TEBIBYTE_FACTOR) - g_string_printf (string, _("%.1f GiB"), (gdouble) size / (gdouble) GIBIBYTE_FACTOR); - - else if (size < PEBIBYTE_FACTOR) - g_string_printf (string, _("%.1f TiB"), (gdouble) size / (gdouble) TEBIBYTE_FACTOR); - - else if (size < EXBIBYTE_FACTOR) - g_string_printf (string, _("%.1f PiB"), (gdouble) size / (gdouble) PEBIBYTE_FACTOR); - - else - g_string_printf (string, _("%.1f EiB"), (gdouble) size / (gdouble) EXBIBYTE_FACTOR); - } - else - { - if (size < KILOBYTE_FACTOR) - { - g_string_printf (string, - g_dngettext(GETTEXT_PACKAGE, "%u byte", "%u bytes", (guint) size), - (guint) size); - flags &= ~G_FORMAT_SIZE_LONG_FORMAT; - } - - else if (size < MEGABYTE_FACTOR) - g_string_printf (string, _("%.1f kB"), (gdouble) size / (gdouble) KILOBYTE_FACTOR); - - else if (size < GIGABYTE_FACTOR) - g_string_printf (string, _("%.1f MB"), (gdouble) size / (gdouble) MEGABYTE_FACTOR); - - else if (size < TERABYTE_FACTOR) - g_string_printf (string, _("%.1f GB"), (gdouble) size / (gdouble) GIGABYTE_FACTOR); - - else if (size < PETABYTE_FACTOR) - g_string_printf (string, _("%.1f TB"), (gdouble) size / (gdouble) TERABYTE_FACTOR); - - else if (size < EXABYTE_FACTOR) - g_string_printf (string, _("%.1f PB"), (gdouble) size / (gdouble) PETABYTE_FACTOR); - - else - g_string_printf (string, _("%.1f EB"), (gdouble) size / (gdouble) EXABYTE_FACTOR); - } - - if (flags & G_FORMAT_SIZE_LONG_FORMAT) - { - /* First problem: we need to use the number of bytes to decide on - * the plural form that is used for display, but the number of - * bytes potentially exceeds the size of a guint (which is what - * ngettext() takes). - * - * From a pragmatic standpoint, it seems that all known languages - * base plural forms on one or both of the following: - * - * - the lowest digits of the number - * - * - if the number if greater than some small value - * - * Here's how we fake it: Draw an arbitrary line at one thousand. - * If the number is below that, then fine. If it is above it, - * then we take the modulus of the number by one thousand (in - * order to keep the lowest digits) and add one thousand to that - * (in order to ensure that 1001 is not treated the same as 1). - */ - guint plural_form = size < 1000 ? size : size % 1000 + 1000; - - /* Second problem: we need to translate the string "%u byte" and - * "%u bytes" for pluralisation, but the correct number format to - * use for a gsize is different depending on which architecture - * we're on. - * - * Solution: format the number separately and use "%s bytes" on - * all platforms. - */ - const gchar *translated_format; - gchar *formatted_number; - - /* Translators: the %s in "%s bytes" will always be replaced by a number. */ - translated_format = g_dngettext(GETTEXT_PACKAGE, "%s byte", "%s bytes", plural_form); - - /* XXX: Windows doesn't support the "'" format modifier, so we - * must not use it there. Instead, just display the number - * without separation. Bug #655336 is open until a solution is - * found. - */ -#ifndef G_OS_WIN32 - formatted_number = g_strdup_printf ("%'"G_GUINT64_FORMAT, size); -#else - formatted_number = g_strdup_printf ("%"G_GUINT64_FORMAT, size); -#endif - - g_string_append (string, " ("); - g_string_append_printf (string, translated_format, formatted_number); - g_free (formatted_number); - g_string_append (string, ")"); - } - - return g_string_free (string, FALSE); -} - -/** - * g_format_size_for_display: - * @size: a size in bytes. - * - * Formats a size (for example the size of a file) into a human readable string. - * Sizes are rounded to the nearest size prefix (KB, MB, GB) and are displayed - * rounded to the nearest tenth. E.g. the file size 3292528 bytes will be - * converted into the string "3.1 MB". - * - * The prefix units base is 1024 (i.e. 1 KB is 1024 bytes). - * - * This string should be freed with g_free() when not needed any longer. - * - * Returns: a newly-allocated formatted string containing a human readable - * file size. - * - * Deprecated:2.30: This function is broken due to its use of SI - * suffixes to denote IEC units. Use g_format_size() - * instead. - * Since: 2.16 - **/ -char * -g_format_size_for_display (goffset size) -{ - if (size < (goffset) KIBIBYTE_FACTOR) - return g_strdup_printf (g_dngettext(GETTEXT_PACKAGE, "%u byte", "%u bytes",(guint) size), (guint) size); - else - { - gdouble displayed_size; - - if (size < (goffset) MEBIBYTE_FACTOR) - { - displayed_size = (gdouble) size / (gdouble) KIBIBYTE_FACTOR; - return g_strdup_printf (_("%.1f KB"), displayed_size); - } - else if (size < (goffset) GIBIBYTE_FACTOR) - { - displayed_size = (gdouble) size / (gdouble) MEBIBYTE_FACTOR; - return g_strdup_printf (_("%.1f MB"), displayed_size); - } - else if (size < (goffset) TEBIBYTE_FACTOR) - { - displayed_size = (gdouble) size / (gdouble) GIBIBYTE_FACTOR; - return g_strdup_printf (_("%.1f GB"), displayed_size); - } - else if (size < (goffset) PEBIBYTE_FACTOR) - { - displayed_size = (gdouble) size / (gdouble) TEBIBYTE_FACTOR; - return g_strdup_printf (_("%.1f TB"), displayed_size); - } - else if (size < (goffset) EXBIBYTE_FACTOR) - { - displayed_size = (gdouble) size / (gdouble) PEBIBYTE_FACTOR; - return g_strdup_printf (_("%.1f PB"), displayed_size); - } - else - { - displayed_size = (gdouble) size / (gdouble) EXBIBYTE_FACTOR; - return g_strdup_printf (_("%.1f EB"), displayed_size); - } - } -} - - /** * g_file_read_link: * @filename: the symbolic link @@ -2369,7 +2112,445 @@ g_file_read_link (const gchar *filename, #endif } -/* NOTE : Keep this part last to ensure nothing in this file uses the +/** + * g_path_is_absolute: + * @file_name: a file name + * + * Returns %TRUE if the given @file_name is an absolute file name. + * Note that this is a somewhat vague concept on Windows. + * + * 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) +{ + g_return_val_if_fail (file_name != NULL, FALSE); + + if (G_IS_DIR_SEPARATOR (file_name[0])) + return TRUE; + +#ifdef G_OS_WIN32 + /* Recognize drive letter on native Windows */ + if (g_ascii_isalpha (file_name[0]) && + file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2])) + return TRUE; +#endif + + return FALSE; +} + +/** + * g_path_skip_root: + * @file_name: a file name + * + * Returns a pointer into @file_name after the root component, + * i.e. after the "/" in UNIX or "C:\" under Windows. If @file_name + * is not an absolute path it returns %NULL. + * + * Returns: a pointer into @file_name after the root component + */ +const 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 or //server/share */ + if (G_IS_DIR_SEPARATOR (file_name[0]) && + G_IS_DIR_SEPARATOR (file_name[1]) && + file_name[2] && + !G_IS_DIR_SEPARATOR (file_name[2])) + { + gchar *p; + p = strchr (file_name + 2, G_DIR_SEPARATOR); + +#ifdef G_OS_WIN32 + { + gchar *q; + + q = strchr (file_name + 2, '/'); + if (p == NULL || (q != NULL && q < p)) + p = q; + } +#endif + + if (p && p > file_name + 2 && p[1]) + { + file_name = p + 1; + + while (file_name[0] && !G_IS_DIR_SEPARATOR (file_name[0])) + file_name++; + + /* Possibly skip a backslash after the share name */ + if (G_IS_DIR_SEPARATOR (file_name[0])) + file_name++; + + return (gchar *)file_name; + } + } +#endif + + /* Skip initial slashes */ + if (G_IS_DIR_SEPARATOR (file_name[0])) + { + while (G_IS_DIR_SEPARATOR (file_name[0])) + file_name++; + return (gchar *)file_name; + } + +#ifdef G_OS_WIN32 + /* Skip X:\ */ + if (g_ascii_isalpha (file_name[0]) && + file_name[1] == ':' && + G_IS_DIR_SEPARATOR (file_name[2])) + return (gchar *)file_name + 3; +#endif + + return NULL; +} + +/** + * g_basename: + * @file_name: the name of the file + * + * Gets the name of the file without any leading directory + * components. It returns a pointer into the given file name + * string. + * + * Return value: the name of the file without any leading + * directory components + * + * Deprecated:2.2: Use g_path_get_basename() instead, but notice + * that g_path_get_basename() allocates new memory for the + * returned string, unlike this function which returns a pointer + * into the argument. + */ +const gchar * +g_basename (const gchar *file_name) +{ + gchar *base; + + g_return_val_if_fail (file_name != NULL, NULL); + + base = strrchr (file_name, G_DIR_SEPARATOR); + +#ifdef G_OS_WIN32 + { + gchar *q; + q = strrchr (file_name, '/'); + if (base == NULL || (q != NULL && q > base)) + base = q; + } +#endif + + 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 + + return (gchar*) file_name; +} + +/** + * g_path_get_basename: + * @file_name: the name of the file + * + * Gets the last component of the filename. + * + * If @file_name ends with a directory separator it gets the component + * before the last slash. If @file_name consists only of directory + * separators (and on Windows, possibly a drive letter), a single + * separator is returned. If @file_name is empty, it gets ".". + * + * Return value: a newly allocated string containing the last + * component of the filename + */ +gchar * +g_path_get_basename (const gchar *file_name) +{ + gssize base; + gssize last_nonslash; + gsize len; + gchar *retval; + + g_return_val_if_fail (file_name != NULL, NULL); + + if (file_name[0] == '\0') + return g_strdup ("."); + + last_nonslash = strlen (file_name) - 1; + + while (last_nonslash >= 0 && G_IS_DIR_SEPARATOR (file_name [last_nonslash])) + 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 + base = last_nonslash; + + while (base >=0 && !G_IS_DIR_SEPARATOR (file_name [base])) + 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; +} + +/** + * g_dirname: + * @file_name: the name of the file + * + * Gets the directory components of a file name. + * + * If the file name has no directory components "." is returned. + * The returned string should be freed when no longer needed. + * + * Returns: the directory components of the file + * + * Deprecated: use g_path_get_dirname() instead + */ + +/** + * g_path_get_dirname: + * @file_name: the name of the file + * + * Gets the directory components of a file name. + * + * If the file name has no directory components "." is returned. + * The returned string should be freed when no longer needed. + * + * Returns: the directory components of the file + */ +gchar * +g_path_get_dirname (const gchar *file_name) +{ + gchar *base; + gsize len; + + g_return_val_if_fail (file_name != NULL, NULL); + + base = strrchr (file_name, G_DIR_SEPARATOR); + +#ifdef G_OS_WIN32 + { + gchar *q; + q = strrchr (file_name, '/'); + if (base == NULL || (q != NULL && q > base)) + base = q; + } +#endif + + if (!base) + { +#ifdef G_OS_WIN32 + if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':') + { + gchar drive_colon_dot[4]; + + drive_colon_dot[0] = file_name[0]; + drive_colon_dot[1] = ':'; + drive_colon_dot[2] = '.'; + drive_colon_dot[3] = '\0'; + + return g_strdup (drive_colon_dot); + } +#endif + return g_strdup ("."); + } + + while (base > file_name && G_IS_DIR_SEPARATOR (*base)) + base--; + +#ifdef G_OS_WIN32 + /* base points to the char before the last slash. + * + * In case file_name is the root of a drive (X:\) or a child of the + * root of a drive (X:\foo), include the slash. + * + * In case file_name is the root share of an UNC path + * (\\server\share), add a slash, returning \\server\share\ . + * + * In case file_name is a direct child of a share in an UNC path + * (\\server\share\foo), include the slash after the share name, + * returning \\server\share\ . + */ + if (base == file_name + 1 && + g_ascii_isalpha (file_name[0]) && + file_name[1] == ':') + base++; + else if (G_IS_DIR_SEPARATOR (file_name[0]) && + G_IS_DIR_SEPARATOR (file_name[1]) && + file_name[2] && + !G_IS_DIR_SEPARATOR (file_name[2]) && + base >= file_name + 2) + { + const gchar *p = file_name + 2; + while (*p && !G_IS_DIR_SEPARATOR (*p)) + p++; + if (p == base + 1) + { + len = (guint) strlen (file_name) + 1; + base = g_new (gchar, len + 1); + strcpy (base, file_name); + base[len-1] = G_DIR_SEPARATOR; + base[len] = 0; + return base; + } + if (G_IS_DIR_SEPARATOR (*p)) + { + p++; + while (*p && !G_IS_DIR_SEPARATOR (*p)) + p++; + if (p == base + 1) + base++; + } + } +#endif + + len = (guint) 1 + base - file_name; + base = g_new (gchar, len + 1); + g_memmove (base, file_name, len); + base[len] = 0; + + return base; +} + +#if defined(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 + +/** + * g_get_current_dir: + * + * Gets the current directory. + * + * The returned string should be freed when no longer needed. + * The encoding of the returned string is system defined. + * On Windows, it is always UTF-8. + * + * Returns: the current directory + */ +gchar * +g_get_current_dir (void) +{ +#ifdef G_OS_WIN32 + + gchar *dir = NULL; + wchar_t dummy[2], *wdir; + int len; + + len = GetCurrentDirectoryW (2, dummy); + wdir = g_new (wchar_t, len); + + if (GetCurrentDirectoryW (len, wdir) == len - 1) + dir = g_utf16_to_utf8 (wdir, -1, NULL, NULL, NULL); + + g_free (wdir); + + if (dir == NULL) + dir = g_strdup ("\\"); + + return dir; + +#else + + gchar *buffer = NULL; + gchar *dir = NULL; + static gulong max_len = 0; + + if (max_len == 0) + max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH; + + /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd") + * and, if that wasn't bad enough, hangs in doing so. + */ +#if (defined (sun) && !defined (__SVR4)) || !defined(HAVE_GETCWD) + buffer = g_new (gchar, max_len + 1); + *buffer = 0; + dir = getwd (buffer); +#else + while (max_len < G_MAXULONG / 2) + { + g_free (buffer); + buffer = g_new (gchar, max_len + 1); + *buffer = 0; + dir = getcwd (buffer, max_len); + + if (dir || errno != ERANGE) + break; + + max_len *= 2; + } +#endif /* !sun || !HAVE_GETCWD */ + + if (!dir || !*buffer) + { + /* hm, should we g_error() out here? + * this can happen if e.g. "./" has mode \0000 + */ + buffer[0] = G_DIR_SEPARATOR; + buffer[1] = 0; + } + + dir = g_strdup (buffer); + g_free (buffer); + + return dir; + +#endif /* !G_OS_WIN32 */ +} + + +/* NOTE : Keep this part last to ensure nothing in this file uses thn * below binary compatibility versions. */ #if defined (G_OS_WIN32) && !defined (_WIN64) @@ -2458,4 +2639,16 @@ g_file_open_tmp (const gchar *tmpl, return retval; } +#undef g_get_current_dir + +gchar * +g_get_current_dir (void) +{ + gchar *utf8_dir = g_get_current_dir_utf8 (); + gchar *dir = g_locale_from_utf8 (utf8_dir, -1, NULL, NULL, NULL); + g_free (utf8_dir); + return dir; +} + #endif + diff --git a/glib/gfileutils.h b/glib/gfileutils.h index 1773177..2a13dca 100644 --- a/glib/gfileutils.h +++ b/glib/gfileutils.h @@ -60,7 +60,7 @@ typedef enum G_FILE_ERROR_FAILED } GFileError; -/* For backward-compat reasons, these are synced to an old +/* For backward-compat reasons, these are synced to an old * anonymous enum in libgnome. But don't use that enum * in new code. */ @@ -90,14 +90,14 @@ gboolean g_file_test (const gchar *filename, GFileTest test); gboolean g_file_get_contents (const gchar *filename, gchar **contents, - gsize *length, + gsize *length, GError **error); gboolean g_file_set_contents (const gchar *filename, - const gchar *contents, - gssize length, - GError **error); + const gchar *contents, + gssize length, + GError **error); gchar *g_file_read_link (const gchar *filename, - GError **error); + GError **error); /* Wrapper / workalike for mkdtemp() */ gchar *g_mkdtemp (gchar *tmpl); @@ -105,46 +105,73 @@ gchar *g_mkdtemp_full (gchar *tmpl, gint mode); /* Wrapper / workalike for mkstemp() */ -gint g_mkstemp (gchar *tmpl); -gint g_mkstemp_full (gchar *tmpl, - gint flags, - gint mode); +gint g_mkstemp (gchar *tmpl); +gint g_mkstemp_full (gchar *tmpl, + gint flags, + gint mode); /* Wrappers for g_mkstemp and g_mkdtemp() */ -gint g_file_open_tmp (const gchar *tmpl, - gchar **name_used, - GError **error); -gchar *g_dir_make_tmp (const gchar *tmpl, - GError **error); +gint g_file_open_tmp (const gchar *tmpl, + gchar **name_used, + GError **error); +gchar *g_dir_make_tmp (const gchar *tmpl, + GError **error); -typedef enum -{ - G_FORMAT_SIZE_DEFAULT = 0, - G_FORMAT_SIZE_LONG_FORMAT = 1 << 0, - G_FORMAT_SIZE_IEC_UNITS = 1 << 1 -} GFormatSizeFlags; +gchar *g_build_path (const gchar *separator, + const gchar *first_element, + ...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED; +gchar *g_build_pathv (const gchar *separator, + gchar **args) G_GNUC_MALLOC; -gchar * g_format_size_full (guint64 size, - GFormatSizeFlags flags); -gchar * g_format_size (guint64 size); +gchar *g_build_filename (const gchar *first_element, + ...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED; +gchar *g_build_filenamev (gchar **args) G_GNUC_MALLOC; + +gint g_mkdir_with_parents (const gchar *pathname, + gint mode); + +#ifdef G_OS_WIN32 + +/* On Win32, the canonical directory separator is the backslash, and + * the search path separator is the semicolon. Note that also the + * (forward) slash works as directory separator. + */ +#define G_DIR_SEPARATOR '\\' +#define G_DIR_SEPARATOR_S "\\" +#define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR || (c) == '/') +#define G_SEARCHPATH_SEPARATOR ';' +#define G_SEARCHPATH_SEPARATOR_S ";" + +#else /* !G_OS_WIN32 */ + +#define G_DIR_SEPARATOR '/' +#define G_DIR_SEPARATOR_S "/" +#define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR) +#define G_SEARCHPATH_SEPARATOR ':' +#define G_SEARCHPATH_SEPARATOR_S ":" + +#endif /* !G_OS_WIN32 */ + +gboolean g_path_is_absolute (const gchar *file_name); +const gchar *g_path_skip_root (const gchar *file_name); #ifndef G_DISABLE_DEPRECATED -GLIB_DEPRECATED_FOR(g_format_size) -char *g_format_size_for_display (goffset size); -#endif -gchar *g_build_path (const gchar *separator, - const gchar *first_element, - ...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED; -gchar *g_build_pathv (const gchar *separator, - gchar **args) G_GNUC_MALLOC; +GLIB_DEPRECATED_FOR(g_path_get_basename) +const gchar *g_basename (const gchar *file_name); +#define g_dirname g_path_get_dirname -gchar *g_build_filename (const gchar *first_element, - ...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED; -gchar *g_build_filenamev (gchar **args) G_GNUC_MALLOC; +#endif /* G_DISABLE_DEPRECATED */ + +#ifndef __GTK_DOC_IGNORE__ +#ifdef G_OS_WIN32 +#define g_get_current_dir g_get_current_dir_utf8 +#endif +#endif -int g_mkdir_with_parents (const gchar *pathname, - int mode); +gchar *g_get_current_dir (void); +gchar *g_path_get_basename (const gchar *file_name) G_GNUC_MALLOC; +gchar *g_path_get_dirname (const gchar *file_name) G_GNUC_MALLOC; G_END_DECLS diff --git a/glib/gutils.c b/glib/gutils.c index 6c930ab..6a422ff 100644 --- a/glib/gutils.c +++ b/glib/gutils.c @@ -88,16 +88,6 @@ * These are portable utility functions. */ -#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 # include # ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS @@ -549,222 +539,6 @@ g_find_program_in_path (const gchar *program) } /** - * g_basename: - * @file_name: the name of the file. - * - * Gets the name of the file without any leading directory components. - * It returns a pointer into the given file name string. - * - * Return value: the name of the file without any leading directory components. - * - * Deprecated:2.2: Use g_path_get_basename() instead, but notice that - * g_path_get_basename() allocates new memory for the returned string, unlike - * this function which returns a pointer into the argument. - **/ -const 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); - -#ifdef G_OS_WIN32 - { - gchar *q = strrchr (file_name, '/'); - if (base == NULL || (q != NULL && q > base)) - base = q; - } -#endif - - 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; -} - -/** - * g_path_get_basename: - * @file_name: the name of the file. - * - * Gets the last component of the filename. If @file_name ends with a - * directory separator it gets the component before the last slash. If - * @file_name consists only of directory separators (and on Windows, - * possibly a drive letter), a single separator is returned. If - * @file_name is empty, it gets ".". - * - * Return value: a newly allocated string containing the last component of - * the filename. - */ -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 && G_IS_DIR_SEPARATOR (file_name [last_nonslash])) - 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 && !G_IS_DIR_SEPARATOR (file_name [base])) - 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; -} - -/** - * g_path_is_absolute: - * @file_name: a file name. - * - * Returns %TRUE if the given @file_name is an absolute file name. - * Note that this is a somewhat vague concept on Windows. - * - * 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) -{ - g_return_val_if_fail (file_name != NULL, FALSE); - - if (G_IS_DIR_SEPARATOR (file_name[0])) - return TRUE; - -#ifdef G_OS_WIN32 - /* Recognize drive letter on native Windows */ - if (g_ascii_isalpha (file_name[0]) && - file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2])) - return TRUE; -#endif /* G_OS_WIN32 */ - - return FALSE; -} - -/** - * g_path_skip_root: - * @file_name: a file name. - * - * Returns a pointer into @file_name after the root component, i.e. after - * the "/" in UNIX or "C:\" under Windows. If @file_name is not an absolute - * path it returns %NULL. - * - * Returns: a pointer into @file_name after the root component. - */ -const 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 or //server/share */ - if (G_IS_DIR_SEPARATOR (file_name[0]) && - G_IS_DIR_SEPARATOR (file_name[1]) && - file_name[2] && - !G_IS_DIR_SEPARATOR (file_name[2])) - { - gchar *p; - - p = strchr (file_name + 2, G_DIR_SEPARATOR); -#ifdef G_OS_WIN32 - { - gchar *q = strchr (file_name + 2, '/'); - if (p == NULL || (q != NULL && q < p)) - p = q; - } -#endif - if (p && - p > file_name + 2 && - p[1]) - { - file_name = p + 1; - - while (file_name[0] && !G_IS_DIR_SEPARATOR (file_name[0])) - file_name++; - - /* Possibly skip a backslash after the share name */ - if (G_IS_DIR_SEPARATOR (file_name[0])) - file_name++; - - return (gchar *)file_name; - } - } -#endif - - /* Skip initial slashes */ - if (G_IS_DIR_SEPARATOR (file_name[0])) - { - while (G_IS_DIR_SEPARATOR (file_name[0])) - file_name++; - return (gchar *)file_name; - } - -#ifdef G_OS_WIN32 - /* Skip X:\ */ - if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2])) - return (gchar *)file_name + 3; -#endif - - return NULL; -} - -/** * g_bit_nth_lsf: * @mask: a #gulong containing flags * @nth_bit: the index of the bit to start the search from @@ -801,197 +575,6 @@ g_path_skip_root (const gchar *file_name) * Returns: the number of bits used to hold @number */ -/** - * g_dirname: - * @file_name: the name of the file - * - * Gets the directory components of a file name. - * If the file name has no directory components "." is returned. - * The returned string should be freed when no longer needed. - * - * Returns: the directory components of the file - * - * Deprecated: use g_path_get_dirname() instead - */ - -/** - * g_path_get_dirname: - * @file_name: the name of the file. - * - * Gets the directory components of a file name. If the file name has no - * directory components "." is returned. The returned string should be - * freed when no longer needed. - * - * Returns: the directory components of the file. - */ -gchar* -g_path_get_dirname (const gchar *file_name) -{ - register gchar *base; - register gsize len; - - g_return_val_if_fail (file_name != NULL, NULL); - - base = strrchr (file_name, G_DIR_SEPARATOR); -#ifdef G_OS_WIN32 - { - gchar *q = strrchr (file_name, '/'); - if (base == NULL || (q != NULL && q > base)) - base = q; - } -#endif - if (!base) - { -#ifdef G_OS_WIN32 - if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':') - { - gchar drive_colon_dot[4]; - - drive_colon_dot[0] = file_name[0]; - drive_colon_dot[1] = ':'; - drive_colon_dot[2] = '.'; - drive_colon_dot[3] = '\0'; - - return g_strdup (drive_colon_dot); - } -#endif - return g_strdup ("."); - } - - while (base > file_name && G_IS_DIR_SEPARATOR (*base)) - base--; - -#ifdef G_OS_WIN32 - /* base points to the char before the last slash. - * - * In case file_name is the root of a drive (X:\) or a child of the - * root of a drive (X:\foo), include the slash. - * - * In case file_name is the root share of an UNC path - * (\\server\share), add a slash, returning \\server\share\ . - * - * In case file_name is a direct child of a share in an UNC path - * (\\server\share\foo), include the slash after the share name, - * returning \\server\share\ . - */ - if (base == file_name + 1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':') - base++; - else if (G_IS_DIR_SEPARATOR (file_name[0]) && - G_IS_DIR_SEPARATOR (file_name[1]) && - file_name[2] && - !G_IS_DIR_SEPARATOR (file_name[2]) && - base >= file_name + 2) - { - const gchar *p = file_name + 2; - while (*p && !G_IS_DIR_SEPARATOR (*p)) - p++; - if (p == base + 1) - { - len = (guint) strlen (file_name) + 1; - base = g_new (gchar, len + 1); - strcpy (base, file_name); - base[len-1] = G_DIR_SEPARATOR; - base[len] = 0; - return base; - } - if (G_IS_DIR_SEPARATOR (*p)) - { - p++; - while (*p && !G_IS_DIR_SEPARATOR (*p)) - p++; - if (p == base + 1) - base++; - } - } -#endif - - len = (guint) 1 + base - file_name; - - base = g_new (gchar, len + 1); - g_memmove (base, file_name, len); - base[len] = 0; - - return base; -} - -/** - * g_get_current_dir: - * - * Gets the current directory. - * The returned string should be freed when no longer needed. The encoding - * of the returned string is system defined. On Windows, it is always UTF-8. - * - * Returns: the current directory. - */ -gchar* -g_get_current_dir (void) -{ -#ifdef G_OS_WIN32 - - gchar *dir = NULL; - wchar_t dummy[2], *wdir; - int len; - - len = GetCurrentDirectoryW (2, dummy); - wdir = g_new (wchar_t, len); - - if (GetCurrentDirectoryW (len, wdir) == len - 1) - dir = g_utf16_to_utf8 (wdir, -1, NULL, NULL, NULL); - - g_free (wdir); - - if (dir == NULL) - dir = g_strdup ("\\"); - - return dir; - -#else - - gchar *buffer = NULL; - gchar *dir = NULL; - static gulong max_len = 0; - - if (max_len == 0) - max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH; - - /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd") - * and, if that wasn't bad enough, hangs in doing so. - */ -#if (defined (sun) && !defined (__SVR4)) || !defined(HAVE_GETCWD) - buffer = g_new (gchar, max_len + 1); - *buffer = 0; - dir = getwd (buffer); -#else /* !sun || !HAVE_GETCWD */ - while (max_len < G_MAXULONG / 2) - { - g_free (buffer); - buffer = g_new (gchar, max_len + 1); - *buffer = 0; - dir = getcwd (buffer, max_len); - - if (dir || errno != ERANGE) - break; - - max_len *= 2; - } -#endif /* !sun || !HAVE_GETCWD */ - - if (!dir || !*buffer) - { - /* hm, should we g_error() out here? - * this can happen if e.g. "./" has mode \0000 - */ - buffer[0] = G_DIR_SEPARATOR; - buffer[1] = 0; - } - - dir = g_strdup (buffer); - g_free (buffer); - - return dir; -#endif /* !Win32 */ -} - G_LOCK_DEFINE_STATIC (g_utils_global); static gchar *g_tmp_dir = NULL; @@ -2499,6 +2082,257 @@ g_nullify_pointer (gpointer *nullify_location) *nullify_location = NULL; } +#define KILOBYTE_FACTOR (G_GOFFSET_CONSTANT (1000)) +#define MEGABYTE_FACTOR (KILOBYTE_FACTOR * KILOBYTE_FACTOR) +#define GIGABYTE_FACTOR (MEGABYTE_FACTOR * KILOBYTE_FACTOR) +#define TERABYTE_FACTOR (GIGABYTE_FACTOR * KILOBYTE_FACTOR) +#define PETABYTE_FACTOR (TERABYTE_FACTOR * KILOBYTE_FACTOR) +#define EXABYTE_FACTOR (PETABYTE_FACTOR * KILOBYTE_FACTOR) + +#define KIBIBYTE_FACTOR (G_GOFFSET_CONSTANT (1024)) +#define MEBIBYTE_FACTOR (KIBIBYTE_FACTOR * KIBIBYTE_FACTOR) +#define GIBIBYTE_FACTOR (MEBIBYTE_FACTOR * KIBIBYTE_FACTOR) +#define TEBIBYTE_FACTOR (GIBIBYTE_FACTOR * KIBIBYTE_FACTOR) +#define PEBIBYTE_FACTOR (TEBIBYTE_FACTOR * KIBIBYTE_FACTOR) +#define EXBIBYTE_FACTOR (PEBIBYTE_FACTOR * KIBIBYTE_FACTOR) + +/** + * g_format_size: + * @size: a size in bytes + * + * Formats a size (for example the size of a file) into a human readable + * string. Sizes are rounded to the nearest size prefix (kB, MB, GB) + * and are displayed rounded to the nearest tenth. E.g. the file size + * 3292528 bytes will be converted into the string "3.2 MB". + * + * The prefix units base is 1000 (i.e. 1 kB is 1000 bytes). + * + * This string should be freed with g_free() when not needed any longer. + * + * See g_format_size_full() for more options about how the size might be + * formatted. + * + * Returns: a newly-allocated formatted string containing a human readable + * file size + * + * Since: 2.30 + */ +gchar * +g_format_size (guint64 size) +{ + return g_format_size_full (size, G_FORMAT_SIZE_DEFAULT); +} + +/** + * GFormatSizeFlags: + * @G_FORMAT_SIZE_DEFAULT: behave the same as g_format_size() + * @G_FORMAT_SIZE_LONG_FORMAT: include the exact number of bytes as part + * of the returned string. For example, "45.6 kB (45,612 bytes)". + * @G_FORMAT_SIZE_IEC_UNITS: use IEC (base 1024) units with "KiB"-style + * suffixes. IEC units should only be used for reporting things with + * a strong "power of 2" basis, like RAM sizes or RAID stripe sizes. + * Network and storage sizes should be reported in the normal SI units. + * + * Flags to modify the format of the string returned by g_format_size_full(). + */ + +/** + * g_format_size_full: + * @size: a size in bytes + * @flags: #GFormatSizeFlags to modify the output + * + * Formats a size. + * + * This function is similar to g_format_size() but allows for flags + * that modify the output. See #GFormatSizeFlags. + * + * Returns: a newly-allocated formatted string containing a human + * readable file size + * + * Since: 2.30 + */ +gchar * +g_format_size_full (guint64 size, + GFormatSizeFlags flags) +{ + GString *string; + + string = g_string_new (NULL); + + if (flags & G_FORMAT_SIZE_IEC_UNITS) + { + if (size < KIBIBYTE_FACTOR) + { + g_string_printf (string, + g_dngettext(GETTEXT_PACKAGE, "%u byte", "%u bytes", (guint) size), + (guint) size); + flags &= ~G_FORMAT_SIZE_LONG_FORMAT; + } + + else if (size < MEBIBYTE_FACTOR) + g_string_printf (string, _("%.1f KiB"), (gdouble) size / (gdouble) KIBIBYTE_FACTOR); + else if (size < GIBIBYTE_FACTOR) + g_string_printf (string, _("%.1f MiB"), (gdouble) size / (gdouble) MEBIBYTE_FACTOR); + + else if (size < TEBIBYTE_FACTOR) + g_string_printf (string, _("%.1f GiB"), (gdouble) size / (gdouble) GIBIBYTE_FACTOR); + + else if (size < PEBIBYTE_FACTOR) + g_string_printf (string, _("%.1f TiB"), (gdouble) size / (gdouble) TEBIBYTE_FACTOR); + + else if (size < EXBIBYTE_FACTOR) + g_string_printf (string, _("%.1f PiB"), (gdouble) size / (gdouble) PEBIBYTE_FACTOR); + + else + g_string_printf (string, _("%.1f EiB"), (gdouble) size / (gdouble) EXBIBYTE_FACTOR); + } + else + { + if (size < KILOBYTE_FACTOR) + { + g_string_printf (string, + g_dngettext(GETTEXT_PACKAGE, "%u byte", "%u bytes", (guint) size), + (guint) size); + flags &= ~G_FORMAT_SIZE_LONG_FORMAT; + } + + else if (size < MEGABYTE_FACTOR) + g_string_printf (string, _("%.1f kB"), (gdouble) size / (gdouble) KILOBYTE_FACTOR); + + else if (size < GIGABYTE_FACTOR) + g_string_printf (string, _("%.1f MB"), (gdouble) size / (gdouble) MEGABYTE_FACTOR); + + else if (size < TERABYTE_FACTOR) + g_string_printf (string, _("%.1f GB"), (gdouble) size / (gdouble) GIGABYTE_FACTOR); + else if (size < PETABYTE_FACTOR) + g_string_printf (string, _("%.1f TB"), (gdouble) size / (gdouble) TERABYTE_FACTOR); + + else if (size < EXABYTE_FACTOR) + g_string_printf (string, _("%.1f PB"), (gdouble) size / (gdouble) PETABYTE_FACTOR); + + else + g_string_printf (string, _("%.1f EB"), (gdouble) size / (gdouble) EXABYTE_FACTOR); + } + + if (flags & G_FORMAT_SIZE_LONG_FORMAT) + { + /* First problem: we need to use the number of bytes to decide on + * the plural form that is used for display, but the number of + * bytes potentially exceeds the size of a guint (which is what + * ngettext() takes). + * + * From a pragmatic standpoint, it seems that all known languages + * base plural forms on one or both of the following: + * + * - the lowest digits of the number + * + * - if the number if greater than some small value + * + * Here's how we fake it: Draw an arbitrary line at one thousand. + * If the number is below that, then fine. If it is above it, + * then we take the modulus of the number by one thousand (in + * order to keep the lowest digits) and add one thousand to that + * (in order to ensure that 1001 is not treated the same as 1). + */ + guint plural_form = size < 1000 ? size : size % 1000 + 1000; + + /* Second problem: we need to translate the string "%u byte" and + * "%u bytes" for pluralisation, but the correct number format to + * use for a gsize is different depending on which architecture + * we're on. + * + * Solution: format the number separately and use "%s bytes" on + * all platforms. + */ + const gchar *translated_format; + gchar *formatted_number; + + /* Translators: the %s in "%s bytes" will always be replaced by a number. */ + translated_format = g_dngettext(GETTEXT_PACKAGE, "%s byte", "%s bytes", plural_form); + /* XXX: Windows doesn't support the "'" format modifier, so we + * must not use it there. Instead, just display the number + * without separation. Bug #655336 is open until a solution is + * found. + */ +#ifndef G_OS_WIN32 + formatted_number = g_strdup_printf ("%'"G_GUINT64_FORMAT, size); +#else + formatted_number = g_strdup_printf ("%"G_GUINT64_FORMAT, size); +#endif + + g_string_append (string, " ("); + g_string_append_printf (string, translated_format, formatted_number); + g_free (formatted_number); + g_string_append (string, ")"); + } + + return g_string_free (string, FALSE); +} + +/** + * g_format_size_for_display: + * @size: a size in bytes + * + * Formats a size (for example the size of a file) into a human + * readable string. Sizes are rounded to the nearest size prefix + * (KB, MB, GB) and are displayed rounded to the nearest tenth. + * E.g. the file size 3292528 bytes will be converted into the + * string "3.1 MB". + * + * The prefix units base is 1024 (i.e. 1 KB is 1024 bytes). + * + * This string should be freed with g_free() when not needed any longer. + * + * Returns: a newly-allocated formatted string containing a human + * readable file size + * + * Since: 2.16 + * + * Deprecated:2.30: This function is broken due to its use of SI + * suffixes to denote IEC units. Use g_format_size() instead. + */ +gchar * +g_format_size_for_display (goffset size) +{ + if (size < (goffset) KIBIBYTE_FACTOR) + return g_strdup_printf (g_dngettext(GETTEXT_PACKAGE, "%u byte", "%u bytes",(guint) size), (guint) size); + else + { + gdouble displayed_size; + + if (size < (goffset) MEBIBYTE_FACTOR) + { + displayed_size = (gdouble) size / (gdouble) KIBIBYTE_FACTOR; + return g_strdup_printf (_("%.1f KB"), displayed_size); + } + else if (size < (goffset) GIBIBYTE_FACTOR) + { + displayed_size = (gdouble) size / (gdouble) MEBIBYTE_FACTOR; + return g_strdup_printf (_("%.1f MB"), displayed_size); + } + else if (size < (goffset) TEBIBYTE_FACTOR) + { + displayed_size = (gdouble) size / (gdouble) GIBIBYTE_FACTOR; + return g_strdup_printf (_("%.1f GB"), displayed_size); + } + else if (size < (goffset) PEBIBYTE_FACTOR) + { + displayed_size = (gdouble) size / (gdouble) TEBIBYTE_FACTOR; + return g_strdup_printf (_("%.1f TB"), displayed_size); + } + else if (size < (goffset) EXBIBYTE_FACTOR) + { + displayed_size = (gdouble) size / (gdouble) PEBIBYTE_FACTOR; + return g_strdup_printf (_("%.1f PB"), displayed_size); + } + else + { + displayed_size = (gdouble) size / (gdouble) EXBIBYTE_FACTOR; + return g_strdup_printf (_("%.1f EB"), displayed_size); + } + } +} + #ifdef G_OS_WIN32 /** @@ -2633,17 +2467,6 @@ g_find_program_in_path (const gchar *program) return retval; } -#undef g_get_current_dir - -gchar* -g_get_current_dir (void) -{ - gchar *utf8_dir = g_get_current_dir_utf8 (); - gchar *dir = g_locale_from_utf8 (utf8_dir, -1, NULL, NULL, NULL); - g_free (utf8_dir); - return dir; -} - #undef g_get_user_name const gchar * diff --git a/glib/gutils.h b/glib/gutils.h index 18f6b41..b1c1460 100644 --- a/glib/gutils.h +++ b/glib/gutils.h @@ -36,30 +36,6 @@ G_BEGIN_DECLS -#ifdef G_OS_WIN32 - -/* On Win32, the canonical directory separator is the backslash, and - * the search path separator is the semicolon. Note that also the - * (forward) slash works as directory separator. - */ -#define G_DIR_SEPARATOR '\\' -#define G_DIR_SEPARATOR_S "\\" -#define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR || (c) == '/') -#define G_SEARCHPATH_SEPARATOR ';' -#define G_SEARCHPATH_SEPARATOR_S ";" - -#else /* !G_OS_WIN32 */ - -/* Unix */ - -#define G_DIR_SEPARATOR '/' -#define G_DIR_SEPARATOR_S "/" -#define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR) -#define G_SEARCHPATH_SEPARATOR ':' -#define G_SEARCHPATH_SEPARATOR_S ":" - -#endif /* !G_OS_WIN32 */ - /* Define G_VA_COPY() to do the right thing for copying va_list variables. * glibconfig.h may have already defined G_VA_COPY as va_copy or __va_copy. */ @@ -222,34 +198,24 @@ gint g_vsnprintf (gchar *string, gchar const *format, va_list args); -/* Check if a file name is an absolute path */ -gboolean g_path_is_absolute (const gchar *file_name); - -/* In case of absolute paths, skip the root part */ -const gchar * g_path_skip_root (const gchar *file_name); - -#ifndef G_DISABLE_DEPRECATED +void g_nullify_pointer (gpointer *nullify_location); -GLIB_DEPRECATED_FOR(g_path_get_basename) -const gchar * g_basename (const gchar *file_name); -#define g_dirname g_path_get_dirname +typedef enum +{ + G_FORMAT_SIZE_DEFAULT = 0, + G_FORMAT_SIZE_LONG_FORMAT = 1 << 0, + G_FORMAT_SIZE_IEC_UNITS = 1 << 1 +} GFormatSizeFlags; -#endif /* G_DISABLE_DEPRECATED */ +gchar *g_format_size_full (guint64 size, + GFormatSizeFlags flags); +gchar *g_format_size (guint64 size); -#ifndef __GTK_DOC_IGNORE__ -#ifdef G_OS_WIN32 -#define g_get_current_dir g_get_current_dir_utf8 -#endif +#ifndef G_DISABLE_DEPRECATED +GLIB_DEPRECATED_FOR(g_format_size) +gchar *g_format_size_for_display (goffset size); #endif -/* The returned strings are newly allocated with g_malloc() */ -gchar* g_get_current_dir (void); -gchar* g_path_get_basename (const gchar *file_name) G_GNUC_MALLOC; -gchar* g_path_get_dirname (const gchar *file_name) G_GNUC_MALLOC; - -/* Set the pointer at the specified location to NULL */ -void g_nullify_pointer (gpointer *nullify_location); - /** * GVoidFunc: *