
/*****
*
* Copyright (C) 2016-2019 CS-SI. All Rights Reserved.
* Author: Yoann Vandoorselaere <yoannv@gmail.com>
*
* This file is part of the Prelude library.
*
* This program 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 2, or (at your option)
* any later version.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*****/

/* Auto-generated by the GenerateIDMEFMessageReadJSONC package */
#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "prelude-error.h"
#include "prelude-inttypes.h"
#include "prelude-list.h"
#include "prelude-extract.h"
#include "prelude-io.h"
#include "idmef-message-id.h"
#include "idmef.h"
#include "idmef-tree-wrap.h"

#define JSMN_PARENT_LINKS

#include "jsmn/jsmn.h"
#include "jsmn/jsmn.c"

#ifndef MIN
# define MIN(x, y) ((x) < (y) ? (x) : (y))
#endif

typedef struct {
        const char *input;
        jsmntok_t jtok[1024];
        int jtoksize;
        unsigned int idx;
} json_data_t;


static int idmef_linkage_read_json(idmef_linkage_t *linkage, json_data_t *ctrl);


static const char *jsmn_type_to_string(int type)
{
        switch(type) {
            case JSMN_STRING:
                return "string";
            case JSMN_PRIMITIVE:
                return "primitive";
            case JSMN_OBJECT:
                return "object";
            case JSMN_ARRAY:
                return "array";
            default:
                return "unknown";
        }
}


/*
 * code from http://stackoverflow.com/a/4609989/697313
 */
static int unicode_to_utf8(unsigned int codepoint, prelude_string_t *out)
{
          char val;

          if ( codepoint < 0x80 )
                prelude_string_ncat(out, (char *) &codepoint, 1);

          else if ( codepoint < 0x800 ) {
                val = 192 + codepoint / 64;
                prelude_string_ncat(out, &val, 1);
                val = 128 + codepoint % 64;
                prelude_string_ncat(out, &val, 1);
          }

          else if ( codepoint - 0xd800u < 0x800 )
                return 0; // surrogate must have been treated earlier

          else if ( codepoint < 0x10000 ) {
                val = 224 + codepoint / 4096;
                prelude_string_ncat(out, &val, 1);
                val = 128 + codepoint /64 % 64;
                prelude_string_ncat(out, &val, 1);
                val = 128 + codepoint % 64;
                prelude_string_ncat(out, &val, 1);
          }

          else if ( codepoint < 0x110000 ) {
                val = 240 + codepoint / 262144;
                prelude_string_ncat(out, &val, 1);
                val = 128 + codepoint / 4096 % 64;
                prelude_string_ncat(out, &val, 1);
                val = 128 + codepoint / 64 % 64;
                prelude_string_ncat(out, &val, 1);
                val = 128 + codepoint % 64;
                prelude_string_ncat(out, &val, 1);
          }

          else
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unicode to utf8 conversion failed");

          return 1;
}


static int hexval(char c)
{
        if ( c >= '0' && c <= '9' )
                return c - '0';

        else if ( c >= 'a' && c <= 'f' )
                return c - 'a' + 10;

        else if ( c >= 'A' && c <= 'F' )
                return c - 'A' + 10;

        else return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "hexval failed");
}


static int unescape_unicode(const char *in, const char *end)
{
        int h1, h2, h3, h4;

        if ( in + 4 > end )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unicode sequence must be at least 4 characters long");;

        if ( (h1 = hexval(in[0])) < 0 || (h2 = hexval(in[1])) < 0 || (h3 = hexval(in[2])) < 0 || (h4 = hexval(in[3])) < 0 )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "invalid unicode escape: '%.6s'", in - 2);

        return h1 << 12 | h2 << 8 | h3 << 4 | h4;
}


static int unescape_string(prelude_string_t *out, const char *in, size_t size)
{
        int ret;
        const char *end = in + size;

        for ( ; in < end; in++ ) {
                if ( *in != '\\' ) {
                        ret = prelude_string_ncat(out, in, 1);
                        continue;
                }

                in++;
                switch(*in) {
                        case '"':
                        case '/':
                        case '\\':
                                ret = prelude_string_ncat(out, in, 1);
                                break;

                        case 'b':
                                ret = prelude_string_ncat(out, "\b", 1);
                                break;
                        case 't':
                                ret = prelude_string_ncat(out, "\t", 1);
                                break;
                        case 'n':
                                ret = prelude_string_ncat(out, "\n", 1);
                                break;
                        case 'f':
                                ret = prelude_string_ncat(out, "\f", 1);
                                break;
                        case 'r':
                                ret = prelude_string_ncat(out, "\r", 1);
                                break;

                        case 'u': {
                                int codepoint;

                                codepoint = unescape_unicode(in + 1, end);
                                if ( codepoint < 0 )
                                        return codepoint;

                                if ( (codepoint & 0xfc00) == 0xd800 ) {
                                        /*
                                         * high surrogate; need one more unicode to succeed
                                         */
                                        in += 7;

                                        ret = unescape_unicode(in, end);
                                        if ( ret < 0 )
                                                return ret;

                                        codepoint = 0x10000 + ((codepoint - 0xd800) << 10) + (ret - 0xdc00);
                                }

                                ret = unicode_to_utf8(codepoint, out);
                                if ( ret < 0 )
                                        return ret;

                                in += 4;
                                break;
                        }

                        default:
                                ret = prelude_string_ncat(out, in, 1);
                                break;
                }

                if ( ret < 0 )
                        return ret;
        }

        return 0;
}


