/* Chrysalide - Outil d'analyse de fichiers binaires
 * item.c - gestion d'éléments destinés à une collection générique
 *
 * Copyright (C) 2014 Cyrille Bagard
 *
 *  This file is part of Chrysalide.
 *
 *  OpenIDA is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  OpenIDA 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 Foobar.  If not, see .
 */
#include "item.h"
#include "item-int.h"
#include "../../common/io.h"
/* Initialise la classe des bases d'éléments pour collection. */
static void g_db_item_class_init(GDbItemClass *);
/* Initialise une base d'élément pour collection générique. */
static void g_db_item_init(GDbItem *);
/* Supprime toutes les références externes. */
static void g_db_item_dispose(GDbItem *);
/* Procède à la libération totale de la mémoire. */
static void g_db_item_finalize(GDbItem *);
/* Effectue la comparaison entre deux éléments de collection. */
static gint g_db_item_cmp(GDbItem *, GDbItem *);
/* Importe la définition d'une base d'éléments pour collection. */
static bool g_db_item_recv_from_fd(GDbItem *, int, int);
/* Exporte la définition d'une base d'éléments pour collection. */
static bool g_db_item_send_to_fd(const GDbItem *, int, int);
/* Indique le type défini pour une base d'élément de collection générique. */
G_DEFINE_TYPE(GDbItem, g_db_item, G_TYPE_OBJECT);
/******************************************************************************
*                                                                             *
*  Paramètres  : klass = classe à initialiser.                                *
*                                                                             *
*  Description : Initialise la classe des bases d'éléments pour collection.   *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static void g_db_item_class_init(GDbItemClass *klass)
{
    GObjectClass *object;                   /* Autre version de la classe  */
    object = G_OBJECT_CLASS(klass);
    object->dispose = (GObjectFinalizeFunc/* ! */)g_db_item_dispose;
    object->finalize = (GObjectFinalizeFunc)g_db_item_finalize;
    klass->cmp = (GCompareFunc)g_db_item_cmp;
    klass->recv = (recv_db_item_fc)g_db_item_recv_from_fd;
    klass->send = (send_db_item_fc)g_db_item_send_to_fd;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : item = instance à initialiser.                               *
*                                                                             *
*  Description : Initialise une base d'élément pour collection générique.     *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static void g_db_item_init(GDbItem *item)
{
}
/******************************************************************************
*                                                                             *
*  Paramètres  : item = instance d'objet GLib à traiter.                      *
*                                                                             *
*  Description : Supprime toutes les références externes.                     *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static void g_db_item_dispose(GDbItem *item)
{
    G_OBJECT_CLASS(g_db_item_parent_class)->dispose(G_OBJECT(item));
}
/******************************************************************************
*                                                                             *
*  Paramètres  : item = instance d'objet GLib à traiter.                      *
*                                                                             *
*  Description : Procède à la libération totale de la mémoire.                *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static void g_db_item_finalize(GDbItem *item)
{
    G_OBJECT_CLASS(g_db_item_parent_class)->finalize(G_OBJECT(item));
}
/******************************************************************************
*                                                                             *
*  Paramètres  : a = premier élément à analyser.                              *
*                b = second élément à analyser.                               *
*                                                                             *
*  Description : Effectue la comparaison entre deux éléments de collection.   *
*                                                                             *
*  Retour      : Bilan de la comparaison : -1, 0 ou 1.                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static gint g_db_item_cmp(GDbItem *a, GDbItem *b)
{
    gint result;                            /* Bilan à retourner           */
    /**
     * A n'utiliser qu'en dernier recours, pour départager deux
     * éléments par un serveur NTP...
     */
    if (a->modified > b->modified)
        result = 1;
    else if (a->modified < b->modified)
        result = -1;
    else
    {
        if (a->created > b->created)
            result = 1;
        else if (a->created < b->created)
            result = -1;
        else
            result = 0;
    }
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : a = premier élément à analyser.                              *
*                b = second élément à analyser.                               *
*                                                                             *
*  Description : Effectue la comparaison entre deux éléments de collection.   *
*                                                                             *
*  Retour      : Bilan de la comparaison : -1, 0 ou 1.                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
gint g_db_item_compare(GDbItem *a, GDbItem *b)
{
    return G_DB_ITEM_GET_CLASS(a)->cmp(a, b);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : item  = base d'éléments à charger. [OUT]                     *
*                fd    = flux ouvert en lecture pour l'importation.           *
*                flags = éventuelles options d'envoi supplémentaires.         *
*                                                                             *
*  Description : Importe la définition d'une base d'éléments pour collection. *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static bool g_db_item_recv_from_fd(GDbItem *item, int fd, int flags)
{
    uint64_t val64;                         /* Valeur sur 64 bits          */
    bool status;                            /* Bilan d'une réception       */
    status = safe_recv(fd, &val64, sizeof(uint64_t), flags);
    if (!status) return false;
    item->created = be64toh(val64);
    status = safe_recv(fd, &val64, sizeof(uint64_t), flags);
    if (!status) return false;
    item->modified = be64toh(val64);
    return true;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : item  = base d'éléments à charger. [OUT]                     *
*                fd    = flux ouvert en lecture pour l'importation.           *
*                flags = éventuelles options d'envoi supplémentaires.         *
*                                                                             *
*  Description : Importe la définition d'une base d'éléments pour collection. *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool g_db_item_recv(GDbItem *item, int fd, int flags)
{
    return G_DB_ITEM_GET_CLASS(item)->recv(item, fd, flags);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : item  = informations à sauvegarer.                           *
*                fd    = flux ouvert en écriture pour l'exportation.          *
*                flags = éventuelles options d'envoi supplémentaires.         *
*                                                                             *
*  Description : Exporte la définition d'une base d'éléments pour collection. *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static bool g_db_item_send_to_fd(const GDbItem *item, int fd, int flags)
{
    bool status;                            /* Bilan d'une émission        */
    printf(" FROM %s...\n", __FUNCTION__);
    status = safe_send(fd, (uint64_t []) { htobe64(item->created) }, sizeof(uint64_t), MSG_MORE | flags);
    if (!status) return false;
    status = safe_send(fd, (uint64_t []) { htobe64(item->modified) }, sizeof(uint64_t), flags);
    if (!status) return false;
    return true;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : item  = informations à sauvegarer.                           *
*                fd    = flux ouvert en écriture pour l'exportation.          *
*                flags = éventuelles options d'envoi supplémentaires.         *
*                                                                             *
*  Description : Exporte la définition d'une base d'éléments pour collection. *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool g_db_item_send(const GDbItem *item, int fd, int flags)
{
    return G_DB_ITEM_GET_CLASS(item)->send(item, fd, flags);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : item        = base d'éléments à modifier.                    *
*                is_volatile = état du besoin en sauvegarde.                  *
*                                                                             *
*  Description : Définit si l'élément contient des données à oublier ou non.  *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void g_db_item_set_volatile(GDbItem *item, bool is_volatile)
{
    item->is_volatile = is_volatile;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : item = base d'éléments à consulter.                          *
*                                                                             *
*  Description : Indique si l'élément contient des données à oublier ou non.  *
*                                                                             *
*  Retour      : Etat du besoin en sauvegarde.                                *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool g_db_item_is_volatile(const GDbItem *item)
{
    return item->is_volatile;
}