Bug 556921 – gpoll.h breaks hal compilation
[platform/upstream/glib.git] / glib / gstrfuncs.c
index 7ab4d64..f45bbf7 100644 (file)
@@ -46,6 +46,7 @@
 #include "glib.h"
 #include "gprintf.h"
 #include "gprintfint.h"
+#include "glibintl.h"
 
 #include "galias.h"
 
@@ -331,10 +332,12 @@ g_strtod (const gchar *nptr,
  *           the last character used in the conversion.
  * 
  * Converts a string to a #gdouble value.
+ *
  * This function behaves like the standard strtod() function
- * does in the C locale. It does this without actually
- * changing the current locale, since that would not be
- * thread-safe.
+ * does in the C locale. It does this without actually changing 
+ * the current locale, since that would not be thread-safe. 
+ * A limitation of the implementation is that this function
+ * will still accept localized versions of infinities and NANs. 
  *
  * This function is typically used when reading configuration
  * files or other non-user input that should be locale independent.
@@ -610,13 +613,12 @@ g_ascii_formatd (gchar       *buffer,
        {
          *p = '.';
          p++;
-         if (decimal_point_len > 1) {
-           rest_len = strlen (p + (decimal_point_len-1));
-           memmove (p, p + (decimal_point_len-1),
-                    rest_len);
-           p[rest_len] = 0;
-           
-         }
+         if (decimal_point_len > 1) 
+            {
+             rest_len = strlen (p + (decimal_point_len-1));
+             memmove (p, p + (decimal_point_len-1), rest_len);
+             p[rest_len] = 0;
+           }
        }
     }
   
@@ -624,10 +626,10 @@ g_ascii_formatd (gchar       *buffer,
 }
 
 static guint64
-g_parse_long_long (const gchar *nptr,
-                  gchar      **endptr,
-                  guint        base,
-                  gboolean    *negative)
+g_parse_long_long (const gchar  *nptr,
+                  const gchar **endptr,
+                  guint         base,
+                  gboolean     *negative)
 {
   /* this code is based on on the strtol(3) code from GNU libc released under
    * the GNU Lesser General Public License.
@@ -651,9 +653,12 @@ g_parse_long_long (const gchar *nptr,
   
   g_return_val_if_fail (nptr != NULL, 0);
   
+  *negative = FALSE;
   if (base == 1 || base > 36)
     {
       errno = EINVAL;
+      if (endptr)
+       *endptr = nptr;
       return 0;
     }
   
@@ -667,7 +672,6 @@ g_parse_long_long (const gchar *nptr,
     goto noconv;
   
   /* Check for a sign.  */
-  *negative = FALSE;
   if (*s == '-')
     {
       *negative = TRUE;
@@ -725,7 +729,7 @@ g_parse_long_long (const gchar *nptr,
   /* Store in ENDPTR the address of one character
      past the last character we converted.  */
   if (endptr)
-    *endptr = (gchar*) s;
+    *endptr = s;
   
   if (G_UNLIKELY (overflow))
     {
@@ -744,10 +748,10 @@ g_parse_long_long (const gchar *nptr,
     {
       if (save - nptr >= 2 && TOUPPER (save[-1]) == 'X'
          && save[-2] == '0')
-       *endptr = (gchar*) &save[-1];
+       *endptr = &save[-1];
       else
        /*  There was no number to convert.  */
-       *endptr = (gchar*) nptr;
+       *endptr = nptr;
     }
   return 0;
 }
@@ -788,7 +792,7 @@ g_ascii_strtoull (const gchar *nptr,
   gboolean negative;
   guint64 result;
 
-  result = g_parse_long_long (nptr, endptr, base, &negative);
+  result = g_parse_long_long (nptr, (const gchar **) endptr, base, &negative);
 
   /* Return the result of the appropriate sign.  */
   return negative ? -result : result;
@@ -830,7 +834,7 @@ g_ascii_strtoll (const gchar *nptr,
   gboolean negative;
   guint64 result;
 
-  result = g_parse_long_long (nptr, endptr, base, &negative);
+  result = g_parse_long_long (nptr, (const gchar **) endptr, base, &negative);
 
   if (negative && result > (guint64) G_MININT64)
     {
@@ -842,6 +846,8 @@ g_ascii_strtoll (const gchar *nptr,
       errno = ERANGE;
       return G_MAXINT64;
     }
+  else if (negative)
+    return - (gint64) result;
   else
     return (gint64) result;
 }
@@ -2286,13 +2292,10 @@ g_strsplit (const gchar *string,
       while (--max_tokens && s)
        {
          gsize len;     
-         gchar *new_string;
 
          len = s - remainder;
-         new_string = g_new (gchar, len + 1);
-         strncpy (new_string, remainder, len);
-         new_string[len] = 0;
-         string_list = g_slist_prepend (string_list, new_string);
+         string_list = g_slist_prepend (string_list,
+                                        g_strndup (remainder, len));
          n++;
          remainder = s + delimiter_len;
          s = strstr (remainder, delimiter);
@@ -2429,8 +2432,8 @@ g_strfreev (gchar **str_array)
     {
       int i;
 
-      for(i = 0; str_array[i] != NULL; i++)
-       g_free(str_array[i]);
+      for (i = 0; str_array[i] != NULL; i++)
+       g_free (str_array[i]);
 
       g_free (str_array);
     }
@@ -2575,7 +2578,9 @@ g_strjoin (const gchar  *separator,
 /**
  * g_strstr_len:
  * @haystack: a string.
- * @haystack_len: the maximum length of @haystack.
+ * @haystack_len: the maximum length of @haystack. Note that -1 is
+ * a valid length, if @haystack is nul-terminated, meaning it will
+ * search through the whole string.
  * @needle: the string to search for.
  *
  * Searches the string @haystack for the first occurrence
@@ -2592,7 +2597,7 @@ g_strstr_len (const gchar *haystack,
 {
   g_return_val_if_fail (haystack != NULL, NULL);
   g_return_val_if_fail (needle != NULL, NULL);
-  
+
   if (haystack_len < 0)
     return strstr (haystack, needle);
   else
@@ -2610,7 +2615,7 @@ g_strstr_len (const gchar *haystack,
       
       end = haystack + haystack_len - needle_len;
       
-      while (*p && p <= end)
+      while (p <= end && *p)
        {
          for (i = 0; i < needle_len; i++)
            if (p[i] != needle[i])
@@ -2843,5 +2848,256 @@ g_strv_length (gchar **str_array)
   return i;
 }
 
+
+/**
+ * g_dpgettext:
+ * @domain: the translation domain to use, or %NULL to use
+ *   the domain set with textdomain()
+ * @msgctxtid: a combined message context and message id, separated
+ *   by a \004 character
+ * @msgidoffset: the offset of the message id in @msgctxid
+ *
+ * This function is a variant of g_dgettext() which supports
+ * a disambiguating message context. GNU gettext uses the
+ * '\004' character to separate the message context and
+ * message id in @msgctxtid.
+ * If 0 is passed as @msgidoffset, this function will fall back to
+ * trying to use the deprecated convention of using "|" as a separation
+ * character.
+ *
+ * This uses g_dgettext() internally.  See that functions for differences
+ * with dgettext() proper.
+ *
+ * Applications should normally not use this function directly,
+ * but use the C_() macro for translations with context.
+ *
+ * Returns: The translated string
+ *
+ * Since: 2.16
+ */
+G_CONST_RETURN gchar *
+g_dpgettext (const gchar *domain, 
+             const gchar *msgctxtid, 
+             gsize        msgidoffset)
+{
+  const gchar *translation;
+  gchar *sep;
+
+  translation = g_dgettext (domain, msgctxtid);
+
+  if (translation == msgctxtid)
+    {
+      if (msgidoffset > 0)
+        return msgctxtid + msgidoffset;
+
+      sep = strchr (msgctxtid, '|');
+      if (sep)
+        {
+          /* try with '\004' instead of '|', in case
+           * xgettext -kQ_:1g was used
+           */
+          gchar *tmp = g_alloca (strlen (msgctxtid) + 1);
+          strcpy (tmp, msgctxtid);
+          tmp[sep - msgctxtid] = '\004';
+
+          translation = g_dgettext (domain, tmp);
+   
+          if (translation == tmp)
+            return sep + 1; 
+        }
+    }
+
+  return translation;
+}
+
+/* This function is taken from gettext.h 
+ * GNU gettext uses '\004' to separate context and msgid in .mo files.
+ */
+/**
+ * g_dpgettext2:
+ * @domain: the translation domain to use, or %NULL to use
+ *   the domain set with textdomain()
+ * @context: the message context
+ * @msgid: the message
+ *
+ * This function is a variant of g_dgettext() which supports
+ * a disambiguating message context. GNU gettext uses the
+ * '\004' character to separate the message context and
+ * message id in @msgctxtid.
+ *
+ * This uses g_dgettext() internally.  See that functions for differences
+ * with dgettext() proper.
+ *
+ * This function differs from C_() in that it is not a macro and 
+ * thus you may use non-string-literals as context and msgid arguments.
+ *
+ * Returns: The translated string
+ *
+ * Since: 2.18
+ */
+G_CONST_RETURN char *
+g_dpgettext2 (const char *domain,
+              const char *msgctxt,
+              const char *msgid)
+{
+  size_t msgctxt_len = strlen (msgctxt) + 1;
+  size_t msgid_len = strlen (msgid) + 1;
+  const char *translation;
+  char* msg_ctxt_id;
+
+  msg_ctxt_id = g_alloca (msgctxt_len + msgid_len);
+
+  memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
+  msg_ctxt_id[msgctxt_len - 1] = '\004';
+  memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
+
+  translation = g_dgettext (domain, msg_ctxt_id);
+
+  if (translation == msg_ctxt_id) 
+    {
+      /* try the old way of doing message contexts, too */
+      msg_ctxt_id[msgctxt_len - 1] = '|';
+      translation = g_dgettext (domain, msg_ctxt_id);
+
+      if (translation == msg_ctxt_id)
+        return msgid;
+    }
+
+  return translation;
+}
+
+static gboolean
+_g_dgettext_should_translate (void)
+{
+  static gsize translate = 0;
+  enum {
+    SHOULD_TRANSLATE = 1,
+    SHOULD_NOT_TRANSLATE = 2
+  };
+
+  if (G_UNLIKELY (g_once_init_enter (&translate)))
+    {
+      gboolean should_translate = TRUE;
+
+      const char *default_domain     = textdomain (NULL);
+      const char *translator_comment = gettext ("");
+#ifndef G_OS_WIN32
+      const char *translate_locale   = setlocale (LC_MESSAGES, NULL);
+#else
+      const char *translate_locale   = g_win32_getlocale ();
+#endif
+      /* We should NOT translate only if all the following hold:
+       *   - user has called textdomain() and set textdomain to non-default
+       *   - default domain has no translations
+       *   - locale does not start with "en_" and is not "C"
+       *
+       * Rationale:
+       *   - If text domain is still the default domain, maybe user calls
+       *     it later. Continue with old behavior of translating.
+       *   - If locale starts with "en_", we can continue using the
+       *     translations even if the app doesn't have translations for
+       *     this locale.  That is, en_UK and en_CA for example.
+       *   - If locale is "C", maybe user calls setlocale(LC_ALL,"") later.
+       *     Continue with old behavior of translating.
+       */
+      if (0 != strcmp (default_domain, "messages") &&
+         '\0' == *translator_comment &&
+         0 != strncmp (translate_locale, "en_", 3) &&
+         0 != strcmp (translate_locale, "C"))
+        should_translate = FALSE;
+      
+      g_once_init_leave (&translate,
+                        should_translate ?
+                        SHOULD_TRANSLATE :
+                        SHOULD_NOT_TRANSLATE);
+    }
+
+  return translate == SHOULD_TRANSLATE;
+}
+
+/**
+ * g_dgettext:
+ * @domain: the translation domain to use, or %NULL to use
+ *   the domain set with textdomain()
+ * @msgid: message to translate
+ *
+ * This function is a wrapper of dgettext() which does not translate
+ * the message if the default domain as set with textdomain() has no
+ * translations for the current locale.
+ *
+ * The advantage of using this function over dgettext() proper is that
+ * libraries using this function (like GTK+) will not use translations
+ * if the application using the library does not have translations for
+ * the current locale.  This results in a consistent English-only
+ * interface instead of one having partial translations.  For this
+ * feature to work, the call to textdomain() and setlocale() should
+ * precede any g_dgettext() invocations.  For GTK+, it means calling
+ * textdomain() before gtk_init or its variants.
+ *
+ * This function disables translations if and only if upon its first
+ * call all the following conditions hold:
+ * <itemizedlist>
+ * <listitem>@domain is not %NULL</listitem>
+ * <listitem>textdomain() has been called to set a default text domain</listitem>
+ * <listitem>there is no translations available for the default text domain
+ *           and the current locale</listitem>
+ * <listitem>current locale is not "C" or any English locales (those
+ *           starting with "en_")</listitem>
+ * </itemizedlist>
+ *
+ * Note that this behavior may not be desired for example if an application
+ * has its untranslated messages in a language other than English.  In those
+ * cases the application should call textdomain() after initializing GTK+.
+ *
+ * Applications should normally not use this function directly,
+ * but use the _() macro for translations.
+ *
+ * Returns: The translated string
+ *
+ * Since: 2.18
+ */
+G_CONST_RETURN gchar *
+g_dgettext (const gchar *domain,
+            const gchar *msgid)
+{
+  if (domain && G_UNLIKELY (!_g_dgettext_should_translate ()))
+    return msgid;
+
+  return dgettext (domain, msgid);
+}
+
+/**
+ * g_dngettext:
+ * @domain: the translation domain to use, or %NULL to use
+ *   the domain set with textdomain()
+ * @msgid: message to translate
+ * @msgid_plural: plural form of the message
+ * @n: the quantity for which translation is needed
+ *
+ * This function is a wrapper of dngettext() which does not translate
+ * the message if the default domain as set with textdomain() has no
+ * translations for the current locale.
+ *
+ * See g_dgettext() for details of how this differs from dngettext()
+ * proper.
+ *
+ * Returns: The translated string
+ *
+ * Since: 2.18
+ */
+G_CONST_RETURN gchar *
+g_dngettext (const gchar *domain,
+             const gchar *msgid,
+             const gchar *msgid_plural,
+            gulong       n)
+{
+  if (domain && G_UNLIKELY (!_g_dgettext_should_translate ()))
+    return n == 1 ? msgid : msgid_plural;
+
+  return dngettext (domain, msgid, msgid_plural, n);
+}
+
+
 #define __G_STRFUNCS_C__
 #include "galiasdef.c"