static int __get_float(json_data_t *ctrl, float *value)
{
        char *end = NULL;
        jsmntok_t *j = &ctrl->jtok[ctrl->idx];
        size_t len = j->end - j->start;
        const char *str = ctrl->input + j->start;

        *value = strtof(ctrl->input + j->start, &end);
        if ( end != (str + len) )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "error decoding to real");

        return 0;
}



static int __get_integer(json_data_t *ctrl, int64_t *out)
{
        char *end = NULL;
        jsmntok_t *j = &ctrl->jtok[ctrl->idx];
        size_t len = j->end - j->start;
        const char *str = ctrl->input + j->start;

        if ( j->type != JSMN_PRIMITIVE )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON integer got '%s'", jsmn_type_to_string(j->type));

        *out = strtoll(ctrl->input + j->start, &end, 10);
        if ( end != (str + len) )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "error decoding to integer");

        return 0;
}


static int __get_string_copy(json_data_t *ctrl, unsigned int idx, char *out, size_t size)
{
        size_t insize;
        jsmntok_t *j = &ctrl->jtok[idx];
        const char *input = ctrl->input + j->start;

        insize = j->end - j->start;

        if ( insize == 0 ) {
                *out = '\0';
                return 0;
        }

        else if ( insize >= size )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "buffer is too small");

        strncpy(out, input, MIN(size, j->end - j->start));
        out[j->end - j->start] = 0;

        return 0;
}

static int __get_string(json_data_t *ctrl, prelude_string_t *out)
{
        jsmntok_t *j = &ctrl->jtok[ctrl->idx];
        const char *input = ctrl->input + j->start;

        if ( j->type != JSMN_STRING )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "JSON value is not string : %s", jsmn_type_to_string(j->type));

        if ( j->end - j->start == 0 )
                return 0;

        return unescape_string(out, input, j->end - j->start);
}


static int jsoneq(json_data_t *data, jsmntok_t *tok, const char *wanted)
{
    size_t size = tok->end - tok->start;
    const char *start = data->input + tok->start;

    if ( tok->type == JSMN_STRING && strlen(wanted) == size && strncmp(start, wanted, size) == 0)
            return 0;

    return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "jsoneq failed");
}



static int __get_json_key(json_data_t *ctrl, const char *wanted, unsigned int sidx)
{
        unsigned int i;

        for ( i = 0; i < ctrl->jtok[sidx].size * 2; i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[sidx + i], wanted) == 0 )
                        return i;
        }

        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "failed to get json key '%s'", wanted);
}

