SUPPORT-8592. Добавлен json-парсер
This commit is contained in:
parent
a221960fbf
commit
17aec4de8b
6 changed files with 376 additions and 61 deletions
|
|
@ -49,8 +49,30 @@ SET (DEP_LIBS
|
|||
-lfcgi
|
||||
-lglib-2.0
|
||||
-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
|
||||
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}/cryptopro.c
|
||||
${UTILS_DIR}/gconf_file.c
|
||||
${UTILS_DIR}/glib_utils.c
|
||||
${UTILS_DIR}/json_parser.c
|
||||
${UTILS_DIR}/library.c
|
||||
${UTILS_DIR}/logger.c
|
||||
${UTILS_DIR}/str_t.c
|
||||
|
|
|
|||
|
|
@ -1,69 +1,9 @@
|
|||
#include "gconf_file.h"
|
||||
#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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* @ini_file: GKeyFile
|
||||
* @section: section name in config file
|
||||
|
|
|
|||
49
src/utils/glib_utils.c
Normal file
49
src/utils/glib_utils.c
Normal 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
32
src/utils/glib_utils.h
Normal 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
239
src/utils/json_parser.c
Normal 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
31
src/utils/json_parser.h
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue