sources.py 47.1 KB
Newer Older
O
overweight 已提交
1 2
# -*- coding: utf-8 -*-
#!/usr/bin/python -Es
L
LiFeng 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#
# libocispec - a C library for parsing OCI spec files.
#
# Copyright (C) 2017, 2019 Giuseppe Scrivano <giuseppe@scrivano.org>
# Copyright (C) Huawei Technologies., Ltd. 2018-2019. All rights reserved.
#
# libocispec is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# libocispec is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libocispec.  If not, see <http://www.gnu.org/licenses/>.
#
O
overweight 已提交
22 23 24
import helpers


O
openeuler-iSula 已提交
25
def append_c_code(obj, c_file, prefix):
O
overweight 已提交
26 27 28 29 30
    """
    Description: append c language code to file
    Interface: None
    History: 2019-06-17
    """
O
openeuler-iSula 已提交
31 32 33
    parse_json_to_c(obj, c_file, prefix)
    make_c_free(obj, c_file, prefix)
    get_c_json(obj, c_file, prefix)
O
overweight 已提交
34

O
openeuler-iSula 已提交
35 36

def parse_map_string_obj(obj, c_file, prefix, obj_typename):
O
overweight 已提交
37 38 39 40 41 42
    """
    Description: generate c language for parse json map string object
    Interface: None
    History: 2019-06-17
    """
    child = obj.children[0]
O
openeuler-iSula 已提交
43 44
    if helpers.valid_basic_map_name(child.typ):
        childname = helpers.make_basic_map_name(child.typ)
O
overweight 已提交
45 46 47 48
    else:
        if child.subtypname:
            childname = child.subtypname
        else:
O
openeuler-iSula 已提交
49
            childname = helpers.get_prefixe_name(child.name, prefix)
O
overweight 已提交
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
    c_file.write('    if (YAJL_GET_OBJECT(tree) != NULL && YAJL_GET_OBJECT(tree)->len > 0) {\n')
    c_file.write('        size_t i;\n')
    c_file.write('        ret->len = YAJL_GET_OBJECT(tree)->len;\n')
    c_file.write('        ret->keys = safe_malloc((YAJL_GET_OBJECT(tree)->len + 1) ' \
                 '* sizeof(*ret->keys));\n')
    c_file.write('        ret->%s = safe_malloc((YAJL_GET_OBJECT(tree)->len + 1) ' \
                 '* sizeof(*ret->%s));\n' % (child.fixname, child.fixname))
    c_file.write('        for (i = 0; i < YAJL_GET_OBJECT(tree)->len; i++) {\n')
    c_file.write('            const char *tmpkey = YAJL_GET_OBJECT(tree)->keys[i];\n')
    c_file.write('            ret->keys[i] = safe_strdup(tmpkey ? tmpkey : "");\n')
    c_file.write('            yajl_val val = YAJL_GET_OBJECT(tree)->values[i];\n')
    c_file.write('            ret->%s[i] = make_%s(val, ctx, err);\n' \
                 % (child.fixname, childname))
    c_file.write('            if (ret->%s[i] == NULL) {\n' % (child.fixname))
    c_file.write("                free_%s(ret);\n" % obj_typename)
    c_file.write("                return NULL;\n")
    c_file.write('            }\n')
    c_file.write('        }\n')
    c_file.write('    }\n')

O
openeuler-iSula 已提交
70 71

def parse_obj_type(obj, c_file, prefix, obj_typename):
O
overweight 已提交
72 73 74 75 76 77 78
    """
    Description: generate c language for parse object type
    Interface: None
    History: 2019-06-17
    """
    if obj.typ == 'string':
        c_file.write('    {\n')
O
openeuler-iSula 已提交
79
        read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_string)' % obj.origname, \
O
overweight 已提交
80 81
                             "ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
        c_file.write('    }\n')
O
openeuler-iSula 已提交
82
    elif helpers.judge_data_type(obj.typ):
O
overweight 已提交
83
        c_file.write('    {\n')
O
openeuler-iSula 已提交
84
        read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_number)' % obj.origname, \
O
overweight 已提交
85 86
                             "ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
        c_file.write('    }\n')
O
openeuler-iSula 已提交
87
    elif helpers.judge_data_pointer_type(obj.typ):
O
overweight 已提交
88
        c_file.write('    {\n')
O
openeuler-iSula 已提交
89
        read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_number)' % obj.origname, \
O
overweight 已提交
90 91 92 93
                             "ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
        c_file.write('    }\n')
    if obj.typ == 'boolean':
        c_file.write('    {\n')
O
openeuler-iSula 已提交
94
        read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_true)' % obj.origname, \
O
overweight 已提交
95 96 97 98
                             "ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
        c_file.write('    }\n')
    if obj.typ == 'booleanPointer':
        c_file.write('    {\n')
O
openeuler-iSula 已提交
99
        read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_true)' % obj.origname, \
O
overweight 已提交
100 101 102 103 104 105
                             "ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
        c_file.write('    }\n')
    elif obj.typ == 'object' or obj.typ == 'mapStringObject':
        if obj.subtypname is not None:
            typename = obj.subtypname
        else:
O
openeuler-iSula 已提交
106
            typename = helpers.get_prefixe_name(obj.name, prefix)
O
overweight 已提交
107 108 109 110 111 112 113 114 115 116 117
        c_file.write(
            '    ret->%s = make_%s(get_val(tree, "%s", yajl_t_object), ctx, err);\n' \
            % (obj.fixname, typename, obj.origname))
        c_file.write("    if (ret->%s == NULL && *err != 0) {\n" % obj.fixname)
        c_file.write("        free_%s(ret);\n" % obj_typename)
        c_file.write("        return NULL;\n")
        c_file.write("    }\n")
    elif obj.typ == 'array' and (obj.subtypobj or obj.subtyp == 'object'):
        if obj.subtypname:
            typename = obj.subtypname
        else:
O
openeuler-iSula 已提交
118
            typename = helpers.get_name_substr(obj.name, prefix)
