[PATCH v9 1/7] JSON: Add double type support
Allen Ye
allen.ye at mediatek.com
Mon Dec 1 03:10:36 PST 2025
Add support for the 'double' type to the JSON parser. This is required
by the AFC feature to handle floating-point values such as geolocation,
Power Spectral Density (PSD) and EIRP in its JSON communication.
Signed-off-by: Allen Ye <allen.ye at mediatek.com>
---
src/utils/json.c | 137 +++++++++++++++++++++++++++++++++++++++--------
src/utils/json.h | 3 ++
2 files changed, 118 insertions(+), 22 deletions(-)
diff --git a/src/utils/json.c b/src/utils/json.c
index 5523f284d..fce2940a8 100644
--- a/src/utils/json.c
+++ b/src/utils/json.c
@@ -157,24 +157,74 @@ fail:
}
-static int json_parse_number(const char **json_pos, const char *end,
- int *ret_val)
+static size_t json_get_number_len(const char *json_pos, const char *end,
+ bool *is_double)
{
- const char *pos = *json_pos;
+ const char *pos = json_pos;
size_t len;
- char *str;
for (; pos < end; pos++) {
- if (*pos != '-' && (*pos < '0' || *pos > '9')) {
+ switch (*pos) {
+ case '.':
+ case 'e':
+ case 'E':
+ *is_double = true;
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ continue;
+ default:
pos--;
break;
}
+ break;
}
if (pos == end)
pos--;
- if (pos < *json_pos)
+ if (pos < json_pos)
+ return 0;
+ len = pos - json_pos + 1;
+
+ return len;
+}
+
+
+static int json_parse_double(const char **json_pos, size_t len,
+ double *ret_val)
+{
+ char *str;
+ char *endptr;
+
+ str = os_malloc(len + 1);
+ if (!str)
+ return -1;
+ os_memcpy(str, *json_pos, len);
+ str[len] = '\0';
+
+ *ret_val = strtod(str, &endptr);
+ if (endptr == str) {
+ os_free(str);
return -1;
- len = pos - *json_pos + 1;
+ }
+ os_free(str);
+ *json_pos += len - 1;
+ return 0;
+}
+
+
+static int json_parse_number(const char **json_pos, size_t len,
+ int *ret_val)
+{
+ char *str;
+
str = os_malloc(len + 1);
if (!str)
return -1;
@@ -183,7 +233,7 @@ static int json_parse_number(const char **json_pos, const char *end,
*ret_val = atoi(str);
os_free(str);
- *json_pos = pos;
+ *json_pos += len - 1;
return 0;
}
@@ -223,8 +273,11 @@ struct json_token * json_parse(const char *data, size_t data_len)
const char *pos, *end;
char *str;
int num;
+ double dnum;
+ bool is_double;
unsigned int depth = 0;
unsigned int tokens = 0;
+ size_t len;
pos = data;
end = data + data_len;
@@ -421,33 +474,65 @@ struct json_token * json_parse(const char *data, size_t data_len)
case '8':
case '9':
/* number */
- if (json_parse_number(&pos, end, &num) < 0)
+ is_double = false;
+ len = json_get_number_len(pos, end, &is_double);
+ if (!len)
goto fail;
+ if (is_double) {
+ if (json_parse_double(&pos, len, &dnum) < 0)
+ goto fail;
+ } else {
+ if (json_parse_number(&pos, len, &num) < 0)
+ goto fail;
+ }
+
if (!curr_token) {
token = json_alloc_token(&tokens);
if (!token)
goto fail;
- token->type = JSON_NUMBER;
- token->number = num;
+ if (is_double) {
+ token->dnumber = dnum;
+ token->type = JSON_DOUBLE;
+ } else {
+ token->number = num;
+ token->type = JSON_NUMBER;
+ }
token->state = JSON_COMPLETED;
} else if (curr_token->state == JSON_WAITING_VALUE) {
- curr_token->number = num;
curr_token->state = JSON_COMPLETED;
- curr_token->type = JSON_NUMBER;
- wpa_printf(MSG_MSGDUMP,
- "JSON: Number value: '%s' = '%d'",
- curr_token->name,
- curr_token->number);
+ if (is_double) {
+ curr_token->dnumber = dnum;
+ curr_token->type = JSON_DOUBLE;
+ wpa_printf(MSG_MSGDUMP,
+ "JSON: Double value: '%s' = '%f'",
+ curr_token->name,
+ curr_token->dnumber);
+ } else {
+ curr_token->number = num;
+ curr_token->type = JSON_NUMBER;
+ wpa_printf(MSG_MSGDUMP,
+ "JSON: Number value: '%s' = '%d'",
+ curr_token->name,
+ curr_token->number);
+ }
} else if (curr_token->parent &&
curr_token->parent->type == JSON_ARRAY &&
curr_token->parent->state == JSON_STARTED &&
curr_token->state == JSON_EMPTY) {
- curr_token->number = num;
curr_token->state = JSON_COMPLETED;
- curr_token->type = JSON_NUMBER;
- wpa_printf(MSG_MSGDUMP,
- "JSON: Number value: %d",
- curr_token->number);
+ if (is_double) {
+ curr_token->dnumber = dnum;
+ curr_token->type = JSON_DOUBLE;
+ wpa_printf(MSG_MSGDUMP,
+ "JSON: Double value: %f",
+ curr_token->dnumber);
+ } else {
+ curr_token->number = num;
+ curr_token->type = JSON_NUMBER;
+ wpa_printf(MSG_MSGDUMP,
+ "JSON: Number value: %d",
+ curr_token->number);
+ }
} else {
wpa_printf(MSG_DEBUG,
"JSON: Invalid state for a number");
@@ -564,6 +649,8 @@ static const char * json_type_str(enum json_type type)
return "STRING";
case JSON_NUMBER:
return "NUMBER";
+ case JSON_DOUBLE:
+ return "DOUBLE";
case JSON_BOOLEAN:
return "BOOLEAN";
case JSON_NULL:
@@ -607,6 +694,12 @@ void json_add_int(struct wpabuf *json, const char *name, int val)
}
+void json_add_double(struct wpabuf *json, const char *name, double val)
+{
+ wpabuf_printf(json, "\"%s\":%f", name, val);
+}
+
+
void json_add_string(struct wpabuf *json, const char *name, const char *val)
{
wpabuf_printf(json, "\"%s\":\"%s\"", name, val);
diff --git a/src/utils/json.h b/src/utils/json.h
index 8448bb0c5..c1b8abd78 100644
--- a/src/utils/json.h
+++ b/src/utils/json.h
@@ -16,6 +16,7 @@ struct json_token {
JSON_ARRAY,
JSON_STRING,
JSON_NUMBER,
+ JSON_DOUBLE,
JSON_BOOLEAN,
JSON_NULL,
} type;
@@ -28,6 +29,7 @@ struct json_token {
char *name;
char *string;
int number;
+ double dnumber;
struct json_token *parent, *child, *sibling;
};
@@ -41,6 +43,7 @@ struct wpabuf * json_get_member_base64(struct json_token *json,
const char *name);
void json_print_tree(struct json_token *root, char *buf, size_t buflen);
void json_add_int(struct wpabuf *json, const char *name, int val);
+void json_add_double(struct wpabuf *json, const char *name, double val);
void json_add_string(struct wpabuf *json, const char *name, const char *val);
int json_add_string_escape(struct wpabuf *json, const char *name,
const void *val, size_t len);
--
2.45.2
More information about the Hostap
mailing list