/* * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "parser.h" #include #include "stdlib.h" struct json_parser { JsonParser *parser; JsonReader *reader; JsonGenerator *generator; }; /** * This is an Internal function, it is used to restore JsonReader location. * * The numbers that restored JsonReader location is as same as the numbers moved it. * * @param jparser [in] The json_parser data pointer. * @param cnt [in] The numbers that need to restore. * @return void. */ static void _restore_json_reader_location(struct json_parser *jparser, int cnt) { if (!jparser || !jparser->reader) { _ERR("Invalid argument"); return; } while (cnt > 0) { json_reader_end_member(jparser->reader); cnt--; } } /** * This is an Internal function, it is used to get json property value with certain json path. * * Use json-glib to create JsonPath variable and load the path to find property * location, then output property value. * * @param jparser [in] The json_parser data pointer. * @param path [in] The json path. * @return the property value, NULL on error. */ static gchar *_get_jsonpath_result(struct json_parser *jparser, const char *path) { JsonPath *jpath; JsonNode *node; gchar *output; if (!jparser || !path) { _ERR("Invalid argument!\n"); return NULL; } jpath = json_path_new(); json_path_compile(jpath, path, NULL); node = json_path_match(jpath, json_parser_get_root(jparser->parser)); json_generator_set_root(jparser->generator, node); output = json_generator_to_data(jparser->generator, NULL); g_object_unref(jpath); json_node_free(node); return output; } /** * Create and init a json_parser data with given json file path. * * @param path [in] The json file path. * @return json_parser data pointer, NULL on error. */ struct json_parser *parser_init(const char *path) { struct json_parser *jparser; GError *error; JsonParser *parser; JsonReader *reader; JsonGenerator *gen; if (!path) { _ERR("Invalid argument!\n"); return NULL; } jparser = (struct json_parser *) calloc(1, sizeof(*jparser)); if (!jparser) return NULL; parser = json_parser_new(); if (!parser) { _ERR("json_parser_new failed\n"); free(jparser); return NULL; } reader = json_reader_new(NULL); if (!reader) { _ERR("json_reader_new failed\n"); free(jparser); g_object_unref(parser); return NULL; } gen = json_generator_new(); if (!gen) { _ERR("json_reader_new failed\n"); free(jparser); g_object_unref(parser); g_object_unref(reader); return NULL; } error = NULL; json_parser_load_from_file(parser, path, &error); if (error) { _ERR("json file error: %s", error->message); free(jparser); g_error_free(error); g_object_unref(parser); g_object_unref(reader); g_object_unref(gen); return NULL; } json_reader_set_root(reader, json_parser_get_root(parser)); jparser->parser = parser; jparser->reader = reader; jparser->generator = gen; return jparser; } /** * Destroy and release given json_parser data. * * @param jparser [in] The json_parser data pointer to be release. * @return void. */ void parser_fini(struct json_parser *jparser) { if (!jparser) return; g_object_unref(jparser->parser); g_object_unref(jparser->reader); g_object_unref(jparser->generator); free(jparser); } /** * Release given json property key-value pair list. * * @param list [in] The given property key-value pair list array. * @return void. */ void parser_release_member_list(char **list) { if (!list) return; g_strfreev(list); } /** * Get JsonReader pointer from given json_parser data. * * @param jparser [in] The json_parser data pointer. * @return JsonReader pointer, NULL on error. */ JsonReader *parser_get_json_reader(struct json_parser *jparser) { if (!jparser) { _ERR("Parameter error!"); return NULL; } return jparser->reader; } /** * Get JsonParser pointer from given json_parser data. * * @param jparser [in] The json_parser data pointer. * @return JsonParser pointer, NULL on error. */ JsonParser *parser_get_json_parser(struct json_parser *jparser) { if (!jparser) { _ERR("Parameter error!"); return NULL; } return jparser->parser; } /** * Get JsonGenerator pointer from given json_parser data. * * @param jparser [in] The json_parser data pointer. * @return JsonGenerator pointer, NULL on error. */ JsonGenerator *parser_get_json_generator(struct json_parser *jparser) { if (!jparser) { _ERR("Parameter error!"); return NULL; } return jparser->generator; } /** * Retrieve given item property key-value pair list from json file. * * According to info_type value to determine to locate either settingitems or settingtree json object, * then retrieve given item property key-value pair list. * * @param jparser [in] The json_parser data pointer. * @param name [in] The item name. * @param cnt [out] The property key-value pair numbers. * @param flag [in] The info type, it stand for "settingitems" or "settingtree". * @return given property key-value pair list, NULL on error. */ char **parser_get_itemlist_from_json(struct json_parser *jparser, const char *name, int *cnt, enum info_type flag) { char **list; int cursor; if (!jparser || !name || !cnt) { _ERR("Invalid argument!"); return NULL; } cursor = 0; // For Debugging //_DBG("[START][ name = %s ][Parser = %x][Reader = %x]",name, jparser, jparser->reader); //_DBG("Member cnt = %d", json_reader_count_members(jparser->reader)); //_DBG("Current Member = %s", json_reader_get_member_name(jparser->reader)); if (flag == DRAWING_INFO) { if (!json_reader_read_member(jparser->reader, JSONSTR_SETTING_ITEMS)) { cursor++; goto error; } } else if (flag == SUBMENU_INFO) { if (!json_reader_read_member(jparser->reader, JSONSTR_SETTING_TREE)) { cursor++; goto error; } } else { goto error; } cursor++; if (!json_reader_read_member(jparser->reader, name)) { cursor++; goto error; } cursor++; *cnt = json_reader_count_members(jparser->reader); list = json_reader_list_members(jparser->reader); _restore_json_reader_location(jparser, cursor); return list; error: _restore_json_reader_location(jparser, cursor); *cnt = 0; return NULL; } /** * Retrieve given item setting UI args property key-value pair list from json file. * * According to name value to locate given item of settingitems object, * then retrieve setting UI args property key-value pair list. * * @param jparser [in] The json_parser data pointer. * @param name [in] The item name. * @param pnode [in] The args's parent json node name. * @param cnt [out] The property key-value pair numbers. * @return given property key-value pair list, NULL on error. */ char **parser_get_settingui_args_from_json(struct json_parser *jparser, const char *name, const char *pnode, int *cnt) { char **list; int cursor; if (!jparser || !name || !cnt || !pnode) return NULL; cursor = 0; if (!json_reader_read_member(jparser->reader, JSONSTR_SETTING_ITEMS)) { cursor++; _DBG("[%s] Fail to read member from json", JSONSTR_SETTING_ITEMS); goto error; } cursor++; if (!json_reader_read_member(jparser->reader, name)) { cursor++; _DBG("[%s] Fail to read member from json", name); goto error; } cursor++; if (!json_reader_read_member(jparser->reader, pnode)) { cursor++; _DBG("[%s] Fail to read member from json", pnode); goto error; } cursor++; if (!json_reader_read_member(jparser->reader, JSONSTR_SETTINGUI_ARGS)) { cursor++; _DBG("[%s] Fail to read member from json", JSONSTR_SETTINGUI_ARGS); goto error; } cursor++; *cnt = json_reader_count_members(jparser->reader); list = json_reader_list_members(jparser->reader); _restore_json_reader_location(jparser, cursor); return list; error: _restore_json_reader_location(jparser, cursor); *cnt = 0; return NULL; } /** * Retrieve given item data property key-value pair list from json file. * * According to name value to locate given item of settingitems object, * then retrieve data property key-value pair list. * * @param jparser [in] The json_parser data pointer. * @param name [in] The item name. * @param cnt [out] The property key-value pair numbers. * @return given property key-value pair list, NULL on error. */ char **parser_get_data_list_from_json(struct json_parser *jparser, const char *name, int *cnt) { char **list; int cursor; if (!jparser || !name || !cnt) return NULL; cursor = 0; if (!json_reader_read_member(jparser->reader, JSONSTR_SETTING_ITEMS)) { cursor++; _DBG("[%s] Fail to read member from json", JSONSTR_SETTING_ITEMS); goto error; } cursor++; if (!json_reader_read_member(jparser->reader, name)) { cursor++; _DBG("[%s] Fail to read member from json", name); goto error; } cursor++; if (!json_reader_read_member(jparser->reader, JSONSTR_DATA)) { cursor++; _DBG("[%s] Fail to read member from json", JSONSTR_DATA); goto error; } cursor++; *cnt = json_reader_count_members(jparser->reader); list = json_reader_list_members(jparser->reader); _restore_json_reader_location(jparser, cursor); return list; error: _restore_json_reader_location(jparser, cursor); *cnt = 0; return NULL; } /** * Retrieve property value with given json path. * * Get property raw value with given json path, then trim raw value and copy it to buffer * and return buffer pointer. * * @param jparser [in] The json_parser data pointer. * @param path [in] The json path. * @return given property string value, NULL on error. */ char *parser_get_string_value_from_json(struct json_parser *jparser, const char *path) { gchar *output; char *result; char **arr; unsigned int cnt; if (!jparser || !path) { _ERR("Invalid argument!\n"); return NULL; } output = _get_jsonpath_result(jparser, path); if (!output) { _ERR("WRONG PATH:%s", path); return NULL; } if (!strcmp(output, "[]") || !strncmp(output, "[\n]", strlen(output))) { g_free(output); return NULL; } result = (char *) calloc(1, sizeof(char) * ARRAY_SIZE); if (!result) { g_free(output); return NULL; } cnt = 0; arr = eina_str_split_full(output, "\"", 0, &cnt); if (cnt == 3) strncpy(result, arr[1], ARRAY_SIZE - 1); else if (cnt > 3) _ERR("Wrong API called %d", cnt); free(arr[0]); free(arr); g_free(output); return result; } /** * Retrieve property array value with given json path. * * Get property raw array value with given json path, then trim raw array value and iterate it * to get every string value and store them into eina list. * * @param jparser [in] The json_parser data pointer. * @param path [in] The json path. * @return given property string value eina list, NULL on error. */ Eina_List *parser_get_string_list_from_json(struct json_parser *jparser, const char *path) { gchar *output; char **arr; unsigned int i, cnt; Eina_List *list; char *result; if (!jparser || !path) return NULL; output = _get_jsonpath_result(jparser, path); if (!output) { _ERR("Data from json is NULL"); return NULL; } if (!strncmp(output, "[]", strlen(output)) || !strncmp(output, "[\n]", strlen(output))) { g_free(output); return NULL; } cnt = 0; arr = eina_str_split_full(output, "\"", 0, &cnt); cnt /= 2; list = NULL; for (i = 0; i < cnt; i++) { result = (char *) calloc(1, sizeof(char) * ARRAY_SIZE); if (!result) { free(arr[0]); free(arr); g_free(output); return NULL; } strncpy(result, arr[2*i+1], ARRAY_SIZE - 1); list = eina_list_append(list, result); } free(arr[0]); free(arr); g_free(output); return list; } /** * Retrieve property array length with given json path. * * According to path to locate json property node, then get the given node's array length. * * @param jparser [in] The json_parser data pointer. * @param path [in] The json path. * @return given property array length, 0 on error. */ int parser_get_array_length_from_json(struct json_parser *jparser, const char *path) { unsigned int i, cnt; int len; char **arr; if (!jparser || !path) return 0; cnt = 0; arr = eina_str_split_full(path, ".", 0, &cnt); for (i = 1; i < cnt; i++) { if (!json_reader_read_member(jparser->reader, arr[i])) { while(i){ json_reader_end_member(jparser->reader); i--; } free(arr[0]); free(arr); return 0; } } len = 0; if (json_reader_is_array(jparser->reader)) len = json_reader_count_elements(jparser->reader); for (i = 1; i < cnt; i++) json_reader_end_member(jparser->reader); free(arr[0]); free(arr); return len; } /** * check raw property value wether correct or not. * * @param jparser [in] The json_parser data pointer. * @param path [in] The json path. * @return true if correct, false if error. */ bool parser_check_json_path(struct json_parser *jparser, const char *path) { char *output; if (!jparser || !path) return false; output = _get_jsonpath_result(jparser, path); if (!output) { _ERR("WRONG PATH:%s", path); return false; } if (!strncmp(output, "[]", strlen(output)) || !strncmp(output, "[\n]", strlen(output))) { g_free(output); return false; } g_free(output); return true; } /** * Get given item's parent item name value with given json file path. * * @param path [in] The json file path. * @param name [in] The given item name. * @return given item's parent item name string value, NULL on error. */ char *parser_get_parent_item_name(const char *path, const char *name) { struct json_parser *jparser; char buf[ARRAY_SIZE]; char *val; jparser = parser_init(path); if (!jparser) { _ERR("json parser init failed."); return NULL; } snprintf(buf, sizeof(buf), "$.%s", name); val = parser_get_string_value_from_json(jparser, buf); if (!val) { _ERR("json parser get string value failed."); parser_fini(jparser); return NULL; } parser_fini(jparser); return val; }