From e002c3060c0adb5d66a917a3e798b54e9ce8f0ef Mon Sep 17 00:00:00 2001 From: Kubat <mael.martin31@gmail.com> Date: Sun, 17 Jan 2021 13:07:36 +0100 Subject: [PATCH] BASE: Add a basic json parser suited for our needs --- inc/lektor/json.h | 26 ++++++++++++++ src/base/json.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 inc/lektor/json.h create mode 100644 src/base/json.c diff --git a/inc/lektor/json.h b/inc/lektor/json.h new file mode 100644 index 00000000..2ae81839 --- /dev/null +++ b/inc/lektor/json.h @@ -0,0 +1,26 @@ +#if ! defined(__LKT_JSON_H__) +#define __LKT_JSON_H__ + +/* LIMITATIONS AND SPECIFICATIONS: + * - parse only one level at the time + * - values can't be arrays or json objects + * - " toto tata" => one string ' toto tata' + * - toto tata => two strings 'toto' and 'tata' + * - to separate a value from a key, the '=' and ':' separators are not + * mendatory, a simple space is enaugth + * - all values are be strings */ + +// *INDENT-OFF* +typedef void(*json_parse_callback)( + const char *key, /* Json key, a string */ + const char *value, /* Json value, a string */ + int new_obj, /* 1 when encountered a new object */ + void *user /* The user pointer from the parse function */ +); +// *INDENT-ON* + +/* Parse only one level of json, simple but only what we need for lektor. The + * callback is used when a couple key/value is found for the correct level. */ +int json_parse(const char *str, int level, json_parse_callback, void *user); + +#endif /* __LKT_JSON_H__ */ diff --git a/src/base/json.c b/src/base/json.c new file mode 100644 index 00000000..5f2de939 --- /dev/null +++ b/src/base/json.c @@ -0,0 +1,89 @@ +#define _POSIX_C_SOURCE 200809L + +#include <lektor/common.h> +#include <lektor/json.h> + +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#define __JSON_SPACE " \n\t:=," +#define __JSON_BEGIN "{[" +#define __JSON_END "}]" + +static inline char * +strip(char *s) +{ + char *p = s + strlen(s); + while (p > s && isspace(*(--p))) + *p = 0; + return s; +} + +static inline char * +skip(char *s) +{ + while (*s && isspace(*s)) + s++; + return s; +} + +#define __SKIP_JSON(str) (str = &str[strspn(str, __JSON_SPACE)]) + +int +json_parse(const char *str, int asked_level, json_parse_callback call, void *user) +{ + int level = 0; + int new_obj = 1; + char key[LKT_LINE_MAX]; + char val[LKT_LINE_MAX]; + + for (;;) { + size_t len = 0; + __SKIP_JSON(str); + + /* Begin of a block */ + if ((len = strspn(str, __JSON_BEGIN))) { + new_obj = 1; + level += len; + str += len; + } + + /* End of a block */ + else if ((len = strspn(str, __JSON_END))) { + new_obj = 1; + str += len; + level -= len; + } + + /* Key Value */ + else { + memset(key, 0, sizeof(key)); + memset(val, 0, sizeof(val)); + + len = strcspn(str, __JSON_SPACE __JSON_BEGIN __JSON_END); + if (level == asked_level && len < LKT_LINE_MAX - 1) + strncpy(key, str, len); + str += len; + + __SKIP_JSON(str); + + len = strcspn(str, __JSON_SPACE __JSON_BEGIN __JSON_END); + if (level == asked_level && len < LKT_LINE_MAX - 1) + strncpy(val, str, len); + str += len; + + if (asked_level == level) + call(key, val, new_obj, user); + + if (new_obj) + new_obj = 0; + + } + + if (level <= 0) { + return 0; + } + } + return 1; +} -- GitLab