[glib] Reshuffle some functions between gutils and gfileutils
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] Reshuffle some functions between gutils and gfileutils
- Date: Mon, 17 Oct 2011 05:31:36 +0000 (UTC)
commit 67bf0083db329d02ad2e99a8f4586ebfdcba1dd2
Author: Matthias Clasen <mclasen redhat com>
Date: Mon Oct 17 01:30:31 2011 -0400
Reshuffle some functions between gutils and gfileutils
Move filename-related functions to gfileutils, and move
size formatting functions to gutils.
glib/gfileutils.c | 709 ++++++++++++++++++++++++++++++++++-------------------
glib/gfileutils.h | 101 +++++---
glib/gutils.c | 679 +++++++++++++++++++--------------------------------
glib/gutils.h | 60 +----
4 files changed, 779 insertions(+), 770 deletions(-)
---
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 <windows.h>
# 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:
*
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]