/**
 * idmef_additional_data_read:
 * @additional_data: Pointer to a #idmef_additional_data_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_additional_data from the @json message, and
 * store it into @additional_data.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_additional_data_read_json(idmef_additional_data_t *additional_data, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

                unsigned int obj_idx = ctrl->idx;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "meaning") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_additional_data_new_meaning(additional_data, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "type") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_additional_data_type_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_additional_data_set_type(additional_data, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "data") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];
                        idmef_data_t *data;
                        idmef_additional_data_type_t type;

                        ret = __get_json_key(ctrl, "type", obj_idx);
                        if ( ret < 0 )
                                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "type argument required for additional data object");

                        ret = __get_string_copy(ctrl, obj_idx + ret + 1, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        type = idmef_additional_data_type_to_numeric(buf);
                        if ( type < 0 )
                                return type;

                        ret = idmef_additional_data_new_data(additional_data, &data);
                        if ( ret < 0 )
                                return ret;

                        switch(type) {
                                case IDMEF_ADDITIONAL_DATA_TYPE_REAL: {
                                        float val;

                                        ret = __get_float(ctrl, &val);
                                        if ( ret < 0 )
                                                return ret;

                                        idmef_data_set_float(data, val);
                                        break;
                                }

                                case IDMEF_ADDITIONAL_DATA_TYPE_BYTE:
                                case IDMEF_ADDITIONAL_DATA_TYPE_BOOLEAN:
                                case IDMEF_ADDITIONAL_DATA_TYPE_NTPSTAMP:
                                case IDMEF_ADDITIONAL_DATA_TYPE_INTEGER: {
                                        int ret;
                                        int64_t val;

                                        ret = __get_integer(ctrl, &val);
                                        if ( ret < 0 )
                                                return ret;

                                        idmef_data_set_int(data, val);
                                        break;
                                }

                                case IDMEF_ADDITIONAL_DATA_TYPE_DATE_TIME: {
                                        idmef_time_t *time;
                                        char buf[128];

                                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                                        if ( ret < 0 )
                                                return ret;

                                        ret = idmef_time_new_from_string(&time, buf);
                                        if ( ret < 0 )
                                                return ret;

                                        idmef_data_set_time(data, time);
                                        break;
                                }

                                case IDMEF_ADDITIONAL_DATA_TYPE_STRING:
                                case IDMEF_ADDITIONAL_DATA_TYPE_BYTE_STRING:
                                case IDMEF_ADDITIONAL_DATA_TYPE_CHARACTER:
                                case IDMEF_ADDITIONAL_DATA_TYPE_PORTLIST:
                                case IDMEF_ADDITIONAL_DATA_TYPE_XML: {
                                        prelude_string_t *str;

                                        ret = prelude_string_new(&str);
                                        if ( ret < 0 )
                                                return ret;

                                        ret = __get_string(ctrl, str);
                                        if ( ret < 0 ) {
                                                prelude_string_destroy(str);
                                                return ret;
                                        }

                                        if ( type == IDMEF_ADDITIONAL_DATA_TYPE_BYTE_STRING )
                                                ret = idmef_data_set_byte_string_dup(data, (const unsigned char *) prelude_string_get_string(str), prelude_string_get_len(str));
                                        else
                                                ret = idmef_data_set_char_string_dup_fast(data, prelude_string_get_string(str), prelude_string_get_len(str));

                                        prelude_string_destroy(str);
                                        break;
                                }

                                default:
                                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unhandled IDMEF additional data type");
;
                        }

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading additional_data", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_reference_read:
 * @reference: Pointer to a #idmef_reference_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_reference from the @json message, and
 * store it into @reference.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_reference_read_json(idmef_reference_t *reference, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "origin") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_reference_origin_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_reference_set_origin(reference, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "name") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_reference_new_name(reference, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "url") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_reference_new_url(reference, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "meaning") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_reference_new_meaning(reference, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading reference", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_classification_read:
 * @classification: Pointer to a #idmef_classification_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_classification from the @json message, and
 * store it into @classification.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_classification_read_json(idmef_classification_t *classification, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "ident") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_classification_new_ident(classification, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "text") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_classification_new_text(classification, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "reference") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_reference_t *reference;

                                                ret = idmef_classification_new_reference(classification, &reference, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_reference_read_json(reference, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading classification", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_user_id_read:
 * @user_id: Pointer to a #idmef_user_id_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_user_id from the @json message, and
 * store it into @user_id.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_user_id_read_json(idmef_user_id_t *user_id, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "ident") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_user_id_new_ident(user_id, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "type") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_user_id_type_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_user_id_set_type(user_id, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "tty") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_user_id_new_tty(user_id, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "name") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_user_id_new_name(user_id, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "number") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_user_id_set_number(user_id, out);

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading user_id", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_user_read:
 * @user: Pointer to a #idmef_user_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_user from the @json message, and
 * store it into @user.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_user_read_json(idmef_user_t *user, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "ident") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_user_new_ident(user, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "category") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_user_category_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_user_set_category(user, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "user_id") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_user_id_t *user_id;

                                                ret = idmef_user_new_user_id(user, &user_id, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_user_id_read_json(user_id, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading user", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_address_read:
 * @address: Pointer to a #idmef_address_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_address from the @json message, and
 * store it into @address.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_address_read_json(idmef_address_t *address, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "ident") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_address_new_ident(address, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "category") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_address_category_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_address_set_category(address, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "vlan_name") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_address_new_vlan_name(address, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "vlan_num") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_address_set_vlan_num(address, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "address") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_address_new_address(address, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "netmask") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_address_new_netmask(address, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading address", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_process_read:
 * @process: Pointer to a #idmef_process_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_process from the @json message, and
 * store it into @process.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_process_read_json(idmef_process_t *process, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "ident") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_process_new_ident(process, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "name") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_process_new_name(process, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "pid") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_process_set_pid(process, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "path") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_process_new_path(process, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "arg") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                        int ret;
                                        prelude_string_t *str;

                                        ret = idmef_process_new_arg(process, &str, IDMEF_LIST_APPEND);
                                        if ( ret < 0 )
                                                return ret;

                                        ret = __get_string(ctrl, str);
                                        if ( ret < 0 )
                                                return ret;

                                                            ctrl->idx += 1;
                    }

                                                ctrl->idx -= 1;
                                                
                        }
                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "env") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                        int ret;
                                        prelude_string_t *str;

                                        ret = idmef_process_new_env(process, &str, IDMEF_LIST_APPEND);
                                        if ( ret < 0 )
                                                return ret;

                                        ret = __get_string(ctrl, str);
                                        if ( ret < 0 )
                                                return ret;

                                                            ctrl->idx += 1;
                    }

                                                ctrl->idx -= 1;
                                                
                        }
                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading process", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_web_service_read:
 * @web_service: Pointer to a #idmef_web_service_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_web_service from the @json message, and
 * store it into @web_service.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_web_service_read_json(idmef_web_service_t *web_service, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "url") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_web_service_new_url(web_service, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "cgi") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_web_service_new_cgi(web_service, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "http_method") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_web_service_new_http_method(web_service, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "arg") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                        int ret;
                                        prelude_string_t *str;

                                        ret = idmef_web_service_new_arg(web_service, &str, IDMEF_LIST_APPEND);
                                        if ( ret < 0 )
                                                return ret;

                                        ret = __get_string(ctrl, str);
                                        if ( ret < 0 )
                                                return ret;

                                                            ctrl->idx += 1;
                    }

                                                ctrl->idx -= 1;
                                                
                        }
                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading web_service", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_snmp_service_read:
 * @snmp_service: Pointer to a #idmef_snmp_service_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_snmp_service from the @json message, and
 * store it into @snmp_service.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_snmp_service_read_json(idmef_snmp_service_t *snmp_service, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "oid") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_snmp_service_new_oid(snmp_service, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "message_processing_model") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_snmp_service_set_message_processing_model(snmp_service, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "security_model") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_snmp_service_set_security_model(snmp_service, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "security_name") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_snmp_service_new_security_name(snmp_service, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "security_level") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_snmp_service_set_security_level(snmp_service, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "context_name") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_snmp_service_new_context_name(snmp_service, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "context_engine_id") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_snmp_service_new_context_engine_id(snmp_service, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "command") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_snmp_service_new_command(snmp_service, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading snmp_service", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_service_read:
 * @service: Pointer to a #idmef_service_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_service from the @json message, and
 * store it into @service.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_service_read_json(idmef_service_t *service, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "ident") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_service_new_ident(service, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "ip_version") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_service_set_ip_version(service, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "iana_protocol_number") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_service_set_iana_protocol_number(service, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "iana_protocol_name") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_service_new_iana_protocol_name(service, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "name") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_service_new_name(service, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "port") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_service_set_port(service, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "portlist") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_service_new_portlist(service, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "protocol") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_service_new_protocol(service, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "web_service") == 0){
                        ctrl->idx++;

                        int ret;
                        idmef_web_service_t *web_service;

                        ret = idmef_service_new_web_service(service, &web_service);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_web_service_read_json(web_service, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "snmp_service") == 0){
                        ctrl->idx++;

                        int ret;
                        idmef_snmp_service_t *snmp_service;

                        ret = idmef_service_new_snmp_service(service, &snmp_service);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_snmp_service_read_json(snmp_service, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading service", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_node_read:
 * @node: Pointer to a #idmef_node_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_node from the @json message, and
 * store it into @node.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_node_read_json(idmef_node_t *node, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "ident") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_node_new_ident(node, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "category") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_node_category_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_node_set_category(node, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "name") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_node_new_name(node, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "location") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_node_new_location(node, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "address") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_address_t *address;

                                                ret = idmef_node_new_address(node, &address, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_address_read_json(address, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading node", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_source_read:
 * @source: Pointer to a #idmef_source_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_source from the @json message, and
 * store it into @source.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_source_read_json(idmef_source_t *source, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "ident") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_source_new_ident(source, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "spoofed") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_source_spoofed_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_source_set_spoofed(source, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "interface") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_source_new_interface(source, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "node") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_node_t *node;

                        ret = idmef_source_new_node(source, &node);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_node_read_json(node, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "user") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_user_t *user;

                        ret = idmef_source_new_user(source, &user);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_user_read_json(user, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "process") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_process_t *process;

                        ret = idmef_source_new_process(source, &process);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_process_read_json(process, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "service") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_service_t *service;

                        ret = idmef_source_new_service(source, &service);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_service_read_json(service, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading source", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_file_access_read:
 * @file_access: Pointer to a #idmef_file_access_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_file_access from the @json message, and
 * store it into @file_access.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_file_access_read_json(idmef_file_access_t *file_access, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "user_id") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_user_id_t *user_id;

                        ret = idmef_file_access_new_user_id(file_access, &user_id);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_user_id_read_json(user_id, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "permission") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                        int ret;
                                        prelude_string_t *str;

                                        ret = idmef_file_access_new_permission(file_access, &str, IDMEF_LIST_APPEND);
                                        if ( ret < 0 )
                                                return ret;

                                        ret = __get_string(ctrl, str);
                                        if ( ret < 0 )
                                                return ret;

                                                            ctrl->idx += 1;
                    }

                                                ctrl->idx -= 1;
                                                
                        }
                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading file_access", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_inode_read:
 * @inode: Pointer to a #idmef_inode_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_inode from the @json message, and
 * store it into @inode.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_inode_read_json(idmef_inode_t *inode, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "change_time") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];
                        idmef_time_t *time;

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_time_new_from_string(&time, buf);
                        if (ret < 0)
                                return ret;

                        idmef_inode_set_change_time(inode, time);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "number") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_inode_set_number(inode, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "major_device") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_inode_set_major_device(inode, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "minor_device") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_inode_set_minor_device(inode, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "c_major_device") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_inode_set_c_major_device(inode, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "c_minor_device") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_inode_set_c_minor_device(inode, out);

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading inode", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_checksum_read:
 * @checksum: Pointer to a #idmef_checksum_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_checksum from the @json message, and
 * store it into @checksum.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_checksum_read_json(idmef_checksum_t *checksum, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "value") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_checksum_new_value(checksum, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "key") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_checksum_new_key(checksum, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "algorithm") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_checksum_algorithm_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_checksum_set_algorithm(checksum, ret);

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading checksum", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_file_read:
 * @file: Pointer to a #idmef_file_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_file from the @json message, and
 * store it into @file.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_file_read_json(idmef_file_t *file, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "ident") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_file_new_ident(file, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "name") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_file_new_name(file, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "path") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_file_new_path(file, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "create_time") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];
                        idmef_time_t *time;

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_time_new_from_string(&time, buf);
                        if (ret < 0)
                                return ret;

                        idmef_file_set_create_time(file, time);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "modify_time") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];
                        idmef_time_t *time;

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_time_new_from_string(&time, buf);
                        if (ret < 0)
                                return ret;

                        idmef_file_set_modify_time(file, time);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "access_time") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];
                        idmef_time_t *time;

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_time_new_from_string(&time, buf);
                        if (ret < 0)
                                return ret;

                        idmef_file_set_access_time(file, time);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "data_size") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_file_set_data_size(file, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "disk_size") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_file_set_disk_size(file, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "file_access") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_file_access_t *file_access;

                                                ret = idmef_file_new_file_access(file, &file_access, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_file_access_read_json(file_access, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "linkage") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_linkage_t *linkage;

                                                ret = idmef_file_new_linkage(file, &linkage, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_linkage_read_json(linkage, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "inode") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_inode_t *inode;

                        ret = idmef_file_new_inode(file, &inode);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_inode_read_json(inode, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "checksum") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_checksum_t *checksum;

                                                ret = idmef_file_new_checksum(file, &checksum, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_checksum_read_json(checksum, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "category") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_file_category_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_file_set_category(file, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "fstype") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_file_fstype_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_file_set_fstype(file, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "file_type") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_file_new_file_type(file, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading file", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_linkage_read:
 * @linkage: Pointer to a #idmef_linkage_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_linkage from the @json message, and
 * store it into @linkage.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_linkage_read_json(idmef_linkage_t *linkage, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "category") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_linkage_category_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_linkage_set_category(linkage, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "name") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_linkage_new_name(linkage, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "path") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_linkage_new_path(linkage, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "file") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_file_t *file;

                        ret = idmef_linkage_new_file(linkage, &file);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_file_read_json(file, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading linkage", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_target_read:
 * @target: Pointer to a #idmef_target_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_target from the @json message, and
 * store it into @target.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_target_read_json(idmef_target_t *target, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "ident") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_target_new_ident(target, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "decoy") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_target_decoy_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_target_set_decoy(target, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "interface") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_target_new_interface(target, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "node") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_node_t *node;

                        ret = idmef_target_new_node(target, &node);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_node_read_json(node, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "user") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_user_t *user;

                        ret = idmef_target_new_user(target, &user);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_user_read_json(user, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "process") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_process_t *process;

                        ret = idmef_target_new_process(target, &process);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_process_read_json(process, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "service") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_service_t *service;

                        ret = idmef_target_new_service(target, &service);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_service_read_json(service, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "file") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_file_t *file;

                                                ret = idmef_target_new_file(target, &file, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_file_read_json(file, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading target", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_analyzer_read:
 * @analyzer: Pointer to a #idmef_analyzer_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_analyzer from the @json message, and
 * store it into @analyzer.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_analyzer_read_json(idmef_analyzer_t *analyzer, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "analyzerid") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_analyzer_new_analyzerid(analyzer, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "name") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_analyzer_new_name(analyzer, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "manufacturer") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_analyzer_new_manufacturer(analyzer, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "model") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_analyzer_new_model(analyzer, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "version") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_analyzer_new_version(analyzer, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "class") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_analyzer_new_class(analyzer, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "ostype") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_analyzer_new_ostype(analyzer, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "osversion") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_analyzer_new_osversion(analyzer, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "node") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_node_t *node;

                        ret = idmef_analyzer_new_node(analyzer, &node);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_node_read_json(node, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "process") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_process_t *process;

                        ret = idmef_analyzer_new_process(analyzer, &process);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_process_read_json(process, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading analyzer", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_alertident_read:
 * @alertident: Pointer to a #idmef_alertident_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_alertident from the @json message, and
 * store it into @alertident.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_alertident_read_json(idmef_alertident_t *alertident, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "alertident") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_alertident_new_alertident(alertident, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "analyzerid") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_alertident_new_analyzerid(alertident, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading alertident", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_impact_read:
 * @impact: Pointer to a #idmef_impact_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_impact from the @json message, and
 * store it into @impact.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_impact_read_json(idmef_impact_t *impact, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "severity") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_impact_severity_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_impact_set_severity(impact, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "completion") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_impact_completion_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_impact_set_completion(impact, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "type") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_impact_type_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_impact_set_type(impact, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "description") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_impact_new_description(impact, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading impact", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_action_read:
 * @action: Pointer to a #idmef_action_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_action from the @json message, and
 * store it into @action.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_action_read_json(idmef_action_t *action, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "category") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_action_category_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_action_set_category(action, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "description") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_action_new_description(action, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading action", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_confidence_read:
 * @confidence: Pointer to a #idmef_confidence_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_confidence from the @json message, and
 * store it into @confidence.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_confidence_read_json(idmef_confidence_t *confidence, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "rating") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_confidence_rating_to_numeric(buf);
                        if ( ret != -1 )
                                idmef_confidence_set_rating(confidence, ret);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "confidence") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        float *value;

                        ret = idmef_confidence_new_confidence(confidence, &value);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_float(ctrl, value);
                        if ( ret < 0 )
                                return ret;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading confidence", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_assessment_read:
 * @assessment: Pointer to a #idmef_assessment_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_assessment from the @json message, and
 * store it into @assessment.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_assessment_read_json(idmef_assessment_t *assessment, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "impact") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_impact_t *impact;

                        ret = idmef_assessment_new_impact(assessment, &impact);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_impact_read_json(impact, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "action") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_action_t *action;

                                                ret = idmef_assessment_new_action(assessment, &action, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_action_read_json(action, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "confidence") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_confidence_t *confidence;

                        ret = idmef_assessment_new_confidence(assessment, &confidence);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_confidence_read_json(confidence, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading assessment", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_tool_alert_read:
 * @tool_alert: Pointer to a #idmef_tool_alert_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_tool_alert from the @json message, and
 * store it into @tool_alert.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_tool_alert_read_json(idmef_tool_alert_t *tool_alert, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "name") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_tool_alert_new_name(tool_alert, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "command") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_tool_alert_new_command(tool_alert, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "alertident") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_alertident_t *alertident;

                                                ret = idmef_tool_alert_new_alertident(tool_alert, &alertident, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_alertident_read_json(alertident, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading tool_alert", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_correlation_alert_read:
 * @correlation_alert: Pointer to a #idmef_correlation_alert_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_correlation_alert from the @json message, and
 * store it into @correlation_alert.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_correlation_alert_read_json(idmef_correlation_alert_t *correlation_alert, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "name") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_correlation_alert_new_name(correlation_alert, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "alertident") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_alertident_t *alertident;

                                                ret = idmef_correlation_alert_new_alertident(correlation_alert, &alertident, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_alertident_read_json(alertident, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading correlation_alert", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_overflow_alert_read:
 * @overflow_alert: Pointer to a #idmef_overflow_alert_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_overflow_alert from the @json message, and
 * store it into @overflow_alert.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_overflow_alert_read_json(idmef_overflow_alert_t *overflow_alert, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "program") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_overflow_alert_new_program(overflow_alert, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "size") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_overflow_alert_set_size(overflow_alert, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "buffer") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_data_t *data;
                        prelude_string_t *str;

                        ret = idmef_overflow_alert_new_buffer(overflow_alert, &data);
                        if ( ret < 0 )
                                return ret;

                        ret = prelude_string_new(&str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 ) {
                                prelude_string_destroy(str);
                                return ret;
                        }

                        ret = idmef_data_set_byte_string_dup(data, (const unsigned char *) prelude_string_get_string(str), prelude_string_get_len(str));
                        prelude_string_destroy(str);

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading overflow_alert", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_alert_read:
 * @alert: Pointer to a #idmef_alert_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_alert from the @json message, and
 * store it into @alert.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_alert_read_json(idmef_alert_t *alert, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "messageid") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_alert_new_messageid(alert, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "analyzer") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_analyzer_t *analyzer;

                                                ret = idmef_alert_new_analyzer(alert, &analyzer, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_analyzer_read_json(analyzer, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "create_time") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];
                        idmef_time_t *time;

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_time_new_from_string(&time, buf);
                        if (ret < 0)
                                return ret;

                        idmef_alert_set_create_time(alert, time);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "classification") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_classification_t *classification;

                        ret = idmef_alert_new_classification(alert, &classification);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_classification_read_json(classification, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "detect_time") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];
                        idmef_time_t *time;

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_time_new_from_string(&time, buf);
                        if (ret < 0)
                                return ret;

                        idmef_alert_set_detect_time(alert, time);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "analyzer_time") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];
                        idmef_time_t *time;

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_time_new_from_string(&time, buf);
                        if (ret < 0)
                                return ret;

                        idmef_alert_set_analyzer_time(alert, time);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "source") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_source_t *source;

                                                ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_source_read_json(source, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "target") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_target_t *target;

                                                ret = idmef_alert_new_target(alert, &target, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_target_read_json(target, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "assessment") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        idmef_assessment_t *assessment;

                        ret = idmef_alert_new_assessment(alert, &assessment);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_assessment_read_json(assessment, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "additional_data") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_additional_data_t *additional_data;

                                                ret = idmef_alert_new_additional_data(alert, &additional_data, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_additional_data_read_json(additional_data, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "tool_alert") == 0){
                        ctrl->idx++;

                        int ret;
                        idmef_tool_alert_t *tool_alert;

                        ret = idmef_alert_new_tool_alert(alert, &tool_alert);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_tool_alert_read_json(tool_alert, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "correlation_alert") == 0){
                        ctrl->idx++;

                        int ret;
                        idmef_correlation_alert_t *correlation_alert;

                        ret = idmef_alert_new_correlation_alert(alert, &correlation_alert);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_correlation_alert_read_json(correlation_alert, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "overflow_alert") == 0){
                        ctrl->idx++;

                        int ret;
                        idmef_overflow_alert_t *overflow_alert;

                        ret = idmef_alert_new_overflow_alert(alert, &overflow_alert);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_overflow_alert_read_json(overflow_alert, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading alert", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_heartbeat_read:
 * @heartbeat: Pointer to a #idmef_heartbeat_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_heartbeat from the @json message, and
 * store it into @heartbeat.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_heartbeat_read_json(idmef_heartbeat_t *heartbeat, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "messageid") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_heartbeat_new_messageid(heartbeat, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "analyzer") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_analyzer_t *analyzer;

                                                ret = idmef_heartbeat_new_analyzer(heartbeat, &analyzer, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_analyzer_read_json(analyzer, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "create_time") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];
                        idmef_time_t *time;

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_time_new_from_string(&time, buf);
                        if (ret < 0)
                                return ret;

                        idmef_heartbeat_set_create_time(heartbeat, time);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "analyzer_time") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        char buf[128];
                        idmef_time_t *time;

                        ret = __get_string_copy(ctrl, ctrl->idx, buf, sizeof(buf));
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_time_new_from_string(&time, buf);
                        if (ret < 0)
                                return ret;

                        idmef_heartbeat_set_analyzer_time(heartbeat, time);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "heartbeat_interval") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        int64_t out;

                        ret = __get_integer(ctrl, &out);
                        if ( ret < 0 )
                                return ret;

                        idmef_heartbeat_set_heartbeat_interval(heartbeat, out);

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "additional_data") == 0 ) {
                        ctrl->idx++;

                        if ( ctrl->jtok[ctrl->idx].type == JSMN_ARRAY) {
                                size_t lsize = ctrl->jtok[ctrl->idx].size;

                                ctrl->idx += 1;
                                for ( unsigned int j = 0; j < lsize; j++ ) {

                                                int ret;
                                                idmef_additional_data_t *additional_data;

                                                ret = idmef_heartbeat_new_additional_data(heartbeat, &additional_data, IDMEF_LIST_APPEND);
                                                if ( ret < 0 )
                                                        return ret;

                                                ret = idmef_additional_data_read_json(additional_data, ctrl);
                                                if ( ret < 0 )
                                                        return ret;
                                        }
                                ctrl->idx -= 1;

                        }
                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading heartbeat", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

/**
 * idmef_message_read:
 * @message: Pointer to a #idmef_message_t object.
 * @json: Pointer to a #json_t object, containing a message.
 *
 * Read an idmef_message from the @json message, and
 * store it into @message.
 *
 * Returns: 0 on success, a negative value if an error occured.
 */
