[glib] Reshuffle some functions between gutils and gfileutils



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]