O
overweight 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
        c_file.write('    {\n')
        c_file.write('        yajl_val tmp = get_val(tree, "%s", yajl_t_array);\n' \
                     % (obj.origname))
        c_file.write('        if (tmp != NULL && YAJL_GET_ARRAY(tmp) != NULL &&' \
                     ' YAJL_GET_ARRAY(tmp)->len > 0) {\n')
        c_file.write('            size_t i;\n')
        c_file.write('            ret->%s_len = YAJL_GET_ARRAY(tmp)->len;\n' % (obj.fixname))
        c_file.write('            ret->%s = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) ' \
                     '* sizeof(*ret->%s));\n' % (obj.fixname, obj.fixname))
        c_file.write('            for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) {\n')
        c_file.write('                yajl_val val = YAJL_GET_ARRAY(tmp)->values[i];\n')
        c_file.write('                ret->%s[i] = make_%s(val, ctx, err);\n' \
                     % (obj.fixname, typename))
        c_file.write('                if (ret->%s[i] == NULL) {\n' % (obj.fixname))
        c_file.write("                    free_%s(ret);\n" % obj_typename)
        c_file.write("                    return NULL;\n")
        c_file.write('                }\n')
        c_file.write('            }\n')
        c_file.write('        }\n')
        c_file.write('    }\n')
    elif obj.typ == 'array' and obj.subtyp == 'byte':
        c_file.write('    {\n')
        c_file.write('        yajl_val tmp = get_val(tree, "%s", yajl_t_string);\n' \
                     % (obj.origname))
        c_file.write('        if (tmp != NULL) {\n')
        c_file.write('            char *str = YAJL_GET_STRING(tmp);\n')
        c_file.write('            ret->%s = (uint8_t *)safe_strdup(str ? str : "");\n' \
                     % obj.fixname)
        c_file.write('            ret->%s_len = str != NULL ? strlen(str) : 0;\n' \
                     % obj.fixname)
        c_file.write('        }\n')
        c_file.write('    }\n')
    elif obj.typ == 'array':
        c_file.write('    {\n')
        c_file.write('        yajl_val tmp = get_val(tree, "%s", yajl_t_array);\n' \
                     % (obj.origname))
        c_file.write('        if (tmp != NULL && YAJL_GET_ARRAY(tmp) != NULL &&'  \
                     ' YAJL_GET_ARRAY(tmp)->len > 0) {\n')
        c_file.write('            size_t i;\n')
        c_file.write('            ret->%s_len = YAJL_GET_ARRAY(tmp)->len;\n' % (obj.fixname))
        c_file.write(
            '            ret->%s = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) *' \
            ' sizeof(*ret->%s));\n' % (obj.fixname, obj.fixname))
        c_file.write('            for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) {\n')
O
openeuler-iSula 已提交
163
        read_val_generator(c_file, 4, 'YAJL_GET_ARRAY(tmp)->values[i]', \
O
overweight 已提交
164 165 166 167
                             "ret->%s[i]" % obj.fixname, obj.subtyp, obj.origname, obj_typename)
        c_file.write('            }\n')
        c_file.write('        }\n')
        c_file.write('    }\n')
O
openeuler-iSula 已提交
168
    elif helpers.valid_basic_map_name(obj.typ):
O
overweight 已提交
169 170 171 172 173
        c_file.write('    {\n')
        c_file.write('        yajl_val tmp = get_val(tree, "%s", yajl_t_object);\n' \
                     % (obj.origname))
        c_file.write('        if (tmp != NULL) {\n')
        c_file.write('            ret->%s = make_%s(tmp, ctx, err);\n' \
O
openeuler-iSula 已提交
174
                     % (obj.fixname, helpers.make_basic_map_name(obj.typ)))
O
overweight 已提交
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
        c_file.write('            if (ret->%s == NULL) {\n' % (obj.fixname))
        c_file.write('                char *new_error = NULL;\n')
        c_file.write("                if (asprintf(&new_error, \"Value error for key" \
                     " '%s': %%s\", *err ? *err : \"null\") < 0) {\n" % (obj.origname))
        c_file.write('                    new_error = safe_strdup(' \
                     '"error allocating memory");\n')
        c_file.write('                }\n')
        c_file.write('                free(*err);\n')
        c_file.write('                *err = new_error;\n')
        c_file.write('                free_%s(ret);\n' % obj_typename)
        c_file.write('                return NULL;\n')
        c_file.write('            }\n')
        c_file.write('        }\n')
        c_file.write('    }\n')

O
openeuler-iSula 已提交
190
def parse_obj_arr_obj(obj, c_file, prefix, obj_typename):
O
overweight 已提交
191 192 193 194 195 196 197 198 199
    """
    Description: generate c language for parse object or array object
    Interface: None
    History: 2019-06-17
    """
    nodes = obj.children if obj.typ == 'object' else obj.subtypobj
    required_to_check = []
    for i in nodes or []:
        if obj.required and i.origname in obj.required and \
O
openeuler-iSula 已提交
200
                not helpers.judge_data_type(i.typ) and i.typ != 'boolean':
O
overweight 已提交
201
            required_to_check.append(i)
O
openeuler-iSula 已提交
202
        parse_obj_type(i, c_file, prefix, obj_typename)
O
overweight 已提交
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228

    for i in required_to_check:
        c_file.write('    if (ret->%s == NULL) {\n' % i.fixname)
        c_file.write('        if (asprintf(err, "Required field \'%%s\' not present", ' \
                     ' "%s") < 0)\n' % i.origname)
        c_file.write('            *err = safe_strdup("error allocating memory");\n')
        c_file.write("        free_%s(ret);\n" % obj_typename)
        c_file.write("        return NULL;\n")
        c_file.write('    }\n')

    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( \
            ['strcmp(tree->u.object.keys[i], "%s")' % i.origname for i in obj.children])
        c_file.write("""
    if (tree->type == yajl_t_object && (ctx->options & OPT_PARSE_STRICT)) {
        size_t i;
        for (i = 0; i < tree->u.object.len; i++)
            if (%s) {
                if (ctx->stderr > 0)
                    (void)fprintf(ctx->stderr, "WARNING: unknown key found: %%s\\n",
                            tree->u.object.keys[i]);
            }
        }
""" % condition)

O
openeuler-iSula 已提交
229 230

def parse_json_to_c(obj, c_file, prefix):
O
overweight 已提交
231 232 233 234 235
    """
    Description: generate c language for parse json file
    Interface: None
    History: 2019-06-17
    """
O
openeuler-iSula 已提交
236
    if not helpers.judge_complex(obj.typ):
O
overweight 已提交
237 238 239 240
        return
    if obj.typ == 'object' or obj.typ == 'mapStringObject':
        if obj.subtypname:
            return
O
openeuler-iSula 已提交
241
        obj_typename = typename = helpers.get_prefixe_name(obj.name, prefix)
O
overweight 已提交
242
    if obj.typ == 'array':
O
openeuler-iSula 已提交
243
        obj_typename = typename = helpers.get_name_substr(obj.name, prefix)
O
overweight 已提交
244 245 246 247 248 249 250 251 252 253 254
        objs = obj.subtypobj
        if objs is None or obj.subtypname:
            return
    c_file.write("%s *make_%s(yajl_val tree, const struct parser_context *ctx, "\
        "parser_error *err) {\n" % (typename, typename))
    c_file.write("    %s *ret = NULL;\n" % (typename))
    c_file.write("    *err = 0;\n")
    c_file.write("    if (tree == NULL)\n")
    c_file.write("        return ret;\n")
    c_file.write("    ret = safe_malloc(sizeof(*ret));\n")
    if obj.typ == 'mapStringObject':
O
openeuler-iSula 已提交
255
        parse_map_string_obj(obj, c_file, prefix, obj_typename)
