diff --git a/Containerfile b/Containerfile new file mode 100644 index 00000000..886bf5b0 --- /dev/null +++ b/Containerfile @@ -0,0 +1,23 @@ +FROM ubuntu:22.04 + +RUN apt-get update && \ + apt-get install -y \ + autoconf \ + build-essential \ + git \ + libtool \ + pkg-config \ + python3 + + +COPY . libocispec + +RUN cd libocispec/jansson && autoreconf -fi && ./configure && make && make install + +RUN cd libocispec && \ + export JANSSON_CFLAGS=-I/usr/local/include && \ + export JANSSON_LIBS=/usr/local/lib/libjansson.so && \ + ./autogen.sh --enable-embedded-yajl && \ + ./configure --enable-embedded-yajl CFLAGS='-Wall -Wextra -Werror' && \ + make -j $(nproc) distcheck DISTCHECK_CONFIGURE_FLAGS="--enable-embedded-yajl" AM_DISTCHECK_DVI_TARGET="" TESTS="" && \ + make clean \ No newline at end of file diff --git a/src/ocispec/headers.py b/src/ocispec/headers.py index 4d1ff88c..34b04746 100755 --- a/src/ocispec/headers.py +++ b/src/ocispec/headers.py @@ -60,7 +60,7 @@ def append_header_arr(obj, header, prefix): typename = helpers.get_name_substr(obj.name, prefix) header.append(f"}}\n{typename};\n\n") header.append(f"void free_{typename} ({typename} *ptr);\n\n") - header.append(f"{typename} *make_{typename} (yajl_val tree, const struct parser_context *ctx, parser_error *err);\n\n") + header.append(f"{typename} *make_{typename} (json_t *jtree, const struct parser_context *ctx, parser_error *err);\n\n") def append_header_map_str_obj(obj, header, prefix): @@ -164,7 +164,7 @@ def append_type_c_header(obj, header, prefix): else: append_header_child_others(i, header, prefix) if obj.children is not None: - header.append(" yajl_val _residual;\n") + header.append(" json_t *_residual;\n") if len(present_tags) > 0: header.append("\n") for tag in present_tags: @@ -173,7 +173,7 @@ def append_type_c_header(obj, header, prefix): header.append(f"}}\n{typename};\n\n") header.append(f"void free_{typename} ({typename} *ptr);\n\n") header.append(f"{typename} *clone_{typename} ({typename} *src);\n") - header.append(f"{typename} *make_{typename} (yajl_val tree, const struct parser_context *ctx, parser_error *err);\n\n") + header.append(f"{typename} *make_{typename} (json_t *jtree, const struct parser_context *ctx, parser_error *err);\n\n") header.append(f"yajl_gen_status gen_{typename} (yajl_gen g, const {typename} *ptr, const struct parser_context *ctx, parser_error *err);\n\n") def header_reflect_top_array(obj, prefix, header): diff --git a/src/ocispec/json_common.c b/src/ocispec/json_common.c index 007d6839..bdec8d4c 100644 --- a/src/ocispec/json_common.c +++ b/src/ocispec/json_common.c @@ -106,9 +106,10 @@ gen_yajl_val (yajl_val obj, yajl_gen g, parser_error *err) } yajl_gen_status -gen_yajl_object_residual (yajl_val obj, yajl_gen g, parser_error *err) +gen_yajl_object_residual (json_t *j, yajl_gen g, parser_error *err) { size_t i; + yajl_val obj = json_to_yajl(j); yajl_gen_status stat = yajl_gen_status_ok; for (i = 0; i < obj->u.object.len; i++) @@ -1673,7 +1674,7 @@ free_json_map_string_string (json_map_string_string *map) define_cleaner_function (json_map_string_string *, free_json_map_string_string) json_map_string_string * -make_json_map_string_string (yajl_val src, const struct parser_context *ctx, +make_json_map_string_string (json_t *src, const struct parser_context *ctx, parser_error *err) { __auto_cleanup (free_json_map_string_string) json_map_string_string *ret = NULL; @@ -1681,10 +1682,11 @@ make_json_map_string_string (yajl_val src, const struct parser_context *ctx, size_t len; (void) ctx; /* Silence compiler warning. */ - if (src == NULL || YAJL_GET_OBJECT (src) == NULL) + if (src == NULL) return NULL; - len = YAJL_GET_OBJECT_NO_CHECK (src)->len; + + len = json_object_to_keys_values (src)->len; ret = calloc (1, sizeof (*ret)); if (ret == NULL) @@ -1710,8 +1712,8 @@ make_json_map_string_string (yajl_val src, const struct parser_context *ctx, } for (i = 0; i < len; i++) { - const char *srckey = YAJL_GET_OBJECT_NO_CHECK (src)->keys[i]; - yajl_val srcval = YAJL_GET_OBJECT_NO_CHECK (src)->values[i]; + const char *srckey = json_object_to_keys_values (src)->keys[i]; + json_t *srcval = &json_object_to_keys_values (src)->values[i]; ret->keys[i] = NULL; ret->values[i] = NULL; @@ -1734,7 +1736,7 @@ make_json_map_string_string (yajl_val src, const struct parser_context *ctx, return NULL; } - str = YAJL_GET_STRING_NO_CHECK (srcval); + str = json_string_value(srcval); ret->values[i] = strdup (str ? str : ""); if (ret->values[i] == NULL) @@ -1941,16 +1943,118 @@ json_t *yajl_to_json(yajl_val val) { jansson_array_values *json_array_to_struct(json_t *array) { if (!json_is_array(array)) { // Handle error: Input is not an array - return (jansson_array_values){NULL, 0}; + return NULL; } size_t len = json_array_size(array); - jansson_array_values r*esult = {json_array(), len}; + jansson_array_values *result = malloc(sizeof(jansson_array_values)); + if (!result) { + return NULL; // Handle allocation failure + } + + result->values = json_array(); + result->len = len; + + if (!result->values) { + free(result); + return NULL; // Handle allocation failure + } for (size_t i = 0; i < len; i++) { json_t *value = json_array_get(array, i); - json_array_append_new(result.values, json_incref(value)); + json_array_append_new(result->values, json_incref(value)); + } + + return result; +} + + +/** + * json_object_to_keys_values + * Input: json_t + * Output: jansson_object_keys_values * + * + * This method extracts keys and values and stores it in array of keys and values + */ +jansson_object_keys_values *json_object_to_keys_values(json_t *object) { + if (!json_is_object(object)) { + // Handle error: Input is not an object + return NULL; + } + + size_t len = json_object_size(object); + jansson_object_keys_values *result = malloc(sizeof(jansson_object_keys_values)); + if (!result) { + return NULL; // Handle allocation failure + } + + result->keys = calloc(len, sizeof(char*)); + result->values = json_array(); + result->len = len; + + if (!result->keys || !result->values) { + free(result->keys); + json_decref(result->values); + free(result); + return NULL; // Handle allocation failure + } + + json_t *key_iter = json_object_iter(object); + for (size_t i = 0; key_iter; key_iter = json_object_iter_next(object, key_iter)) { + const char *key = json_object_iter_key(key_iter); + json_t *value = json_object_iter_value(key_iter); + + result->keys[i] = strdup(key); + json_array_append_new(result->values, json_incref(value)); + i++; } return result; +} + + +/** + * copy_unmatched_fields + * Input: json_t, const char **, size_t + * Ouput: jsont_t + * + * We exxtract all the fields and we match them with the supplied keys if they don't match + * we add it to new json_t + */ +json_t *copy_unmatched_fields(json_t *src, const char **exclude_keys, size_t num_keys) { + json_t *dst = json_object(); + json_t *value; + + json_t *key_iter = json_object_iter(src); + while (key_iter) { + const char *key = json_object_iter_key(key_iter); + value = json_object_iter_value(key_iter); + + bool found = false; + for (size_t i = 0; i < num_keys; i++) { + if (strcmp(key, exclude_keys[i]) == 0) { + found = true; + break; + } + } + + if (!found) { + json_object_set_new(dst, key, json_incref(value)); + } + + key_iter = json_object_iter_next(src, key_iter); + } + + return dst; +} + +/** Temporary function we will not need it once transformation is done */ +yajl_val json_to_yajl(json_t *json) { + char errbuf[1024]; + + char *json_string = json_dumps(json, JSON_INDENT(2)); + if (!json_string) { + return NULL; + } + return yajl_tree_parse((const char *)json_string, errbuf, sizeof(errbuf)); } \ No newline at end of file diff --git a/src/ocispec/json_common.h b/src/ocispec/json_common.h index 02f8542d..530ef5f6 100644 --- a/src/ocispec/json_common.h +++ b/src/ocispec/json_common.h @@ -80,7 +80,7 @@ struct parser_context FILE *errfile; }; -yajl_gen_status gen_yajl_object_residual (yajl_val obj, yajl_gen g, parser_error *err); +yajl_gen_status gen_yajl_object_residual (json_t *j, yajl_gen g, parser_error *err); yajl_gen_status map_uint (void *ctx, long long unsigned int num); @@ -245,7 +245,7 @@ void free_json_map_string_string (json_map_string_string *map); json_map_string_string *clone_map_string_string (json_map_string_string *src); -json_map_string_string *make_json_map_string_string (yajl_val src, const struct parser_context *ctx, parser_error *err); +json_map_string_string *make_json_map_string_string (json_t *src, const struct parser_context *ctx, parser_error *err); yajl_gen_status gen_json_map_string_string (void *ctx, const json_map_string_string *map, const struct parser_context *ptx, parser_error *err); @@ -264,6 +264,19 @@ typedef struct jansson_array_values *json_array_to_struct(json_t *array); +typedef struct +{ + const char **keys; + json_t * values; + size_t len; +} jansson_object_keys_values; + +jansson_object_keys_values *json_object_to_keys_values(json_t *object); + +json_t *copy_unmatched_fields(json_t *src, const char **exclude_keys, size_t num_keys); + +yajl_val json_to_yajl(json_t *json); + #ifdef __cplusplus } #endif diff --git a/src/ocispec/sources.py b/src/ocispec/sources.py index bece04a5..e085c2da 100755 --- a/src/ocispec/sources.py +++ b/src/ocispec/sources.py @@ -59,8 +59,9 @@ def parse_map_string_obj(obj, c_file, prefix, obj_typename): c_file.append(' {\n') c_file.append(' size_t i;\n') c_file.append(' size_t len = json_object_size(jtree);\n') - c_file.append(' const char **keys = YAJL_GET_OBJECT_NO_CHECK (tree)->keys;\n') - c_file.append(' yajl_val *values = YAJL_GET_OBJECT_NO_CHECK (tree)->values;\n') + c_file.append(' jansson_object_keys_values *kvobj = json_object_to_keys_values(jtree);\n') + c_file.append(' const char **keys = kvobj->keys;\n') + c_file.append(' json_t *values = kvobj->values;\n') c_file.append(' ret->len = len;\n') c_file.append(' ret->keys = calloc (len + 1, sizeof (*ret->keys));\n') c_file.append(' if (ret->keys == NULL)\n') @@ -70,14 +71,12 @@ def parse_map_string_obj(obj, c_file, prefix, obj_typename): c_file.append(' return NULL;\n') c_file.append(' for (i = 0; i < len; i++)\n') c_file.append(' {\n') - c_file.append(' yajl_val val;\n') c_file.append(' json_t *jval;\n') c_file.append(' const char *tmpkey = keys[i];\n') c_file.append(' ret->keys[i] = strdup (tmpkey ? tmpkey : "");\n') c_file.append(' if (ret->keys[i] == NULL)\n') c_file.append(" return NULL;\n") - c_file.append(' val = values[i];\n') - c_file.append(' jval = yajl_to_json(values[i]);\n') + c_file.append(' jval = &values[i];\n') c_file.append(f' ret->{child.fixname}[i] = make_{childname} (jval, ctx, err);\n') c_file.append(f' if (ret->{child.fixname}[i] == NULL)\n') c_file.append(" return NULL;\n") @@ -93,13 +92,13 @@ def parse_obj_type_array(obj, c_file, prefix, obj_typename): typename = helpers.get_name_substr(obj.name, prefix) c_file.append(' do\n') c_file.append(' {\n') - c_file.append(f' yajl_val tmp = get_val (tree, "{obj.origname}", yajl_t_array);\n') - c_file.append(f' json_t *jtmp = yajl_to_json(tmp);\n') - c_file.append(' if (jtmp != NULL && json_array_to_struct (jtmp) != NULL)\n') + c_file.append(f' json_t *tmp = json_object_get (jtree, "{obj.origname}");\n') + c_file.append(f' jansson_array_values *jarray = json_array_to_struct(tmp);') + c_file.append(' if (tmp != NULL && jarray != NULL)\n') c_file.append(' {\n') c_file.append(' size_t i;\n') - c_file.append(' size_t len = json_array_size (jtmp);\n') - c_file.append(' json_t *values = json_array_to_struct (jtmp)->values;\n') + c_file.append(' size_t len = json_array_size (tmp);\n') + c_file.append(' json_t *values = jarray->values;\n') c_file.append(f' ret->{obj.fixname}_len = len;\n') c_file.append(f' ret->{obj.fixname} = calloc (len + 1, sizeof (*ret->{obj.fixname}));\n') c_file.append(f' if (ret->{obj.fixname} == NULL)\n') @@ -113,13 +112,13 @@ def parse_obj_type_array(obj, c_file, prefix, obj_typename): c_file.append(' json_t *val = &values[i];\n') if obj.doublearray: c_file.append(' size_t j;\n') - c_file.append(f' ret->{obj.fixname}[i] = calloc ( json_array_to_struct(val)->len + 1, sizeof (**ret->{obj.fixname}));\n') + c_file.append(f' ret->{obj.fixname}[i] = calloc ( jarray->len + 1, sizeof (**ret->{obj.fixname}));\n') c_file.append(f' if (ret->{obj.fixname}[i] == NULL)\n') c_file.append(' return NULL;\n') - c_file.append(' json_t *items = json_array_to_struct(val)->values;\n') - c_file.append(' for (j = 0; j < json_array_to_struct(val)->len; j++)\n') + c_file.append(' json_t *items = jarray->values;\n') + c_file.append(' for (j = 0; j < jarray->len; j++)\n') c_file.append(' {\n') - c_file.append(f' ret->{obj.fixname}[i][j] = make_{typename} (items[j], ctx, err);\n') + c_file.append(f' ret->{obj.fixname}[i][j] = make_{typename} (&items[j], ctx, err);\n') c_file.append(f' if (ret->{obj.fixname}[i][j] == NULL)\n') c_file.append(" return NULL;\n") c_file.append(f' ret->{obj.fixname}_item_lens[i] += 1;\n') @@ -163,12 +162,12 @@ def parse_obj_type_array(obj, c_file, prefix, obj_typename): else: c_file.append(' do\n') c_file.append(' {\n') - c_file.append(f' yajl_val tmp = get_val (tree, "{obj.origname}", yajl_t_array);\n') - c_file.append(' if (tmp != NULL && YAJL_GET_ARRAY (tmp) != NULL)\n') + c_file.append(f' json_t *tmp = json_object_get (jtree, "{obj.origname}");\n') + c_file.append(' if (tmp != NULL && (tmp) != NULL)\n') c_file.append(' {\n') c_file.append(' size_t i;\n') - c_file.append(' size_t len = YAJL_GET_ARRAY_NO_CHECK (tmp)->len;\n') - c_file.append(' yajl_val *values = YAJL_GET_ARRAY_NO_CHECK (tmp)->values;\n') + c_file.append(' size_t len = json_array_to_struct (tmp)->len;\n') + c_file.append(' json_t *values = json_array_to_struct(tmp)->values;\n') c_file.append(f' ret->{obj.fixname}_len = len;\n') c_file.append(f' ret->{obj.fixname} = calloc (len + 1, sizeof (*ret->{obj.fixname}));\n') c_file.append(f' if (ret->{obj.fixname} == NULL)\n') @@ -180,12 +179,12 @@ def parse_obj_type_array(obj, c_file, prefix, obj_typename): c_file.append(' for (i = 0; i < len; i++)\n') c_file.append(' {\n') if obj.doublearray: - c_file.append(' yajl_val *items = YAJL_GET_ARRAY_NO_CHECK(values[i])->values;\n') - c_file.append(f' ret->{obj.fixname}[i] = calloc ( YAJL_GET_ARRAY_NO_CHECK(values[i])->len + 1, sizeof (**ret->{obj.fixname}));\n') + c_file.append(' json_t *items = json_array_to_struct(&values[i])->values;\n') + c_file.append(f' ret->{obj.fixname}[i] = calloc ( json_array_to_struct(&values[i])->len + 1, sizeof (**ret->{obj.fixname}));\n') c_file.append(f' if (ret->{obj.fixname}[i] == NULL)\n') c_file.append(' return NULL;\n') c_file.append(' size_t j;\n') - c_file.append(' for (j = 0; j < YAJL_GET_ARRAY_NO_CHECK(values[i])->len; j++)\n') + c_file.append(' for (j = 0; j < json_array_to_struct(&values[i])->len; j++)\n') c_file.append(' {\n') read_val_generator(c_file, 5, 'items[j]', \ f"ret->{obj.fixname}[i][j]", obj.subtyp, obj.origname, obj_typename) @@ -208,35 +207,35 @@ def parse_obj_type(obj, c_file, prefix, obj_typename): if obj.typ == 'string': c_file.append(' do\n') c_file.append(' {\n') - read_val_generator(c_file, 2, f'get_val (tree, "{obj.origname}", yajl_t_string)', \ + read_val_generator(c_file, 2, f'json_object_get (jtree, "{obj.origname}")', \ f"ret->{obj.fixname}", obj.typ, obj.origname, obj_typename) c_file.append(' }\n') c_file.append(' while (0);\n') elif helpers.judge_data_type(obj.typ): c_file.append(' do\n') c_file.append(' {\n') - read_val_generator(c_file, 2, f'get_val (tree, "{obj.origname}", yajl_t_number)', \ + read_val_generator(c_file, 2, f'json_object_get (jtree, "{obj.origname}")', \ f"ret->{obj.fixname}", obj.typ, obj.origname, obj_typename) c_file.append(' }\n') c_file.append(' while (0);\n') elif helpers.judge_data_pointer_type(obj.typ): c_file.append(' do\n') c_file.append(' {\n') - read_val_generator(c_file, 2, f'get_val (tree, "{obj.origname}", yajl_t_number)', \ + read_val_generator(c_file, 2, f'json_object_get (jtree, "{obj.origname}")', \ f"ret->{obj.fixname}", obj.typ, obj.origname, obj_typename) c_file.append(' }\n') c_file.append(' while (0);\n') if obj.typ == 'boolean': c_file.append(' do\n') c_file.append(' {\n') - read_val_generator(c_file, 2, f'get_val (tree, "{obj.origname}", yajl_t_true)', \ + read_val_generator(c_file, 2, f'json_object_get (jtree, "{obj.origname}")', \ f"ret->{obj.fixname}", obj.typ, obj.origname, obj_typename) c_file.append(' }\n') c_file.append(' while (0);\n') if obj.typ == 'booleanPointer': c_file.append(' do\n') c_file.append(' {\n') - read_val_generator(c_file, 2, f'get_val (tree, "{obj.origname}", yajl_t_true)', \ + read_val_generator(c_file, 2, f'json_object_get (jtree, "{obj.origname}")', \ f"ret->{obj.fixname}", obj.typ, obj.origname, obj_typename) c_file.append(' }\n') c_file.append(' while (0);\n') @@ -246,7 +245,7 @@ def parse_obj_type(obj, c_file, prefix, obj_typename): else: typename = helpers.get_prefixed_name(obj.name, prefix) c_file.append( - f' ret->{obj.fixname} = make_{typename} (get_val (tree, "{obj.origname}", yajl_t_object), ctx, err);\n') + f' ret->{obj.fixname} = make_{typename} (json_object_get (jtree, "{obj.origname}"), ctx, err);\n') c_file.append(f" if (ret->{obj.fixname} == NULL && *err != 0)\n") c_file.append(" return NULL;\n") elif obj.typ == 'array': @@ -254,7 +253,7 @@ def parse_obj_type(obj, c_file, prefix, obj_typename): elif helpers.valid_basic_map_name(obj.typ): c_file.append(' do\n') c_file.append(' {\n') - c_file.append(f' yajl_val tmp = get_val (tree, "{obj.origname}", yajl_t_object);\n') + c_file.append(f' json_t *tmp = json_object_get (jtree, "{obj.origname}");\n') c_file.append(' if (tmp != NULL)\n') c_file.append(' {\n') c_file.append(f' ret->{obj.fixname} = make_{helpers.make_basic_map_name(obj.typ)} (tmp, ctx, err);\n') @@ -296,57 +295,25 @@ def parse_obj_arr_obj(obj, c_file, prefix, obj_typename): if obj.typ == 'object' and obj.children is not None: # O(n^2) complexity, but the objects should not really be big... - condition = "\n && ".join( \ - [f'strcmp (tree->u.object.keys[i], "{i.origname}")' for i in obj.children]) + + condition = ", ".join([f'"{i.origname}"' for i in obj.children]) c_file.append(""" - if (tree->type == yajl_t_object) + if (json_is_object(jtree)) { - size_t i; - size_t j = 0; - size_t cnt = tree->u.object.len; - yajl_val resi = NULL; - if (ctx->options & OPT_PARSE_FULLKEY) { - resi = calloc (1, sizeof(*tree)); - if (resi == NULL) - return NULL; - - resi->type = yajl_t_object; - resi->u.object.keys = calloc (cnt, sizeof (const char *)); - if (resi->u.object.keys == NULL) - { - yajl_tree_free (resi); - return NULL; - } - resi->u.object.values = calloc (cnt, sizeof (yajl_val)); - if (resi->u.object.values == NULL) - { - yajl_tree_free (resi); + if (jtree == NULL) return NULL; - } - } - - for (i = 0; i < tree->u.object.len; i++) - {\n""" \ - f" if ({condition})" \ - """{ - if (ctx->options & OPT_PARSE_FULLKEY) - { - resi->u.object.keys[j] = tree->u.object.keys[i]; - tree->u.object.keys[i] = NULL; - resi->u.object.values[j] = tree->u.object.values[i]; - tree->u.object.values[i] = NULL; - resi->u.object.len++; - } - j++; - } } + """ + f"const char *excluded[] = {'{'}{condition}{'}'};" + """ + size_t len = json_object_size(jtree); + json_t *resi = copy_unmatched_fields(jtree, excluded, len); - if ((ctx->options & OPT_PARSE_STRICT) && j > 0 && ctx->errfile != NULL) - (void) fprintf (ctx->errfile, "WARNING: unknown key found\\n"); + size_t resilen = json_object_size(resi); - if (ctx->options & OPT_PARSE_FULLKEY) + if (ctx->options & OPT_PARSE_FULLKEY && resi != NULL && resilen > 0) ret->_residual = resi; } """) @@ -710,8 +677,7 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): History: 2019-06-17 """ if helpers.valid_basic_map_name(typ): - c_file.append(f"{' ' * level}yajl_val val = {src};\n") - c_file.append(f"{' ' * level}const json_t *jval = yajl_to_json(val);\n") + c_file.append(f"{' ' * level}const json_t *jval = {src};\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)} (jval, ctx, err);\n') @@ -726,47 +692,50 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): c_file.append(f'{" " * (level + 1)} }}\n') 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 (jtree != NULL)\n") + if not (src.startswith("json") or src.startswith("work")): + src = '&' + src + c_file.append(f"{' ' * level}const json_t *val = {src};\n") + c_file.append(f"{' ' * level}if (val != NULL)\n") c_file.append(f"{' ' * (level)} {{\n") - c_file.append(f"{' ' * (level + 1)}char *str = json_string_value (jtree);\n") + c_file.append(f"{' ' * (level + 1)}char *str = json_string_value (val);\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}const json_t *jval = yajl_to_json(val);\n") - c_file.append(f"{' ' * level}if (jval != NULL)\n") + if not (src.startswith("json") or src.startswith("work")): + src = '&' + src + c_file.append(f"{' ' * level}const json_t *val = {src};\n") + c_file.append(f"{' ' * level}if (val != 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 (!json_is_number (jval))\n") + c_file.append(f"{' ' * (level + 1)}if (!json_is_number (val))\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 = json_double_to_{typ} (json_number_value(jval), &{dest});\n') + c_file.append(f'{" " * (level + 1)}invalid = json_double_to_{typ} (json_number_value(val), &{dest});\n') elif typ == "integer": c_file.append(f"{' ' * (level + 1)}int invalid;\n") - c_file.append(f"{' ' * (level + 1)}if (!json_is_number (jval))\n") + c_file.append(f"{' ' * (level + 1)}if (!json_is_number (val))\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 = json_double_to_int (json_number_value(jval), (int *)&{dest});\n') + c_file.append(f'{" " * (level + 1)}invalid = json_double_to_int (json_number_value(val), (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 (!json_is_number (jval))\n") + c_file.append(f"{' ' * (level + 1)}if (!json_is_number (val))\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 = json_double_to_uint (json_number_value(jval), (unsigned int *)&{dest});\n') + c_file.append(f'{" " * (level + 1)}invalid = json_double_to_uint (json_number_value(val), (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 \'%f\' with type \'{typ}\' for key \'{keyname}\': %s", json_number_value (jval), 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 (val), 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') @@ -777,20 +746,19 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): num_type = helpers.obtain_data_pointer_type(typ) if num_type == "": return - c_file.append(f"{' ' * level}yajl_val val = {src};\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}const json_t *val = {src};\n") + c_file.append(f"{' ' * level}if (val != 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 (! json_is_number (jval))\n") + c_file.append(f"{' ' * (level + 1)}if (! json_is_number (val))\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 = json_double_to_{num_type} (json_number_value(jval), {dest});\n') + c_file.append(f'{" " * (level + 1)}sinvalid = json_double_to_{num_type} (json_number_value(val), {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}\' ' \ @@ -800,17 +768,18 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): c_file.append(f'{" " * (level + 1)}}}\n') c_file.append(f'{" " * (level)}}}\n') elif typ == 'boolean': - c_file.append(f"{' ' * level}yajl_val val = {src};\n") - c_file.append(f"{' ' * level}const json_t *jval = yajl_to_json(val);\n") - c_file.append(f"{' ' * level}if (jval != NULL)\n") + if src.startswith("items"): + src = '&' + src + c_file.append(f"{' ' * level}json_t *val = {src};\n") + c_file.append(f"{' ' * level}if (val != NULL)\n") c_file.append(f'{" " * (level)} {{\n') - c_file.append(f"{' ' * (level + 1)}{dest} = json_is_true(jval);\n") + c_file.append(f"{' ' * (level + 1)}{dest} = json_is_true(val);\n") if '[' not in dest: c_file.append(f"{' ' * (level + 1)}{dest}_present = 1;\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 = {src.replace('yajl_t_true', 'yajl_t_false')};\n") + c_file.append(f"{' ' * (level + 1)}val = {src};\n") c_file.append(f"{' ' * (level + 1)}if (val != NULL)\n") c_file.append(f'{" " * (level+1)} {{\n') c_file.append(f"{' ' * (level + 2)}{dest} = 0;\n") @@ -818,9 +787,8 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): c_file.append(f'{" " * (level+1)} }}\n') c_file.append(f'{" " * (level)} }}\n') elif typ == 'booleanPointer': - c_file.append(f"{' ' * level}yajl_val val = {src};\n") + c_file.append(f"{' ' * level}json_t *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") @@ -829,14 +797,13 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): 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)}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)}val = json_object_get (jtree, "{keyname}");\n') + c_file.append(f"{' ' * (level + 1)}if (val != 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}) = json_is_true(jval);\n") + c_file.append(f"{' ' * (level + 2)}*({dest}) = json_is_true(val);\n") c_file.append(f'{" " * (level + 1)}}}\n') c_file.append(f'{" " * (level)}}}\n') @@ -1151,7 +1118,7 @@ def make_c_free (obj, c_file, prefix): c_file.append(" }\n") if obj.typ == 'object': if obj.children is not None: - c_file.append(" yajl_tree_free (ptr->_residual);\n") + c_file.append(" json_decref (ptr->_residual);\n") c_file.append(" ptr->_residual = NULL;\n") c_file.append(" free (ptr);\n") c_file.append("}\n\n") @@ -1224,8 +1191,6 @@ def src_reflect(structs, schema_info, c_file, root_typ): c_file.append('#include \n') c_file.append('#include \n') c_file.append(f'#include "ocispec/{schema_info.header.basename}"\n\n') - c_file.append('#define YAJL_GET_ARRAY_NO_CHECK(v) (&(v)->u.array)\n') - c_file.append('#define YAJL_GET_OBJECT_NO_CHECK(v) (&(v)->u.object)\n') for i in structs: append_c_code(i, c_file, schema_info.prefix) @@ -1273,8 +1238,8 @@ def get_c_epilog_for_array_make_parse(c_file, prefix, typ, obj): c_file.append("""\n for (i = 0; i < alen; i++) { - json_t work = json_array_to_struct (jtree)->values[i]; -"""); + json_t *work = &json_array_to_struct (jtree)->values[i]; +""") if obj.subtypobj or obj.subtyp == 'object': if obj.subtypname: @@ -1287,10 +1252,10 @@ def get_c_epilog_for_array_make_parse(c_file, prefix, typ, obj): c_file.append(' ptr->items[i] = calloc ( json_array_to_struct(work)->len + 1, sizeof (**ptr->items));\n') c_file.append(' if (ptr->items[i] == NULL)\n') c_file.append(' return NULL;\n') - c_file.append(' yajl_val *tmps = json_array_to_struct(work)->values;\n') + c_file.append(' json_t *tmps = json_array_to_struct(work)->values;\n') c_file.append(' for (j = 0; j < json_array_to_struct(work)->len; j++)\n') c_file.append(' {\n') - c_file.append(f' ptr->items[i][j] = make_{subtypename} (tmps[j], ctx, err);\n') + c_file.append(f' ptr->items[i][j] = make_{subtypename} (&tmps[j], ctx, err);\n') c_file.append(' if (ptr->items[i][j] == NULL)\n') c_file.append(" return NULL;\n") c_file.append(' ptr->subitem_lens[i] += 1;\n') @@ -1624,6 +1589,7 @@ def get_c_epilog(c_file, prefix, typ, obj): ctx = (const struct parser_context *)(&tmp_ctx); tree = yajl_tree_parse (jsondata, errbuf, sizeof (errbuf)); + // we will rename the jtree to tree once we use jansson to parse json_t *jtree = yajl_to_json(tree); if (jtree == NULL) { @@ -1631,8 +1597,8 @@ def get_c_epilog(c_file, prefix, typ, obj): *err = strdup ("error allocating memory"); return NULL; }\n""" + - f"ptr = make_{typename} (jtree, ctx, err);" + - "return ptr; \n}\n" + f"\tptr = make_{typename} (jtree, ctx, err);\n" + + "\treturn ptr; \n}\n" ) c_file.append("""\nstatic void\ncleanup_yajl_gen (yajl_gen g)