summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-sysdeps.c
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2003-04-08 15:52:51 +0000
committerAlexander Larsson <alexl@redhat.com>2003-04-08 15:52:51 +0000
commitc5020ac870c5990a36c3576453cc23431213e8bf (patch)
tree8b5c4c5b884e9481d1ce17b9a24d9c1bbe094428 /dbus/dbus-sysdeps.c
parenta162febe6746269f51b3a16db5f6fb240001f828 (diff)
2003-04-08 Alexander Larsson <alexl@redhat.com>
Implemented recursive types, named types and new-style iters * bus/driver.c: * glib/test-thread-client.c: (thread_func): * glib/test-thread-server.c: (handle_test_message): * test/test-service.c: (handle_echo): Update to new api * dbus/Makefile.am: * dbus/dbus-dict.c: * dbus/dbus-dict.h: * dbus/dbus.h Remove DBusDict * dbus/dbus-internals.c: (_dbus_type_to_string): Update for new types. * dbus/dbus-marshal.[ch]: Implement recursive types and the new marshalling format. Remove hardcoded dict marshalling. Marshal named types. * dbus/dbus-message-builder.c: Add BYTE_ARRAY. Remove references to old types * dbus/dbus-message.[ch]: New non-refcounted iter API that supports recursive iters. Use iters for appending, including support for recursive iters. Add byte and named type support. Update everything to new marshalling formats. Add tests for new API. * dbus/dbus-protocol.h: Remove old array types. Add types: BYTE, ARRAY, DICT, NAMED * dbus/dbus-string.c: * dbus/dbus-sysdeps.c: Make parse_double locale safe. * dbus/dbus-test-main.c: Call setlocale. * dbus/dbus-test.c: Kill dict test * doc/dbus-specification.sgml: Update spec * test/data/incomplete-messages/missing-body.message: * test/data/invalid-messages/bad-boolean.message: * test/data/invalid-messages/bad-boolean-array.message: * test/data/invalid-messages/boolean-array-length-too-long.message-raw: * test/data/invalid-messages/boolean-has-no-value.message-raw: * test/data/invalid-messages/too-short-dict.message: * test/data/valid-messages/dict-simple.message: * test/data/valid-messages/dict.message: * test/data/valid-messages/emptiness.message: * test/data/valid-messages/lots-of-arguments.message: * test/data/valid-messages/no-padding.message: * test/data/valid-messages/recursive-types.message: Add missing NAME fields Fix up dicts & arrays * test/data/invalid-messages/dict-with-nil-value.message: Removed, this is not invalid anymore. * test/data/valid-messages/recursive-types.message: Add new test for deeply recursive types.
Diffstat (limited to 'dbus/dbus-sysdeps.c')
-rw-r--r--dbus/dbus-sysdeps.c188
1 files changed, 181 insertions, 7 deletions
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index df921b17..bb471876 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -39,6 +39,7 @@
#include <sys/un.h>
#include <pwd.h>
#include <time.h>
+#include <locale.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -1107,16 +1108,168 @@ _dbus_string_parse_uint (const DBusString *str,
return TRUE;
}
+static dbus_bool_t
+ascii_isspace (char c)
+{
+ return (c == ' ' ||
+ c == '\f' ||
+ c == '\n' ||
+ c == '\r' ||
+ c == '\t' ||
+ c == '\v');
+}
+
+static dbus_bool_t
+ascii_isdigit (char c)
+{
+ return c >= '0' && c <= '9';
+}
+
+static dbus_bool_t
+ascii_isxdigit (char c)
+{
+ return (ascii_isdigit (c) ||
+ (c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F'));
+}
+
+
+/* Calls strtod in a locale-independent fashion, by looking at
+ * the locale data and patching the decimal comma to a point.
+ *
+ * Relicensed from glib.
+ */
+static double
+ascii_strtod (const char *nptr,
+ char **endptr)
+{
+ char *fail_pos;
+ double val;
+ struct lconv *locale_data;
+ const char *decimal_point;
+ int decimal_point_len;
+ const char *p, *decimal_point_pos;
+ const char *end = NULL; /* Silence gcc */
+
+ fail_pos = NULL;
+
+ locale_data = localeconv ();
+ decimal_point = locale_data->decimal_point;
+ decimal_point_len = strlen (decimal_point);
+
+ _dbus_assert (decimal_point_len != 0);
+
+ decimal_point_pos = NULL;
+ if (decimal_point[0] != '.' ||
+ decimal_point[1] != 0)
+ {
+ p = nptr;
+ /* Skip leading space */
+ while (ascii_isspace (*p))
+ p++;
+
+ /* Skip leading optional sign */
+ if (*p == '+' || *p == '-')
+ p++;
+
+ if (p[0] == '0' &&
+ (p[1] == 'x' || p[1] == 'X'))
+ {
+ p += 2;
+ /* HEX - find the (optional) decimal point */
+
+ while (ascii_isxdigit (*p))
+ p++;
+
+ if (*p == '.')
+ {
+ decimal_point_pos = p++;
+
+ while (ascii_isxdigit (*p))
+ p++;
+
+ if (*p == 'p' || *p == 'P')
+ p++;
+ if (*p == '+' || *p == '-')
+ p++;
+ while (ascii_isdigit (*p))
+ p++;
+ end = p;
+ }
+ }
+ else
+ {
+ while (ascii_isdigit (*p))
+ p++;
+
+ if (*p == '.')
+ {
+ decimal_point_pos = p++;
+
+ while (ascii_isdigit (*p))
+ p++;
+
+ if (*p == 'e' || *p == 'E')
+ p++;
+ if (*p == '+' || *p == '-')
+ p++;
+ while (ascii_isdigit (*p))
+ p++;
+ end = p;
+ }
+ }
+ /* For the other cases, we need not convert the decimal point */
+ }
+
+ /* Set errno to zero, so that we can distinguish zero results
+ and underflows */
+ errno = 0;
+
+ if (decimal_point_pos)
+ {
+ char *copy, *c;
+
+ /* We need to convert the '.' to the locale specific decimal point */
+ copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
+
+ c = copy;
+ memcpy (c, nptr, decimal_point_pos - nptr);
+ c += decimal_point_pos - nptr;
+ memcpy (c, decimal_point, decimal_point_len);
+ c += decimal_point_len;
+ memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
+ c += end - (decimal_point_pos + 1);
+ *c = 0;
+
+ val = strtod (copy, &fail_pos);
+
+ if (fail_pos)
+ {
+ if (fail_pos > decimal_point_pos)
+ fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
+ else
+ fail_pos = (char *)nptr + (fail_pos - copy);
+ }
+
+ dbus_free (copy);
+
+ }
+ else
+ val = strtod (nptr, &fail_pos);
+
+ if (endptr)
+ *endptr = fail_pos;
+
+ return val;
+}
+
+
/**
* Parses a floating point number contained in a DBusString. Either
* return parameter may be #NULL if you aren't interested in it. The
* integer is parsed and stored in value_return. Return parameters are
* not initialized if the function returns #FALSE.
*
- * @todo this function is currently locale-dependent. Should
- * ask alexl to relicense g_ascii_strtod() code and put that in
- * here instead, so it's locale-independent.
- *
* @param str the string
* @param start the byte index of the start of the float
* @param value_return return location of the float value or #NULL
@@ -1133,14 +1286,12 @@ _dbus_string_parse_double (const DBusString *str,
const char *p;
char *end;
- _dbus_warn ("_dbus_string_parse_double() needs to be made locale-independent\n");
-
p = _dbus_string_get_const_data_len (str, start,
_dbus_string_get_length (str) - start);
end = NULL;
errno = 0;
- v = strtod (p, &end);
+ v = ascii_strtod (p, &end);
if (end == NULL || end == p || errno != 0)
return FALSE;
@@ -3173,6 +3324,10 @@ check_path_absolute (const char *path,
dbus_bool_t
_dbus_sysdeps_test (void)
{
+ DBusString str;
+ double val;
+ int pos;
+
check_dirname ("foo", ".");
check_dirname ("foo/bar", "foo");
check_dirname ("foo//bar", "foo");
@@ -3192,6 +3347,25 @@ _dbus_sysdeps_test (void)
check_dirname ("///", "/");
check_dirname ("", ".");
+
+ _dbus_string_init_const (&str, "3.5");
+ if (!_dbus_string_parse_double (&str,
+ 0, &val, &pos))
+ {
+ _dbus_warn ("Failed to parse double");
+ exit (1);
+ }
+ if (val != 3.5)
+ {
+ _dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
+ exit (1);
+ }
+ if (pos != 3)
+ {
+ _dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
+ exit (1);
+ }
+
check_path_absolute ("/", TRUE);
check_path_absolute ("/foo", TRUE);
check_path_absolute ("", FALSE);