summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analysis/db/collection.c291
-rw-r--r--src/analysis/db/item-int.h8
-rw-r--r--src/analysis/db/item.c113
-rw-r--r--src/analysis/db/item.h6
-rw-r--r--src/analysis/db/items/bookmark.c74
-rw-r--r--src/analysis/db/items/comment.c183
-rw-r--r--src/analysis/db/items/move.c80
-rw-r--r--src/analysis/db/items/switcher.c129
-rw-r--r--src/analysis/db/misc/rlestr.c101
-rw-r--r--src/analysis/db/misc/rlestr.h9
-rw-r--r--src/analysis/db/misc/timestamp.c69
-rw-r--r--src/analysis/db/misc/timestamp.h9
-rw-r--r--src/arch/vmpa.c81
-rw-r--r--src/arch/vmpa.h5
-rw-r--r--src/common/sqlite.c382
-rw-r--r--src/common/sqlite.h12
-rw-r--r--src/glibext/gbinarycursor.c38
-rw-r--r--src/glibext/gbinarycursor.h4
-rw-r--r--src/glibext/glinecursor-int.h8
-rw-r--r--src/glibext/glinecursor.c6
-rw-r--r--src/glibext/glinecursor.h2
21 files changed, 885 insertions, 725 deletions
diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c
index 0a617f3..cdc91aa 100644
--- a/src/analysis/db/collection.c
+++ b/src/analysis/db/collection.c
@@ -67,6 +67,9 @@ static bool _g_db_collection_setup_load(GDbCollection *, bound_value **, size_t
/* Décrit les colonnes utiles à un chargement de données. */
static bool g_db_collection_setup_load(GDbCollection *, bound_value **, size_t *);
+/* Charge et intère un élément dans une collection. */
+static bool g_db_collection_load_new_item(const bound_value *, size_t, GDbCollection *);
+
/* Enregistre un élément de collection dans une base de données. */
static bool g_db_collection_store_item(const GDbCollection *, const GDbItem *, sqlite3 *);
@@ -961,16 +964,16 @@ bool g_db_collection_create_db_table(const GDbCollection *collec, sqlite3 *db)
static bool _g_db_collection_setup_load(GDbCollection *collec, bound_value **values, size_t *count)
{
- if (!setup_load_of_timestamp(NULL, "created", values, count))
+ if (!store_timestamp(NULL, "created", values, count))
return false;
- if (!setup_load_of_timestamp(NULL, "timestamp", values, count))
+ if (!store_timestamp(NULL, "timestamp", values, count))
return false;
- if (!setup_load_of_rle_string(NULL, "author", values, count))
+ if (!store_rle_string(NULL, "author", values, count))
return false;
- if (!setup_load_of_rle_string(NULL, "tool", values, count))
+ if (!store_rle_string(NULL, "tool", values, count))
return false;
return true;
@@ -1004,157 +1007,63 @@ static bool g_db_collection_setup_load(GDbCollection *collec, bound_value **valu
/******************************************************************************
* *
-* Paramètres : collec = ensemble d'éléments à peupler. *
-* db = base de données repondant aux requêtes. *
+* Paramètres : values = couples de champs et de valeurs à lier. *
+* count = nombre de ces couples. *
+* collec = collection à manipuler. *
* *
-* Description : Charge un ensemble d'éléments à partir d'une base de données.*
+* Description : Charge et intère un élément dans une collection. *
* *
-* Retour : Bilan de l'exécution de l'opération. *
+* Retour : Bilan de l'opération : succès ou non. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db)
+static bool g_db_collection_load_new_item(const bound_value *values, size_t count, GDbCollection *collec)
{
- bool result; /* Conclusion à faire remonter */
- bound_value *values; /* Champs de table à inclure */
- size_t count; /* Nombre de ces champs */
- char *sql; /* Requête SQL à construire */
- size_t i; /* Boucle de parcours */
- sqlite3_stmt *stmt; /* Déclaration mise en place */
- int ret; /* Bilan d'un appel à SQLite */
- int native_type; /* Type de valeur dans la base */
+ bool result; /* Bilan à retourner */
GDbItem *new; /* Nouvel élément à insérer */
- result = false;
-
- if (!g_db_collection_setup_load(collec, &values, &count))
- goto gdclai_building_values;
-
- /* Préparation de la requête */
+ new = g_object_new(G_DB_COLLECTION(collec)->type, NULL);
- sql = strdup("SELECT ");
+ result = g_db_item_load(new, values, count);
- for (i = 0; i < count; i++)
+ if (result)
{
- if (i > 0) sql = stradd(sql, ", ");
+ result = g_db_collection_add_item(G_DB_COLLECTION(collec), new);
- sql = stradd(sql, values[i].name);
+ g_object_unref(G_OBJECT(new));
}
- sql = stradd(sql, " FROM ");
- sql = stradd(sql, collec->name);
- sql = stradd(sql, ";");
-
- ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
- if (ret != SQLITE_OK)
- {
- fprintf(stderr, "Can't prepare SELECT statment '%s' (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db));
- goto gdclai_exit;
- }
-
- /* Chargement des valeurs existantes */
-
- result = true;
-
- for (ret = sqlite3_step(stmt); ret == SQLITE_ROW && result; ret = sqlite3_step(stmt))
- {
- /* Conversion des valeurs */
-
- for (i = 0; i < count; i++)
- {
- native_type = sqlite3_column_type(stmt, i);
-
- /**
- * On réalise une petite conversion selon le champ.
- *
- * Le filtre SQLITE_NATIVE est destiné à conserver le type choisi par
- * SQLite. Typiquement, une chaîne peut être à SQLITE_NULL ou SQLITE_TEXT
- * selon la valeur conservée dans la base.
- *
- * D'autres éléments, comme les localisations en mémoire, peuvent aussi
- * avoir un champ éventuellement nul, donc la définition à partir des
- * indications de la base de données reste importante.
- *
- * En ce qui concerne les valeurs numériques, SQLite ne fait pas de
- * distinction : tout passe par la fonction sqlite3VdbeIntValue(),
- * qui effectue des transtypages au besoin pour tout ce qui n'est
- * pas numérique.
- *
- * Pour les types internes SQLITE_INTEGER et SQLITE_BOOLEAN,
- * il est donc nécessaire d'ajuster en interne.
- */
-
- if (native_type == SQLITE_INTEGER)
- native_type = SQLITE_INT64;
-
- if (values[i].type == SQLITE_NATIVE)
- values[i].type = native_type;
-
- else
- assert(values[i].type == native_type
- || values[i].type == SQLITE_INTEGER
- || values[i].type == SQLITE_BOOLEAN);
-
- switch (values[i].type)
- {
- case SQLITE_BOOLEAN:
- values[i].boolean = (bool)sqlite3_column_int(stmt, i);
- break;
-
- case SQLITE_INTEGER:
- values[i].integer = sqlite3_column_int(stmt, i);
- break;
-
- case SQLITE_INT64:
- values[i].integer64 = sqlite3_column_int64(stmt, i);
- break;
-
- case SQLITE_FLOAT:
- assert(0);
- break;
-
- case SQLITE_TEXT:
- values[i].cstring = (const char *)sqlite3_column_text(stmt, i);
- break;
-
- case SQLITE_BLOB:
- assert(0);
- break;
-
- case SQLITE_NULL:
- break;
-
- default:
- assert(0);
- break;
-
- }
-
- }
-
- /* Chargement d'un nouvel élément */
-
- new = g_object_new(G_DB_COLLECTION(collec)->type, NULL);
-
- result = g_db_item_load(new, values, count);
- result &= g_db_collection_add_item(G_DB_COLLECTION(collec), new);
-
- g_object_unref(G_OBJECT(new));
+ return result;
- }
+}
- /* Sortie propre */
- sqlite3_finalize(stmt);
+/******************************************************************************
+* *
+* Paramètres : collec = ensemble d'éléments à peupler. *
+* db = base de données repondant aux requêtes. *
+* *
+* Description : Charge un ensemble d'éléments à partir d'une base de données.*
+* *
+* Retour : Bilan de l'exécution de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- gdclai_exit:
+bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db)
+{
+ bool result; /* Conclusion à faire remonter */
+ bound_value *values; /* Champs de table à inclure */
+ size_t count; /* Nombre de ces champs */
- free(sql);
+ result = g_db_collection_setup_load(collec, &values, &count);
- gdclai_building_values:
+ if (result)
+ result = load_db_values(db, collec->name, values, count, (db_load_cb)g_db_collection_load_new_item, collec);
free_all_bound_values(values, count);
@@ -1182,121 +1091,11 @@ static bool g_db_collection_store_item(const GDbCollection *collec, const GDbIte
bool result; /* Conclusion à faire remonter */
bound_value *values; /* Champs de table à inclure */
size_t count; /* Nombre de ces champs */
- char *sql; /* Requête SQL à construire */
- size_t i; /* Boucle de parcours */
- sqlite3_stmt *stmt; /* Déclaration mise en place */
- int ret; /* Bilan d'un appel à SQLite */
- int index; /* Indice de valeur attachée */
- result = false;
-
- if (!g_db_item_prepare_db_statement(item, &values, &count))
- goto gdcsi_building_values;
-
- /* Préparation de la requête */
-
- sql = strdup("INSERT INTO ");
- sql = stradd(sql, collec->name);
- sql = stradd(sql, " (");
+ result = g_db_item_store(item, &values, &count);
- for (i = 0; i < count; i++)
- {
- if (i > 0) sql = stradd(sql, ", ");
-
- sql = stradd(sql, values[i].name);
-
- }
-
- sql = stradd(sql, ") VALUES (");
-
- for (i = 0; i < count; i++)
- {
- if (i > 0) sql = stradd(sql, ", ");
-
- if (values[i].type == SQLITE_RAW)
- sql = stradd(sql, values[i].cstring);
- else
- sql = stradd(sql, "?");
-
- }
-
- sql = stradd(sql, ");");
-
- ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
- if (ret != SQLITE_OK)
- {
- fprintf(stderr, "Can't prepare INSERT statment '%s' (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db));
- goto gdcsi_exit;
- }
-
- /* Attribution des valeurs */
-
- index = 1;
-
- for (i = 0; i < count; i++)
- {
- switch (values[i].type)
- {
- case SQLITE_BOOLEAN:
- ret = sqlite3_bind_int(stmt, index, values[i].boolean);
- index++;
- break;
-
- case SQLITE_INTEGER:
- ret = sqlite3_bind_int(stmt, index, values[i].integer);
- index++;
- break;
-
- case SQLITE_INT64:
- ret = sqlite3_bind_int64(stmt, index, values[i].integer64);
- index++;
- break;
-
- case SQLITE_TEXT:
- ret = sqlite3_bind_text(stmt, index, values[i].string, -1, values[i].delete);
- index++;
- break;
-
- case SQLITE_NULL:
- ret = sqlite3_bind_null(stmt, index);
- index++;
- break;
-
- default:
- assert(false);
- ret = SQLITE_ERROR;
- break;
-
- }
-
- if (ret != SQLITE_OK)
- {
- fprintf(stderr, "Can't bind value for parameter nb %d in '%s' (ret=%d): %s\n",
- index - 1, sql, ret, sqlite3_errmsg(db));
- goto gdcsi_exit;
- }
-
- }
-
- /* Exécution finale */
-
- ret = sqlite3_step(stmt);
-
- if (ret != SQLITE_DONE)
- {
- fprintf(stderr, "INSERT statement '%s' didn't return DONE (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db));
- goto gdcsi_exit;
- }
-
- sqlite3_finalize(stmt);
-
- result = true;
-
- gdcsi_exit:
-
- free(sql);
-
- gdcsi_building_values:
+ if (result)
+ result = store_db_values(db, collec->name, values, count);
free_all_bound_values(values, count);
@@ -1334,7 +1133,7 @@ static bool g_db_collection_store_updated_item(const GDbCollection *collec, cons
result = false;
- if (!g_db_item_prepare_db_statement(item, &values, &count))
+ if (!g_db_item_store(item, &values, &count))
goto gdcsui_building_values;
/* Préparation de la requête */
diff --git a/src/analysis/db/item-int.h b/src/analysis/db/item-int.h
index 618bab9..3a5f47d 100644
--- a/src/analysis/db/item-int.h
+++ b/src/analysis/db/item-int.h
@@ -51,12 +51,12 @@ typedef void (* build_item_label_fc) (GDbItem *);
/* Exécute un élément de collection sur un binaire. */
typedef bool (* run_item_fc) (GDbItem *, GLoadedBinary *);
-/* Constitue les champs destinés à une insertion / modification. */
-typedef bool (* prepare_db_statement) (const GDbItem *, bound_value **, size_t *);
-
/* Charge les valeurs utiles pour une localisation. */
typedef bool (* load_db_item_fc) (GDbItem *, const bound_value *, size_t);
+/* Constitue les champs destinés à une insertion / modification. */
+typedef bool (* store_db_item_fc) (const GDbItem *, bound_value **, size_t *);
+
/* Base d'un élément pour collection générique (instance) */
struct _GDbItem
@@ -91,8 +91,8 @@ struct _GDbItemClass
run_item_fc apply; /* Application de l'élément */
run_item_fc cancel; /* Retrait de l'élément */
- prepare_db_statement prepare_stmt; /* Préparation d'une requête */
load_db_item_fc load; /* Chargement à partir d'une BD*/
+ store_db_item_fc store; /* Préparation d'une requête */
};
diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c
index f01a953..6fa168f 100644
--- a/src/analysis/db/item.c
+++ b/src/analysis/db/item.c
@@ -58,12 +58,12 @@ static bool _g_db_item_pack(const GDbItem *, packed_buffer *);
/* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */
-/* Constitue les champs destinés à une insertion / modification. */
-static bool _g_db_item_prepare_db_statement(const GDbItem *, bound_value **, size_t *);
-
/* Charge les valeurs utiles pour un élément de collection. */
static bool _g_db_item_load(GDbItem *, const bound_value *, size_t);
+/* Constitue les champs destinés à une insertion / modification. */
+static bool _g_db_item_store(const GDbItem *, bound_value **, size_t *);
+
/* Indique le type défini pour une base d'élément de collection générique. */
@@ -96,8 +96,8 @@ static void g_db_item_class_init(GDbItemClass *klass)
klass->unpack = (unpack_db_item_fc)_g_db_item_unpack;
klass->pack = (pack_db_item_fc)_g_db_item_pack;
- klass->prepare_stmt = (prepare_db_statement)_g_db_item_prepare_db_statement;
klass->load = (load_db_item_fc)_g_db_item_load;
+ klass->store = (store_db_item_fc)_g_db_item_store;
}
@@ -616,31 +616,31 @@ bool g_db_item_is_volatile(const GDbItem *item)
/******************************************************************************
* *
-* Paramètres : item = base d'éléments sur laquelle s'appuyer. *
-* values = couples de champs et de valeurs à lier. [OUT] *
-* count = nombre de ces couples. [OUT] *
+* Paramètres : item = base d'éléments à charger depuis les réponses. *
+* values = tableau d'éléments à consulter. *
+* count = nombre de descriptions renseignées. *
* *
-* Description : Constitue les champs destinés à une insertion / modification.*
+* Description : Charge les valeurs utiles pour un élément de collection. *
* *
-* Retour : Bilan de l'opération : succès ou non. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool _g_db_item_prepare_db_statement(const GDbItem *item, bound_value **values, size_t *count)
+static bool _g_db_item_load(GDbItem *item, const bound_value *values, size_t count)
{
- bool result; /* Bilan à retourner */
+ bool result; /* Bilan global à retourner */
result = true;
- result &= prepare_db_statement_for_timestamp(&item->created, "created", values, count);
+ result &= load_timestamp(&item->created, "created", values, count);
- result &= prepare_db_statement_for_timestamp(&item->timestamp, "timestamp", values, count);
+ result &= load_timestamp(&item->timestamp, "timestamp", values, count);
- result &= prepare_db_statement_for_rle_string(&item->author, "author", values, count);
+ result &= load_rle_string(&item->author, "author", values, count);
- result &= prepare_db_statement_for_rle_string(&item->tool, "tool", values, count);
+ result &= load_rle_string(&item->tool, "tool", values, count);
return result;
@@ -649,55 +649,75 @@ static bool _g_db_item_prepare_db_statement(const GDbItem *item, bound_value **v
/******************************************************************************
* *
-* Paramètres : item = base d'éléments sur laquelle s'appuyer. *
-* values = couples de champs et de valeurs à lier. [OUT] *
-* count = nombre de ces couples. [OUT] *
+* Paramètres : item = base d'éléments à charger depuis les réponses. *
+* values = tableau d'éléments à consulter. *
+* count = nombre de descriptions renseignées. *
* *
-* Description : Constitue les champs destinés à une insertion / modification.*
+* Description : Charge les valeurs utiles pour un élément de collection. *
* *
-* Retour : Bilan de l'opération : succès ou non. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_db_item_prepare_db_statement(const GDbItem *item, bound_value **values, size_t *count)
+bool g_db_item_load(GDbItem *item, const bound_value *values, size_t count)
{
- *values = NULL;
- *count = 0;
+ bool result; /* Bilan à retourner */
+
+ result = G_DB_ITEM_GET_CLASS(item)->load(item, values, count);
- return G_DB_ITEM_GET_CLASS(item)->prepare_stmt(item, values, count);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : item = base d'éléments à charger depuis les réponses. *
-* values = tableau d'éléments à consulter. *
-* count = nombre de descriptions renseignées. *
+* Paramètres : item = base d'éléments sur laquelle s'appuyer. *
+* values = couples de champs et de valeurs à lier. [OUT] *
+* count = nombre de ces couples. [OUT] *
* *
-* Description : Charge les valeurs utiles pour un élément de collection. *
+* Description : Constitue les champs destinés à une insertion / modification.*
* *
-* Retour : Bilan de l'opération. *
+* Retour : Bilan de l'opération : succès ou non. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool _g_db_item_load(GDbItem *item, const bound_value *values, size_t count)
+static bool _g_db_item_store(const GDbItem *item, bound_value **values, size_t *count)
{
- bool result; /* Bilan global à retourner */
-
- result = true;
+ bool result; /* Bilan à retourner */
- result &= load_timestamp(&item->created, "created", values, count);
+ if (item == NULL)
+ result = store_timestamp(NULL, "created", values, count);
+ else
+ result = store_timestamp(&item->created, "created", values, count);
- result &= load_timestamp(&item->timestamp, "timestamp", values, count);
+ if (result)
+ {
+ if (item == NULL)
+ result = store_timestamp(NULL, "timestamp", values, count);
+ else
+ result = store_timestamp(&item->timestamp, "timestamp", values, count);
+ }
- result &= load_rle_string(&item->author, "author", values, count);
+ if (result)
+ {
+ if (item == NULL)
+ result = store_rle_string(NULL, "author", values, count);
+ else
+ result = store_rle_string(&item->author, "author", values, count);
+ }
- result &= load_rle_string(&item->tool, "tool", values, count);
+ if (result)
+ {
+ if (item == NULL)
+ result = store_rle_string(NULL, "tool", values, count);
+ else
+ result = store_rle_string(&item->tool, "tool", values, count);
+ }
return result;
@@ -706,24 +726,23 @@ static bool _g_db_item_load(GDbItem *item, const bound_value *values, size_t cou
/******************************************************************************
* *
-* Paramètres : item = base d'éléments à charger depuis les réponses. *
-* values = tableau d'éléments à consulter. *
-* count = nombre de descriptions renseignées. *
+* Paramètres : item = base d'éléments sur laquelle s'appuyer. *
+* values = couples de champs et de valeurs à lier. [OUT] *
+* count = nombre de ces couples. [OUT] *
* *
-* Description : Charge les valeurs utiles pour un élément de collection. *
+* Description : Constitue les champs destinés à une insertion / modification.*
* *
-* Retour : Bilan de l'opération. *
+* Retour : Bilan de l'opération : succès ou non. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_db_item_load(GDbItem *item, const bound_value *values, size_t count)
+bool g_db_item_store(const GDbItem *item, bound_value **values, size_t *count)
{
- bool result; /* Bilan à retourner */
-
- result = G_DB_ITEM_GET_CLASS(item)->load(item, values, count);
+ *values = NULL;
+ *count = 0;
- return result;
+ return G_DB_ITEM_GET_CLASS(item)->store(item, values, count);
}
diff --git a/src/analysis/db/item.h b/src/analysis/db/item.h
index 1cb0a0b..6644507 100644
--- a/src/analysis/db/item.h
+++ b/src/analysis/db/item.h
@@ -108,12 +108,12 @@ bool g_db_item_is_volatile(const GDbItem *);
/* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */
-/* Constitue les champs destinés à une insertion / modification. */
-bool g_db_item_prepare_db_statement(const GDbItem *, bound_value **, size_t *);
-
/* Charge les valeurs utiles pour un élément de collection. */
bool g_db_item_load(GDbItem *, const bound_value *, size_t);
+/* Constitue les champs destinés à une insertion / modification. */
+bool g_db_item_store(const GDbItem *, bound_value **, size_t *);
+
#endif /* _ANALYSIS_DB_ITEM_H */
diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c
index d3010dd..5d6ccfa 100644
--- a/src/analysis/db/items/bookmark.c
+++ b/src/analysis/db/items/bookmark.c
@@ -93,12 +93,12 @@ static bool g_db_bookmark_apply(GDbBookmark *, GLoadedBinary *);
/* Annule un signet sur un tampon de binaire chargé. */
static bool g_db_bookmark_cancel(GDbBookmark *, GLoadedBinary *);
-/* Constitue les champs destinés à une insertion / modification. */
-static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *, bound_value **, size_t *);
-
/* Charge les valeurs utiles pour un signet. */
static bool g_db_bookmark_load(GDbBookmark *, const bound_value *, size_t);
+/* Constitue les champs destinés à une insertion / modification. */
+static bool g_db_bookmark_store(const GDbBookmark *, bound_value **, size_t *);
+
/* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */
@@ -186,8 +186,8 @@ static void g_db_bookmark_class_init(GDbBookmarkClass *klass)
item->apply = (run_item_fc)g_db_bookmark_apply;
item->cancel = (run_item_fc)g_db_bookmark_cancel;
- item->prepare_stmt = (prepare_db_statement)g_db_bookmark_prepare_db_statement;
item->load = (load_db_item_fc)g_db_bookmark_load;
+ item->store = (store_db_item_fc)g_db_bookmark_store;
}
@@ -492,61 +492,73 @@ static bool g_db_bookmark_cancel(GDbBookmark *bookmark, GLoadedBinary *binary)
/******************************************************************************
* *
-* Paramètres : bookmark = base d'éléments sur laquelle s'appuyer. *
-* values = couples de champs et de valeurs à lier. [OUT] *
-* count = nombre de ces couples. [OUT] *
+* Paramètres : bookmark = bascule d'affichage à charger depuis les réponses.*
+* values = tableau d'éléments à consulter. *
+* count = nombre de descriptions renseignées. *
* *
-* Description : Constitue les champs destinés à une insertion / modification.*
+* Description : Charge les valeurs utiles pour un signet. *
* *
-* Retour : Etat du besoin en sauvegarde. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *bookmark, bound_value **values, size_t *count)
+static bool g_db_bookmark_load(GDbBookmark *bookmark, const bound_value *values, size_t count)
{
- bool status; /* Bilan d'opération initiale */
+ bool result; /* Bilan à faire remonter */
- status = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->prepare_stmt(G_DB_ITEM(bookmark), values, count);
- if (!status) return false;
+ result = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->load(G_DB_ITEM(bookmark), values, count);
- status = prepare_vmpa_db_statement(&bookmark->addr, NULL, values, count);
- if (!status) return false;
+ result &= load_vmpa(&bookmark->addr, NULL, values, count);
- status &= prepare_db_statement_for_rle_string(&bookmark->comment, "comment", values, count);
- if (!status) return false;
+ result &= load_rle_string(&bookmark->comment, "comment", values, count);
- return true;
+ return result;
}
/******************************************************************************
* *
-* Paramètres : bookmark = bascule d'affichage à charger depuis les réponses.*
-* values = tableau d'éléments à consulter. *
-* count = nombre de descriptions renseignées. *
+* Paramètres : bookmark = base d'éléments sur laquelle s'appuyer. *
+* values = couples de champs et de valeurs à lier. [OUT] *
+* count = nombre de ces couples. [OUT] *
* *
-* Description : Charge les valeurs utiles pour un signet. *
+* Description : Constitue les champs destinés à une insertion / modification.*
* *
-* Retour : Bilan de l'opération. *
+* Retour : Etat du besoin en sauvegarde. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_db_bookmark_load(GDbBookmark *bookmark, const bound_value *values, size_t count)
+static bool g_db_bookmark_store(const GDbBookmark *bookmark, bound_value **values, size_t *count)
{
- bool result; /* Bilan à faire remonter */
+ bool status; /* Bilan d'opération initiale */
- result = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->load(G_DB_ITEM(bookmark), values, count);
+ if (bookmark == NULL)
+ status = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->store(NULL, values, count);
+ else
+ status = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->store(G_DB_ITEM(bookmark), values, count);
- result &= load_vmpa(&bookmark->addr, NULL, values, count);
+ if (!status) return false;
- result &= load_rle_string(&bookmark->comment, "comment", values, count);
+ if (bookmark == NULL)
+ status = store_vmpa(NULL, NULL, values, count);
+ else
+ status = store_vmpa(&bookmark->addr, NULL, values, count);
- return result;
+ if (!status) return false;
+
+ if (bookmark == NULL)
+ status &= store_rle_string(NULL, "comment", values, count);
+ else
+ status &= store_rle_string(&bookmark->comment, "comment", values, count);
+
+ if (!status) return false;
+
+ return true;
}
@@ -801,10 +813,10 @@ static bool g_bookmark_collection_setup_load(GBookmarkCollection *collec, bound_
values, count);
if (!status) return false;
- if (!setup_load_for_vmpa(NULL, values, count))
+ if (!store_vmpa(NULL, NULL, values, count))
return false;
- if (!setup_load_of_rle_string(NULL, "comment", values, count))
+ if (!store_rle_string(NULL, "comment", values, count))
return false;
return true;
diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c
index 7eb7906..6ac37fd 100644
--- a/src/analysis/db/items/comment.c
+++ b/src/analysis/db/items/comment.c
@@ -113,12 +113,12 @@ static bool g_db_comment_apply(GDbComment *, GLoadedBinary *);
/* Annule l'impression d'un commentaire dans du code de binaire. */
static bool g_db_comment_cancel(GDbComment *, GLoadedBinary *);
-/* Constitue les champs destinés à une insertion / modification. */
-static bool g_db_comment_prepare_db_statement(GDbComment *, bound_value **, size_t *);
-
/* Charge les valeurs utiles pour un commentaire. */
static bool g_db_comment_load(GDbComment *, const bound_value *, size_t);
+/* Constitue les champs destinés à une insertion / modification. */
+static bool g_db_comment_store(GDbComment *, bound_value **, size_t *);
+
/* Associe un contenu formaté supplémentaire à un commentaire. */
static void g_db_comment_add_rle_string(GDbComment *, const rle_string *);
@@ -236,8 +236,8 @@ static void g_db_comment_class_init(GDbCommentClass *klass)
item->apply = (run_item_fc)g_db_comment_apply;
item->cancel = (run_item_fc)g_db_comment_cancel;
- item->prepare_stmt = (prepare_db_statement)g_db_comment_prepare_db_statement;
item->load = (load_db_item_fc)g_db_comment_load;
+ item->store = (store_db_item_fc)g_db_comment_store;
}
@@ -694,8 +694,7 @@ static bool g_db_comment_run(GDbComment *comment, GLoadedBinary *binary, bool ap
if (apply)
{
comment->old_count = scount;
- comment->old_inlined = (GLineGenerator **)realloc(comment->old_inlined,
- comment->old_count * sizeof(GLineGenerator *));
+ comment->old_inlined = realloc(comment->old_inlined, comment->old_count * sizeof(GLineGenerator *));
}
for (i = 0; i < scount && result; i++)
@@ -805,7 +804,7 @@ static bool g_db_comment_run(GDbComment *comment, GLoadedBinary *binary, bool ap
assert(comment->old_count == 0);
comment->old_count = 1;
- comment->oldies = (GDbComment **)calloc(comment->old_count, sizeof(GDbComment *));
+ comment->oldies = calloc(comment->old_count, sizeof(GDbComment *));
}
@@ -876,8 +875,7 @@ static bool g_db_comment_run(GDbComment *comment, GLoadedBinary *binary, bool ap
if (apply)
{
comment->old_count += scount;
- comment->oldies = (GDbComment **)realloc(comment->oldies,
- comment->old_count * sizeof(GDbComment *));
+ comment->oldies = realloc(comment->oldies, comment->old_count * sizeof(GDbComment *));
}
for (i = 0; i < scount && result; i++)
@@ -970,73 +968,6 @@ static bool g_db_comment_cancel(GDbComment *comment, GLoadedBinary *binary)
/******************************************************************************
* *
-* Paramètres : comment = base d'éléments sur laquelle s'appuyer. *
-* values = couples de champs et de valeurs à lier. [OUT] *
-* count = nombre de ces couples. [OUT] *
-* *
-* Description : Constitue les champs destinés à une insertion / modification.*
-* *
-* Retour : Etat du besoin en sauvegarde. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_db_comment_prepare_db_statement(GDbComment *comment, bound_value **values, size_t *count)
-{
- bool status; /* Bilan d'opération initiale */
- bound_value *value; /* Valeur à éditer / définir */
- rle_string text; /* Texte brut récupéré */
-
- status = G_DB_ITEM_CLASS(g_db_comment_parent_class)->prepare_stmt(G_DB_ITEM(comment), values, count);
- if (!status) return false;
-
- status = prepare_vmpa_db_statement(&comment->addr, NULL, values, count);
- if (!status) return false;
-
- *count += 1;
- *values = (bound_value *)realloc(*values, *count * sizeof(bound_value));
-
- value = &(*values)[*count - 1];
-
- value->cname = "flags";
- value->built_name = false;
- value->type = SQLITE_INTEGER;
- value->integer = comment->flags;
- value->delete = NULL;
-
- init_dynamic_rle_string(&text, g_db_comment_get_text(comment));
- status &= prepare_db_statement_for_rle_string(&text, "text", values, count);
- exit_rle_string(&text);
-
- if (!status) return false;
-
- *count += 2;
- *values = (bound_value *)realloc(*values, *count * sizeof(bound_value));
-
- value = &(*values)[*count - 2];
-
- value->cname = "inlined";
- value->built_name = false;
- value->type = SQLITE_BOOLEAN;
- value->boolean = comment->inlined;
- value->delete = NULL;
-
- value = &(*values)[*count - 1];
-
- value->cname = "repeatable";
- value->built_name = false;
- value->type = SQLITE_BOOLEAN;
- value->boolean = comment->repeatable;
- value->delete = NULL;
-
- return true;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : comment = commentaire textuel à charger depuis les réponses. *
* values = tableau d'éléments à consulter. *
* count = nombre de descriptions renseignées. *
@@ -1101,6 +1032,98 @@ static bool g_db_comment_load(GDbComment *comment, const bound_value *values, si
/******************************************************************************
* *
+* Paramètres : comment = base d'éléments sur laquelle s'appuyer. *
+* values = couples de champs et de valeurs à lier. [OUT] *
+* count = nombre de ces couples. [OUT] *
+* *
+* Description : Constitue les champs destinés à une insertion / modification.*
+* *
+* Retour : Etat du besoin en sauvegarde. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_db_comment_store(GDbComment *comment, bound_value **values, size_t *count)
+{
+ bool status; /* Bilan d'opération initiale */
+ bound_value *value; /* Valeur à éditer / définir */
+ rle_string text; /* Texte brut récupéré */
+
+ if (comment == NULL)
+ status = G_DB_ITEM_CLASS(g_db_comment_parent_class)->store(NULL, values, count);
+ else
+ status = G_DB_ITEM_CLASS(g_db_comment_parent_class)->store(G_DB_ITEM(comment), values, count);
+
+ if (!status) return false;
+
+ if (comment == NULL)
+ status = store_vmpa(NULL, NULL, values, count);
+ else
+ status = store_vmpa(&comment->addr, NULL, values, count);
+
+ if (!status) return false;
+
+ *count += 1;
+ *values = realloc(*values, *count * sizeof(bound_value));
+
+ value = &(*values)[*count - 1];
+
+ value->cname = "flags";
+ value->built_name = false;
+ value->type = SQLITE_INTEGER;
+ value->integer = comment->flags;
+ value->delete = NULL;
+
+ value->has_value = (comment != NULL);
+
+ if (value->has_value)
+ {
+ init_dynamic_rle_string(&text, g_db_comment_get_text(comment));
+ status = store_rle_string(&text, "text", values, count);
+ exit_rle_string(&text);
+ }
+
+ if (!status) return false;
+
+ *count += 2;
+ *values = realloc(*values, *count * sizeof(bound_value));
+
+ value = &(*values)[*count - 2];
+
+ value->cname = "inlined";
+ value->built_name = false;
+ value->type = SQLITE_BOOLEAN;
+
+ value->has_value = (comment != NULL);
+
+ if (value->has_value)
+ {
+ value->boolean = comment->inlined;
+ value->delete = NULL;
+ }
+
+ value = &(*values)[*count - 1];
+
+ value->cname = "repeatable";
+ value->built_name = false;
+ value->type = SQLITE_BOOLEAN;
+
+ value->has_value = (comment != NULL);
+
+ if (value->has_value)
+ {
+ value->boolean = comment->repeatable;
+ value->delete = NULL;
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : comment = informations à consulter. *
* *
* Description : Fournit l'adresse associée à un commentaire. *
@@ -1649,11 +1672,11 @@ static bool g_comment_collection_setup_load(GCommentCollection *collec, bound_va
values, count);
if (!status) return false;
- if (!setup_load_for_vmpa(NULL, values, count))
+ if (!store_vmpa(NULL, NULL, values, count))
return false;
*count += 1;
- *values = (bound_value *)realloc(*values, *count * sizeof(bound_value));
+ *values = realloc(*values, *count * sizeof(bound_value));
value = &(*values)[*count - 1];
@@ -1661,11 +1684,11 @@ static bool g_comment_collection_setup_load(GCommentCollection *collec, bound_va
value->built_name = false;
value->type = SQLITE_INTEGER;
- if (!setup_load_of_rle_string(NULL, "text", values, count))
+ if (!store_rle_string(NULL, "text", values, count))
return false;
*count += 2;
- *values = (bound_value *)realloc(*values, *count * sizeof(bound_value));
+ *values = realloc(*values, *count * sizeof(bound_value));
value = &(*values)[*count - 2];
diff --git a/src/analysis/db/items/move.c b/src/analysis/db/items/move.c
index 6929ec3..286215b 100644
--- a/src/analysis/db/items/move.c
+++ b/src/analysis/db/items/move.c
@@ -95,12 +95,12 @@ static bool g_db_move_apply(GDbMove *, GLoadedBinary *);
/* Annule un déplacement au sein d'une zone de code. */
static bool g_db_move_cancel(GDbMove *, GLoadedBinary *);
-/* Constitue les champs destinés à une insertion / modification. */
-static bool g_db_move_prepare_db_statement(const GDbMove *, bound_value **, size_t *);
-
/* Charge les valeurs utiles pour un déplacement dans du code. */
static bool g_db_move_load(GDbMove *, const bound_value *, size_t);
+/* Constitue les champs destinés à une insertion / modification. */
+static bool g_db_move_store(const GDbMove *, bound_value **, size_t *);
+
/* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */
@@ -188,8 +188,8 @@ static void g_db_move_class_init(GDbMoveClass *klass)
item->apply = (run_item_fc)g_db_move_apply;
item->cancel = (run_item_fc)g_db_move_cancel;
- item->prepare_stmt = (prepare_db_statement)g_db_move_prepare_db_statement;
item->load = (load_db_item_fc)g_db_move_load;
+ item->store = (store_db_item_fc)g_db_move_store;
}
@@ -455,7 +455,7 @@ static bool g_db_move_run(const GDbMove *move, GLineCursor *cursor)
if (G_IS_LOADED_PANEL(panel))
{
- params = (move_params *)calloc(1, sizeof(move_params));
+ params = calloc(1, sizeof(move_params));
params->panel = panel;
params->cursor = cursor;
@@ -527,63 +527,75 @@ static bool g_db_move_cancel(GDbMove *move, GLoadedBinary *binary)
/******************************************************************************
* *
-* Paramètres : move = base d'éléments sur laquelle s'appuyer. *
-* values = couples de champs et de valeurs à lier. [OUT] *
-* count = nombre de ces couples. [OUT] *
+* Paramètres : move = bascule d'affichage à charger depuis les réponses. *
+* values = tableau d'éléments à consulter. *
+* count = nombre de descriptions renseignées. *
* *
-* Description : Constitue les champs destinés à une insertion / modification.*
+* Description : Charge les valeurs utiles pour un déplacement dans du code. *
* *
-* Retour : Etat du besoin en sauvegarde. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_db_move_prepare_db_statement(const GDbMove *move, bound_value **values, size_t *count)
+static bool g_db_move_load(GDbMove *move, const bound_value *values, size_t count)
{
- bool status; /* Bilan d'opération initiale */
+ bool result; /* Bilan à faire remonter */
- status = G_DB_ITEM_CLASS(g_db_move_parent_class)->prepare_stmt(G_DB_ITEM(move), values, count);
- if (!status) return false;
+ result = G_DB_ITEM_CLASS(g_db_move_parent_class)->load(G_DB_ITEM(move), values, count);
- status = g_line_cursor_prepare_db_statement(move->src, "src", values, count);
- if (!status) return false;
+ if (result)
+ result = g_line_cursor_load(move->src, "src", values, count);
- status = g_line_cursor_prepare_db_statement(move->src, "dest", values, count);
- if (!status) return false;
+ if (result)
+ result = g_line_cursor_load(move->dest, "dest", values, count);
- return true;
+ return result;
}
/******************************************************************************
* *
-* Paramètres : move = bascule d'affichage à charger depuis les réponses. *
-* values = tableau d'éléments à consulter. *
-* count = nombre de descriptions renseignées. *
+* Paramètres : move = base d'éléments sur laquelle s'appuyer. *
+* values = couples de champs et de valeurs à lier. [OUT] *
+* count = nombre de ces couples. [OUT] *
* *
-* Description : Charge les valeurs utiles pour un déplacement dans du code. *
+* Description : Constitue les champs destinés à une insertion / modification.*
* *
-* Retour : Bilan de l'opération. *
+* Retour : Etat du besoin en sauvegarde. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_db_move_load(GDbMove *move, const bound_value *values, size_t count)
+static bool g_db_move_store(const GDbMove *move, bound_value **values, size_t *count)
{
- bool result; /* Bilan à faire remonter */
+ bool status; /* Bilan d'opération initiale */
- result = G_DB_ITEM_CLASS(g_db_move_parent_class)->load(G_DB_ITEM(move), values, count);
+ if (move == NULL)
+ status = G_DB_ITEM_CLASS(g_db_move_parent_class)->store(NULL, values, count);
+ else
+ status = G_DB_ITEM_CLASS(g_db_move_parent_class)->store(G_DB_ITEM(move), values, count);
- if (result)
- result = g_line_cursor_load(move->src, "src", values, count);
+ if (!status) return false;
- if (result)
- result = g_line_cursor_load(move->dest, "dest", values, count);
+ if (move == NULL)
+ status = g_line_cursor_setup_load(move->src, "src", values, count);
+ else
+ status = g_line_cursor_store(move->src, "src", values, count);
- return result;
+ if (!status) return false;
+
+ if (move == NULL)
+ status = g_line_cursor_setup_load(move->dest, "dest", values, count);
+ else
+ status = g_line_cursor_store(move->dest, "dest", values, count);
+
+ if (!status) return false;
+
+ return true;
}
@@ -783,10 +795,10 @@ static bool g_move_collection_setup_load(GMoveCollection *collec, bound_value **
values, count);
if (!status) return false;
- if (!g_binary_cursor_setup_load("src", values, count))
+ if (!g_binary_cursor_store(NULL, "src", values, count))
return false;
- if (!g_binary_cursor_setup_load("dest", values, count))
+ if (!g_binary_cursor_store(NULL, "dest", values, count))
return false;
return true;
diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c
index b4f0379..e086b14 100644
--- a/src/analysis/db/items/switcher.c
+++ b/src/analysis/db/items/switcher.c
@@ -95,12 +95,11 @@ static bool g_db_switcher_apply(GDbSwitcher *, GLoadedBinary *);
/* Annule une bascule d'affichage d'opérande sur un binaire. */
static bool g_db_switcher_cancel(GDbSwitcher *, GLoadedBinary *);
-/* Constitue les champs destinés à une insertion / modification. */
-static bool g_db_switcher_prepare_db_statement(const GDbSwitcher *, bound_value **, size_t *);
-
/* Charge les valeurs utiles pour un basculement d'affichage. */
static bool g_db_switcher_load(GDbSwitcher *, const bound_value *, size_t);
+/* Constitue les champs destinés à une insertion / modification. */
+static bool g_db_switcher_store(const GDbSwitcher *, bound_value **, size_t *);
@@ -189,8 +188,8 @@ static void g_db_switcher_class_init(GDbSwitcherClass *klass)
item->apply = (run_item_fc)g_db_switcher_apply;
item->cancel = (run_item_fc)g_db_switcher_cancel;
- item->prepare_stmt = (prepare_db_statement)g_db_switcher_prepare_db_statement;
item->load = (load_db_item_fc)g_db_switcher_load;
+ item->store = (store_db_item_fc)g_db_switcher_store;
}
@@ -638,55 +637,6 @@ static bool g_db_switcher_cancel(GDbSwitcher *switcher, GLoadedBinary *binary)
/******************************************************************************
* *
-* Paramètres : switcher = base d'éléments sur laquelle s'appuyer. *
-* values = couples de champs et de valeurs à lier. [OUT] *
-* count = nombre de ces couples. [OUT] *
-* *
-* Description : Constitue les champs destinés à une insertion / modification.*
-* *
-* Retour : Etat du besoin en sauvegarde. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool g_db_switcher_prepare_db_statement(const GDbSwitcher *switcher, bound_value **values, size_t *count)
-{
- bool status; /* Bilan d'opération initiale */
- bound_value *value; /* Valeur à éditer / définir */
-
- status = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->prepare_stmt(G_DB_ITEM(switcher), values, count);
- if (!status) return false;
-
- status = prepare_vmpa_db_statement(&switcher->addr, NULL, values, count);
- if (!status) return false;
-
- *count += 2;
- *values = (bound_value *)realloc(*values, *count * sizeof(bound_value));
-
- value = &(*values)[*count - 2];
-
- value->cname = "op_index";
- value->built_name = false;
- value->type = SQLITE_INTEGER;
- value->integer = switcher->index;
- value->delete = NULL;
-
- value = &(*values)[*count - 1];
-
- value->cname = "type";
- value->built_name = false;
- value->type = SQLITE_INTEGER;
- value->integer = switcher->display;
- value->delete = NULL;
-
- return true;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : switcher = bascule d'affichage à charger depuis les réponses.*
* values = tableau d'éléments à consulter. *
* count = nombre de descriptions renseignées. *
@@ -733,6 +683,75 @@ static bool g_db_switcher_load(GDbSwitcher *switcher, const bound_value *values,
}
+/******************************************************************************
+* *
+* Paramètres : switcher = base d'éléments sur laquelle s'appuyer. *
+* values = couples de champs et de valeurs à lier. [OUT] *
+* count = nombre de ces couples. [OUT] *
+* *
+* Description : Constitue les champs destinés à une insertion / modification.*
+* *
+* Retour : Etat du besoin en sauvegarde. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_db_switcher_store(const GDbSwitcher *switcher, bound_value **values, size_t *count)
+{
+ bool status; /* Bilan d'opération initiale */
+ bound_value *value; /* Valeur à éditer / définir */
+
+ if (switcher == NULL)
+ status = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->store(NULL, values, count);
+ else
+ status = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->store(G_DB_ITEM(switcher), values, count);
+
+ if (!status) return false;
+
+ if (switcher == NULL)
+ status = store_vmpa(NULL, NULL, values, count);
+ else
+ status = store_vmpa(&switcher->addr, NULL, values, count);
+
+ if (!status) return false;
+
+ *count += 2;
+ *values = realloc(*values, *count * sizeof(bound_value));
+
+ value = &(*values)[*count - 2];
+
+ value->cname = "op_index";
+ value->built_name = false;
+ value->type = SQLITE_INTEGER;
+
+ value->has_value = (switcher != NULL);
+
+ if (value->has_value)
+ {
+ value->integer = switcher->index;
+ value->delete = NULL;
+ }
+
+ value = &(*values)[*count - 1];
+
+ value->cname = "type";
+ value->built_name = false;
+ value->type = SQLITE_INTEGER;
+
+ value->has_value = (switcher != NULL);
+
+ if (value->has_value)
+ {
+ value->integer = switcher->display;
+ value->delete = NULL;
+ }
+
+ return true;
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
/* DEFINITION DE LA COLLECTION ASSOCIEE */
@@ -927,11 +946,11 @@ static bool g_switcher_collection_setup_load(GSwitcherCollection *collec, bound_
values, count);
if (!status) return false;
- if (!setup_load_for_vmpa(NULL, values, count))
+ if (!store_vmpa(NULL, NULL, values, count))
return false;
*count += 2;
- *values = (bound_value *)realloc(*values, *count * sizeof(bound_value));
+ *values = realloc(*values, *count * sizeof(bound_value));
value = &(*values)[*count - 2];
diff --git a/src/analysis/db/misc/rlestr.c b/src/analysis/db/misc/rlestr.c
index 196b934..f26c146 100644
--- a/src/analysis/db/misc/rlestr.c
+++ b/src/analysis/db/misc/rlestr.c
@@ -326,31 +326,42 @@ bool pack_rle_string(const rle_string *str, packed_buffer *pbuf)
/******************************************************************************
* *
-* Paramètres : str = chaîne de caractères aux informations inutiles. *
+* Paramètres : str = chaîne de caractères à compléter. *
* name = désignation personnalisée du champ dans la BD. *
-* values = couples de champs et de valeurs à lier. [OUT] *
-* count = nombre de ces couples. [OUT] *
+* values = tableau d'éléments à consulter. *
+* count = nombre de descriptions renseignées. *
* *
-* Description : Constitue les champs destinés à une insertion / modification.*
+* Description : Charge les valeurs utiles pour une chaîne de caractères. *
* *
-* Retour : Bilan de l'opération : succès ou non. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool prepare_db_statement_for_rle_string(const rle_string *str, const char *name, bound_value **values, size_t *count)
+bool load_rle_string(rle_string *str, const char *name, const bound_value *values, size_t count)
{
- bound_value *value; /* Valeur à éditer / définir */
+ const bound_value *value; /* Valeur à intégrer */
- *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value));
- value = &(*values)[*count - 1];
+ value = find_bound_value(values, count, name);
+ if (value == NULL) return false;
- value->cname = name;
- value->built_name = false;
- value->type = (get_rle_string(str) != NULL ? SQLITE_TEXT : SQLITE_NULL);
- value->cstring = get_rle_string(str);
- value->delete = SQLITE_STATIC;
+ switch (value->type)
+ {
+ case SQLITE_TEXT:
+ unset_rle_string(str);
+ dup_into_rle_string(str, value->cstring);
+ break;
+
+ case SQLITE_NULL:
+ unset_rle_string(str);
+ break;
+
+ default:
+ return false;
+ break;
+
+ }
return true;
@@ -361,71 +372,39 @@ bool prepare_db_statement_for_rle_string(const rle_string *str, const char *name
* *
* Paramètres : str = chaîne de caractères aux informations inutiles. *
* name = désignation personnalisée du champ dans la BD. *
-* values = tableau d'éléments à compléter. [OUT] *
-* count = nombre de descriptions renseignées. [OUT] *
+* values = couples de champs et de valeurs à lier. [OUT] *
+* count = nombre de ces couples. [OUT] *
* *
-* Description : Décrit les colonnes utiles à une chaîne de caractères. *
+* Description : Constitue les champs destinés à une insertion / modification.*
* *
-* Retour : Bilan de l'opération. *
+* Retour : Bilan de l'opération : succès ou non. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool setup_load_of_rle_string(const rle_string *str, const char *name, bound_value **values, size_t *count)
+bool store_rle_string(const rle_string *str, const char *name, bound_value **values, size_t *count)
{
bound_value *value; /* Valeur à éditer / définir */
- *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value));
+ *values = realloc(*values, ++(*count) * sizeof(bound_value));
+
value = &(*values)[*count - 1];
value->cname = name;
value->built_name = false;
- value->type = SQLITE_NATIVE;
- return true;
+ value->has_value = (str != NULL);
+ if (value->has_value)
+ value->type = (get_rle_string(str) != NULL ? SQLITE_TEXT : SQLITE_NULL);
+ else
+ value->type = SQLITE_NATIVE;
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : str = chaîne de caractères à compléter. *
-* name = désignation personnalisée du champ dans la BD. *
-* values = tableau d'éléments à consulter. *
-* count = nombre de descriptions renseignées. *
-* *
-* Description : Charge les valeurs utiles pour une chaîne de caractères. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool load_rle_string(rle_string *str, const char *name, const bound_value *values, size_t count)
-{
- const bound_value *value; /* Valeur à intégrer */
-
- value = find_bound_value(values, count, name);
- if (value == NULL) return false;
-
- switch (value->type)
+ if (value->has_value)
{
- case SQLITE_TEXT:
- unset_rle_string(str);
- dup_into_rle_string(str, value->cstring);
- break;
-
- case SQLITE_NULL:
- unset_rle_string(str);
- break;
-
- default:
- return false;
- break;
-
+ value->cstring = get_rle_string(str);
+ value->delete = SQLITE_STATIC;
}
return true;
diff --git a/src/analysis/db/misc/rlestr.h b/src/analysis/db/misc/rlestr.h
index 7b317b6..eb71582 100644
--- a/src/analysis/db/misc/rlestr.h
+++ b/src/analysis/db/misc/rlestr.h
@@ -94,15 +94,12 @@ bool pack_rle_string(const rle_string *, packed_buffer *);
#define SQLITE_RLESTR_CREATE(n) \
n " TEXT"
-/* Constitue les champs destinés à une insertion / modification. */
-bool prepare_db_statement_for_rle_string(const rle_string *, const char *, bound_value **, size_t *);
-
-/* Décrit les colonnes utiles à une chaîne de caractères. */
-bool setup_load_of_rle_string(const rle_string *, const char *, bound_value **, size_t *);
-
/* Charge les valeurs utiles pour une chaîne de caractères. */
bool load_rle_string(rle_string *, const char *, const bound_value *, size_t);
+/* Constitue les champs destinés à une insertion / modification. */
+bool store_rle_string(const rle_string *, const char *, bound_value **, size_t *);
+
#endif /* _ANALYSIS_DB_MISC_RLESTR_H */
diff --git a/src/analysis/db/misc/timestamp.c b/src/analysis/db/misc/timestamp.c
index 5302c60..1d2fcd9 100644
--- a/src/analysis/db/misc/timestamp.c
+++ b/src/analysis/db/misc/timestamp.c
@@ -166,30 +166,28 @@ bool pack_timestamp(const timestamp_t *timestamp, packed_buffer *pbuf)
/******************************************************************************
* *
-* Paramètres : timestamp = horodatage aux informations inutiles. *
+* Paramètres : timestamp = horodatage à compléter. *
* name = désignation personnalisée du champ dans la BD. *
-* values = couples de champs et de valeurs à lier. [OUT] *
-* count = nombre de ces couples. [OUT] *
+* values = tableau d'éléments à consulter. *
+* count = nombre de descriptions renseignées. *
* *
-* Description : Constitue les champs destinés à une insertion / modification.*
+* Description : Charge les valeurs utiles pour un horodatage. *
* *
-* Retour : Bilan de l'opération : succès ou non. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool prepare_db_statement_for_timestamp(const timestamp_t *timestamp, const char *name, bound_value **values, size_t *count)
+bool load_timestamp(timestamp_t *timestamp, const char *name, const bound_value *values, size_t count)
{
- bound_value *value; /* Valeur à éditer / définir */
+ const bound_value *value; /* Valeur à intégrer */
- *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value));
- value = &(*values)[*count - 1];
+ value = find_bound_value(values, count, name);
+ if (value == NULL) return false;
+ if (value->type != SQLITE_INT64) return false;
- value->cname = name;
- value->built_name = false;
- value->type = SQLITE_INT64;
- value->integer64 = *timestamp;
+ *timestamp = value->integer64;
return true;
@@ -200,58 +198,33 @@ bool prepare_db_statement_for_timestamp(const timestamp_t *timestamp, const char
* *
* Paramètres : timestamp = horodatage aux informations inutiles. *
* name = désignation personnalisée du champ dans la BD. *
-* values = tableau d'éléments à compléter. [OUT] *
-* count = nombre de descriptions renseignées. [OUT] *
+* values = couples de champs et de valeurs à lier. [OUT] *
+* count = nombre de ces couples. [OUT] *
* *
-* Description : Décrit les colonnes utiles à un horodatage. *
+* Description : Constitue les champs destinés à une insertion / modification.*
* *
-* Retour : Bilan de l'opération. *
+* Retour : Bilan de l'opération : succès ou non. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool setup_load_of_timestamp(const timestamp_t *timestamp, const char *name, bound_value **values, size_t *count)
+bool store_timestamp(const timestamp_t *timestamp, const char *name, bound_value **values, size_t *count)
{
bound_value *value; /* Valeur à éditer / définir */
- *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value));
+ *values = realloc(*values, ++(*count) * sizeof(bound_value));
+
value = &(*values)[*count - 1];
value->cname = name;
value->built_name = false;
value->type = SQLITE_INT64;
- return true;
-
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : timestamp = horodatage à compléter. *
-* name = désignation personnalisée du champ dans la BD. *
-* values = tableau d'éléments à consulter. *
-* count = nombre de descriptions renseignées. *
-* *
-* Description : Charge les valeurs utiles pour un horodatage. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool load_timestamp(timestamp_t *timestamp, const char *name, const bound_value *values, size_t count)
-{
- const bound_value *value; /* Valeur à intégrer */
-
- value = find_bound_value(values, count, name);
- if (value == NULL) return false;
- if (value->type != SQLITE_INT64) return false;
+ value->has_value = (timestamp != NULL);
- *timestamp = value->integer64;
+ if (value->has_value)
+ value->integer64 = *timestamp;
return true;
diff --git a/src/analysis/db/misc/timestamp.h b/src/analysis/db/misc/timestamp.h
index 076a4e0..eba0fa7 100644
--- a/src/analysis/db/misc/timestamp.h
+++ b/src/analysis/db/misc/timestamp.h
@@ -67,15 +67,12 @@ bool pack_timestamp(const timestamp_t *, packed_buffer *);
#define SQLITE_TIMESTAMP_CREATE(n) \
n " INTEGER"
-/* Constitue les champs destinés à une insertion / modification. */
-bool prepare_db_statement_for_timestamp(const timestamp_t *, const char *, bound_value **, size_t *);
-
-/* Décrit les colonnes utiles à un horodatage. */
-bool setup_load_of_timestamp(const timestamp_t *, const char *, bound_value **, size_t *);
-
/* Charge les valeurs utiles pour un horodatage. */
bool load_timestamp(timestamp_t *, const char *, const bound_value *, size_t);
+/* Constitue les champs destinés à une insertion / modification. */
+bool store_timestamp(const timestamp_t *, const char *, bound_value **, size_t *);
+
#endif /* _ANALYSIS_DB_MISC_TIMESTAMP_H */
diff --git a/src/arch/vmpa.c b/src/arch/vmpa.c
index 0c0511b..a2a3ba5 100644
--- a/src/arch/vmpa.c
+++ b/src/arch/vmpa.c
@@ -715,44 +715,6 @@ char *create_vmpa_db_table(const char *base)
/******************************************************************************
* *
-* Paramètres : base = tronc commun pour les champs de la base de données. *
-* values = tableau d'éléments à compléter. [OUT] *
-* count = nombre de descriptions renseignées. [OUT] *
-* *
-* Description : Décrit les colonnes utiles à un chargement de données. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool setup_load_for_vmpa(const char *base, bound_value **values, size_t *count)
-{
- bound_value *value; /* Valeur à éditer / définir */
-
- (*count) += 2;
- *values = (bound_value *)realloc(*values, (*count) * sizeof(bound_value));
-
- value = &(*values)[*count - 2];
-
- asprintf(&value->name, "%s%sphys", base != NULL ? base : "", base != NULL ? "_" : "");
- value->built_name = true;
- value->type = SQLITE_NATIVE;
-
- value = &(*values)[*count - 1];
-
- asprintf(&value->name, "%s%svirt", base != NULL ? base : "", base != NULL ? "_" : "");
- value->built_name = true;
- value->type = SQLITE_NATIVE;
-
- return true;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : addr = localisation dont la définition est à définir. *
* base = tronc commun pour les champs de la base de données. *
* values = tableau d'éléments à consulter. *
@@ -839,40 +801,47 @@ bool load_vmpa(vmpa2t *addr, const char *base, const bound_value *values, size_t
* *
******************************************************************************/
-bool prepare_vmpa_db_statement(const vmpa2t *addr, const char *base, bound_value **values, size_t *count)
+bool store_vmpa(const vmpa2t *addr, const char *base, bound_value **values, size_t *count)
{
bound_value *value; /* Valeur à éditer / définir */
- *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value));
- value = &(*values)[*count - 1];
+ *count += 2;
+ *values = realloc(*values, *count * sizeof(bound_value));
+
+ value = &(*values)[*count - 2];
asprintf(&value->name, "%s%sphys", base != NULL ? base : "", base != NULL ? "_" : "");
value->built_name = true;
- if (addr->physical != VMPA_NO_PHYSICAL)
- {
- value->type = SQLITE_INT64;
- value->integer64 = addr->physical;
- }
- else
+ value->has_value = (addr != NULL);
+
+ if (value->has_value)
{
- value->type = SQLITE_NULL;
+ if (addr->physical != VMPA_NO_PHYSICAL)
+ {
+ value->type = SQLITE_INT64;
+ value->integer64 = addr->physical;
+ }
+ else
+ value->type = SQLITE_NULL;
}
- *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value));
value = &(*values)[*count - 1];
asprintf(&value->name, "%s%svirt", base != NULL ? base : "", base != NULL ? "_" : "");
value->built_name = true;
- if (addr->virtual != VMPA_NO_VIRTUAL)
- {
- value->type = SQLITE_INT64;
- value->integer64 = addr->virtual;
- }
- else
+ value->has_value = (addr != NULL);
+
+ if (value->has_value)
{
- value->type = SQLITE_NULL;
+ if (addr->virtual != VMPA_NO_VIRTUAL)
+ {
+ value->type = SQLITE_INT64;
+ value->integer64 = addr->virtual;
+ }
+ else
+ value->type = SQLITE_NULL;
}
return true;
diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h
index fc997e5..8dfc646 100644
--- a/src/arch/vmpa.h
+++ b/src/arch/vmpa.h
@@ -145,14 +145,11 @@ vmpa2t *string_to_vmpa_virt(const char *);
/* Donne les éléments requis pour la construction d'une table. */
char *create_vmpa_db_table(const char *);
-/* Décrit les colonnes utiles à un chargement de données. */
-bool setup_load_for_vmpa(const char *, bound_value **, size_t *);
-
/* Charge les valeurs utiles pour une localisation. */
bool load_vmpa(vmpa2t *, const char *, const bound_value *, size_t);
/* Constitue les champs destinés à une insertion / modification. */
-bool prepare_vmpa_db_statement(const vmpa2t *, const char *, bound_value **, size_t *);
+bool store_vmpa(const vmpa2t *, const char *, bound_value **, size_t *);
diff --git a/src/common/sqlite.c b/src/common/sqlite.c
index a3b97b0..af2af9f 100644
--- a/src/common/sqlite.c
+++ b/src/common/sqlite.c
@@ -24,10 +24,19 @@
#include "sqlite.h"
+#include <assert.h>
#include <malloc.h>
#include <string.h>
+#include "extstr.h"
+
+
+
+/* Attribue une définition aux valeurs paramétrées. */
+static bool bind_bound_values(sqlite3 *, sqlite3_stmt *, const char *, const bound_value *, size_t, bool, int *);
+
+
/******************************************************************************
* *
@@ -92,3 +101,376 @@ const bound_value *find_bound_value(const bound_value *values, size_t count, con
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : db = base de données à consulter. *
+* stmt = requête SQL en préparation à faire évoluer. *
+* sql = définition brute de cette requête SQL. *
+* values = tableau d'éléments à consulter. *
+* count = nombre de descriptions renseignées. *
+* has_value = fitre sur la définition des valeurs. *
+* index = indice évolutif des valeurs paramétrées. [OUT] *
+* *
+* Description : Attribue une définition aux valeurs paramétrées. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool bind_bound_values(sqlite3 *db, sqlite3_stmt *stmt, const char *sql, const bound_value *values, size_t count, bool has_value, int *index)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+ int ret; /* Bilan d'un appel à SQLite */
+
+ result = true;
+
+ for (i = 0; i < count && result; i++)
+ {
+ if (values[i].has_value != has_value)
+ continue;
+
+ switch (values[i].type)
+ {
+ case SQLITE_BOOLEAN:
+ ret = sqlite3_bind_int(stmt, *index, values[i].boolean);
+ break;
+
+ case SQLITE_INTEGER:
+ ret = sqlite3_bind_int(stmt, *index, values[i].integer);
+ break;
+
+ case SQLITE_INT64:
+ ret = sqlite3_bind_int64(stmt, *index, values[i].integer64);
+ break;
+
+ case SQLITE_TEXT:
+ ret = sqlite3_bind_text(stmt, *index, values[i].string, -1, values[i].delete);
+ break;
+
+ case SQLITE_NULL:
+ ret = sqlite3_bind_null(stmt, *index);
+ break;
+
+ default:
+ assert(false);
+ ret = SQLITE_ERROR;
+ break;
+
+ }
+
+ if (ret == SQLITE_OK)
+ (*index)++;
+
+ else
+ {
+ result = false;
+
+ fprintf(stderr, "Can't bind value for parameter nb %d in '%s' (ret=%d): %s\n",
+ *index, sql, ret, sqlite3_errmsg(db));
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : db = base de données à consulter. *
+* table = nom de la table concernée. *
+* values = champs avec leur valeur. *
+* count = quantité de ces champs. *
+* cb = procédure à appeler pour chaque nouvelle série. *
+* data = éventuelles données associées à transmettre. *
+* *
+* Description : Charge une série de valeurs depuis une base de données. *
+* *
+* Retour : Bilan de l'exécution de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_db_values(sqlite3 *db, const char *table, bound_value *values, size_t count, db_load_cb cb, void *data)
+{
+ bool result; /* Conclusion à faire remonter */
+ char *sql; /* Requête SQL à construire */
+ bool first; /* Marque du premier passage */
+ size_t i; /* Boucle de parcours */
+ sqlite3_stmt *stmt; /* Déclaration mise en place */
+ int ret; /* Bilan d'un appel à SQLite */
+ int index; /* Indice de valeur attachée */
+ int native_type; /* Type de valeur dans la base */
+
+ result = false;
+
+ /* Préparation de la requête */
+
+ sql = strdup("SELECT ");
+
+ first = true;
+
+ for (i = 0; i < count; i++)
+ {
+ if (values[i].has_value)
+ continue;
+
+ if (!first) sql = stradd(sql, ", ");
+
+ sql = stradd(sql, values[i].name);
+
+ first = false;
+
+ }
+
+ assert(!first);
+
+ sql = stradd(sql, " FROM ");
+ sql = stradd(sql, table);
+
+ first = true;
+
+ for (i = 0; i < count; i++)
+ {
+ if (!values[i].has_value)
+ continue;
+
+ if (first)
+ sql = stradd(sql, " WHERE ");
+ else
+ sql = stradd(sql, " AND ");
+
+ sql = stradd(sql, values[i].name);
+
+ sql = stradd(sql, " = ?");
+
+ first = false;
+
+ }
+
+ sql = stradd(sql, ";");
+
+ ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
+ if (ret != SQLITE_OK)
+ {
+ fprintf(stderr, "Can't prepare SELECT statment '%s' (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db));
+ goto prepare_error;
+ }
+
+ /* Attribution des valeurs */
+
+ index = 1;
+
+ if (!bind_bound_values(db, stmt, sql, values, count, true, &index))
+ goto bind_error;
+
+ /* Chargement des valeurs existantes */
+
+ result = true;
+
+ for (ret = sqlite3_step(stmt); ret == SQLITE_ROW && result; ret = sqlite3_step(stmt))
+ {
+ /* Conversion des valeurs */
+
+ index = 0;
+
+ for (i = 0; i < count; i++)
+ {
+ if (values[i].has_value)
+ continue;
+
+ native_type = sqlite3_column_type(stmt, index);
+
+ /**
+ * On réalise une petite conversion selon le champ.
+ *
+ * Le filtre SQLITE_NATIVE est destiné à conserver le type choisi par
+ * SQLite. Typiquement, une chaîne peut être à SQLITE_NULL ou SQLITE_TEXT
+ * selon la valeur conservée dans la base.
+ *
+ * D'autres éléments, comme les localisations en mémoire, peuvent aussi
+ * avoir un champ éventuellement nul, donc la définition à partir des
+ * indications de la base de données reste importante.
+ *
+ * En ce qui concerne les valeurs numériques, SQLite ne fait pas de
+ * distinction : tout passe par la fonction sqlite3VdbeIntValue(),
+ * qui effectue des transtypages au besoin pour tout ce qui n'est
+ * pas numérique.
+ *
+ * Pour les types internes SQLITE_INTEGER et SQLITE_BOOLEAN,
+ * il est donc nécessaire d'ajuster en interne.
+ */
+
+ if (native_type == SQLITE_INTEGER)
+ native_type = SQLITE_INT64;
+
+ if (values[i].type == SQLITE_NATIVE)
+ values[i].type = native_type;
+
+ else
+ assert(values[i].type == native_type
+ || values[i].type == SQLITE_INTEGER
+ || values[i].type == SQLITE_BOOLEAN);
+
+ switch (values[i].type)
+ {
+ case SQLITE_BOOLEAN:
+ values[i].boolean = (bool)sqlite3_column_int(stmt, index);
+ break;
+
+ case SQLITE_INTEGER:
+ values[i].integer = sqlite3_column_int(stmt, index);
+ break;
+
+ case SQLITE_INT64:
+ values[i].integer64 = sqlite3_column_int64(stmt, index);
+ break;
+
+ case SQLITE_FLOAT:
+ assert(0);
+ break;
+
+ case SQLITE_TEXT:
+ values[i].cstring = (const char *)sqlite3_column_text(stmt, index);
+ break;
+
+ case SQLITE_BLOB:
+ assert(0);
+ break;
+
+ case SQLITE_NULL:
+ break;
+
+ default:
+ assert(0);
+ break;
+
+ }
+
+ }
+
+ /* Chargement d'un nouvel élément */
+
+ cb(values, count, data);
+
+ index++;
+
+ }
+
+ bind_error:
+
+ sqlite3_finalize(stmt);
+
+ prepare_error:
+
+ free(sql);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : db = base de données à mettre à jour. *
+* table = nom de la table concernée. *
+* values = champs avec leur valeur. *
+* count = quantité de ces champs. *
+* *
+* Description : Enregistre une série de valeurs dans une base de données. *
+* *
+* Retour : Bilan de l'exécution de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool store_db_values(sqlite3 *db, const char *table, const bound_value *values, size_t count)
+{
+ bool result; /* Conclusion à faire remonter */
+ char *sql; /* Requête SQL à construire */
+ size_t i; /* Boucle de parcours */
+ sqlite3_stmt *stmt; /* Déclaration mise en place */
+ int ret; /* Bilan d'un appel à SQLite */
+ int index; /* Indice de valeur attachée */
+
+ result = false;
+
+ /* Préparation de la requête */
+
+ sql = strdup("INSERT INTO ");
+ sql = stradd(sql, table);
+ sql = stradd(sql, " (");
+
+ for (i = 0; i < count; i++)
+ {
+ assert(values[i].has_value);
+
+ if (i > 0) sql = stradd(sql, ", ");
+
+ sql = stradd(sql, values[i].name);
+
+ }
+
+ sql = stradd(sql, ") VALUES (");
+
+ for (i = 0; i < count; i++)
+ {
+ if (i > 0) sql = stradd(sql, ", ");
+
+ if (values[i].type == SQLITE_RAW)
+ sql = stradd(sql, values[i].cstring);
+ else
+ sql = stradd(sql, "?");
+
+ }
+
+ sql = stradd(sql, ");");
+
+ ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
+ if (ret != SQLITE_OK)
+ {
+ fprintf(stderr, "Can't prepare INSERT statment '%s' (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db));
+ goto prepare_error;
+ }
+
+ /* Attribution des valeurs */
+
+ index = 1;
+
+ if (!bind_bound_values(db, stmt, sql, values, count, true, &index))
+ goto bind_error;
+
+ /* Exécution finale */
+
+ ret = sqlite3_step(stmt);
+
+ if (ret != SQLITE_DONE)
+ {
+ fprintf(stderr, "INSERT statement '%s' didn't return DONE (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db));
+ goto insert_error;
+ }
+
+ result = true;
+
+ insert_error:
+
+ bind_error:
+
+ sqlite3_finalize(stmt);
+
+ prepare_error:
+
+ free(sql);
+
+ return result;
+
+}
diff --git a/src/common/sqlite.h b/src/common/sqlite.h
index 1d31746..291eec8 100644
--- a/src/common/sqlite.h
+++ b/src/common/sqlite.h
@@ -25,6 +25,7 @@
#define _COMMON_SQLITE_H
+#include <sqlite3.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
@@ -51,6 +52,8 @@ typedef struct _bound_value
unsigned int type; /* Type de valeur à associer */
+ bool has_value; /* Validité des champs suivants*/
+
union
{
bool boolean; /* Etat sur 1 bit */
@@ -72,6 +75,15 @@ void free_all_bound_values(bound_value *, size_t);
/* Effectue une recherche au sein d'un ensemble de valeurs. */
const bound_value *find_bound_value(const bound_value *, size_t, const char *);
+/* Interagit avec des valeurs chargées. */
+typedef bool (* db_load_cb) (const bound_value *, size_t, void *);
+
+/* Charge une série de valeurs depuis une base de données. */
+bool load_db_values(sqlite3 *, const char *, bound_value *, size_t, db_load_cb, void *);
+
+/* Enregistre une série de valeurs dans une base de données. */
+bool store_db_values(sqlite3 *, const char *, const bound_value *, size_t);
+
#endif /* _COMMON_SQLITE_H */
diff --git a/src/glibext/gbinarycursor.c b/src/glibext/gbinarycursor.c
index ee9eb5f..9c4e82b 100644
--- a/src/glibext/gbinarycursor.c
+++ b/src/glibext/gbinarycursor.c
@@ -97,9 +97,6 @@ static bool g_binary_cursor_unserialize(GBinaryCursor *, packed_buffer *);
/* Charge les valeurs utiles pour une localisation. */
static bool g_binary_cursor_load(GBinaryCursor *, const char *, const bound_value *, size_t);
-/* Constitue les champs destinés à une insertion / modification. */
-static bool g_binary_cursor_prepare_db_statement(const GBinaryCursor *, const char *, bound_value **, size_t *);
-
/* ---------------------------------------------------------------------------------- */
@@ -145,9 +142,8 @@ static void g_binary_cursor_class_init(GBinaryCursorClass *class)
line->unserialize = (unserialize_cursor_fc)g_binary_cursor_unserialize;
line->create_db = (create_cursor_db_table_fc)g_binary_cursor_create_db_table;
- line->setup_load = (setup_cursor_load_fc)g_binary_cursor_setup_load;
line->load = (load_cursor_fc)g_binary_cursor_load;
- line->prepare = (prepare_cursor_db_statement_fc)g_binary_cursor_prepare_db_statement;
+ line->store = (store_cursor_fc)g_binary_cursor_store;
}
@@ -500,31 +496,6 @@ char *g_binary_cursor_create_db_table(const char *base)
/******************************************************************************
* *
-* Paramètres : base = tronc commun pour les champs de la base de données. *
-* values = tableau d'éléments à compléter. [OUT] *
-* count = nombre de descriptions renseignées. [OUT] *
-* *
-* Description : Décrit les colonnes utiles à un chargement de données. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_binary_cursor_setup_load(const char *base, bound_value **values, size_t *count)
-{
- bool result; /* Bilan à renvoyer */
-
- result = setup_load_for_vmpa(base, values, count);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : cursor = suivi de positions dont la définition est à définir.*
* base = tronc commun pour les champs de la base de données. *
* values = tableau d'éléments à consulter. *
@@ -564,11 +535,14 @@ static bool g_binary_cursor_load(GBinaryCursor *cursor, const char *base, const
* *
******************************************************************************/
-static bool g_binary_cursor_prepare_db_statement(const GBinaryCursor *cursor, const char *base, bound_value **values, size_t *count)
+bool g_binary_cursor_store(const GBinaryCursor *cursor, const char *base, bound_value **values, size_t *count)
{
bool result; /* Bilan à renvoyer */
- result = prepare_vmpa_db_statement(&cursor->addr, base, values, count);
+ if (cursor == NULL)
+ result = store_vmpa(NULL, base, values, count);
+ else
+ result = store_vmpa(&cursor->addr, base, values, count);
return result;
diff --git a/src/glibext/gbinarycursor.h b/src/glibext/gbinarycursor.h
index 63a6f1b..ffac19a 100644
--- a/src/glibext/gbinarycursor.h
+++ b/src/glibext/gbinarycursor.h
@@ -71,8 +71,8 @@ void g_binary_cursor_get_info(const GBinaryCursor *, vmpa2t *);
/* Donne les éléments requis pour la construction d'une table. */
char *g_binary_cursor_create_db_table(const char *);
-/* Décrit les colonnes utiles à un chargement de données. */
-bool g_binary_cursor_setup_load(const char *, bound_value **, size_t *);
+/* Constitue les champs destinés à une insertion / modification. */
+bool g_binary_cursor_store(const GBinaryCursor *, const char *, bound_value **, size_t *);
diff --git a/src/glibext/glinecursor-int.h b/src/glibext/glinecursor-int.h
index 18ec147..b6a0f19 100644
--- a/src/glibext/glinecursor-int.h
+++ b/src/glibext/glinecursor-int.h
@@ -54,14 +54,11 @@ typedef bool (* unserialize_cursor_fc) (GLineCursor *, packed_buffer *);
/* Donne les éléments requis pour la construction d'une table. */
typedef char *(* create_cursor_db_table_fc) (const char *);
-/* Décrit les colonnes utiles à un chargement de données. */
-typedef bool (* setup_cursor_load_fc) (const char *, bound_value **, size_t *);
-
/* Charge les valeurs utiles pour une localisation. */
typedef bool (* load_cursor_fc) (GLineCursor *, const char *, const bound_value *, size_t);
/* Constitue les champs destinés à une insertion / modification. */
-typedef bool (* prepare_cursor_db_statement_fc) (const GLineCursor *, const char *, bound_value **, size_t *);
+typedef bool (* store_cursor_fc) (const GLineCursor *, const char *, bound_value **, size_t *);
/* Suivi de positions dans un panneau de chargement (instance) */
@@ -86,9 +83,8 @@ struct _GLineCursorClass
unserialize_cursor_fc unserialize; /* Chargement d'un emplacement */
create_cursor_db_table_fc create_db; /* Création de table */
- setup_cursor_load_fc setup_load; /* Préparation du chargement */
load_cursor_fc load; /* Chargement de valeurs */
- prepare_cursor_db_statement_fc prepare; /* Préparation d'enregistrement*/
+ store_cursor_fc store; /* Préparation d'enregistrement*/
};
diff --git a/src/glibext/glinecursor.c b/src/glibext/glinecursor.c
index 64521f4..bef9cb6 100644
--- a/src/glibext/glinecursor.c
+++ b/src/glibext/glinecursor.c
@@ -356,7 +356,7 @@ bool g_line_cursor_setup_load(const GLineCursor *cursor, const char *base, bound
{
bool result; /* Bilan à renvoyer */
- result = G_LINE_CURSOR_GET_CLASS(cursor)->setup_load(base, values, count);
+ result = G_LINE_CURSOR_GET_CLASS(cursor)->store(NULL, base, values, count);
return result;
@@ -404,11 +404,11 @@ bool g_line_cursor_load(GLineCursor *cursor, const char *base, const bound_value
* *
******************************************************************************/
-bool g_line_cursor_prepare_db_statement(const GLineCursor *cursor, const char *base, bound_value **values, size_t *count)
+bool g_line_cursor_store(const GLineCursor *cursor, const char *base, bound_value **values, size_t *count)
{
bool result; /* Bilan à renvoyer */
- result = G_LINE_CURSOR_GET_CLASS(cursor)->prepare(cursor, base, values, count);
+ result = G_LINE_CURSOR_GET_CLASS(cursor)->store(cursor, base, values, count);
return result;
diff --git a/src/glibext/glinecursor.h b/src/glibext/glinecursor.h
index 4fa93c1..c373562 100644
--- a/src/glibext/glinecursor.h
+++ b/src/glibext/glinecursor.h
@@ -102,7 +102,7 @@ bool g_line_cursor_setup_load(const GLineCursor *, const char *, bound_value **,
bool g_line_cursor_load(GLineCursor *, const char *, const bound_value *, size_t);
/* Constitue les champs destinés à une insertion / modification. */
-bool g_line_cursor_prepare_db_statement(const GLineCursor *, const char *, bound_value **, size_t *);
+bool g_line_cursor_store(const GLineCursor *, const char *, bound_value **, size_t *);