Handle numbers like 1e1, nan, -infinity. Also try harder to preserve
[platform/upstream/glib.git] / glib / gstrfuncs.c
index 5644519..afb0223 100644 (file)
@@ -43,6 +43,7 @@
 #include <signal.h>
 #endif
 
+#include "galias.h"
 #include "glib.h"
 #include "gprintf.h"
 #include "gprintfint.h"
@@ -334,6 +335,7 @@ g_ascii_strtod (const gchar *nptr,
   int decimal_point_len;
   const char *p, *decimal_point_pos;
   const char *end = NULL; /* Silence gcc */
+  int strtod_errno;
 
   g_return_val_if_fail (nptr != NULL, 0);
 
@@ -346,6 +348,8 @@ g_ascii_strtod (const gchar *nptr,
   g_assert (decimal_point_len != 0);
   
   decimal_point_pos = NULL;
+  end = NULL;
+
   if (decimal_point[0] != '.' || 
       decimal_point[1] != 0)
     {
@@ -368,48 +372,43 @@ g_ascii_strtod (const gchar *nptr,
            p++;
          
          if (*p == '.')
-           {
-             decimal_point_pos = p++;
-             
-             while (g_ascii_isxdigit (*p))
-               p++;
+           decimal_point_pos = p++;
              
-             if (*p == 'p' || *p == 'P')
-               p++;
-             if (*p == '+' || *p == '-')
-               p++;
-             while (g_ascii_isdigit (*p))
-               p++;
-           }
+         while (g_ascii_isxdigit (*p))
+           p++;
+         
+         if (*p == 'p' || *p == 'P')
+           p++;
+         if (*p == '+' || *p == '-')
+           p++;
+         while (g_ascii_isdigit (*p))
+           p++;
+
+         end = p;
        }
-      else
+      else if (g_ascii_isdigit (*p))
        {
          while (g_ascii_isdigit (*p))
            p++;
          
          if (*p == '.')
-           {
-             decimal_point_pos = p++;
-             
-             while (g_ascii_isdigit (*p))
-               p++;
-             
-             if (*p == 'e' || *p == 'E')
-               p++;
-             if (*p == '+' || *p == '-')
-               p++;
-             while (g_ascii_isdigit (*p))
-               p++;
-           }
+           decimal_point_pos = p++;
+         
+         while (g_ascii_isdigit (*p))
+           p++;
+         
+         if (*p == 'e' || *p == 'E')
+           p++;
+         if (*p == '+' || *p == '-')
+           p++;
+         while (g_ascii_isdigit (*p))
+           p++;
+
+         end = p;
        }
       /* For the other cases, we need not convert the decimal point */
-      end = p;
     }
 
-  /* Set errno to zero, so that we can distinguish zero results
-     and underflows */
-  errno = 0;
-  
   if (decimal_point_pos)
     {
       char *copy, *c;
@@ -426,7 +425,9 @@ g_ascii_strtod (const gchar *nptr,
       c += end - (decimal_point_pos + 1);
       *c = 0;
 
+      errno = 0;
       val = strtod (copy, &fail_pos);
+      strtod_errno = errno;
 
       if (fail_pos)
        {
@@ -439,8 +440,7 @@ g_ascii_strtod (const gchar *nptr,
       g_free (copy);
          
     }
-  else if (decimal_point[0] != '.' ||
-          decimal_point[1] != 0)
+  else if (end)
     {
       char *copy;
       
@@ -448,8 +448,10 @@ g_ascii_strtod (const gchar *nptr,
       memcpy (copy, nptr, end - nptr);
       *(copy + (end - (char *)nptr)) = 0;
       
+      errno = 0;
       val = strtod (copy, &fail_pos);
-      
+      strtod_errno = errno;
+
       if (fail_pos)
        {
          fail_pos = (char *)nptr + (fail_pos - copy);
@@ -459,12 +461,16 @@ g_ascii_strtod (const gchar *nptr,
     }
   else
     {
+      errno = 0;
       val = strtod (nptr, &fail_pos);
+      strtod_errno = errno;
     }
 
   if (endptr)
     *endptr = fail_pos;
-  
+
+  errno = strtod_errno;
+
   return val;
 }
 
@@ -1875,7 +1881,7 @@ g_strcasecmp (const gchar *s1,
 gint
 g_strncasecmp (const gchar *s1,
               const gchar *s2,
-              gsize n)     
+              guint n)     
 {
 #ifdef HAVE_STRNCASECMP
   return strncasecmp (s1, s2, n);
@@ -2207,11 +2213,11 @@ g_strsplit (const gchar *string,
  * contain any of the characters in @delimiters. If @max_tokens is reached, the
  * remainder is appended to the last token.
  *
- * For example the result of g_strtokenize ("abc:def/ghi", ":/", -1) is a
+ * For example the result of g_strsplit_set ("abc:def/ghi", ":/", -1) is a
  * %NULL-terminated vector containing the three strings "abc", "def", 
  * and "ghi".
  *
- * The result if g_strtokenize (":def/ghi:", ":/", -1) is a %NULL-terminated
+ * The result if g_strsplit_set (":def/ghi:", ":/", -1) is a %NULL-terminated
  * vector containing the four strings "", "def", "ghi", and "".
  * 
  * As a special case, the result of splitting the empty string "" is an empty
@@ -2219,7 +2225,7 @@ g_strsplit (const gchar *string,
  * special case is that being able to represent a empty vector is typically
  * more useful than consistent handling of empty elements. If you do need
  * to represent empty elements, you'll need to check for the empty string
- * before calling g_strsplit().
+ * before calling g_strsplit_set().
  *
  * Note that this function works on bytes not characters, so it can't be used 
  * to delimit UTF-8 strings for anything but ASCII characters.
@@ -2696,3 +2702,28 @@ g_strip_context  (const gchar *msgid,
   
   return msgval;
 }
+
+
+/**
+ * g_strv_length:
+ * @str_array: a %NULL-terminated array of strings.
+ * 
+ * Returns the length of the given %NULL-terminated 
+ * string array @str_array.
+ * 
+ * Return value: length of @str_array.
+ *
+ * Since: 2.6
+ **/
+guint
+g_strv_length (gchar **str_array)
+{
+  guint i = 0;
+
+  g_return_val_if_fail (str_array != NULL, 0);
+
+  while (str_array[i])
+    ++i;
+
+  return i;
+}