From 78ccdaa4e90a320cdf52127af2e71a0ab9626a76 Mon Sep 17 00:00:00 2001 From: Sourav Moitra Date: Sun, 27 Oct 2024 01:26:37 +0530 Subject: [PATCH] Moving YAJL to Jansson Added a temporary function to yajl_val to json_t converted YAJL_GET_STRING to json_string_value converted YAJL_IS_NUMBER to json_is_number added functions from double to various int types. YAJL_GET_NUMBER returns string. While json_number_value returns double. Signed-off-by: Sourav Moitra --- src/ocispec/json_common.c | 218 ++++++++++++++++++++++++++++++++++++++ src/ocispec/json_common.h | 24 +++++ src/ocispec/sources.py | 50 +++++---- 3 files changed, 271 insertions(+), 21 deletions(-) diff --git a/src/ocispec/json_common.c b/src/ocispec/json_common.c index fb2b8829..5ef863fc 100644 --- a/src/ocispec/json_common.c +++ b/src/ocispec/json_common.c @@ -454,6 +454,187 @@ common_safe_int (const char *numstr, int *converted) return 0; } +/* +* This function converts double to int +* Input: double d, int *converted +* Ouput: int +*/ +int +json_double_to_int (double d, int *converted) +{ + long long int lli; + lli = (long long int) d; + + if (lli > INT_MAX || lli < INT_MIN) + return -ERANGE; + + *converted = (int) lli; + return 0; +} + +/* +* This function converts double to int64 +* Input: double d, int64 *converted +* Ouput: int +*/ +int +json_double_to_int64 (double d, int64_t *converted) +{ + long long int lli; + lli = (long long int) d; + *converted = (int64_t) lli; + return 0; +} + +/* +* This function converts double to int32 +* Input: double d, int32 *converted +* Ouput: int +*/ +int +json_double_to_int32 (double d, int32_t *converted) +{ + long long int lli; + lli = (long long int) d; + + if (lli > INT32_MAX || lli < INT32_MIN) + return -ERANGE; + + *converted = (int32_t) lli; + return 0; +} + +/* +* This function converts double to int16 +* Input: double d, int16 *converted +* Ouput: int +*/ +int +json_double_to_int16 (double d, int16_t *converted) +{ + long int li; + li = (long int) d; + if (li > INT16_MAX || li < INT16_MIN) + return -ERANGE; + + *converted = (int16_t) li; + return 0; +} + +/* +* This function converts double to int8 +* Input: double d, int8 *converted +* Ouput: int +*/ +int +json_double_to_int8 (double d, int8_t *converted) +{ + long int li; + li = (long int) d; + if (li > INT8_MAX || li < INT8_MIN) + return -ERANGE; + *converted = (int8_t) li; + return 0; +} + +/* +* This function converts double to uint +* Input: double d, unsigned int *converted +* Ouput: int +*/ +int +json_double_to_uint (double d, unsigned int *converted) +{ + unsigned long long int ull; + ull = (unsigned long long int) d; + + if (ull > UINT_MAX) + return -ERANGE; + + *converted = (unsigned int) ull; + return 0; +} + +/* +* This function converts double to uint64 +* Input: double d, uint64_t *converted +* Ouput: int +*/ +int +json_double_to_uint64 (double d, uint64_t *converted) +{ + unsigned long long int ull; + ull = (unsigned long long int) d; + *converted = (uint64_t) ull; + return 0; +} + +/* +* This function converts double to uint32 +* Input: double d, uint32_t *converted +* Ouput: int +*/ +int +json_double_to_uint32 (double d, uint32_t *converted) +{ + unsigned long long int ull; + ull = (unsigned long long int) d; + + if (ull > UINT32_MAX) + return -ERANGE; + + *converted = (uint32_t) ull; + return 0; +} + +/* +* This function converts double to uint16 +* Input: double d, uint16_t *converted +* Ouput: int +*/ +int +json_double_to_uint16 (double d, uint16_t *converted) +{ + unsigned long int uli; + uli = (unsigned long int) d; + if (uli > UINT16_MAX) + return -ERANGE; + + *converted = (uint16_t) uli; + return 0; +} + +/* +* This function converts double to uint8 +* Input: double d, uint8_t *converted +* Ouput: int +*/ +int +json_double_to_uint8 (double d, uint8_t *converted) +{ + unsigned long int uli; + uli = (unsigned long int) d; + + if (uli > UINT8_MAX) + return -ERANGE; + + *converted = (uint8_t) uli; + return 0; +} + +/* +* This function converts double to double, kind of silly :) +* Input: double d, double *converted +* Ouput: int +*/ +int +json_double_to_double (double d, double *converted) +{ + *converted = d; + return 0; +} + + yajl_gen_status gen_json_map_int_int (void *ctx, const json_map_int_int *map, const struct parser_context *ptx, parser_error *err) { @@ -1719,3 +1900,40 @@ json_marshal_string (const char *str, size_t length, const struct parser_context return json_buf; } + +/* +This function is temporary function to convert yajl_val. This fuction will +not be required once we completely move to jansson + +Input: yajl_val + +Output: json_t +*/ +json_t *yajl_to_json(yajl_val val) { + if YAJL_IS_NULL(val) { + return json_null(); + } else if (YAJL_IS_TRUE(val)) { + return json_true(); + } else if (YAJL_IS_FALSE(val)) { + return json_false(); + } else if (YAJL_IS_DOUBLE(val)) { + return json_real(YAJL_GET_DOUBLE(val)); + } else if (YAJL_IS_INTEGER(val)) { + return json_integer(YAJL_GET_INTEGER(val)); + } else if (YAJL_IS_STRING(val)) { + return json_string(YAJL_GET_STRING(val)); + } else if (YAJL_IS_ARRAY(val)) { + json_t *jansson_array = json_array(); + for (size_t i = 0; i < val->u.array.len; i++) { + json_array_append(jansson_array, yajl_to_json(val->u.array.values[i])); + } + return jansson_array; + } else { + json_t *jansson_object = json_object(); + for (size_t i = 0; i < val->u.object.len; i++) { + json_object_set_new(jansson_object, val->u.object.keys[i], yajl_to_json(val->u.object.values[i])); + } + return jansson_object; + } + return NULL; +} diff --git a/src/ocispec/json_common.h b/src/ocispec/json_common.h index 41c73f59..f565200b 100644 --- a/src/ocispec/json_common.h +++ b/src/ocispec/json_common.h @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -115,6 +116,28 @@ int common_safe_int64 (const char *numstr, int64_t *converted); int common_safe_int (const char *numstr, int *converted); +int json_double_to_int (double d, int *converted); + +int json_double_to_int64 (double d, int64_t *converted); + +int json_double_to_int32 (double d, int32_t *converted); + +int json_double_to_int16 (double d, int16_t *converted); + +int json_double_to_int8 (double d, int8_t *converted); + +int json_double_to_uint (double d, unsigned int *converted); + +int json_double_to_uint64 (double d, uint64_t *converted); + +int json_double_to_uint32 (double d, uint32_t *converted); + +int json_double_to_uint16 (double d, uint16_t *converted); + +int json_double_to_uint8 (double d, uint8_t *converted); + +int json_double_to_double (double d, double *converted); + typedef struct { int *keys; @@ -231,6 +254,7 @@ int append_json_map_string_string (json_map_string_string *map, const char *key, char *json_marshal_string (const char *str, size_t length, const struct parser_context *ctx, parser_error *err); +json_t *yajl_to_json(yajl_val val); #ifdef __cplusplus } #endif diff --git a/src/ocispec/sources.py b/src/ocispec/sources.py index d2e7ac15..091e78e1 100755 --- a/src/ocispec/sources.py +++ b/src/ocispec/sources.py @@ -369,10 +369,11 @@ def parse_json_to_c(obj, c_file, prefix): c_file.append(f"define_cleaner_function ({typename} *, free_{typename})\n") c_file.append(f"{typename} *\nmake_{typename} (yajl_val tree, const struct parser_context *ctx, parser_error *err)\n") c_file.append("{\n") + c_file.append(" const json_t *jtree = yajl_to_json(tree);\n") c_file.append(f" __auto_cleanup(free_{typename}) {typename} *ret = NULL;\n") c_file.append(" *err = NULL;\n") c_file.append(" (void) ctx; /* Silence compiler warning. */\n") - c_file.append(" if (tree == NULL)\n") + c_file.append(" if (jtree == NULL)\n") c_file.append(" return NULL;\n") c_file.append(" ret = calloc (1, sizeof (*ret));\n") c_file.append(" if (ret == NULL)\n") @@ -708,7 +709,8 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): """ if helpers.valid_basic_map_name(typ): c_file.append(f"{' ' * level}yajl_val val = {src};\n") - c_file.append(f"{' ' * level}if (val != NULL)\n") + c_file.append(f"{' ' * level}const json_t *jval = yajl_to_json(val);\n") + c_file.append(f"{' ' * level}if (jval != NULL)\n") c_file.append(f'{" " * level} {{\n') c_file.append(f'{" " * (level + 1)}{dest} = make_{helpers.make_basic_map_name(typ)} (val, ctx, err);\n') c_file.append(f"{' ' * (level + 1)}if ({dest} == NULL)\n") @@ -723,45 +725,46 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): c_file.append(f'{" " * (level)}}}\n') elif typ == 'string': c_file.append(f"{' ' * level}yajl_val val = {src};\n") - c_file.append(f"{' ' * level}if (val != NULL)\n") + c_file.append(f"{' ' * level}if (jtree != NULL)\n") c_file.append(f"{' ' * (level)} {{\n") - c_file.append(f"{' ' * (level + 1)}char *str = YAJL_GET_STRING (val);\n") + c_file.append(f"{' ' * (level + 1)}char *str = json_string_value (jtree);\n") c_file.append(f"{' ' * (level + 1)}{dest} = strdup (str ? str : \"\");\n") c_file.append(f"{' ' * (level + 1)}if ({dest} == NULL)\n") c_file.append(f"{' ' * (level + 1)} return NULL;\n") c_file.append(f'{" " * level} }}\n') elif helpers.judge_data_type(typ): c_file.append(f"{' ' * level}yajl_val val = {src};\n") - c_file.append(f"{' ' * level}if (val != NULL)\n") + c_file.append(f"{' ' * level}const json_t *jval = yajl_to_json(val);\n") + c_file.append(f"{' ' * level}if (jval != NULL)\n") c_file.append(f'{" " * (level)} {{\n') if typ.startswith("uint") or \ (typ.startswith("int") and typ != "integer") or typ == "double": c_file.append(f"{' ' * (level + 1)}int invalid;\n") - c_file.append(f"{' ' * (level + 1)}if (! YAJL_IS_NUMBER (val))\n") + c_file.append(f"{' ' * (level + 1)}if (!json_is_number (jval))\n") c_file.append(f'{" " * (level + 1)} {{\n') c_file.append(f"{' ' * (level + 1)} *err = strdup (\"invalid type\");\n") c_file.append(f"{' ' * (level + 1)} return NULL;\n") c_file.append(f'{" " * (level + 1)} }}\n') - c_file.append(f'{" " * (level + 1)}invalid = common_safe_{typ} (YAJL_GET_NUMBER (val), &{dest});\n') + c_file.append(f'{" " * (level + 1)}invalid = json_double_to_{typ} (json_number_value(jval), &{dest});\n') elif typ == "integer": c_file.append(f"{' ' * (level + 1)}int invalid;\n") - c_file.append(f"{' ' * (level + 1)}if (! YAJL_IS_NUMBER (val))\n") + c_file.append(f"{' ' * (level + 1)}if (!json_is_number (jval))\n") c_file.append(f'{" " * (level + 1)} {{\n') c_file.append(f"{' ' * (level + 1)} *err = strdup (\"invalid type\");\n") c_file.append(f"{' ' * (level + 1)} return NULL;\n") c_file.append(f'{" " * (level + 1)} }}\n') - c_file.append(f'{" " * (level + 1)}invalid = common_safe_int (YAJL_GET_NUMBER (val), (int *)&{dest});\n') + c_file.append(f'{" " * (level + 1)}invalid = json_double_to_int (json_number_value(jval), (int *)&{dest});\n') elif typ == "UID" or typ == "GID": c_file.append(f"{' ' * (level + 1)}int invalid;\n") - c_file.append(f"{' ' * (level + 1)}if (! YAJL_IS_NUMBER (val))\n") + c_file.append(f"{' ' * (level + 1)}if (!json_is_number (jval))\n") c_file.append(f'{" " * (level + 1)} {{\n') c_file.append(f"{' ' * (level + 1)} *err = strdup (\"invalid type\");\n") c_file.append(f"{' ' * (level + 1)} return NULL;\n") c_file.append(f'{" " * (level + 1)} }}\n') - c_file.append(f'{" " * (level + 1)}invalid = common_safe_uint (YAJL_GET_NUMBER (val), (unsigned int *)&{dest});\n') + c_file.append(f'{" " * (level + 1)}invalid = json_double_to_uint (json_number_value(jval), (unsigned int *)&{dest});\n') c_file.append(f"{' ' * (level + 1)}if (invalid)\n") c_file.append(f'{" " * (level + 1)} {{\n') - c_file.append(f'{" " * (level + 1)} if (asprintf (err, "Invalid value \'%s\' with type \'{typ}\' for key \'{keyname}\': %s", YAJL_GET_NUMBER (val), strerror (-invalid)) < 0)\n') + c_file.append(f'{" " * (level + 1)} if (asprintf (err, "Invalid value \'%f\' with type \'{typ}\' for key \'{keyname}\': %s", json_number_value (jval), strerror (-invalid)) < 0)\n') c_file.append(f'{" " * (level + 1)} *err = strdup ("error allocating memory");\n') c_file.append(f"{' ' * (level + 1)} return NULL;\n") c_file.append(f'{" " * (level + 1)}}}\n') @@ -773,18 +776,19 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): if num_type == "": return c_file.append(f"{' ' * level}yajl_val val = {src};\n") - c_file.append(f"{' ' * level}if (val != NULL)\n") + c_file.append(f"{' ' * level}const json_t *jval = yajl_to_json(val);\n") + c_file.append(f"{' ' * level}if (jval != NULL)\n") c_file.append(f'{" " * (level)} {{\n') c_file.append(f'{" " * (level + 1)}{dest} = calloc (1, sizeof ({helpers.get_map_c_types(num_type)}));\n') c_file.append(f"{' ' * (level + 1)}if ({dest} == NULL)\n") c_file.append(f"{' ' * (level + 1)} return NULL;\n") c_file.append(f"{' ' * (level + 1)}int invalid;\n") - c_file.append(f"{' ' * (level + 1)}if (! YAJL_IS_NUMBER (val))\n") + c_file.append(f"{' ' * (level + 1)}if (! json_is_number (jval))\n") c_file.append(f'{" " * (level + 1)} {{\n') c_file.append(f"{' ' * (level + 1)} *err = strdup (\"invalid type\");\n") c_file.append(f"{' ' * (level + 1)} return NULL;\n") c_file.append(f'{" " * (level + 1)}}}\n') - c_file.append(f'{" " * (level + 1)}sinvalid = common_safe_{num_type} (YAJL_GET_NUMBER (val), {dest});\n') + c_file.append(f'{" " * (level + 1)}sinvalid = json_double_to_{num_type} (json_number_value(jval), {dest});\n') c_file.append(f"{' ' * (level + 1)}if (invalid)\n") c_file.append(f'{" " * (level + 1)} {{\n') c_file.append(f'{" " * (level + 1)} if (asprintf (err, "Invalid value \'%s\' with type \'{typ}\' ' \ @@ -795,9 +799,10 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): c_file.append(f'{" " * (level)}}}\n') elif typ == 'boolean': c_file.append(f"{' ' * level}yajl_val val = {src};\n") - c_file.append(f"{' ' * level}if (val != NULL)\n") + c_file.append(f"{' ' * level}const json_t *jval = yajl_to_json(val);\n") + c_file.append(f"{' ' * level}if (jval != NULL)\n") c_file.append(f'{" " * (level)} {{\n') - c_file.append(f"{' ' * (level + 1)}{dest} = YAJL_IS_TRUE(val);\n") + c_file.append(f"{' ' * (level + 1)}{dest} = json_is_true(jval);\n") if '[' not in dest: c_file.append(f"{' ' * (level + 1)}{dest}_present = 1;\n") c_file.append(f'{" " * (level)} }}\n') @@ -813,21 +818,23 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): elif typ == 'booleanPointer': c_file.append(f"{' ' * level}yajl_val val = {src};\n") c_file.append(f"{' ' * level}if (val != NULL)\n") + c_file.append(f"{' ' * level}const json_t *jval = yajl_to_json(val);\n") c_file.append(f'{" " * (level)} {{\n') c_file.append(f"{' ' * (level + 1)}{dest} = calloc (1, sizeof (bool));\n") c_file.append(f"{' ' * (level + 1)}if ({dest} == NULL)\n") c_file.append(f"{' ' * (level + 1)} return NULL;\n") - c_file.append(f"{' ' * (level + 1)}*({dest}) = YAJL_IS_TRUE(val);\n") + c_file.append(f"{' ' * (level + 1)}*({dest}) = json_is_true(jval);\n") c_file.append(f'{" " * (level)} }}\n') c_file.append(f"{' ' * level}else\n") c_file.append(f'{" " * (level)} {{\n') c_file.append(f'{" " * (level + 1)}val = get_val (tree, "{keyname}", yajl_t_false);\n') - c_file.append(f"{' ' * (level + 1)}if (val != NULL)\n") + c_file.append(f"{' ' * (level + 1)}const json_t *jval = yajl_to_json(val);\n") + c_file.append(f"{' ' * (level + 1)}if (jval != NULL)\n") c_file.append(f'{" " * (level + 1)} {{\n') c_file.append(f"{' ' * (level + 2)}{dest} = calloc (1, sizeof (bool));\n") c_file.append(f"{' ' * (level + 2)}if ({dest} == NULL)\n") c_file.append(f"{' ' * (level + 2)} return NULL;\n") - c_file.append(f"{' ' * (level + 2)}*({dest}) = YAJL_IS_TRUE(val);\n") + c_file.append(f"{' ' * (level + 2)}*({dest}) = json_is_true(jval);\n") c_file.append(f'{" " * (level + 1)}}}\n') c_file.append(f'{" " * (level)}}}\n') @@ -1236,6 +1243,7 @@ def get_c_epilog_for_array_make_parse(c_file, prefix, typ, obj): f"{typename}\n" + f"*make_{typename} (yajl_val tree, const struct parser_context *ctx, parser_error *err)\n" + "{\n" + + f" const json_t *jtree = yajl_to_json(tree);\n" f" __auto_cleanup(free_{typename}) {typename} *ptr = NULL;\n" + f" size_t i, alen;\n" + f" "+ @@ -1297,7 +1305,7 @@ def get_c_epilog_for_array_make_parse(c_file, prefix, typ, obj): c_file.append(' if (ptr->items[j] == NULL)\n') c_file.append(" return NULL;\n") else: - c_file.append(' char *str = YAJL_GET_STRING (tree);\n') + c_file.append(' char *str = json_string_value (jtree);\n') c_file.append(' memcpy(ptr->items, str ? str : "", strlen(str ? str : ""));\n') c_file.append(' break;\n') else: