# -*- coding: utf-8 -*-
'''
Description: commom source file
Interface: None
History: 2019-06-17
'''
# - Copyright (C) Huawei Technologies., Ltd. 2018-2019. All rights reserved.
# - lcr licensed under the Mulan PSL v1.
# - You can use this software according to the terms and conditions of the Mulan PSL v1.
# - You may obtain a copy of Mulan PSL v1 at:
# -     http://license.coscl.org.cn/MulanPSL
# - THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
# - IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
# - PURPOSE.
# - See the Mulan PSL v1 for more details.
# - Description: generate json
# - Author: tanyifeng
# - Create: 2018-04-25
#!/usr/bin/python -Es

CODE = '''// Auto generated file. Do not edit!
# define _GNU_SOURCE
# include <stdio.h>
# include <errno.h>
# include <limits.h>
# include "json_common.h"

# define MAX_NUM_STR_LEN 21



yajl_gen_status map_uint(void *ctx, long long unsigned int num) {
    char numstr[MAX_NUM_STR_LEN];
    int ret;

    ret = sprintf_s(numstr, sizeof(numstr), "%llu", num);
    if (ret < 0) {
        return yajl_gen_in_error_state;
    }
    return yajl_gen_number((yajl_gen)ctx, (const char *)numstr, strlen(numstr));
}

yajl_gen_status map_int(void *ctx, long long int num) {
    char numstr[MAX_NUM_STR_LEN];
    int ret;

    ret = sprintf_s(numstr, sizeof(numstr), "%lld", num);
    if (ret < 0) {
        return yajl_gen_in_error_state;
    }
    return yajl_gen_number((yajl_gen)ctx, (const char *)numstr, strlen(numstr));
}


bool json_gen_init(yajl_gen *g, const struct parser_context *ctx) {
    *g = yajl_gen_alloc(NULL);
    if (NULL == *g) {
        return false;

    }
    yajl_gen_config(*g, yajl_gen_beautify, (int)(!(ctx->options & OPT_GEN_SIMPLIFY)));
    yajl_gen_config(*g, yajl_gen_validate_utf8, (int)(!(ctx->options & OPT_GEN_NO_VALIDATE_UTF8)));
    return true;
}

yajl_val get_val(yajl_val tree, const char *name, yajl_type type) {
    const char *path[] = { name, NULL };
    return yajl_tree_get(tree, path, type);
}

void *safe_malloc(size_t size) {
    void *ret = NULL;
    if (size == 0) {
        abort();
    }
    ret = calloc(1, size);
    if (ret == NULL) {
        abort();
    }
    return ret;
}

int common_safe_double(const char *numstr, double *converted) {
    char *err_str = NULL;
    double d;

    if (numstr == NULL) {
        return -EINVAL;
    }

    errno = 0;
    d = strtod(numstr, &err_str);
    if (errno > 0) {
        return -errno;
    }

    if (err_str == NULL || err_str == numstr || *err_str != '\\0') {
        return -EINVAL;
    }

    *converted = d;
    return 0;
}

int common_safe_uint8(const char *numstr, uint8_t *converted) {
    char *err = NULL;
    unsigned long int uli;

    if (numstr == NULL) {
        return -EINVAL;
    }

    errno = 0;
    uli = strtoul(numstr, &err, 0);
    if (errno > 0) {
        return -errno;
    }

    if (err == NULL || err == numstr || *err != '\\0') {
        return -EINVAL;
    }

    if (uli > UINT8_MAX) {
        return -ERANGE;
    }

    *converted = (uint8_t)uli;
    return 0;
}

int common_safe_uint16(const char *numstr, uint16_t *converted) {
    char *err = NULL;
    unsigned long int uli;

    if (numstr == NULL) {
        return -EINVAL;
    }

    errno = 0;
    uli = strtoul(numstr, &err, 0);
    if (errno > 0) {
        return -errno;
    }

    if (err == NULL || err == numstr || *err != '\\0') {
        return -EINVAL;
    }

    if (uli > UINT16_MAX) {
        return -ERANGE;
    }

    *converted = (uint16_t)uli;
    return 0;
}

int common_safe_uint32(const char *numstr, uint32_t *converted) {
    char *err = NULL;
    unsigned long long int ull;

    if (numstr == NULL) {
        return -EINVAL;
    }

    errno = 0;
    ull = strtoull(numstr, &err, 0);
    if (errno > 0) {
        return -errno;
    }

    if (err == NULL || err == numstr || *err != '\\0') {
        return -EINVAL;
    }

    if (ull > UINT32_MAX) {
        return -ERANGE;
    }

    *converted = (uint32_t)ull;
    return 0;
}

int common_safe_uint64(const char *numstr, uint64_t *converted) {
    char *err = NULL;
    unsigned long long int ull;

    if (numstr == NULL) {
        return -EINVAL;
    }

    errno = 0;
    ull = strtoull(numstr, &err, 0);
    if (errno > 0) {
        return -errno;
    }

    if (err == NULL || err == numstr || *err != '\\0') {
        return -EINVAL;
    }

    *converted = (uint64_t)ull;
    return 0;
}

int common_safe_uint(const char *numstr, unsigned int *converted) {
    char *err = NULL;
    unsigned long long int ull;

    if (numstr == NULL) {
        return -EINVAL;
    }

    errno = 0;
    ull = strtoull(numstr, &err, 0);
    if (errno > 0) {
        return -errno;
    }

    if (err == NULL || err == numstr || *err != '\\0') {
        return -EINVAL;
    }

    if (ull > UINT_MAX) {
        return -ERANGE;
    }

    *converted = (unsigned int)ull;
    return 0;
}

int common_safe_int8(const char *numstr, int8_t *converted) {
    char *err = NULL;
    long int li;

    if (numstr == NULL) {
        return -EINVAL;
    }

    errno = 0;
    li = strtol(numstr, &err, 0);
    if (errno > 0) {
        return -errno;
    }

    if (err == NULL || err == numstr || *err != '\\0') {
        return -EINVAL;
    }

    if (li > INT8_MAX || li < INT8_MIN) {
        return -ERANGE;
    }

    *converted = (int8_t)li;
    return 0;
}

int common_safe_int16(const char *numstr, int16_t *converted) {
    char *err = NULL;
    long int li;

    if (numstr == NULL) {
        return -EINVAL;
    }

    errno = 0;
    li = strtol(numstr, &err, 0);
    if (errno > 0) {
        return -errno;
    }

    if (err == NULL || err == numstr || *err != '\\0') {
        return -EINVAL;
    }

    if (li > INT16_MAX || li < INT16_MIN) {
        return -ERANGE;
    }

    *converted = (int16_t)li;
    return 0;
}

int common_safe_int32(const char *numstr, int32_t *converted) {
    char *err = NULL;
    long long int lli;

    if (numstr == NULL) {
        return -EINVAL;
    }

    errno = 0;
    lli = strtol(numstr, &err, 0);
    if (errno > 0) {
        return -errno;
    }

    if (err == NULL || err == numstr || *err != '\\0') {
        return -EINVAL;
    }

    if (lli > INT32_MAX || lli < INT32_MIN) {
        return -ERANGE;
    }

    *converted = (int32_t)lli;
    return 0;
}

int common_safe_int64(const char *numstr, int64_t *converted) {
    char *err = NULL;
    long long int lli;

    if (numstr == NULL) {
        return -EINVAL;
    }

    errno = 0;
    lli = strtoll(numstr, &err, 0);
    if (errno > 0) {
        return -errno;
    }

    if (err == NULL || err == numstr || *err != '\\0') {
        return -EINVAL;
    }

    *converted = (int64_t)lli;
    return 0;
}

int common_safe_int(const char *numstr, int *converted) {
    char *err = NULL;
    long long int lli;

    if (numstr == NULL) {
        return -EINVAL;
    }

    errno = 0;
    lli = strtol(numstr, &err, 0);
    if (errno > 0) {
        return -errno;
    }

    if (err == NULL || err == numstr || *err != '\\0') {
        return -EINVAL;
    }

    if (lli > INT_MAX || lli < INT_MIN) {
        return -ERANGE;
    }

    *converted = (int)lli;
    return 0;
}

char *safe_strdup(const char *src)
{
    char *dst = NULL;

    if (src == NULL) {
        return NULL;
    }

    dst = strdup(src);
    if (dst == NULL) {
        abort();
    }

    return dst;
}


yajl_gen_status gen_json_map_int_int(void *ctx, const json_map_int_int *map, const struct parser_context *ptx, parser_error *err) {
    yajl_gen_status stat = yajl_gen_status_ok;
    yajl_gen g = (yajl_gen) ctx;
    size_t len = 0, i = 0;
    if (map != NULL) {
        len = map->len;
    }
    if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) {
        yajl_gen_config(g, yajl_gen_beautify, 0);
    }
    stat = yajl_gen_map_open((yajl_gen)g);
    if (yajl_gen_status_ok != stat) {
        GEN_SET_ERROR_AND_RETURN(stat, err);

    }
    for (i = 0; i < len; i++) {
        char numstr[MAX_NUM_STR_LEN];
        int nret;
        nret = sprintf_s(numstr, sizeof(numstr), "%lld", (long long int)map->keys[i]);
        if (nret < 0) {
            if (!*err && asprintf(err, "Error to print string") < 0) {
                *(err) = safe_strdup("error allocating memory");
            }
            return yajl_gen_in_error_state;
        }
        stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)numstr, strlen(numstr));
        if (yajl_gen_status_ok != stat) {
            GEN_SET_ERROR_AND_RETURN(stat, err);
        }
        stat = map_int(g, map->values[i]);
        if (yajl_gen_status_ok != stat) {
            GEN_SET_ERROR_AND_RETURN(stat, err);
        }
    }

    stat = yajl_gen_map_close((yajl_gen)g);
    if (yajl_gen_status_ok != stat) {
        GEN_SET_ERROR_AND_RETURN(stat, err);
    }
    if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) {
        yajl_gen_config(g, yajl_gen_beautify, 1);
    }
    return yajl_gen_status_ok;
}

void free_json_map_int_int(json_map_int_int *map) {
    if (map != NULL) {
        free(map->keys);
        map->keys = NULL;
        free(map->values);
        map->values = NULL;
        free(map);
    }
}
json_map_int_int *make_json_map_int_int(yajl_val src, const struct parser_context *ctx, parser_error *err) {
    json_map_int_int *ret = NULL;
    if (src != NULL && YAJL_GET_OBJECT(src) != NULL) {
        size_t i;
        size_t len = YAJL_GET_OBJECT(src)->len;
        ret = safe_malloc(sizeof(*ret));
        ret->len = len;
        ret->keys = safe_malloc((len + 1) * sizeof(int));
        ret->values = safe_malloc((len + 1) * sizeof(int));
        for (i = 0; i < len; i++) {
            const char *srckey = YAJL_GET_OBJECT(src)->keys[i];
            yajl_val srcval = YAJL_GET_OBJECT(src)->values[i];

            if (srckey != NULL) {
                int invalid;
                invalid = common_safe_int(srckey, &(ret->keys[i]));
                if (invalid) {
                    if (*err == NULL && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) {
                        *(err) = safe_strdup("error allocating memory");
                    }
                    free_json_map_int_int(ret);
                    return NULL;
                }
            }

            if (srcval != NULL) {
                int invalid;
                if (!YAJL_IS_NUMBER(srcval)) {
                    if (*err == NULL && asprintf(err, "Invalid value with type 'int' for key '%s'", srckey) < 0) {
                        *(err) = safe_strdup("error allocating memory");
                    }
                    free_json_map_int_int(ret);
                    return NULL;
                }
                invalid = common_safe_int(YAJL_GET_NUMBER(srcval), &(ret->values[i]));
                if (invalid) {
                    if (*err == NULL && asprintf(err, "Invalid value with type 'int' for key '%s': %s", srckey, strerror(-invalid)) < 0) {
                        *(err) = safe_strdup("error allocating memory");
                    }
                    free_json_map_int_int(ret);
                    return NULL;
                }
            }
        }
    }
    return ret;
}
int append_json_map_int_int(json_map_int_int *map, int key, int val) {
    size_t len;
    int *keys = NULL;
    int *vals = NULL;

    if (map == NULL) {
        return -1;
    }

    if ((SIZE_MAX / sizeof(int) - 1) < map->len) {
        return -1;
    }

    len = map->len + 1;
    keys = safe_malloc(len * sizeof(int));
    vals = safe_malloc(len * sizeof(int));

    if (map->len) {
        if (memcpy_s(keys, len * sizeof(int), map->keys, map->len * sizeof(int)) != EOK) {
            free(keys);
            free(vals);
            return -1;
        }
        if (memcpy_s(vals, len * sizeof(int), map->values, map->len * sizeof(int)) != EOK) {
            free(keys);
            free(vals);
            return -1;
        }
    }
    free(map->keys);
    map->keys = keys;
    free(map->values);
    map->values = vals;
    map->keys[map->len] = key;
    map->values[map->len] = val;

    map->len++;
    return 0;
}

yajl_gen_status gen_json_map_int_bool(void *ctx, const json_map_int_bool *map, const struct parser_context *ptx, parser_error *err) {
    yajl_gen_status stat = yajl_gen_status_ok;
    yajl_gen g = (yajl_gen) ctx;
    size_t len = 0, i = 0;
    if (map != NULL) {
        len = map->len;
    }
    if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) {
        yajl_gen_config(g, yajl_gen_beautify, 0);
    }
    stat = yajl_gen_map_open((yajl_gen)g);
    if (yajl_gen_status_ok != stat) {
        GEN_SET_ERROR_AND_RETURN(stat, err);

    }
    for (i = 0; i < len; i++) {
        char numstr[MAX_NUM_STR_LEN];
        int nret;
        nret = sprintf_s(numstr, sizeof(numstr), "%lld", (long long int)map->keys[i]);
        if (nret < 0) {
            if (!*err && asprintf(err, "Error to print string") < 0) {
                *(err) = safe_strdup("error allocating memory");
            }
            return yajl_gen_in_error_state;
        }
        stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)numstr, strlen(numstr));
        if (yajl_gen_status_ok != stat) {
            GEN_SET_ERROR_AND_RETURN(stat, err);
        }
        stat = yajl_gen_bool((yajl_gen)g, (int)(map->values[i]));
        if (yajl_gen_status_ok != stat) {
            GEN_SET_ERROR_AND_RETURN(stat, err);
        }
    }

    stat = yajl_gen_map_close((yajl_gen)g);
    if (yajl_gen_status_ok != stat) {
        GEN_SET_ERROR_AND_RETURN(stat, err);
    }
    if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) {
        yajl_gen_config(g, yajl_gen_beautify, 1);
    }
    return yajl_gen_status_ok;
}

void free_json_map_int_bool(json_map_int_bool *map) {
    if (map != NULL) {
        size_t i;
        for (i = 0; i < map->len; i++) {
            // No need to free key for type int
            // No need to free value for type bool
        }
        free(map->keys);
        map->keys = NULL;
        free(map->values);
        map->values = NULL;
        free(map);
    }
}
json_map_int_bool *make_json_map_int_bool(yajl_val src, const struct parser_context *ctx, parser_error *err) {
    json_map_int_bool *ret = NULL;
    if (src != NULL && YAJL_GET_OBJECT(src) != NULL) {
        size_t i;
        size_t len = YAJL_GET_OBJECT(src)->len;
        ret = safe_malloc(sizeof(*ret));
        ret->len = len;
        ret->keys = safe_malloc((len + 1) * sizeof(int));
        ret->values = safe_malloc((len + 1) * sizeof(bool));
        for (i = 0; i < len; i++) {
            const char *srckey = YAJL_GET_OBJECT(src)->keys[i];
            yajl_val srcval = YAJL_GET_OBJECT(src)->values[i];

            if (srckey != NULL) {
                int invalid;
                invalid = common_safe_int(srckey, &(ret->keys[i]));
                if (invalid) {
                    if (*err == NULL && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) {
                        *(err) = safe_strdup("error allocating memory");
                    }
                    free_json_map_int_bool(ret);
                    return NULL;
                }
            }

            if (srcval != NULL) {
                if (YAJL_IS_TRUE(srcval)) {
                    ret->values[i] = true;
                } else if (YAJL_IS_FALSE(srcval)) {
                    ret->values[i] = false;
                } else {
                    if (*err == NULL && asprintf(err, "Invalid value with type 'bool' for key '%s'", srckey) < 0) {
                        *(err) = safe_strdup("error allocating memory");
                    }
                    free_json_map_int_bool(ret);
                    return NULL;
                }
            }
        }
    }
    return ret;
}
int append_json_map_int_bool(json_map_int_bool *map, int key, bool val) {
    size_t len;
    int *keys = NULL;
    bool *vals = NULL;

    if (map == NULL) {
        return -1;
    }

    if ((SIZE_MAX / sizeof(int) - 1) < map->len || (SIZE_MAX / sizeof(bool) - 1) < map->len) {
        return -1;
    }

    len = map->len + 1;
    keys = safe_malloc(len * sizeof(int));
    vals = safe_malloc(len * sizeof(bool));

    if (map->len) {
        if (memcpy_s(keys, len * sizeof(int), map->keys, map->len * sizeof(int)) != EOK) {
            free(keys);
            free(vals);
            return -1;
        }
        if (memcpy_s(vals, len * sizeof(bool), map->values, map->len * sizeof(bool)) != EOK) {
            free(keys);
            free(vals);
            return -1;
        }
    }
    free(map->keys);
    map->keys = keys;
    free(map->values);
    map->values = vals;
    map->keys[map->len] = key;
    map->values[map->len] = val;

    map->len++;
    return 0;
}

yajl_gen_status gen_json_map_int_string(void *ctx, const json_map_int_string *map, const struct parser_context *ptx, parser_error *err) {
    yajl_gen_status stat = yajl_gen_status_ok;
    yajl_gen g = (yajl_gen) ctx;
    size_t len = 0, i = 0;
    if (map != NULL) {
        len = map->len;
    }
    if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) {
        yajl_gen_config(g, yajl_gen_beautify, 0);
    }
    stat = yajl_gen_map_open((yajl_gen)g);
    if (yajl_gen_status_ok != stat) {
        GEN_SET_ERROR_AND_RETURN(stat, err);

    }
    for (i = 0; i < len; i++) {
        char numstr[MAX_NUM_STR_LEN];
        int nret;
        nret = sprintf_s(numstr, sizeof(numstr), "%lld", (long long int)map->keys[i]);
        if (nret < 0) {
            if (!*err && asprintf(err, "Error to print string") < 0) {
                *(err) = safe_strdup("error allocating memory");
            }
            return yajl_gen_in_error_state;
        }
        stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)numstr, strlen(numstr));
        if (yajl_gen_status_ok != stat) {
            GEN_SET_ERROR_AND_RETURN(stat, err);
        }
        stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)(map->values[i]), strlen(map->values[i]));
        if (yajl_gen_status_ok != stat) {
            GEN_SET_ERROR_AND_RETURN(stat, err);
        }
    }

    stat = yajl_gen_map_close((yajl_gen)g);
    if (yajl_gen_status_ok != stat) {
        GEN_SET_ERROR_AND_RETURN(stat, err);
    }
    if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) {
        yajl_gen_config(g, yajl_gen_beautify, 1);
    }
    return yajl_gen_status_ok;
}

void free_json_map_int_string(json_map_int_string *map) {
    if (map != NULL) {
        size_t i;
        for (i = 0; i < map->len; i++) {
            // No need to free key for type int
            free(map->values[i]);
            map->values[i] = NULL;
        }
        free(map->keys);
        map->keys = NULL;
        free(map->values);
        map->values = NULL;
        free(map);
    }
}
json_map_int_string *make_json_map_int_string(yajl_val src, const struct parser_context *ctx, parser_error *err) {
    json_map_int_string *ret = NULL;
    if (src != NULL && YAJL_GET_OBJECT(src) != NULL) {
        size_t i;
        size_t len = YAJL_GET_OBJECT(src)->len;
        ret = safe_malloc(sizeof(*ret));
        ret->len = len;
        ret->keys = safe_malloc((len + 1) * sizeof(int));
        ret->values = safe_malloc((len + 1) * sizeof(char *));
        for (i = 0; i < len; i++) {
            const char *srckey = YAJL_GET_OBJECT(src)->keys[i];
            yajl_val srcval = YAJL_GET_OBJECT(src)->values[i];

            if (srckey != NULL) {
                int invalid;
                invalid = common_safe_int(srckey, &(ret->keys[i]));
                if (invalid) {
                    if (*err == NULL && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) {
                        *(err) = safe_strdup("error allocating memory");
                    }
                    free_json_map_int_string(ret);
                    return NULL;
                }
            }

            if (srcval != NULL) {
                if (!YAJL_IS_STRING(srcval)) {
                    if (*err == NULL && asprintf(err, "Invalid value with type 'string' for key '%s'", srckey) < 0) {
                        *(err) = safe_strdup("error allocating memory");
                    }
                    free_json_map_int_string(ret);
                    return NULL;
                }
                char *str = YAJL_GET_STRING(srcval);
                ret->values[i] = safe_strdup(str ? str : "");
            }
        }
    }
    return ret;
}
int append_json_map_int_string(json_map_int_string *map, int key, const char *val) {
    size_t len;
    int *keys = NULL;
    char **vals = NULL;

    if (map == NULL) {
        return -1;
    }

    if ((SIZE_MAX / sizeof(int) - 1) < map->len || (SIZE_MAX / sizeof(char *) - 1) < map->len) {
        return -1;
    }

    len = map->len + 1;
    keys = safe_malloc(len * sizeof(int));
    vals = safe_malloc(len * sizeof(char *));

    if (map->len) {
        if (memcpy_s(keys, len * sizeof(int), map->keys, map->len * sizeof(int)) != EOK) {
            free(keys);
            free(vals);
            return -1;
        }
        if (memcpy_s(vals, len * sizeof(char *), map->values, map->len * sizeof(char *)) != EOK) {
            free(keys);
            free(vals);
            return -1;
        }
    }
    free(map->keys);
    map->keys = keys;
    free(map->values);
    map->values = vals;
    map->keys[map->len] = key;
    map->values[map->len] = safe_strdup(val ? val : "");

    map->len++;
    return 0;
}

yajl_gen_status gen_json_map_string_int(void *ctx, const json_map_string_int *map, const struct parser_context *ptx, parser_error *err) {
    yajl_gen_status stat = yajl_gen_status_ok;
    yajl_gen g = (yajl_gen) ctx;
    size_t len = 0, i = 0;
    if (map != NULL) {
        len = map->len;
    }
    if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) {
        yajl_gen_config(g, yajl_gen_beautify, 0);
    }
    stat = yajl_gen_map_open((yajl_gen)g);
    if (yajl_gen_status_ok != stat) {
        GEN_SET_ERROR_AND_RETURN(stat, err);

    }
    for (i = 0; i < len; i++) {
        stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)(map->keys[i]), strlen(map->keys[i]));
        if (yajl_gen_status_ok != stat) {
            GEN_SET_ERROR_AND_RETURN(stat, err);
        }
        stat = map_int(g, map->values[i]);
        if (yajl_gen_status_ok != stat) {
            GEN_SET_ERROR_AND_RETURN(stat, err);
        }
    }

    stat = yajl_gen_map_close((yajl_gen)g);
    if (yajl_gen_status_ok != stat) {
        GEN_SET_ERROR_AND_RETURN(stat, err);
    }
    if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) {
        yajl_gen_config(g, yajl_gen_beautify, 1);
    }
    return yajl_gen_status_ok;
}

void free_json_map_string_int(json_map_string_int *map) {
    if (map != NULL) {
        size_t i;
        for (i = 0; i < map->len; i++) {
            free(map->keys[i]);
            map->keys[i] = NULL;
        }
        free(map->keys);
        map->keys = NULL;
        free(map->values);
        map->values = NULL;
        free(map);
    }
}
json_map_string_int *make_json_map_string_int(yajl_val src, const struct parser_context *ctx, parser_error *err) {
    json_map_string_int *ret = NULL;
    if (src != NULL && YAJL_GET_OBJECT(src) != NULL) {
        size_t i;
        size_t len = YAJL_GET_OBJECT(src)->len;
        ret = safe_malloc(sizeof(*ret));
        ret->len = len;
        ret->keys = safe_malloc((len + 1) * sizeof(char *));
        ret->values = safe_malloc((len + 1) * sizeof(int));
        for (i = 0; i < len; i++) {
            const char *srckey = YAJL_GET_OBJECT(src)->keys[i];
            yajl_val srcval = YAJL_GET_OBJECT(src)->values[i];
            ret->keys[i] = safe_strdup(srckey ? srckey : "");

            if (srcval != NULL) {
                int invalid;
                if (!YAJL_IS_NUMBER(srcval)) {
                    if (*err == NULL && asprintf(err, "Invalid value with type 'int' for key '%s'", srckey) < 0) {
                        *(err) = safe_strdup("error allocating memory");
                    }
                    free_json_map_string_int(ret);
                    return NULL;
                }
                invalid = common_safe_int(YAJL_GET_NUMBER(srcval), &(ret->values[i]));
                if (invalid) {
                    if (*err == NULL && asprintf(err, "Invalid value with type 'int' for key '%s': %s", srckey, strerror(-invalid)) < 0) {
                        *(err) = safe_strdup("error allocating memory");
                    }
                    free_json_map_string_int(ret);
                    return NULL;
                }
            }
        }
    }
    return ret;
}
int append_json_map_string_int(json_map_string_int *map, const char *key, int val) {
    size_t len;
    char **keys = NULL;
    int *vals = NULL;

    if (map == NULL) {
        return -1;
    }

    if ((SIZE_MAX / sizeof(char *) - 1) < map->len || (SIZE_MAX / sizeof(int) - 1) < map->len) {
        return -1;
    }

    len = map->len + 1;
    keys = safe_malloc(len * sizeof(char *));
    vals = safe_malloc(len * sizeof(int));

    if (map->len) {
        if (memcpy_s(keys, len * sizeof(char *), map->keys, map->len * sizeof(char *)) != EOK) {
            free(keys);
            free(vals);
            return -1;
        }
        if (memcpy_s(vals, len * sizeof(int), map->values, map->len * sizeof(int)) != EOK) {
            free(keys);
            free(vals);
            return -1;
        }
    }
    free(map->keys);
    map->keys = keys;
    free(map->values);
    map->values = vals;
    map->keys[map->len] = safe_strdup(key ? key : "");
    map->values[map->len] = val;

    map->len++;
    return 0;
}

yajl_gen_status gen_json_map_string_bool(void *ctx, const json_map_string_bool *map, const struct parser_context *ptx, parser_error *err) {
    yajl_gen_status stat = yajl_gen_status_ok;
    yajl_gen g = (yajl_gen) ctx;
    size_t len = 0, i = 0;
    if (map != NULL) {
        len = map->len;
    }
    if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) {
        yajl_gen_config(g, yajl_gen_beautify, 0);
    }
    stat = yajl_gen_map_open((yajl_gen)g);
    if (yajl_gen_status_ok != stat) {
        GEN_SET_ERROR_AND_RETURN(stat, err);

    }
    for (i = 0; i < len; i++) {
        stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)(map->keys[i]), strlen(map->keys[i]));
        if (yajl_gen_status_ok != stat) {
            GEN_SET_ERROR_AND_RETURN(stat, err);
        }
        stat = yajl_gen_bool((yajl_gen)g, (int)(map->values[i]));
        if (yajl_gen_status_ok != stat) {
            GEN_SET_ERROR_AND_RETURN(stat, err);
        }
    }

    stat = yajl_gen_map_close((yajl_gen)g);
    if (yajl_gen_status_ok != stat) {
        GEN_SET_ERROR_AND_RETURN(stat, err);
    }
    if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) {
        yajl_gen_config(g, yajl_gen_beautify, 1);
    }
    return yajl_gen_status_ok;
}

void free_json_map_string_bool(json_map_string_bool *map) {
    if (map != NULL) {
        size_t i;
        for (i = 0; i < map->len; i++) {
            free(map->keys[i]);
            map->keys[i] = NULL;
            // No need to free value for type bool
        }
        free(map->keys);
        map->keys = NULL;
        free(map->values);
        map->values = NULL;
        free(map);
    }
}
json_map_string_bool *make_json_map_string_bool(yajl_val src, const struct parser_context *ctx, parser_error *err) {
    json_map_string_bool *ret = NULL;
    if (src != NULL && YAJL_GET_OBJECT(src) != NULL) {
        size_t i;
        size_t len = YAJL_GET_OBJECT(src)->len;
        ret = safe_malloc(sizeof(*ret));
        ret->len = len;
        ret->keys = safe_malloc((len + 1) * sizeof(char *));
        ret->values = safe_malloc((len + 1) * sizeof(bool));
        for (i = 0; i < len; i++) {
            const char *srckey = YAJL_GET_OBJECT(src)->keys[i];
            yajl_val srcval = YAJL_GET_OBJECT(src)->values[i];
            ret->keys[i] = safe_strdup(srckey ? srckey : "");

            if (srcval != NULL) {
                if (YAJL_IS_TRUE(srcval)) {
                    ret->values[i] = true;
                } else if (YAJL_IS_FALSE(srcval)) {
                    ret->values[i] = false;
                } else {
                    if (*err == NULL && asprintf(err, "Invalid value with type 'bool' for key '%s'", srckey) < 0) {
                        *(err) = safe_strdup("error allocating memory");
                    }
                    free_json_map_string_bool(ret);
                    return NULL;
                }
            }
        }
    }
    return ret;
}
int append_json_map_string_bool(json_map_string_bool *map, const char *key, bool val) {
    size_t len;
    char **keys = NULL;
    bool *vals = NULL;

    if (map == NULL) {
        return -1;
    }

    if ((SIZE_MAX / sizeof(char *) - 1) < map->len || (SIZE_MAX / sizeof(bool) - 1) < map->len) {
        return -1;
    }

    len = map->len + 1;
    keys = safe_malloc(len * sizeof(char *));
    vals = safe_malloc(len * sizeof(bool));

    if (map->len) {
        if (memcpy_s(keys, len * sizeof(char *), map->keys, map->len * sizeof(char *)) != EOK) {
            free(keys);
            free(vals);
            return -1;
        }
        if (memcpy_s(vals, len * sizeof(bool), map->values, map->len * sizeof(bool)) != EOK) {
            free(keys);
            free(vals);
            return -1;
        }
    }
    free(map->keys);
    map->keys = keys;
    free(map->values);
    map->values = vals;
    map->keys[map->len] = safe_strdup(key ? key : "");
    map->values[map->len] = val;

    map->len++;
    return 0;
}

yajl_gen_status gen_json_map_string_string(void *ctx, const json_map_string_string *map, const struct parser_context *ptx, parser_error *err) {
    yajl_gen_status stat = yajl_gen_status_ok;
    yajl_gen g = (yajl_gen) ctx;
    size_t len = 0, i = 0;
    if (map != NULL) {
        len = map->len;
    }
    if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) {
        yajl_gen_config(g, yajl_gen_beautify, 0);
    }
    stat = yajl_gen_map_open((yajl_gen)g);
    if (yajl_gen_status_ok != stat) {
        GEN_SET_ERROR_AND_RETURN(stat, err);

    }
    for (i = 0; i < len; i++) {
        stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)(map->keys[i]), strlen(map->keys[i]));
        if (yajl_gen_status_ok != stat) {
            GEN_SET_ERROR_AND_RETURN(stat, err);
        }
        stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)(map->values[i]), strlen(map->values[i]));
        if (yajl_gen_status_ok != stat) {
            GEN_SET_ERROR_AND_RETURN(stat, err);
        }
    }

    stat = yajl_gen_map_close((yajl_gen)g);
    if (yajl_gen_status_ok != stat) {
        GEN_SET_ERROR_AND_RETURN(stat, err);
    }
    if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) {
        yajl_gen_config(g, yajl_gen_beautify, 1);
    }
    return yajl_gen_status_ok;
}

void free_json_map_string_string(json_map_string_string *map) {
    if (map != NULL) {
        size_t i;
        for (i = 0; i < map->len; i++) {
            free(map->keys[i]);
            map->keys[i] = NULL;
            free(map->values[i]);
            map->values[i] = NULL;
        }
        free(map->keys);
        map->keys = NULL;
        free(map->values);
        map->values = NULL;
        free(map);
    }
}
json_map_string_string *make_json_map_string_string(yajl_val src, const struct parser_context *ctx, parser_error *err) {
    json_map_string_string *ret = NULL;
    if (src != NULL && YAJL_GET_OBJECT(src) != NULL) {
        size_t i;
        size_t len = YAJL_GET_OBJECT(src)->len;
        ret = safe_malloc(sizeof(*ret));
        ret->len = len;
        ret->keys = safe_malloc((len + 1) * sizeof(char *));
        ret->values = safe_malloc((len + 1) * sizeof(char *));
        for (i = 0; i < len; i++) {
            const char *srckey = YAJL_GET_OBJECT(src)->keys[i];
            yajl_val srcval = YAJL_GET_OBJECT(src)->values[i];
            ret->keys[i] = safe_strdup(srckey ? srckey : "");

            if (srcval != NULL) {
                if (!YAJL_IS_STRING(srcval)) {
                    if (*err == NULL && asprintf(err, "Invalid value with type 'string' for key '%s'", srckey) < 0) {
                        *(err) = safe_strdup("error allocating memory");
                    }
                    free_json_map_string_string(ret);
                    return NULL;
                }
                char *str = YAJL_GET_STRING(srcval);
                ret->values[i] = safe_strdup(str ? str : "");
            }
        }
    }
    return ret;
}
int append_json_map_string_string(json_map_string_string *map, const char *key, const char *val) {
    size_t len, i;
    char **keys = NULL;
    char **vals = NULL;

    if (map == NULL) {
        return -1;
    }

    for (i = 0; i < map->len; i++) {
        if (strcmp(map->keys[i], key) == 0) {
                free(map->values[i]);
                map->values[i] = safe_strdup(val ? val : "");
                return 0;
        }
    }

    if ((SIZE_MAX / sizeof(char *) - 1) < map->len) {
        return -1;
    }

    len = map->len + 1;
    keys = safe_malloc(len * sizeof(char *));
    vals = safe_malloc(len * sizeof(char *));

    if (map->len) {
        if (memcpy_s(keys, len * sizeof(char *), map->keys, map->len * sizeof(char *)) != EOK) {
            free(keys);
            free(vals);
            return -1;
        }
        if (memcpy_s(vals, len * sizeof(char *), map->values, map->len * sizeof(char *)) != EOK) {
            free(keys);
            free(vals);
            return -1;
        }
    }
    free(map->keys);
    map->keys = keys;
    free(map->values);
    map->values = vals;
    map->keys[map->len] = safe_strdup(key ? key : "");
    map->values[map->len] = safe_strdup(val ? val : "");

    map->len++;
    return 0;
}

char *json_marshal_string(const char *str, size_t strlen, const struct parser_context *ctx, parser_error *err)
{
    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;
    yajl_gen_status stat;

    if (str == 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;
    }
    stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)str, strlen);
    if (yajl_gen_status_ok != stat) {
        if (asprintf(err, "error generating json, errcode: %d", (int)stat) < 0) {
            *err = safe_strdup("error allocating memory");
        }
        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);
    if (memcpy_s(json_buf, gen_len + 1, gen_buf, gen_len) != EOK) {
        *err = safe_strdup("Error to memcpy json");
        free(json_buf);
        json_buf = NULL;
        goto free_out;
    }
    json_buf[gen_len] = '\\0';

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

'''
