jsmn_parse can be called with a NULL buffer to determine the needed
allocation size beforehand. Most users will go on to dynamically
allocate that buffer, so add a helper that does just that and start
using it to simplify the json selftest.

Signed-off-by: Ahmad Fatoum <[email protected]>
---
 include/jsmn.h   |  6 ++++++
 lib/jsmn.c       | 36 ++++++++++++++++++++++++++++++++++++
 test/self/json.c | 33 ++++-----------------------------
 3 files changed, 46 insertions(+), 29 deletions(-)

diff --git a/include/jsmn.h b/include/jsmn.h
index 2dd1d5ffc08b..62197c2593b4 100644
--- a/include/jsmn.h
+++ b/include/jsmn.h
@@ -84,6 +84,12 @@ JSMN_API void jsmn_init(jsmn_parser *parser);
 JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
                        jsmntok_t *tokens, const unsigned int num_tokens);
 
+/**
+ * Like jsmn_parse, but allocates tokens dynamically.
+ */
+JSMN_API jsmntok_t *jsmn_parse_alloc(const char *js, const size_t len,
+                                    unsigned int *num_tokens);
+
 static inline int jsmn_token_size(const jsmntok_t *token)
 {
        return token->end - token->start;
diff --git a/lib/jsmn.c b/lib/jsmn.c
index 9eeed790d93d..3d2ada7b7fdc 100644
--- a/lib/jsmn.c
+++ b/lib/jsmn.c
@@ -370,6 +370,42 @@ JSMN_API void jsmn_init(jsmn_parser *parser) {
        parser->toksuper = -1;
 }
 
+/**
+ * Parse JSON string and fill tokens into self-allocated buffer.
+ */
+JSMN_API jsmntok_t *jsmn_parse_alloc(const char *js, const size_t len,
+                                    unsigned int *num_tokens)
+{
+
+       ssize_t token_count;
+       jsmn_parser parser;
+       jsmntok_t *tokens;
+       int ret;
+
+       jsmn_init(&parser);
+
+       /* Figure out how many tokens we need. */
+       ret = jsmn_parse(&parser, js, len, NULL, 0);
+       if (ret < 0)
+               return NULL;
+
+       token_count = ret;
+
+       tokens = kmalloc_array(token_count, sizeof(jsmntok_t), GFP_KERNEL);
+       if (!tokens)
+               return NULL;
+
+       jsmn_init(&parser);
+       ret = jsmn_parse(&parser, js, len, tokens, token_count);
+       if (ret < 0) {
+               free(tokens);
+               return NULL;
+       }
+
+       if (num_tokens)
+               *num_tokens = ret;
+       return tokens;
+}
 JSMN_API bool jsmn_eq(const char *val, const char *json, const jsmntok_t 
*token)
 {
        size_t token_size = jsmn_token_size(token);
diff --git a/test/self/json.c b/test/self/json.c
index 54323cf4350c..d3088f1b7542 100644
--- a/test/self/json.c
+++ b/test/self/json.c
@@ -75,45 +75,20 @@ static const char json[] =
 
 static void test_json(void)
 {
-       ssize_t token_count;
        const jsmntok_t *token;
        jsmntok_t *tokens;
-       jsmn_parser parser;
        char *string;
-       int ret;
 
        total_tests++;
 
-       jsmn_init(&parser);
-
        /* Figure out how many tokens we need. */
-       ret = jsmn_parse(&parser, json, sizeof(json), NULL, 0);
-       if (ret < 0) {
-               printf("failed to determine number of tokens: %d\n", ret);
+       tokens = jsmn_parse_alloc(json, sizeof(json), NULL);
+       if (!tokens) {
+               printf("failed to parse JSON\n");
                failed_tests++;
                return;
        }
 
-       token_count = ret;
-
-       /* `token_count` is strictly less than `length` which is strictly less
-        * than CONFIG_SYS_EEPROM_SIZE (or 8K), so we should never overflow an
-        * int here.
-        */
-       tokens = kmalloc_array(token_count, sizeof(jsmntok_t), GFP_KERNEL);
-       if (WARN_ON(!tokens))
-               return;
-
-       total_tests++;
-
-       jsmn_init(&parser);
-       ret = jsmn_parse(&parser, json, sizeof(json), tokens, token_count);
-       if (ret < 0) {
-               printf("failed to parse JSON with tokens: %d\n", ret);
-               failed_tests++;
-               goto out;
-       }
-
        json_expect(json, tokens, JP("null"), JSMN_PRIMITIVE, "null");
        json_expect(json, tokens, JP("number"), JSMN_PRIMITIVE, "0x42");
        json_expect(json, tokens, JP("object"), JSMN_OBJECT, NULL);
@@ -131,7 +106,7 @@ static void test_json(void)
 
        string = jsmn_strcpy(JP("string"), json, tokens);
        if (WARN_ON(!string))
-               return;
+               goto out;
 
        total_tests++;
        if (strcmp(string, "Hello World\n")) {
-- 
2.39.2


Reply via email to