diff options
author | Allen Winter <allen.winter@kdab.com> | 2022-06-09 12:41:41 -0400 |
---|---|---|
committer | Allen Winter <allen.winter@kdab.com> | 2022-06-11 08:52:33 -0400 |
commit | b0aa3088b8b7aeafba3624c957e8eea3ad72b7a7 (patch) | |
tree | 82fbaced4e5cf3149f3ef3f45e4b97d34bd43f43 /src/libical | |
parent | 29b385d07c399026f56fce4540c95fc1e7c6cdc3 (diff) | |
download | libical-git-b0aa3088b8b7aeafba3624c957e8eea3ad72b7a7.tar.gz |
Internally represent GEO properties as text
This allows arbitrary precision for the GEO values
fixes: #531
Diffstat (limited to 'src/libical')
-rw-r--r-- | src/libical/icalderivedvalue.c.in | 5 | ||||
-rw-r--r-- | src/libical/icaltypes.h | 5 | ||||
-rw-r--r-- | src/libical/icalvalue.c | 40 |
3 files changed, 25 insertions, 25 deletions
diff --git a/src/libical/icalderivedvalue.c.in b/src/libical/icalderivedvalue.c.in index 1b87c353..8dde33eb 100644 --- a/src/libical/icalderivedvalue.c.in +++ b/src/libical/icalderivedvalue.c.in @@ -430,9 +430,8 @@ void icalvalue_set_geo(icalvalue *value, struct icalgeotype v) struct icalgeotype icalvalue_get_geo(const icalvalue *value) { struct icalgeotype gt; - - gt.lat = 255.0; - gt.lon = 255.0; + strcpy(gt.lat, "255.0"); + strcpy(gt.lon, "255.0"); icalerror_check_arg_rx((value != 0), "value", gt); icalerror_check_value_type(value, ICAL_GEO_VALUE); diff --git a/src/libical/icaltypes.h b/src/libical/icaltypes.h index d606bc37..bad766b5 100644 --- a/src/libical/icaltypes.h +++ b/src/libical/icaltypes.h @@ -22,10 +22,11 @@ struct icaldatetimeperiodtype struct icalperiodtype period; }; +#define ICAL_GEO_LEN 16 struct icalgeotype { - double lat; - double lon; + char lat[ICAL_GEO_LEN]; + char lon[ICAL_GEO_LEN]; }; struct icaltriggertype diff --git a/src/libical/icalvalue.c b/src/libical/icalvalue.c index 6a15d788..c41a69a3 100644 --- a/src/libical/icalvalue.c +++ b/src/libical/icalvalue.c @@ -357,23 +357,20 @@ static icalvalue *icalvalue_new_enum(icalvalue_kind kind, int x_type, const char } /** - * Transforms a simple float number string into a double. + * Extracts a simple floating point number as a substring. * The decimal separator (if any) of the double has to be '.' * The code is locale *independent* and does *not* change the locale. * It should be thread safe. - * If you want a code that does the same job with a decimal separator - * dependent on the current locale, then use strtof() from libc. */ -static int simple_str_to_double(const char *from, double *result, char **to) +static int simple_str_to_doublestr(const char *from, char *result, char **to) { -#define TMP_NUM_SIZE 100 char *start = NULL, *end = NULL, *cur = (char *)from; - char tmp_buf[TMP_NUM_SIZE + 1]; /*hack */ #if !defined(HAVE_GETNUMBERFORMAT) struct lconv *loc_data = localeconv(); #endif int i = 0; + double dtest; /*sanity checks */ if (!from || !result) { @@ -385,8 +382,7 @@ static int simple_str_to_double(const char *from, double *result, char **to) cur++; start = cur; - /* copy the part that looks like a double into tmp_buf - * so that we can call strtof() on it. + /* copy the part that looks like a double into result. * during the copy, we give ourselves a chance to convert the '.' * into the decimal separator of the current locale. */ @@ -398,7 +394,6 @@ static int simple_str_to_double(const char *from, double *result, char **to) /*huh hoh, number is too big. getting out */ return 1; } - memset(tmp_buf, 0, TMP_NUM_SIZE + 1); /* copy the float number string into tmp_buf, and take * care to have the (optional) decimal separator be the one @@ -409,18 +404,22 @@ static int simple_str_to_double(const char *from, double *result, char **to) if (start[i] == '.' && loc_data && loc_data->decimal_point && loc_data->decimal_point[0] && loc_data->decimal_point[0] != '.') { /*replace '.' by the digit separator of the current locale */ - tmp_buf[i] = loc_data->decimal_point[0]; + result[i] = loc_data->decimal_point[0]; } else { - tmp_buf[i] = start[i]; + result[i] = start[i]; } } #else - GetNumberFormat(LOCALE_SYSTEM_DEFAULT, 0, start, NULL, tmp_buf, TMP_NUM_SIZE); + GetNumberFormat(LOCALE_SYSTEM_DEFAULT, 0, start, NULL, result, TMP_NUM_SIZE); #endif if (to) { *to = end; } - *result = atof(tmp_buf); + + /* now try to convert to a floating point number, to check for validity only */ + if (sscanf(result, "%lf", &dtest) != 1) { + return 1; + } return 0; } @@ -580,13 +579,14 @@ static icalvalue *icalvalue_new_from_string_with_error(icalvalue_kind kind, case ICAL_GEO_VALUE: { char *cur = NULL; - struct icalgeotype geo = { 0.0, 0.0 }; + struct icalgeotype geo; + memset(geo.lat, 0, ICAL_GEO_LEN); + memset(geo.lon, 0, ICAL_GEO_LEN); - if (simple_str_to_double(str, &geo.lat, &cur)) { + if (simple_str_to_doublestr(str, geo.lat, &cur)) { goto geo_parsing_error; } - - /*skip white spaces */ + /* skip white spaces */ while (cur && isspace((int)*cur)) { ++cur; } @@ -598,12 +598,12 @@ static icalvalue *icalvalue_new_from_string_with_error(icalvalue_kind kind, ++cur; - /*skip white spaces */ + /* skip white spaces */ while (cur && isspace((int)*cur)) { ++cur; } - if (simple_str_to_double(cur, &geo.lon, &cur)) { + if (simple_str_to_doublestr(cur, geo.lon, &cur)) { goto geo_parsing_error; } value = icalvalue_new_geo(geo); @@ -1102,7 +1102,7 @@ static char *icalvalue_geo_as_ical_string_r(const icalvalue *value) str = (char *)icalmemory_new_buffer(80); - snprintf(str, 80, "%f;%f", data.lat, data.lon); + snprintf(str, 80, "%s;%s", data.lat, data.lon); /* restore saved locale */ (void)setlocale(LC_NUMERIC, old_locale); |