SUPPORT-8592. Добавлен json-парсер

This commit is contained in:
alashkova 2024-10-15 13:47:38 +03:00
parent a221960fbf
commit 17aec4de8b
6 changed files with 376 additions and 61 deletions

View file

@ -49,8 +49,30 @@ SET (DEP_LIBS
-lfcgi -lfcgi
-lglib-2.0 -lglib-2.0
-ldl -ldl
-ljson-glib-1.0
-lgobject-2.0
) )
# JSON-GLIB
MESSAGE ("")
MESSAGE ("Try to find the JSON-glib-1.0..")
pkg_check_modules (JSONGLIB REQUIRED json-glib-1.0)
IF (NOT JSONGLIB_FOUND)
MESSAGE(SEND_ERROR "Can not find json-glib-1.0")
ELSE ()
MESSAGE ("json-glib-1.0 is found: ")
MESSAGE ("JSONGLIB_LIB_INCLUDE_DIR : " ${JSONGLIB_LIB_INCLUDE_DIR})
MESSAGE ("JSONGLIB_INCLUDE_DIR : " ${JSONGLIB_INCLUDE_DIR})
MESSAGE ("JSONGLIB_LIBRARY_DIR : " ${JSONGLIB_LIBRARY_DIR})
MESSAGE ("JSONGLIB_INCLUDE_DIRS : " ${JSONGLIB_INCLUDE_DIRS})
MESSAGE ("JSONGLIB_LIBRARY_DIRS : " ${JSONGLIB_LIBRARY_DIRS})
MESSAGE ("JSONGLIB_LIBRARIES : " ${JSONGLIB_LIBRARIES})
ENDIF (NOT JSONGLIB_FOUND)
MESSAGE ("")
INCLUDE_DIRECTORIES ("${JSONGLIB_INCLUDE_DIRS}")
# version.h # version.h
CONFIGURE_FILE (${SOURCE_DIR}/version.h.in ${SOURCE_DIR}/version.h) CONFIGURE_FILE (${SOURCE_DIR}/version.h.in ${SOURCE_DIR}/version.h)
@ -88,6 +110,8 @@ ADD_EXECUTABLE (${PROJECT_NAME}
${UTILS_DIR}/conf_file_context.c ${UTILS_DIR}/conf_file_context.c
${UTILS_DIR}/cryptopro.c ${UTILS_DIR}/cryptopro.c
${UTILS_DIR}/gconf_file.c ${UTILS_DIR}/gconf_file.c
${UTILS_DIR}/glib_utils.c
${UTILS_DIR}/json_parser.c
${UTILS_DIR}/library.c ${UTILS_DIR}/library.c
${UTILS_DIR}/logger.c ${UTILS_DIR}/logger.c
${UTILS_DIR}/str_t.c ${UTILS_DIR}/str_t.c

View file

@ -1,69 +1,9 @@
#include "gconf_file.h" #include "gconf_file.h"
#include "glib_utils.h"
#include "logger.h" #include "logger.h"
#include <assert.h> #include <assert.h>
/** Returns the length of the gchar string @str
*/
static inline size_t gstr_byte_len(const gchar* str)
{
return strlen((char*) str);
}
/*
* Copies the gchar string pointed by src into the content pointed by dst, including
* the terminating null character (and stopping at that point).
* Uses to avoid dependence from glib.
* @src: gchar string to be copied
* @dst: pointer to destination of type str_t where content is to be copied
* Return value: 0 - success, -1 - error
*/
static int
copy_gchar2strt(const gchar* src, str_t* dst)
{
assert(src != NULL);
assert(dst != NULL);
size_t len = gstr_byte_len(src);
char* data = (char*) malloc(len + 1);
if (data == NULL) {
LOG_ERROR("gchar2strt exit with error: could not allocate memory for dst");
return -1;
}
dst->data = data;
dst->len = len;
memcpy(dst->data, src, dst->len + 1);
dst->data[dst->len] = '\0';
return 0;
}
/*
* Copies the gchar string pointed by src into the content pointed by return value,
* including the terminating null character (and stopping at that point).
* Uses to avoid dependence from glib.
* @src: gchar string to be copied
* Return value: pointer to destination where content is to be copied
*/
static char*
copy_gchar2char(const gchar* src)
{
assert(src != NULL);
// char* tmp_end = strchr(src, '\0');
char* dst = NULL;
size_t len = gstr_byte_len(src);
dst = (char*) malloc(len + 1);
if (dst == NULL) {
LOG_ERROR("gchar2char exit with error: could not allocate memory for dst");
return NULL;
}
memcpy(dst, src, len + 1);
return dst;
}
/* Returns the string value from GKeyFile associated with key under section and converted to str_t /* Returns the string value from GKeyFile associated with key under section and converted to str_t
* @ini_file: GKeyFile * @ini_file: GKeyFile
* @section: section name in config file * @section: section name in config file

49
src/utils/glib_utils.c Normal file
View file

@ -0,0 +1,49 @@
#include "glib_utils.h"
#include "logger.h"
#include <assert.h>
/** Returns the length of the gchar string @str
*/
static inline size_t
gstr_byte_len(const gchar* str)
{
return strlen((char*) str);
}
int
copy_gchar2strt(const gchar* src, str_t* dst)
{
assert(src != NULL);
assert(dst != NULL);
size_t len = gstr_byte_len(src);
char* data = (char*) malloc(len + 1);
if (data == NULL) {
LOG_ERROR("gchar2strt exit with error: could not allocate memory for dst");
return -1;
}
dst->data = data;
dst->len = len;
memcpy(dst->data, src, dst->len + 1);
dst->data[dst->len] = '\0';
return 0;
}
char*
copy_gchar2char(const gchar* src)
{
assert(src != NULL);
char* dst = NULL;
size_t len = gstr_byte_len(src);
dst = (char*) malloc(len + 1);
if (dst == NULL) {
LOG_ERROR("gchar2char exit with error: could not allocate memory for dst");
return NULL;
}
memcpy(dst, src, len + 1);
return dst;
}

32
src/utils/glib_utils.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef GLIB_UTULS_H_INCLUDED
#define GLIB_UTULS_H_INCLUDED
#include "str_t.h"
#include <glib.h>
/*
* Copies the gchar string pointed by src into the content pointed by dst, including
* the terminating null character (and stopping at that point).
* Uses to avoid dependence from glib.
* @src: gchar string to be copied
* @dst: pointer to destination of type str_t where content is to be copied
* Return value: 0 - success, -1 - error
*/
int
copy_gchar2strt(const gchar* src, str_t* dst);
/*
* Copies the gchar string pointed by src into the content pointed by return value,
* including the terminating null character (and stopping at that point).
* Uses to avoid dependence from glib.
* @src: gchar string to be copied
* Return value: pointer to destination where content is to be copied
*/
char*
copy_gchar2char(const gchar* src);
#endif // GLIB_UTULS_H_INCLUDED

239
src/utils/json_parser.c Normal file
View file

@ -0,0 +1,239 @@
#include "json_parser.h"
#include "glib_utils.h"
#include "logger.h"
#include <assert.h>
#include <json-glib/json-glib.h>
typedef struct json_parser_s {
JsonParser *parser;
void *root;
json_parser_type root_type;
} json_parser_t;
static JsonObject* get_object_from_node(JsonNode *node);
static int json_get_object_member_as_string(Hjson_parser hparser, const char* field_name,
/*out*/ str_t* field_value);
Hjson_parser
json_parser_create(const char* data, size_t data_len)
{
GError* gerror = NULL;
JsonNode* json_node = NULL;
JsonNodeType json_node_type;
const char *desc = "";
LOG_TRACE("json_parser_create enter");
assert(data != NULL && data_len != 0 && "json data is empty");
json_parser_t* parser = calloc (sizeof(json_parser_t), 1);
if (parser == NULL) {
desc = "Could not allocate memory for json_parser_t";
goto error;
}
parser->parser = json_parser_new();
if (parser->parser == NULL) {
desc = "Could not create JsonParser";
goto error;
}
LOG_DEBUG("json_parser_create. json data: %.*s", (int)data_len, data);
if (json_parser_load_from_data(parser->parser, data, data_len, &gerror) != TRUE) {
LOG_ERROR("json_parser_create. json_parser_load_from_data failed: %s", gerror->message);
g_error_free(gerror);
goto error;
}
/* get root node */
json_node = json_parser_get_root(parser->parser);
if (json_node == NULL) {
desc = "Could not parse json object: json_parser_get_root failed";
goto error;
}
json_node_type = json_node_get_node_type(json_node);
if (json_node_type != JSON_NODE_OBJECT) {
desc = "Could not parse json object: unexpected root type";
goto error;
}
parser->root_type = JSON_PARSER_TYPE_OBJECT;
/* try to get root as object */
parser->root = get_object_from_node(json_node);
if (parser->root == NULL) {
desc = "Could not parse json object: json_node_get_object failed";
goto error;
}
return (Hjson_parser)parser;
error:
json_parser_free((Hjson_parser)parser);
LOG_ERROR("json_parser_create exit with error. Desc: %s", desc);
return NULL;;
}
void
json_parser_free(Hjson_parser hparser)
{
json_parser_t* parser = (json_parser_t*) hparser;
if (parser == NULL) return;
if (parser->parser != NULL) {
g_object_unref(parser->parser);
}
free(parser);
}
int
json_get_string_member(Hjson_parser hparser, const char* field_name,
/*out*/ str_t* field_value)
{
LOG_TRACE("json_get_string_member enter");
switch (json_get_object_member_as_string(hparser, field_name, field_value)) {
case 0:
LOG_TRACE("json_get_string_member exit successfully. field_value: %.*s",
(int) field_value->len,
field_value->data);
return 0;
case 1:
LOG_ERROR("Could not retrieve '%.*s' from json object. "
"Desc: field does not exist or it has not proper type. "
"Expected: string member",
(int) field_value->len, field_value->data);
break;
default:
LOG_ERROR("json_get_object_member_as_string failed, member: '%.*s'",
(int) field_value->len, field_value->data);
break;
}
LOG_ERROR("json_get_string_member exit with error");
return -1;
}
static JsonObject*
get_object_from_node(JsonNode *node)
{
JsonObject *ret = NULL;
if (node == NULL) {
LOG_WARN("get_object_from_node. node is NULL");
return NULL;
}
if (!JSON_NODE_HOLDS_OBJECT(node)) {
LOG_ERROR("Bad json scheme. Expected node: object");
return NULL;
}
ret = json_node_get_object(node);
assert(ret != NULL && "Could not extract the node of correct type");
return ret;
}
static int
get_string_from_node(JsonNode *node, /*out*/ const gchar **value)
{
assert(value != NULL);
*value = NULL;
if (node == NULL) {
LOG_WARN("get_string_from_node. node is NULL");
return 0;
}
/* если нод содержит нулевое значение, оставляем наш указатель так же нулевым */
if (JSON_NODE_HOLDS_NULL(node)) {
LOG_DEBUG("get_string_from_node. node holds NULL");
return 0;
}
if (!JSON_NODE_HOLDS_VALUE(node) || G_TYPE_STRING != json_node_get_value_type(node)) {
LOG_ERROR("Bad json scheme. Expected node: string value. Actual node type: %s",
json_node_type_name(node));
return -1;
}
*value = json_node_get_string(node);
if (*value == NULL) {
LOG_ERROR("Bad json node. Expected node: string value");
return -1;
}
return 0;
}
static int
json_object_get_string(JsonObject *object, const gchar *key, /*out*/const gchar** value)
{
JsonNode *node = NULL;
LOG_TRACE("json_object_get_string");
assert(object != NULL);
assert(key != NULL);
assert(value != NULL);
*value = NULL;
node = json_object_get_member(object, key);
if (node == NULL) {
LOG_DEBUG("object member by key '%s' is not exists", key);
/* ret = NULL; */
return 0;
}
return get_string_from_node(node, value);
}
static int
json_get_object_member_as_string(Hjson_parser hparser, const char* field_name,
/*out*/ str_t* field_value)
{
json_parser_t* parser = (json_parser_t*) hparser;
const gchar* value = NULL;
assert(parser != NULL);
assert(parser->root_type == JSON_PARSER_TYPE_OBJECT);
assert(parser->root != NULL);
assert(field_name != NULL);
assert(field_value != NULL && str_t_is_null(*field_value));
LOG_DEBUG("json_get_object_member_as_string. field name: %s", field_name);
if (json_object_get_string((JsonObject*) (parser->root), field_name, &value)) {
return -1;
}
if (value == NULL) {
return 1;
}
if (copy_gchar2strt(value, field_value) != 0) {
LOG_ERROR("json_get_object_member_as_string. Could not copy field_value");
return -1;
}
return 0;
}

31
src/utils/json_parser.h Normal file
View file

@ -0,0 +1,31 @@
#ifndef JSON_PARSER_H_INCLUDED
#define JSON_PARSER_H_INCLUDED
#include "str_t.h"
#include <stdbool.h>
#include <stddef.h>
typedef struct json_parser_t *Hjson_parser;
typedef enum json_parser_type_e {
JSON_PARSER_TYPE_UNKNOWN,
JSON_PARSER_TYPE_STRING,
JSON_PARSER_TYPE_OBJECT,
JSON_PARSER_TYPE_ARRAY
} json_parser_type;
Hjson_parser json_parser_create(const char* data, size_t data_len);
void json_parser_free(Hjson_parser hparser);
int json_get_string_member(Hjson_parser hparser, const char* field_name,
/*out*/ str_t* field_value);
#endif // JSON_PARSER_H_INCLUDED