static int idmef_message_read_json(idmef_message_t *message, json_data_t *ctrl)
{
        unsigned int i = 0;
        size_t size = ctrl->jtok[ctrl->idx].size;

        if ( ctrl->jtok[ctrl->idx].type != JSMN_OBJECT )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected JSON object got '%s'", jsmn_type_to_string(ctrl->jtok[ctrl->idx].type));

        for ( ctrl->idx += 1; i < size && ctrl->idx < ctrl->jtoksize; ctrl->idx++, i++ ) {
                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "_self") == 0 ) {
                        ctrl->idx++;
                        continue;
                }

                if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "version") == 0 ) {
                        ctrl->idx++;

                        int ret;
                        prelude_string_t *str;

                        ret = idmef_message_new_version(message, &str);
                        if ( ret < 0 )
                                return ret;

                        ret = __get_string(ctrl, str);
                        if ( ret < 0 )
                                return ret;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "alert") == 0){
                        ctrl->idx++;

                        int ret;
                        idmef_alert_t *alert;

                        ret = idmef_message_new_alert(message, &alert);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_alert_read_json(alert, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else if ( jsoneq(ctrl, &ctrl->jtok[ctrl->idx], "heartbeat") == 0){
                        ctrl->idx++;

                        int ret;
                        idmef_heartbeat_t *heartbeat;

                        ret = idmef_message_new_heartbeat(message, &heartbeat);
                        if ( ret < 0 )
                                return ret;

                        ret = idmef_heartbeat_read_json(heartbeat, ctrl);
                        if ( ret < 0 )
                                return ret;

                        ctrl->idx -= 1;

                }

                else {
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unexpected field '%.*s' while reading message", ctrl->jtok[ctrl->idx].end - ctrl->jtok[ctrl->idx].start, ctrl->input + ctrl->jtok[ctrl->idx].start);
                }
        }

        return 0;
}

