diff --git a/src/ocispec/headers.py b/src/ocispec/headers.py
index cbf00de2..4d1ff88c 100755
--- a/src/ocispec/headers.py
+++ b/src/ocispec/headers.py
@@ -172,6 +172,7 @@ def append_type_c_header(obj, header, prefix):
typename = helpers.get_prefixed_name(obj.name, 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"yajl_gen_status gen_{typename} (yajl_gen g, const {typename} *ptr, const struct parser_context *ctx, parser_error *err);\n\n")
@@ -232,13 +233,13 @@ def header_reflect(structs, schema_info, header):
length = len(structs)
toptype = structs[length - 1].typ if length != 0 else ""
if toptype == 'object':
- header.append(f"{prefix} *{prefix}_parse_file(const char *filename, const struct parser_context *ctx, "\
+ header.append(f"{prefix} *{prefix}_parse_file (const char *filename, const struct parser_context *ctx, "\
"parser_error *err);\n\n")
- header.append(f"{prefix} *{prefix}_parse_file_stream(FILE *stream, const struct parser_context *ctx, "\
+ header.append(f"{prefix} *{prefix}_parse_file_stream (FILE *stream, const struct parser_context *ctx, "\
"parser_error *err);\n\n")
- header.append(f"{prefix} *{prefix}_parse_data(const char *jsondata, const struct parser_context *ctx, "\
+ header.append(f"{prefix} *{prefix}_parse_data (const char *jsondata, const struct parser_context *ctx, "\
"parser_error *err);\n\n")
- header.append(f"char *{prefix}_generate_json(const {prefix} *ptr, const struct parser_context *ctx, "\
+ header.append(f"char *{prefix}_generate_json (const {prefix} *ptr, const struct parser_context *ctx, "\
"parser_error *err);\n\n")
elif toptype == 'array':
header_reflect_top_array(structs[length - 1], prefix, header)
diff --git a/src/ocispec/json_common.c b/src/ocispec/json_common.c
index 9722b955..a8d742a7 100644
--- a/src/ocispec/json_common.c
+++ b/src/ocispec/json_common.c
@@ -509,7 +509,8 @@ free_json_map_int_int (json_map_int_int *map)
define_cleaner_function (json_map_int_int *, free_json_map_int_int)
- json_map_int_int *make_json_map_int_int (yajl_val src, const struct parser_context *ctx, parser_error *err)
+json_map_int_int *
+make_json_map_int_int (yajl_val src, const struct parser_context *ctx, parser_error *err)
{
__auto_cleanup (free_json_map_int_int) json_map_int_int *ret = NULL;
size_t i;
@@ -689,7 +690,8 @@ free_json_map_int_bool (json_map_int_bool *map)
define_cleaner_function (json_map_int_bool *, free_json_map_int_bool)
- json_map_int_bool *make_json_map_int_bool (yajl_val src, const struct parser_context *ctx, parser_error *err)
+json_map_int_bool *
+make_json_map_int_bool (yajl_val src, const struct parser_context *ctx, parser_error *err)
{
__auto_cleanup (free_json_map_int_bool) json_map_int_bool *ret = NULL;
size_t i;
@@ -861,7 +863,8 @@ free_json_map_int_string (json_map_int_string *map)
define_cleaner_function (json_map_int_string *, free_json_map_int_string)
- json_map_int_string *make_json_map_int_string (yajl_val src, const struct parser_context *ctx, parser_error *err)
+json_map_int_string *
+make_json_map_int_string (yajl_val src, const struct parser_context *ctx, parser_error *err)
{
__auto_cleanup (free_json_map_int_string) json_map_int_string *ret = NULL;
size_t i;
@@ -1020,7 +1023,8 @@ free_json_map_string_int (json_map_string_int *map)
define_cleaner_function (json_map_string_int *, free_json_map_string_int)
- json_map_string_int *make_json_map_string_int (yajl_val src, const struct parser_context *ctx, parser_error *err)
+json_map_string_int *
+make_json_map_string_int (yajl_val src, const struct parser_context *ctx, parser_error *err)
{
__auto_cleanup (free_json_map_string_int) json_map_string_int *ret = NULL;
size_t i;
@@ -1181,7 +1185,8 @@ free_json_map_string_int64 (json_map_string_int64 *map)
define_cleaner_function (json_map_string_int64 *, free_json_map_string_int64)
- json_map_string_int64 *make_json_map_string_int64 (yajl_val src, const struct parser_context *ctx,
+json_map_string_int64 *
+make_json_map_string_int64 (yajl_val src, const struct parser_context *ctx,
parser_error *err)
{
__auto_cleanup (free_json_map_string_int64) json_map_string_int64 *ret = NULL;
@@ -1316,7 +1321,8 @@ free_json_map_string_bool (json_map_string_bool *map)
define_cleaner_function (json_map_string_bool *, free_json_map_string_bool)
- json_map_string_bool *make_json_map_string_bool (yajl_val src, const struct parser_context *ctx, parser_error *err)
+json_map_string_bool *
+make_json_map_string_bool (yajl_val src, const struct parser_context *ctx, parser_error *err)
{
__auto_cleanup (free_json_map_string_bool) json_map_string_bool *ret = NULL;
size_t i;
@@ -1485,7 +1491,8 @@ 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,
+json_map_string_string *
+make_json_map_string_string (yajl_val src, const struct parser_context *ctx,
parser_error *err)
{
__auto_cleanup (free_json_map_string_string) json_map_string_string *ret = NULL;
@@ -1498,7 +1505,7 @@ define_cleaner_function (json_map_string_string *, free_json_map_string_string)
len = YAJL_GET_OBJECT_NO_CHECK (src)->len;
- ret = malloc (sizeof (*ret));
+ ret = calloc (sizeof (*ret), 1);
if (ret == NULL)
{
*(err) = strdup ("error allocating memory");
@@ -1558,6 +1565,42 @@ define_cleaner_function (json_map_string_string *, free_json_map_string_string)
return move_ptr (ret);
}
+json_map_string_string *
+clone_map_string_string (json_map_string_string *src)
+{
+ __auto_cleanup (free_json_map_string_string) json_map_string_string *ret = NULL;
+ size_t i;
+
+ if (src == NULL)
+ return NULL;
+
+ ret = calloc (sizeof (*ret), 1);
+ if (ret == NULL)
+ return NULL;
+
+ ret->len = src->len;
+
+ ret->keys = calloc (src->len + 1, sizeof (char *));
+ if (ret->keys == NULL)
+ return NULL;
+
+ ret->values = calloc (src->len + 1, sizeof (char *));
+ if (ret->values == NULL)
+ return NULL;
+
+ for (i = 0; i < src->len; i++)
+ {
+ ret->keys[i] = strdup (src->keys[i]);
+ if (ret->keys[i] == NULL)
+ return NULL;
+
+ ret->values[i] = strdup (src->values[i]);
+ if (ret->values[i] == NULL)
+ return NULL;
+ }
+ return move_ptr (ret);
+}
+
int
append_json_map_string_string (json_map_string_string *map, const char *key, const char *val)
{
@@ -1628,7 +1671,8 @@ cleanup_yajl_gen (yajl_gen g)
define_cleaner_function (yajl_gen, cleanup_yajl_gen)
- char *json_marshal_string (const char *str, size_t length, const struct parser_context *ctx, parser_error *err)
+char *
+json_marshal_string (const char *str, size_t length, const struct parser_context *ctx, parser_error *err)
{
__auto_cleanup (cleanup_yajl_gen) yajl_gen g = NULL;
struct parser_context tmp_ctx = { 0 };
diff --git a/src/ocispec/json_common.h b/src/ocispec/json_common.h
index 11f4a76b..41c73f59 100644
--- a/src/ocispec/json_common.h
+++ b/src/ocispec/json_common.h
@@ -220,6 +220,8 @@ typedef struct
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);
yajl_gen_status gen_json_map_string_string (void *ctx, const json_map_string_string *map,
diff --git a/src/ocispec/sources.py b/src/ocispec/sources.py
index f1c499d2..ebdd752c 100755
--- a/src/ocispec/sources.py
+++ b/src/ocispec/sources.py
@@ -37,9 +37,9 @@ def append_c_code(obj, c_file, prefix):
History: 2019-06-17
"""
parse_json_to_c(obj, c_file, prefix)
- make_c_free (obj, c_file, prefix)
+ make_c_free(obj, c_file, prefix)
get_c_json(obj, c_file, prefix)
-
+ make_clone(obj, c_file, prefix)
def parse_map_string_obj(obj, c_file, prefix, obj_typename):
"""
@@ -325,8 +325,8 @@ def parse_obj_arr_obj(obj, c_file, prefix, obj_typename):
}
for (i = 0; i < tree->u.object.len; i++)
- {""" \
- f"if ({condition})" \
+ {\n""" \
+ f" if ({condition})" \
"""{
if (ctx->options & OPT_PARSE_FULLKEY)
{
@@ -339,13 +339,12 @@ def parse_obj_arr_obj(obj, c_file, prefix, obj_typename):
j++;
}
}
- if (ctx->options & OPT_PARSE_STRICT)
- {
- if (j > 0 && ctx->errfile != NULL)
- (void) fprintf (ctx->errfile, "WARNING: unknown key found\\n");
- }
+
+ if ((ctx->options & OPT_PARSE_STRICT) && j > 0 && ctx->errfile != NULL)
+ (void) fprintf (ctx->errfile, "WARNING: unknown key found\\n");
+
if (ctx->options & OPT_PARSE_FULLKEY)
- ret->_residual = resi;
+ ret->_residual = resi;
}
""")
@@ -647,6 +646,7 @@ def get_obj_arr_obj(obj, c_file, prefix):
c_file.append(" GEN_SET_ERROR_AND_RETURN (stat, err);\n")
c_file.append(" }\n")
+
def get_c_json(obj, c_file, prefix):
"""
Description: c language generate json file
@@ -832,6 +832,149 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename):
c_file.append(f'{" " * (level)}}}\n')
+def make_clone(obj, c_file, prefix):
+ """
+ Description: generate a clone operation for the specified object
+ Interface: None
+ History: 2024-09-03
+ """
+
+ if not helpers.judge_complex(obj.typ) or obj.subtypname:
+ return
+ typename = helpers.get_prefixed_name(obj.name, prefix)
+ case = obj.typ
+ result = {'mapStringObject': lambda x: [], 'object': lambda x: x.children,
+ 'array': lambda x: x.subtypobj}[case](obj)
+ objs = result
+ if obj.typ == 'array':
+ if objs is None:
+ return
+ else:
+ typename = helpers.get_name_substr(obj.name, prefix)
+
+ c_file.append(f"{typename} *\nclone_{typename} ({typename} *src)\n")
+ c_file.append("{\n")
+ c_file.append(f" __auto_cleanup(free_{typename}) {typename} *ret = NULL;\n")
+
+ c_file.append(" ret = calloc (1, sizeof (*ret));\n")
+ c_file.append(" if (ret == NULL)\n")
+ c_file.append(" return NULL;\n")
+
+ nodes = obj.children if obj.typ == 'object' else obj.subtypobj
+ for i in nodes or []:
+ if helpers.judge_data_type(i.typ) or i.typ == 'boolean':
+ c_file.append(f" ret->{i.fixname} = src->{i.fixname};\n")
+ c_file.append(f" ret->{i.fixname}_present = src->{i.fixname}_present;\n")
+ elif i.typ == 'object':
+ node_name = i.subtypname or helpers.get_prefixed_name(i.name, prefix)
+ c_file.append(f" if (src->{i.fixname})\n")
+ c_file.append(f" {{\n")
+ c_file.append(f" ret->{i.fixname} = clone_{node_name} (src->{i.fixname});\n")
+ c_file.append(f" if (ret->{i.fixname} == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ c_file.append(f" }}\n")
+ elif i.typ == 'string':
+ c_file.append(f" if (src->{i.fixname})\n")
+ c_file.append(f" {{\n")
+ c_file.append(f" ret->{i.fixname} = strdup (src->{i.fixname});\n")
+ c_file.append(f" if (ret->{i.fixname} == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ c_file.append(f" }}\n")
+ elif i.typ == 'array':
+ c_file.append(f" if (src->{i.fixname})\n")
+ c_file.append(f" {{\n")
+ c_file.append(f" ret->{i.fixname}_len = src->{i.fixname}_len;\n")
+ c_file.append(f" ret->{i.fixname} = calloc (src->{i.fixname}_len + 1, sizeof (*ret->{i.fixname}));\n")
+ c_file.append(f" if (ret->{i.fixname} == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ c_file.append(f" for (size_t i = 0; i < src->{i.fixname}_len; i++)\n")
+ c_file.append(f" {{\n")
+ if helpers.judge_data_type(i.subtyp) or i.subtyp == 'boolean':
+ c_file.append(f" ret->{i.fixname}[i] = src->{i.fixname}[i];\n")
+ elif i.subtyp == 'object':
+ subnode_name = i.subtypname or helpers.get_prefixed_name(i.name, prefix)
+ if False: # i.subtypname is not None:
+ typename = i.subtypname
+ c_file.append(f" ret->{i.fixname}[i] = clone_{typename} (src->{i.fixname}[i]);\n")
+ c_file.append(f" if (ret->{i.fixname}[i] == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ else:
+ typename = helpers.get_prefixed_name(i.name, prefix)
+ if i.subtypname is not None:
+ typename = i.subtypname
+ maybe_element = "_element" if i.subtypname is None else ""
+ if i.doublearray:
+ c_file.append(f" ret->{i.fixname}_item_lens[i] = src->{i.fixname}_item_lens[i];\n")
+ c_file.append(f" ret->{i.fixname}[i] = calloc (ret->{i.fixname}_item_lens[i] + 1, sizeof (**ret->{i.fixname}[i]));\n")
+ c_file.append(f" if (ret->{i.fixname}[i] == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ c_file.append(f" for (size_t j = 0; j < src->{i.fixname}_item_lens[i]; j++)\n")
+ c_file.append(f" {{\n")
+ c_file.append(f" ret->{i.fixname}[i][j] = clone_{typename}{maybe_element} (src->{i.fixname}[i][j]);\n")
+ c_file.append(f" if (ret->{i.fixname}[i][j] == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ c_file.append(f" }}\n")
+ else:
+ c_file.append(f" ret->{i.fixname}[i] = clone_{typename}{maybe_element} (src->{i.fixname}[i]);\n")
+ c_file.append(f" if (ret->{i.fixname}[i] == NULL)\n")
+ c_file.append(f" return NULL;\n")
+
+ elif i.subtyp == 'string':
+ if i.doublearray:
+ c_file.append(f" ret->{i.fixname}[i] = calloc (ret->{i.fixname}_item_lens[i] + 1, sizeof (**ret->{i.fixname}[i]));\n")
+ c_file.append(f" if (ret->{i.fixname}[i] == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ c_file.append(f" for (size_t j = 0; j < src->{i.fixname}_item_lens[i]; j++)\n")
+ c_file.append(f" {{\n")
+ c_file.append(f" ret->{i.fixname}[i][j] = strdup (src->{i.fixname}[i][j]);\n")
+ c_file.append(f" if (ret->{i.fixname}[i][j] == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ c_file.append(f" }}\n")
+ else:
+ c_file.append(f" if (src->{i.fixname}[i])\n")
+ c_file.append(f" {{\n")
+ c_file.append(f" ret->{i.fixname}[i] = strdup (src->{i.fixname}[i]);\n")
+ c_file.append(f" if (ret->{i.fixname}[i] == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ c_file.append(f" }}\n")
+ else:
+ raise Exception("Unimplemented type for array clone: %s (%s)" % (i.subtyp, i.subtypname))
+ c_file.append(f" }}\n")
+ c_file.append(f" }}\n")
+ elif i.typ == 'mapStringString':
+ c_file.append(f" ret->{i.fixname} = clone_map_string_string (src->{i.fixname});\n")
+ c_file.append(f" if (ret->{i.fixname} == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ elif i.typ == 'mapStringObject':
+ c_file.append(f" if (src->{i.fixname})\n")
+ c_file.append(f" {{\n")
+ c_file.append(f" ret->{i.fixname} = calloc (1, sizeof ({i.subtypname}));\n")
+ c_file.append(f" if (ret->{i.fixname} == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ c_file.append(f" ret->{i.fixname}->len = src->{i.fixname}->len;\n")
+ c_file.append(f" ret->{i.fixname}->keys = calloc (src->{i.fixname}->len + 1, sizeof (char *));\n")
+ c_file.append(f" if (ret->{i.fixname}->keys == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ c_file.append(f" ret->{i.fixname}->values = calloc (src->{i.fixname}->len + 1, sizeof (*ret->{i.fixname}->values));\n")
+ c_file.append(f" if (ret->{i.fixname}->values == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ c_file.append(f" for (size_t i = 0; i < ret->{i.fixname}->len; i++)\n")
+ c_file.append(f" {{\n")
+ c_file.append(f" ret->{i.fixname}->keys[i] = strdup (src->{i.fixname}->keys[i]);\n")
+ c_file.append(f" if (ret->{i.fixname}->keys[i] == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ c_file.append(f" ret->{i.fixname}->values[i] = clone_{i.subtypname}_element (src->{i.fixname}->values[i]);\n")
+ c_file.append(f" if (ret->{i.fixname}->values[i] == NULL)\n")
+ c_file.append(f" return NULL;\n")
+ c_file.append(f" }}\n")
+ c_file.append(f" }}\n")
+ else:
+ raise Exception("Unimplemented type for clone: %s" % i.typ)
+
+ c_file.append(f" return move_ptr (ret);\n")
+ c_file.append("}\n\n")
+
+
def json_value_generator(c_file, level, src, dst, ptx, typ):
"""
Description: json value generateor
diff --git a/tests/test-1.c b/tests/test-1.c
index 705c021f..6e35b424 100644
--- a/tests/test-1.c
+++ b/tests/test-1.c
@@ -86,6 +86,9 @@ main ()
if (container->linux->seccomp == NULL || container->linux->seccomp->flags == NULL || container->linux->seccomp->flags_len != 0)
exit (5);
+ free_runtime_spec_schema_config_schema (clone_runtime_spec_schema_config_schema (container));
+ free_runtime_spec_schema_config_schema_process (clone_runtime_spec_schema_config_schema_process (container->process));
+
free(json_buf);
free_runtime_spec_schema_config_schema (container);
free_runtime_spec_schema_config_schema (container_gen);
diff --git a/tests/test-8.c b/tests/test-8.c
index ecea86a4..f066660a 100644
--- a/tests/test-8.c
+++ b/tests/test-8.c
@@ -22,12 +22,11 @@ along with libocispec. If not, see .
#include
#include "ocispec/image_manifest_items_image_manifest_items_schema.h"
-
int
main ()
{
parser_error err = NULL;
- image_manifest_items_image_manifest_items_schema_container *image_items =
+ image_manifest_items_image_manifest_items_schema_container *image_items =
image_manifest_items_image_manifest_items_schema_container_parse_file ("tests/data/image_manifest_item.json", 0, &err);
image_manifest_items_image_manifest_items_schema_container *image_items_gen = NULL;
char *json_buf = NULL;