O
overweight 已提交
256 257

    if obj.typ == 'object' or (obj.typ == 'array' and obj.subtypobj):
O
openeuler-iSula 已提交
258
        parse_obj_arr_obj(obj, c_file, prefix, obj_typename)
O
overweight 已提交
259 260 261 262
    c_file.write('    return ret;\n')
    c_file.write("}\n\n")


O
openeuler-iSula 已提交
263
def get_map_string_obj(obj, c_file, prefix):
O
overweight 已提交
264 265 266 267 268 269
    """
    Description: c language generate map string object
    Interface: None
    History: 2019-06-17
    """
    child = obj.children[0]
O
openeuler-iSula 已提交
270 271
    if helpers.valid_basic_map_name(child.typ):
        childname = helpers.make_basic_map_name(child.typ)
O
overweight 已提交
272 273 274 275
    else:
        if child.subtypname:
            childname = child.subtypname
        else:
O
openeuler-iSula 已提交
276
            childname = helpers.get_prefixe_name(child.name, prefix)
O
overweight 已提交
277 278 279 280 281 282 283 284 285 286 287 288
    c_file.write('    size_t len = 0, i;\n')
    c_file.write("    if (ptr != NULL)\n")
    c_file.write("        len = ptr->len;\n")
    c_file.write("    if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n")
    c_file.write('        yajl_gen_config(g, yajl_gen_beautify, 0);\n')
    c_file.write("    stat = yajl_gen_map_open((yajl_gen)g);\n")
    c_file.write("    if (yajl_gen_status_ok != stat)\n")
    c_file.write("        GEN_SET_ERROR_AND_RETURN(stat, err);\n")
    c_file.write('    if (len ||(ptr != NULL && ptr->keys != NULL && ptr->%s != NULL)) {\n' \
                 % child.fixname)
    c_file.write('        for (i = 0; i < len; i++) {\n')
    c_file.write('            char *str = ptr->keys[i] ? ptr->keys[i] : "";\n')
O
openeuler-iSula 已提交
289 290
    c_file.write('            stat = yajl_gen_string((yajl_gen)g, \
        (const unsigned char *)str, strlen(str));\n')
O
overweight 已提交
291 292 293 294 295 296 297 298 299 300 301 302 303 304
    c_file.write("            if (yajl_gen_status_ok != stat)\n")
    c_file.write("                GEN_SET_ERROR_AND_RETURN(stat, err);\n")
    c_file.write('            stat = gen_%s(g, ptr->%s[i], ctx, err);\n' \
                 % (childname, child.fixname))
    c_file.write("            if (yajl_gen_status_ok != stat)\n")
    c_file.write("                GEN_SET_ERROR_AND_RETURN(stat, err);\n")
    c_file.write('        }\n')
    c_file.write('    }\n')
    c_file.write("    stat = yajl_gen_map_close((yajl_gen)g);\n")
    c_file.write("    if (yajl_gen_status_ok != stat)\n")
    c_file.write("        GEN_SET_ERROR_AND_RETURN(stat, err);\n")
    c_file.write("    if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n")
    c_file.write('        yajl_gen_config(g, yajl_gen_beautify, 1);\n')

O
openeuler-iSula 已提交
305 306

