/* Chrysalide - Outil d'analyse de fichiers binaires
* symiter.c - prototypes pour le parcours simplifié d'un ensemble de symboles
*
* Copyright (C) 2017 Cyrille Bagard
*
* This file is part of Chrysalide.
*
* Chrysalide 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.
*
* Chrysalide 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 "symiter.h"
#include
#include "format.h"
/* Suivi d'un parcours de symboles */
typedef struct _sym_iter_t
{
GBinFormat *format; /* Conteneur associé */
unsigned int stamp; /* Suivi d'évolutions externes */
size_t index; /* Symbole courant */
mrange_t restriction; /* Enventuelle limite de zone */
bool is_restricted; /* Validité de l'étendue */
} sym_iter_t;
/******************************************************************************
* *
* Paramètres : format = processeur recensant divers symboles. *
* index = indice du premier symbole à fournir. *
* *
* Description : Construit un itérateur pour parcourir des symboles. *
* *
* Retour : Itérateur prêt à emploi. *
* *
* Remarques : - *
* *
******************************************************************************/
sym_iter_t *create_symbol_iterator(GBinFormat *format, size_t index)
{
sym_iter_t *result; /* Structure à retourner */
result = (sym_iter_t *)malloc(sizeof(sym_iter_t));
g_object_ref(G_OBJECT(format));
result->format = format;
result->stamp = g_binary_format_get_symbols_stamp(format);
result->index = index;
result->is_restricted = false;
return result;
}
/******************************************************************************
* *
* Paramètres : iter = itérateur à traiter. *
* *
* Description : Détruit un itérateur mis en place. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void delete_symbol_iterator(sym_iter_t *iter)
{
g_object_unref(G_OBJECT(iter->format));
free(iter);
}
/******************************************************************************
* *
* Paramètres : iter = itérateur à traiter. *
* range = bornes de l'espace de parcours. *
* *
* Description : Limite le parcours des symboles à une zone donnée. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void restrict_symbol_iterator(sym_iter_t *iter, const mrange_t *range)
{
copy_mrange(&iter->restriction, range);
iter->is_restricted = true;
}
/******************************************************************************
* *
* Paramètres : iter = itérateur à manipuler. *
* *
* Description : Fournit le symbole courant de l'itérateur. *
* *
* Retour : Symbole suivant trouvé, ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
GBinSymbol *get_symbol_iterator_current(sym_iter_t *iter)
{
GBinSymbol *result; /* Résultat à retourner */
const mrange_t *irange; /* Emplacement de symbole */
g_binary_format_lock_symbols_rd(iter->format);
if (iter->stamp != g_binary_format_get_symbols_stamp(iter->format))
result = NULL;
else
{
if (iter->index < g_binary_format_count_symbols(iter->format))
{
result = g_binary_format_get_symbol(iter->format, iter->index);
/* Le symbole sort-il des clous ? */
if (iter->is_restricted)
{
irange = g_binary_symbol_get_range(result);
if (!mrange_contains_mrange(&iter->restriction, irange))
{
g_object_unref(G_OBJECT(result));
result = NULL;
}
}
}
else
result = NULL;
}
g_binary_format_unlock_symbols_rd(iter->format);
return result;
}
/******************************************************************************
* *
* Paramètres : iter = itérateur à manipuler. *
* *
* Description : Fournit le symbole qui en précède un autre. *
* *
* Retour : Symbole suivant trouvé, ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
GBinSymbol *get_symbol_iterator_prev(sym_iter_t *iter)
{
GBinSymbol *result; /* Résultat à retourner */
const mrange_t *irange; /* Emplacement de symbole */
g_binary_format_lock_symbols_rd(iter->format);
if (iter->stamp != g_binary_format_get_symbols_stamp(iter->format))
result = NULL;
else
{
if (iter->index > 1)
{
iter->index--;
result = g_binary_format_get_symbol(iter->format, iter->index);
/* Le symbole sort-il des clous ? */
if (iter->is_restricted)
{
irange = g_binary_symbol_get_range(result);
if (!mrange_contains_mrange(&iter->restriction, irange))
{
g_object_unref(G_OBJECT(result));
result = NULL;
}
}
}
else
result = NULL;
}
g_binary_format_unlock_symbols_rd(iter->format);
return result;
}
/******************************************************************************
* *
* Paramètres : iter = itérateur à manipuler. *
* *
* Description : Fournit le symbole qui en suit un autre. *
* *
* Retour : Symbole suivant trouvé, ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
GBinSymbol *get_symbol_iterator_next(sym_iter_t *iter)
{
GBinSymbol *result; /* Résultat à retourner */
const mrange_t *irange; /* Emplacement de symbole */
g_binary_format_lock_symbols_rd(iter->format);
if (iter->stamp != g_binary_format_get_symbols_stamp(iter->format))
result = NULL;
else
{
if ((iter->index + 1) < g_binary_format_count_symbols(iter->format))
{
iter->index++;
result = g_binary_format_get_symbol(iter->format, iter->index);
/* Le symbole sort-il des clous ? */
if (iter->is_restricted)
{
irange = g_binary_symbol_get_range(result);
if (!mrange_contains_mrange(&iter->restriction, irange))
{
g_object_unref(G_OBJECT(result));
result = NULL;
}
}
}
else
result = NULL;
}
g_binary_format_unlock_symbols_rd(iter->format);
return result;
}