int idmef_object_new_from_json(idmef_object_t **object, const char *json_message)
{
        int ret, selfkey;
        jsmn_parser parser;
        json_data_t ctrl;

        jsmn_init(&parser);
        ctrl.idx = 0;
        ctrl.input = json_message;

        ret = ctrl.jtoksize = jsmn_parse(&parser, json_message, strlen(json_message), ctrl.jtok, sizeof(ctrl.jtok) / sizeof(*ctrl.jtok));
        if ( ret < 0 )
                return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "JSON parser error");

        selfkey = __get_json_key(&ctrl, "_self", 0);
        if ( selfkey < 0 ) {
                ret = idmef_message_new((idmef_message_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_message_read_json(*(idmef_message_t **) object, &ctrl);
                if ( ret < 0 ) {
                        idmef_message_destroy(*(idmef_message_t **) object);
                        return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "json message miss '_self' attribute and is not a complete message");
                }

                return ret;
        }

        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_additional_data_t") == 0 ) {
                ret = idmef_additional_data_new((idmef_additional_data_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_additional_data_read_json((idmef_additional_data_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_classification_t") == 0 ) {
                ret = idmef_classification_new((idmef_classification_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_classification_read_json((idmef_classification_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_user_id_t") == 0 ) {
                ret = idmef_user_id_new((idmef_user_id_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_user_id_read_json((idmef_user_id_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_user_t") == 0 ) {
                ret = idmef_user_new((idmef_user_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_user_read_json((idmef_user_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_address_t") == 0 ) {
                ret = idmef_address_new((idmef_address_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_address_read_json((idmef_address_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_process_t") == 0 ) {
                ret = idmef_process_new((idmef_process_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_process_read_json((idmef_process_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_web_service_t") == 0 ) {
                ret = idmef_web_service_new((idmef_web_service_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_web_service_read_json((idmef_web_service_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_snmp_service_t") == 0 ) {
                ret = idmef_snmp_service_new((idmef_snmp_service_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_snmp_service_read_json((idmef_snmp_service_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_service_t") == 0 ) {
                ret = idmef_service_new((idmef_service_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_service_read_json((idmef_service_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_node_t") == 0 ) {
                ret = idmef_node_new((idmef_node_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_node_read_json((idmef_node_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_source_t") == 0 ) {
                ret = idmef_source_new((idmef_source_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_source_read_json((idmef_source_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_file_access_t") == 0 ) {
                ret = idmef_file_access_new((idmef_file_access_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_file_access_read_json((idmef_file_access_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_inode_t") == 0 ) {
                ret = idmef_inode_new((idmef_inode_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_inode_read_json((idmef_inode_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_file_t") == 0 ) {
                ret = idmef_file_new((idmef_file_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_file_read_json((idmef_file_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_linkage_t") == 0 ) {
                ret = idmef_linkage_new((idmef_linkage_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_linkage_read_json((idmef_linkage_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_target_t") == 0 ) {
                ret = idmef_target_new((idmef_target_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_target_read_json((idmef_target_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_analyzer_t") == 0 ) {
                ret = idmef_analyzer_new((idmef_analyzer_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_analyzer_read_json((idmef_analyzer_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_alertident_t") == 0 ) {
                ret = idmef_alertident_new((idmef_alertident_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_alertident_read_json((idmef_alertident_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_impact_t") == 0 ) {
                ret = idmef_impact_new((idmef_impact_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_impact_read_json((idmef_impact_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_action_t") == 0 ) {
                ret = idmef_action_new((idmef_action_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_action_read_json((idmef_action_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_confidence_t") == 0 ) {
                ret = idmef_confidence_new((idmef_confidence_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_confidence_read_json((idmef_confidence_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_assessment_t") == 0 ) {
                ret = idmef_assessment_new((idmef_assessment_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_assessment_read_json((idmef_assessment_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_tool_alert_t") == 0 ) {
                ret = idmef_tool_alert_new((idmef_tool_alert_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_tool_alert_read_json((idmef_tool_alert_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_correlation_alert_t") == 0 ) {
                ret = idmef_correlation_alert_new((idmef_correlation_alert_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_correlation_alert_read_json((idmef_correlation_alert_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_overflow_alert_t") == 0 ) {
                ret = idmef_overflow_alert_new((idmef_overflow_alert_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_overflow_alert_read_json((idmef_overflow_alert_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_alert_t") == 0 ) {
                ret = idmef_alert_new((idmef_alert_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_alert_read_json((idmef_alert_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_heartbeat_t") == 0 ) {
                ret = idmef_heartbeat_new((idmef_heartbeat_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_heartbeat_read_json((idmef_heartbeat_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_message_t") == 0 ) {
                ret = idmef_message_new((idmef_message_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_message_read_json((idmef_message_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_reference_t") == 0 ) {
                ret = idmef_reference_new((idmef_reference_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_reference_read_json((idmef_reference_t *) *object, &ctrl);
        }
        else 
        if ( jsoneq(&ctrl, &ctrl.jtok[selfkey + 1], "idmef_checksum_t") == 0 ) {
                ret = idmef_checksum_new((idmef_checksum_t **) object);
                if ( ret < 0 )
                        return ret;

                ret = idmef_checksum_read_json((idmef_checksum_t *) *object, &ctrl);
        }
        
        else {
                ret = prelude_error_verbose(PRELUDE_ERROR_GENERIC, "unknown object type '%s'", "");
        }

        return ret;
}