def get_obj_arr_obj(obj, c_file, prefix):
O
overweight 已提交
307 308 309 310 311 312 313 314 315
    """
    Description: c language generate object or array object
    Interface: None
    History: 2019-06-17
    """
    if obj.typ == 'string':
        c_file.write('    if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \
                     ' (ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
        c_file.write('        char *str = "";\n')
O
openeuler-iSula 已提交
316 317
        c_file.write('        stat = yajl_gen_string((yajl_gen)g, \
            (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
O
overweight 已提交
318 319 320 321 322
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write("        if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
        c_file.write("            str = ptr->%s;\n" % obj.fixname)
        c_file.write("        }\n")
O
openeuler-iSula 已提交
323
        json_value_generator(c_file, 2, "str", 'g', 'ctx', obj.typ)
O
overweight 已提交
324
        c_file.write("    }\n")
O
openeuler-iSula 已提交
325
    elif helpers.judge_data_type(obj.typ):
O
overweight 已提交
326 327 328 329 330 331 332 333 334
        c_file.write('    if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \
                     ' (ptr != NULL && ptr->%s)) {\n' % obj.fixname)
        if obj.typ == 'double':
            numtyp = 'double'
        elif obj.typ.startswith("uint") or obj.typ == 'GID' or obj.typ == 'UID':
            numtyp = 'long long unsigned int'
        else:
            numtyp = 'long long int'
        c_file.write('        %s num = 0;\n' % numtyp)
O
openeuler-iSula 已提交
335 336
        c_file.write('        stat = yajl_gen_string((yajl_gen)g, \
            (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
O
overweight 已提交
337 338 339 340 341
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write("        if (ptr != NULL && ptr->%s) {\n" % obj.fixname)
        c_file.write("            num = (%s)ptr->%s;\n" % (numtyp, obj.fixname))
        c_file.write("        }\n")
O
openeuler-iSula 已提交
342
        json_value_generator(c_file, 2, "num", 'g', 'ctx', obj.typ)
O
overweight 已提交
343
        c_file.write("    }\n")
O
openeuler-iSula 已提交
344
    elif helpers.judge_data_pointer_type(obj.typ):
O
overweight 已提交
345
        c_file.write('    if ((ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
O
openeuler-iSula 已提交
346
        numtyp = helpers.obtain_data_pointer_type(obj.typ)
O
overweight 已提交
347 348
        if numtyp == "":
            return
O
openeuler-iSula 已提交
349 350 351
        c_file.write('        %s num = 0;\n' % helpers.get_map_c_types(numtyp))
        c_file.write('        stat = yajl_gen_string((yajl_gen)g, \
            (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
O
overweight 已提交
352 353 354 355
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write("        if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
        c_file.write("            num = (%s)*(ptr->%s);\n" \
O
openeuler-iSula 已提交
356
                     % (helpers.get_map_c_types(numtyp), obj.fixname))
O
overweight 已提交
357
        c_file.write("        }\n")
O
openeuler-iSula 已提交
358
        json_value_generator(c_file, 2, "num", 'g', 'ctx', numtyp)
O
overweight 已提交
359 360 361 362 363
        c_file.write("    }\n")
    elif obj.typ == 'boolean':
        c_file.write('    if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \
                     ' (ptr != NULL && ptr->%s)) {\n' % obj.fixname)
        c_file.write('        bool b = false;\n')
O
openeuler-iSula 已提交
364 365
        c_file.write('        stat = yajl_gen_string((yajl_gen)g, \
            (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
O
overweight 已提交
366 367 368 369 370
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write("        if (ptr != NULL && ptr->%s) {\n" % obj.fixname)
        c_file.write("            b = ptr->%s;\n" % obj.fixname)
        c_file.write("        }\n")
O
openeuler-iSula 已提交
371
        json_value_generator(c_file, 2, "b", 'g', 'ctx', obj.typ)
O
overweight 已提交
372 373 374 375 376
        c_file.write("    }\n")
    elif obj.typ == 'object' or obj.typ == 'mapStringObject':
        if obj.subtypname:
            typename = obj.subtypname
        else:
O
openeuler-iSula 已提交
377
            typename = helpers.get_prefixe_name(obj.name, prefix)
O
overweight 已提交
378 379
        c_file.write('    if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \
                     ' (ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
O
openeuler-iSula 已提交
380 381
        c_file.write('        stat = yajl_gen_string((yajl_gen)g, \
            (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
O
overweight 已提交
382 383 384 385 386 387 388 389 390 391 392
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write('        stat = gen_%s(g, ptr != NULL ? ptr->%s : NULL, ctx, err);\n' \
                     % (typename, obj.fixname))
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write("    }\n")
    elif obj.typ == 'array' and (obj.subtypobj or obj.subtyp == 'object'):
        if obj.subtypname:
            typename = obj.subtypname
        else:
O
openeuler-iSula 已提交
393
            typename = helpers.get_name_substr(obj.name, prefix)
O
overweight 已提交
394 395 396
        c_file.write('    if ((ctx->options & OPT_GEN_KAY_VALUE) || ' \
                     '(ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
        c_file.write('        size_t len = 0, i;\n')
O
openeuler-iSula 已提交
397 398
        c_file.write('        stat = yajl_gen_string((yajl_gen)g, \
            (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
O
overweight 已提交
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write("        if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
        c_file.write("            len = ptr->%s_len;\n" % obj.fixname)
        c_file.write("        }\n")
        c_file.write("        if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n")
        c_file.write('            yajl_gen_config(g, yajl_gen_beautify, 0);\n')
        c_file.write('        stat = yajl_gen_array_open((yajl_gen)g);\n')
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write('        for (i = 0; i < len; i++) {\n')
        c_file.write('            stat = gen_%s(g, ptr->%s[i], ctx, err);\n' \
                     % (typename, obj.fixname))
        c_file.write("            if (yajl_gen_status_ok != stat)\n")
        c_file.write("                GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write('        }\n')
        c_file.write('        stat = yajl_gen_array_close((yajl_gen)g);\n')
        c_file.write("        if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n")
        c_file.write('            yajl_gen_config(g, yajl_gen_beautify, 1);\n')
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write('    }\n')
    elif obj.typ == 'array' and obj.subtyp == 'byte':
        c_file.write('    if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \
                     ' (ptr != NULL && ptr->%s != NULL && ptr->%s_len)) {\n' \
                     % (obj.fixname, obj.fixname))
        c_file.write('        const char *str = "";\n')
        c_file.write('        size_t len = 0;\n')
O
openeuler-iSula 已提交
427 428
        c_file.write('        stat = yajl_gen_string((yajl_gen)g, \
        (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
O
overweight 已提交
429 430 431 432 433 434
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write("        if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
        c_file.write("            str = (const char *)ptr->%s;\n" % obj.fixname)
        c_file.write("            len = ptr->%s_len;\n" % obj.fixname)
        c_file.write("        }\n")
O
openeuler-iSula 已提交
435 436
        c_file.write('        stat = yajl_gen_string((yajl_gen)g, \
        (const unsigned char *)str, len);\n')
O
overweight 已提交
437 438 439 440 441 442 443
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write("    }\n")
    elif obj.typ == 'array':
        c_file.write('    if ((ctx->options & OPT_GEN_KAY_VALUE) || ' \
                     '(ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
        c_file.write('        size_t len = 0, i;\n')
O
openeuler-iSula 已提交
444 445
        c_file.write('        stat = yajl_gen_string((yajl_gen)g, \
            (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
O
overweight 已提交
446 447 448 449 450 451 452 453 454 455 456
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write("        if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
        c_file.write("            len = ptr->%s_len;\n" % obj.fixname)
        c_file.write("        }\n")
        c_file.write("        if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n")
        c_file.write('            yajl_gen_config(g, yajl_gen_beautify, 0);\n')
        c_file.write('        stat = yajl_gen_array_open((yajl_gen)g);\n')
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write('        for (i = 0; i < len; i++) {\n')
O
openeuler-iSula 已提交
457
        json_value_generator(c_file, 3, "ptr->%s[i]" % obj.fixname, 'g', 'ctx', obj.subtyp)
O
overweight 已提交
458 459 460 461 462 463 464
        c_file.write('        }\n')
        c_file.write('        stat = yajl_gen_array_close((yajl_gen)g);\n')
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write("        if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n")
        c_file.write('            yajl_gen_config(g, yajl_gen_beautify, 1);\n')
        c_file.write('    }\n')
O
openeuler-iSula 已提交
465
    elif helpers.valid_basic_map_name(obj.typ):
O
overweight 已提交
466 467
        c_file.write('    if ((ctx->options & OPT_GEN_KAY_VALUE) || ' \
                     '(ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
O
openeuler-iSula 已提交
468 469
        c_file.write('        stat = yajl_gen_string((yajl_gen)g, \
        (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
O
overweight 已提交
470 471 472
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write('        stat = gen_%s(g, ptr ? ptr->%s : NULL, ctx, err);\n' \
O
openeuler-iSula 已提交
473
                     % (helpers.make_basic_map_name(obj.typ), obj.fixname))
O
overweight 已提交
474 475 476 477
        c_file.write("        if (yajl_gen_status_ok != stat)\n")
        c_file.write("            GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        c_file.write("    }\n")

O
openeuler-iSula 已提交
478 479

def get_c_json(obj, c_file, prefix):
O
overweight 已提交
480 481 482 483 484
    """
    Description: c language generate json file
    Interface: None
    History: 2019-06-17
    """
O
openeuler-iSula 已提交
485
    if not helpers.judge_complex(obj.typ) or obj.subtypname:
O
overweight 已提交
486 487
        return
    if obj.typ == 'object' or obj.typ == 'mapStringObject':
O
openeuler-iSula 已提交
488
        typename = helpers.get_prefixe_name(obj.name, prefix)
O
overweight 已提交
489
    elif obj.typ == 'array':
O
openeuler-iSula 已提交
490
        typename = helpers.get_name_substr(obj.name, prefix)
O
overweight 已提交
491 492 493 494 495 496 497 498 499
        objs = obj.subtypobj
        if objs is None:
            return
    c_file.write(
        "yajl_gen_status gen_%s(yajl_gen g, const %s *ptr, const struct parser_context " \
        "*ctx, parser_error *err) {\n" % (typename, typename))
    c_file.write("    yajl_gen_status stat = yajl_gen_status_ok;\n")
    c_file.write("    *err = 0;\n")
    if obj.typ == 'mapStringObject':
O
openeuler-iSula 已提交
500
        get_map_string_obj(obj, c_file, prefix)
O
overweight 已提交
501 502 503 504 505 506 507 508 509 510
    elif obj.typ == 'object' or (obj.typ == 'array' and obj.subtypobj):
        nodes = obj.children if obj.typ == 'object' else obj.subtypobj
        if nodes is None:
            c_file.write('    if (!(ctx->options & OPT_GEN_SIMPLIFY))\n')
            c_file.write('        yajl_gen_config(g, yajl_gen_beautify, 0);\n')

        c_file.write("    stat = yajl_gen_map_open((yajl_gen)g);\n")
        c_file.write("    if (yajl_gen_status_ok != stat)\n")
        c_file.write("        GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        for i in nodes or []:
O
openeuler-iSula 已提交
511
            get_obj_arr_obj(i, c_file, prefix)
O
overweight 已提交
512 513 514 515 516 517 518 519 520 521
        c_file.write("    stat = yajl_gen_map_close((yajl_gen)g);\n")
        c_file.write("    if (yajl_gen_status_ok != stat)\n")
        c_file.write("        GEN_SET_ERROR_AND_RETURN(stat, err);\n")
        if nodes is None:
            c_file.write('    if (!(ctx->options & OPT_GEN_SIMPLIFY))\n')
            c_file.write('        yajl_gen_config(g, yajl_gen_beautify, 1);\n')
    c_file.write('    return yajl_gen_status_ok;\n')
    c_file.write("}\n\n")


O
openeuler-iSula 已提交
522
def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename):
O
overweight 已提交
523 524 525 526 527
    """
    Description: read value generateor
    Interface: None
    History: 2019-06-17
    """
O
openeuler-iSula 已提交
528
    if helpers.valid_basic_map_name(typ):
O
overweight 已提交
529 530 531
        c_file.write('%syajl_val val = %s;\n' % ('    ' * level, src))
        c_file.write('%sif (val != NULL) {\n' % ('    ' * level))
        c_file.write('%s%s = make_%s(val, ctx, err);\n' \
O
openeuler-iSula 已提交
532
                     % ('    ' * (level + 1), dest, helpers.make_basic_map_name(typ)))
O
overweight 已提交
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
        c_file.write('%sif (%s == NULL) {\n' % ('    ' * (level + 1), dest))
        c_file.write('%s    char *new_error = NULL;\n' % ('    ' * (level + 1)))
        c_file.write("%s    if (asprintf(&new_error, \"Value error for key" \
                     " '%s': %%s\", *err ? *err : \"null\") < 0) {\n" \
                     % ('    ' * (level + 1), keyname))
        c_file.write('%s        new_error = safe_strdup("error allocating memory");\n' \
                     % ('    ' * (level + 1)))
        c_file.write('%s    }\n' % ('    ' * (level + 1)))
        c_file.write('%s    free(*err);\n' % ('    ' * (level + 1)))
        c_file.write('%s    *err = new_error;\n' % ('    ' * (level + 1)))
        c_file.write('%s    free_%s(ret);\n' % ('    ' * (level + 1), obj_typename))
        c_file.write('%s    return NULL;\n' % ('    ' * (level + 1)))
        c_file.write('%s}\n' % ('    ' * (level + 1)))
        c_file.write('%s}\n' % ('    ' * (level)))
    elif typ == 'string':
        c_file.write('%syajl_val val = %s;\n' % ('    ' * (level), src))
        c_file.write('%sif (val != NULL) {\n' % ('    ' * (level)))
        c_file.write('%schar *str = YAJL_GET_STRING(val);\n' % ('    ' * (level + 1)))
        c_file.write('%s%s = safe_strdup(str ? str : "");\n' % ('    ' * (level + 1), dest))
        c_file.write('%s}\n' % ('    ' * level))
O
openeuler-iSula 已提交
553
    elif helpers.judge_data_type(typ):
O
overweight 已提交
554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
        c_file.write('%syajl_val val = %s;\n' % ('    ' * (level), src))
        c_file.write('%sif (val != NULL) {\n' % ('    ' * (level)))
        if typ.startswith("uint") or \
                (typ.startswith("int") and typ != "integer") or typ == "double":
            c_file.write('%sint invalid = common_safe_%s(YAJL_GET_NUMBER(val), &%s);\n' \
                         % ('    ' * (level + 1), typ, dest))
        elif typ == "integer":
            c_file.write('%sint invalid = common_safe_int(YAJL_GET_NUMBER(val), (int *)&%s);\n' \
                         % ('    ' * (level + 1), dest))
        elif typ == "UID" or typ == "GID":
            c_file.write('%sint invalid = common_safe_uint(YAJL_GET_NUMBER(val),' \
                         ' (unsigned int *)&%s);\n' % ('    ' * (level + 1), dest))
        c_file.write('%sif (invalid) {\n' % ('    ' * (level + 1)))
        c_file.write('%s    if (asprintf(err, "Invalid value \'%%s\' with type \'%s\' '
                     'for key \'%s\': %%s", YAJL_GET_NUMBER(val), strerror(-invalid)) < 0)\n' \
                     % ('    ' * (level + 1), typ, keyname))
        c_file.write('%s        *err = safe_strdup("error allocating memory");\n' \
                     % ('    ' * (level + 1)))
        c_file.write('%s    free_%s(ret);\n' % ('    ' * (level + 1), obj_typename))
        c_file.write('%s    return NULL;\n' % ('    ' * (level + 1)))
        c_file.write('%s}\n' % ('    ' * (level + 1)))
        c_file.write('%s}\n' % ('    ' * (level)))
O
openeuler-iSula 已提交
576 577
    elif helpers.judge_data_pointer_type(typ):
        num_type = helpers.obtain_data_pointer_type(typ)
O
overweight 已提交
578 579 580 581 582
        if num_type == "":
            return
        c_file.write('%syajl_val val = %s;\n' % ('    ' * (level), src))
        c_file.write('%sif (val != NULL) {\n' % ('    ' * (level)))
        c_file.write('%s%s = safe_malloc(sizeof(%s));\n' %
O
openeuler-iSula 已提交
583
                     ('    ' * (level + 1), dest, helpers.get_map_c_types(num_type)))
O
overweight 已提交
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
        c_file.write('%sint invalid = common_safe_%s(YAJL_GET_NUMBER(val), %s);\n' \
                     % ('    ' * (level + 1), num_type, dest))
        c_file.write('%sif (invalid) {\n' % ('    ' * (level + 1)))
        c_file.write('%s    if (asprintf(err, "Invalid value \'%%s\' with type \'%s\' ' \
                     'for key \'%s\': %%s", YAJL_GET_NUMBER(val), strerror(-invalid)) < 0)\n' \
                     % ('    ' * (level + 1), typ, keyname))
        c_file.write('%s        *err = safe_strdup("error allocating memory");\n' \
                     % ('    ' * (level + 1)))
        c_file.write('%s    free_%s(ret);\n' % ('    ' * (level + 1), obj_typename))
        c_file.write('%s    return NULL;\n' % ('    ' * (level + 1)))
        c_file.write('%s}\n' % ('    ' * (level + 1)))
        c_file.write('%s}\n' % ('    ' * (level)))
    elif typ == 'boolean':
        c_file.write('%syajl_val val = %s;\n' % ('    ' * (level), src))
        c_file.write('%sif (val != NULL)\n' % ('    ' * (level)))
        c_file.write('%s%s = YAJL_IS_TRUE(val);\n' % ('    ' * (level + 1), dest))
    elif typ == 'booleanPointer':
        c_file.write('%syajl_val val = %s;\n' % ('    ' * (level), src))
        c_file.write('%sif (val != NULL) {\n' % ('    ' * (level)))
        c_file.write('%s%s = safe_malloc(sizeof(bool));\n' % ('    ' * (level + 1), dest))
        c_file.write('%s*(%s) = YAJL_IS_TRUE(val);\n' % ('    ' * (level + 1), dest))
        c_file.write('%s} else {\n' % ('    ' * (level)))
        c_file.write('%sval = get_val(tree, "%s", yajl_t_false);\n' \
                     % ('    ' * (level + 1), keyname))
        c_file.write('%sif (val != NULL) {\n' % ('    ' * (level + 1)))
        c_file.write('%s%s = safe_malloc(sizeof(bool));\n' % ('    ' * (level + 2), dest))
        c_file.write('%s*(%s) = YAJL_IS_TRUE(val);\n' % ('    ' * (level + 2), dest))
        c_file.write('%s}\n' % ('    ' * (level + 1)))
        c_file.write('%s}\n' % ('    ' * (level)))


O
openeuler-iSula 已提交
615
def json_value_generator(c_file, level, src, dst, ptx, typ):
O
overweight 已提交
616 617 618 619 620
    """
    Description: json value generateor
    Interface: None
    History: 2019-06-17
    """
O
openeuler-iSula 已提交
621
    if helpers.valid_basic_map_name(typ):
O
overweight 已提交
622
        c_file.write('%sstat = gen_%s(%s, %s, %s, err);\n' \
O
openeuler-iSula 已提交
623
                     % ('    ' * (level), helpers.make_basic_map_name(typ), dst, src, ptx))
O
overweight 已提交
624 625 626
        c_file.write("%sif (yajl_gen_status_ok != stat)\n" % ('    ' * (level)))
        c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" % ('    ' * (level + 1)))
    elif typ == 'string':
O
openeuler-iSula 已提交
627 628
        c_file.write('%sstat = yajl_gen_string((yajl_gen)%s, \
        (const unsigned char *)(%s), strlen(%s));\n' % ('    ' * (level), dst, src, src))
O
overweight 已提交
629 630
        c_file.write("%sif (yajl_gen_status_ok != stat)\n" % ('    ' * (level)))
        c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" % ('    ' * (level + 1)))
O
openeuler-iSula 已提交
631
    elif helpers.judge_data_type(typ):
O
overweight 已提交
632
        if typ == 'double':
O
openeuler-iSula 已提交
633 634
            c_file.write('%sstat = yajl_gen_double((yajl_gen)%s, %s);\n' \
                         % ('    ' * (level), dst, src))
O
overweight 已提交
635 636 637 638 639
        elif typ.startswith("uint") or typ == 'GID' or typ == 'UID':
            c_file.write('%sstat = map_uint(%s, %s);\n' % ('    ' * (level), dst, src))
        else:
            c_file.write('%sstat = map_int(%s, %s);\n' % ('    ' * (level), dst, src))
        c_file.write("%sif (yajl_gen_status_ok != stat)\n" % ('    ' * (level)))
O
openeuler-iSula 已提交
640 641
        c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" \
                     % ('    ' * (level + 1)))
O
overweight 已提交
642
    elif typ == 'boolean':
O
openeuler-iSula 已提交
643 644
        c_file.write('%sstat = yajl_gen_bool((yajl_gen)%s, (int)(%s));\n' \
                     % ('    ' * (level), dst, src))
O
overweight 已提交
645 646 647 648
        c_file.write("%sif (yajl_gen_status_ok != stat)\n" % ('    ' * (level)))
        c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" % ('    ' * (level + 1)))


O
openeuler-iSula 已提交
649
def make_c_free(obj, c_file, prefix):
O
overweight 已提交
650 651 652 653 654
    """
    Description: generate c free function
    Interface: None
    History: 2019-06-17
    """
O
openeuler-iSula 已提交
655
    if not helpers.judge_complex(obj.typ) or obj.subtypname:
O
overweight 已提交
656
        return
O
openeuler-iSula 已提交
657
    typename = helpers.get_prefixe_name(obj.name, prefix)
O
overweight 已提交
658
    case = obj.typ
O
openeuler-iSula 已提交
659 660
    result = {'mapStringObject': lambda x: [], 'object': lambda x: x.children,
              'array': lambda x: x.subtypobj}[case](obj)
O
overweight 已提交
661 662 663 664 665
    objs = result
    if obj.typ == 'array':
        if objs is None:
            return
        else:
O
openeuler-iSula 已提交
666
            typename = helpers.get_name_substr(obj.name, prefix)
O
overweight 已提交
667 668 669 670 671
    c_file.write("void free_%s(%s *ptr) {\n" % (typename, typename))
    c_file.write("    if (ptr == NULL)\n")
    c_file.write("        return;\n")
    if obj.typ == 'mapStringObject':
        child = obj.children[0]
O
openeuler-iSula 已提交
672 673
        if helpers.valid_basic_map_name(child.typ):
            childname = helpers.make_basic_map_name(child.typ)
O
overweight 已提交
674 675 676 677
        else:
            if child.subtypname:
                childname = child.subtypname
            else:
O
openeuler-iSula 已提交
678 679
                childname = helpers.get_prefixe_name(child.name, prefix)
        c_file_map_str(c_file, child, childname)
O
overweight 已提交
680
    for i in objs or []:
O
openeuler-iSula 已提交
681 682
        if helpers.valid_basic_map_name(i.typ):
            free_func = helpers.make_basic_map_name(i.typ)
O
overweight 已提交
683 684 685 686 687 688
            c_file.write("    free_%s(ptr->%s);\n" % (free_func, i.fixname))
            c_file.write("    ptr->%s = NULL;\n" % (i.fixname))
        if i.typ == 'mapStringObject':
            if i.subtypname:
                free_func = i.subtypname
            else:
O
openeuler-iSula 已提交
689
                free_func = helpers.get_prefixe_name(i.name, prefix)
O
overweight 已提交
690 691 692
            c_file.write("    free_%s(ptr->%s);\n" % (free_func, i.fixname))
            c_file.write("    ptr->%s = NULL;\n" % (i.fixname))
        elif i.typ == 'array':
O
openeuler-iSula 已提交
693 694
            if helpers.valid_basic_map_name(i.subtyp):
                free_func = helpers.make_basic_map_name(i.subtyp)
O
overweight 已提交
695 696 697 698 699 700 701 702 703 704 705 706
                c_file.write("    if (ptr->%s != NULL) {\n" % i.fixname)
                c_file.write("        size_t i;\n")
                c_file.write("        for (i = 0; i < ptr->%s_len; i++) {\n" % i.fixname)
                c_file.write("            if (ptr->%s[i] != NULL) {\n" % (i.fixname))
                c_file.write("                free_%s(ptr->%s[i]);\n" % (free_func, i.fixname))
                c_file.write("                ptr->%s[i] = NULL;\n" % (i.fixname))
                c_file.write("            }\n")
                c_file.write("        }\n")
                c_file.write("        free(ptr->%s);\n" % (i.fixname))
                c_file.write("        ptr->%s = NULL;\n" % (i.fixname))
                c_file.write("    }\n")
            elif i.subtyp == 'string':
O
openeuler-iSula 已提交
707 708
                c_file_str(c_file, i)
            elif not helpers.judge_complex(i.subtyp):
O
overweight 已提交
709 710 711 712 713 714
                c_file.write("    free(ptr->%s);\n" % (i.fixname))
                c_file.write("    ptr->%s = NULL;\n" % (i.fixname))
            elif i.subtyp == 'object' or i.subtypobj is not None:
                if i.subtypname is not None:
                    free_func = i.subtypname
                else:
O
openeuler-iSula 已提交
715
                    free_func = helpers.get_name_substr(i.name, prefix)
O
overweight 已提交
716 717 718 719 720 721 722 723 724 725
                c_file.write("    if (ptr->%s != NULL) {\n" % i.fixname)
                c_file.write("        size_t i;\n")
                c_file.write("        for (i = 0; i < ptr->%s_len; i++)\n" % i.fixname)
                c_file.write("            if (ptr->%s[i] != NULL) {\n" % (i.fixname))
                c_file.write("                free_%s(ptr->%s[i]);\n" % (free_func, i.fixname))
                c_file.write("                ptr->%s[i] = NULL;\n" % (i.fixname))
                c_file.write("            }\n")
                c_file.write("        free(ptr->%s);\n" % i.fixname)
                c_file.write("        ptr->%s = NULL;\n" % (i.fixname))
                c_file.write("    }\n")
O
openeuler-iSula 已提交
726
            c_typ = helpers.obtain_pointer(i.name, i.subtypobj, prefix)
O
overweight 已提交
727 728 729 730 731 732
            if c_typ == "":
                continue
            if i.subobj is not None:
                c_typ = c_typ + "_element"
            c_file.write("    free_%s(ptr->%s);\n" % (c_typ, i.fixname))
            c_file.write("    ptr->%s = NULL;\n" % (i.fixname))
O
openeuler-iSula 已提交
733 734 735 736
        else:
            typename = helpers.get_prefixe_name(i.name, prefix)
            if i.typ == 'string' or i.typ == 'booleanPointer' or \
                    helpers.judge_data_pointer_type(i.typ):
O
overweight 已提交
737 738 739 740 741 742 743 744 745 746 747 748 749
                c_file.write("    free(ptr->%s);\n" % (i.fixname))
                c_file.write("    ptr->%s = NULL;\n" % (i.fixname))
            elif i.typ == 'object':
                if i.subtypname is not None:
                    typename = i.subtypname
                c_file.write("    if (ptr->%s != NULL) {\n" % (i.fixname))
                c_file.write("        free_%s(ptr->%s);\n" % (typename, i.fixname))
                c_file.write("        ptr->%s = NULL;\n" % (i.fixname))
                c_file.write("    }\n")
    c_file.write("    free(ptr);\n")
    c_file.write("}\n\n")


O
openeuler-iSula 已提交
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
def c_file_map_str(c_file, child, childname):
    """
    Description: generate c code for map string
    Interface: None
    History: 2019-10-31
    """
    c_file.write("    if (ptr->keys != NULL && ptr->%s != NULL) {\n" % child.fixname)
    c_file.write("        size_t i;\n")
    c_file.write("        for (i = 0; i < ptr->len; i++) {\n")
    c_file.write("            free(ptr->keys[i]);\n")
    c_file.write("            ptr->keys[i] = NULL;\n")
    c_file.write("            free_%s(ptr->%s[i]);\n" % (childname, child.fixname))
    c_file.write("            ptr->%s[i] = NULL;\n" % (child.fixname))
    c_file.write("        }\n")
    c_file.write("        free(ptr->keys);\n")
    c_file.write("        ptr->keys = NULL;\n")
    c_file.write("        free(ptr->%s);\n" % (child.fixname))
    c_file.write("        ptr->%s = NULL;\n" % (child.fixname))
    c_file.write("    }\n")


def c_file_str(c_file, i):
    """
    Description: generate c code template
    Interface: None
    History: 2019-10-31
    """
    c_file.write("    if (ptr->%s != NULL) {\n" % i.fixname)
    c_file.write("        size_t i;\n")
    c_file.write("        for (i = 0; i < ptr->%s_len; i++) {\n" % i.fixname)
    c_file.write("            if (ptr->%s[i] != NULL) {\n" % (i.fixname))
    c_file.write("                free(ptr->%s[i]);\n" % (i.fixname))
    c_file.write("                ptr->%s[i] = NULL;\n" % (i.fixname))
    c_file.write("            }\n")
    c_file.write("        }\n")
    c_file.write("        free(ptr->%s);\n" % (i.fixname))
    c_file.write("        ptr->%s = NULL;\n" % (i.fixname))
    c_file.write("    }\n")


def src_reflect(structs, schema_info, c_file, root_typ):
O
overweight 已提交
791 792 793 794 795
    """
    Description: reflect code
    Interface: None
    History: 2019-06-17
    """
O
openeuler-iSula 已提交
796 797
    c_file.write("// Generated from %s. Do not edit!\n" \
                 % (schema_info.name.basename))
O
overweight 已提交
798 799 800 801 802 803 804
    c_file.write("#ifndef _GNU_SOURCE\n")
    c_file.write("#define _GNU_SOURCE\n")
    c_file.write("#endif\n")
    c_file.write('#include <string.h>\n')
    c_file.write('#include <read_file.h>\n')
    c_file.write('#include "%s"\n\n' % schema_info.header.basename)
    for i in structs:
O
openeuler-iSula 已提交
805 806
        append_c_code(i, c_file, schema_info.prefix)
    get_c_epilog(c_file, schema_info.prefix, root_typ)
O
overweight 已提交
807 808


O
openeuler-iSula 已提交
809
def get_c_epilog(c_file, prefix, typ):
O
overweight 已提交
810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
    """
    Description: generate c language epilogue
    Interface: None
    History: 2019-06-17
    """
    if typ != 'array' and typ != 'object':
        return
    if typ == 'array':
        c_file.write("""\n
%s_element **make_%s(yajl_val tree, const struct parser_context *ctx, parser_error *err, size_t *len) {
    %s_element **ptr = NULL;
    size_t i, alen;
    if (tree == NULL || err == NULL || !len || YAJL_GET_ARRAY(tree) == NULL)
        return NULL;
    *err = 0;
    alen = YAJL_GET_ARRAY(tree)->len;
    if (alen == 0)
        return NULL;
    ptr = safe_malloc((alen + 1) * sizeof(%s_element *));
    for (i = 0; i < alen; i++) {
        yajl_val val = YAJL_GET_ARRAY(tree)->values[i];
        ptr[i] = make_%s_element(val, ctx, err);
        if (ptr[i] == NULL) {
            free_%s(ptr, alen);
            return NULL;
        }
    }
    *len = alen;
    return ptr;
}
""" % (prefix, prefix, prefix, prefix, prefix, prefix))
        c_file.write("""\n
void free_%s(%s_element **ptr, size_t len) {
    size_t i;

    if (ptr == NULL || len == 0)
        return;

    for (i = 0; i < len; i++) {
        if (ptr[i] != NULL) {
            free_%s_element(ptr[i]);
            ptr[i] = NULL;
        }
    }
    free(ptr);
}
""" % (prefix, prefix, prefix))
        c_file.write("""\n
yajl_gen_status gen_%s(yajl_gen g, const %s_element **ptr, size_t len, const struct parser_context *ctx,
                       parser_error *err) {
    yajl_gen_status stat;
    size_t i;
    *err = 0;
    stat = yajl_gen_array_open((yajl_gen)g);
    if (yajl_gen_status_ok != stat)
        GEN_SET_ERROR_AND_RETURN(stat, err);
    for (i = 0; i < len; i++) {
        stat = gen_%s_element(g, ptr[i], ctx, err);
        if (yajl_gen_status_ok != stat)
            GEN_SET_ERROR_AND_RETURN(stat, err);
    }
    stat = yajl_gen_array_close((yajl_gen)g);
    if (yajl_gen_status_ok != stat)
        GEN_SET_ERROR_AND_RETURN(stat, err);
    return yajl_gen_status_ok;
}
""" % (prefix, prefix, prefix))
    c_file.write("""
%s%s*%s_parse_file(const char *filename, const struct parser_context *ctx, parser_error *err%s) {
    %s%s*ptr = NULL;""" % (prefix, ' ' if typ == 'object' else '_element *', \
                           prefix, '' if typ == 'object' else ', size_t *len', \
                           prefix, ' ' if typ == 'object' else '_element *'))
    c_file.write("""
    size_t filesize;
    char *content = NULL;

    if (filename == NULL || err == NULL)
        return NULL;

    *err = NULL;
    content = read_file(filename, &filesize);
    if (content == NULL) {
        if (asprintf(err, "cannot read the file: %%s", filename) < 0)
            *err = safe_strdup("error allocating memory");
        return NULL;
    }
    ptr = %s_parse_data(content, ctx, err%s);
    free(content);
    return ptr;
}
""" % (prefix, '' if typ == 'object' else ', len'))
    c_file.write("""
%s%s*%s_parse_file_stream(FILE *stream, const struct parser_context *ctx, parser_error *err%s) {
    %s%s*ptr = NULL;""" % (prefix, ' ' if typ == 'object' else '_element *', \
                           prefix, '' if typ == 'object' else ', size_t *len', \
                           prefix, ' ' if typ == 'object' else '_element *'))
    c_file.write("""
    size_t filesize;
    char *content = NULL ;

    if (stream == NULL || err == NULL)
        return NULL;

    *err = NULL;
    content = fread_file(stream, &filesize);
    if (content == NULL) {
        *err = safe_strdup("cannot read the file");
        return NULL;
    }
    ptr = %s_parse_data(content, ctx, err%s);
    free(content);
    return ptr;
}
""" % (prefix, '' if typ == 'object' else ', len'))
    c_file.write("""
%s%s*%s_parse_data(const char *jsondata, const struct parser_context *ctx, parser_error *err%s) {
    %s%s*ptr = NULL;""" % (prefix, ' ' if typ == 'object' else '_element *', \
                           prefix, '' if typ == 'object' else ', size_t *len', \
                           prefix, ' ' if typ == 'object' else '_element *'))
    c_file.write("""
    yajl_val tree;
    char errbuf[1024];
    struct parser_context tmp_ctx = { 0 };

    if (jsondata == NULL || err == NULL)
        return NULL;

    *err = NULL;
    if (ctx == NULL) {
       ctx = (const struct parser_context *)(&tmp_ctx);
    }
    tree = yajl_tree_parse(jsondata, errbuf, sizeof(errbuf));
    if (tree == NULL) {
        if (asprintf(err, "cannot parse the data: %%s", errbuf) < 0)
            *err = safe_strdup("error allocating memory");
        return NULL;
    }
    ptr = make_%s(tree, ctx, err%s);
    yajl_tree_free(tree);
    return ptr;
}
""" % (prefix, '' if typ == 'object' else ', len'))
    c_file.write("char *%s_generate_json(const %s%s*ptr%s, const struct parser_context *ctx," \
                 " parser_error *err) {" % (prefix, prefix, \
                                            ' ' if typ == 'object' else '_element *', \
                                            '' if typ == 'object' else ', size_t len'))
    c_file.write("""
    yajl_gen g = NULL;
    struct parser_context tmp_ctx = { 0 };
    const unsigned char *gen_buf = NULL;
    char *json_buf = NULL;
    size_t gen_len = 0;

    if (ptr == NULL || err == NULL)
        return NULL;

    *err = NULL;
    if (ctx == NULL) {
        ctx = (const struct parser_context *)(&tmp_ctx);
    }

    if (!json_gen_init(&g, ctx)) {
        *err = safe_strdup("Json_gen init failed");
        goto out;
    }
    if (yajl_gen_status_ok != gen_%s(g, ptr%s, ctx, err)) {
        if (*err == NULL)
            *err = safe_strdup("Failed to generate json");
        goto free_out;
    }
    yajl_gen_get_buf(g, &gen_buf, &gen_len);
    if (gen_buf == NULL) {
        *err = safe_strdup("Error to get generated json");
        goto free_out;
    }

    json_buf = safe_malloc(gen_len + 1);
O
openeuler-iSula 已提交
987
    (void)memcpy(json_buf, gen_buf, gen_len);
O
overweight 已提交
988 989 990 991 992 993 994 995 996 997
    json_buf[gen_len] = '\\0';

free_out:
    yajl_gen_clear(g);
    yajl_gen_free(g);
out:
    return json_buf;
}

""" % (prefix, '' if typ == 'object' else ', len'))
O
openeuler-iSula 已提交
998 999