diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/analysis/db/items/comment.c | 793 | ||||
-rw-r--r-- | src/analysis/db/items/comment.h | 60 | ||||
-rw-r--r-- | src/core/collections.c | 2 | ||||
-rw-r--r-- | src/format/preload.c | 77 | ||||
-rw-r--r-- | src/format/preload.h | 6 |
5 files changed, 431 insertions, 507 deletions
diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c index 4b22502..136b62b 100644 --- a/src/analysis/db/items/comment.c +++ b/src/analysis/db/items/comment.c @@ -27,6 +27,7 @@ #include <assert.h> #include <malloc.h> #include <stdio.h> +#include <string.h> #include <sys/socket.h> @@ -53,23 +54,10 @@ struct _GDbComment GDbItem parent; /* A laisser en premier */ vmpa2t addr; /* Adresse du commentaire */ + CommentEmbeddingType type; /* Type d'incrustation */ BufferLineFlags flags; /* Identification de l'accroche*/ flat_array_t *text; /* Contenu du commentaire */ - size_t count; /* Quantité de lignes affichées*/ - - bool inlined; /* Intégration dans une ligne ?*/ - - union - { - bool repeatable; /* Répétition aux lignes liées */ - bool before; /* Zone dédiée au dessus ? */ - }; - - GLineGenerator *previous; /* Commentaire remplacé */ - - GLineGenerator **old_inlined; /* Commentaires d'origine ? */ - size_t old_count; /* Nombre de places à restaurer*/ }; @@ -93,6 +81,15 @@ static void g_db_comment_dispose(GDbComment *); /* Procède à la libération totale de la mémoire. */ static void g_db_comment_finalize(GDbComment *); +/* Constitue un ensemble de lignes pour un commentaire. */ +static void g_db_comment_define_text_lines(GDbComment *, const char *); + +/* Calcule le condensat associé à l'élément vu comme clef. */ +static guint g_db_comment_hash_key(const GDbComment *); + +/* Compare deux éléments en tant que clefs. */ +static gboolean g_db_comment_cmp_key(const GDbComment *, const GDbComment *); + /* Effectue la comparaison entre deux commentaires enregistrés. */ static gint g_db_comment_cmp(const GDbComment *, const GDbComment *); @@ -120,19 +117,13 @@ 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 *); - /* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ -/* Calcule le nombre de lignes suite à un changement de contenu. */ -static void g_db_comment_update_count_lines(GDbComment *); - /* Indique le nombre de ligne prêtes à être générées. */ -static size_t g_db_comment_count_lines(const GDbComment *); +static size_t g_db_comment_count_lines(GDbComment *); /* Retrouve l'emplacement correspondant à une position donnée. */ static void g_db_comment_compute_cursor(const GDbComment *, gint, size_t, size_t, GLineCursor **); @@ -141,7 +132,7 @@ static void g_db_comment_compute_cursor(const GDbComment *, gint, size_t, size_t static int g_db_comment_contain_cursor(const GDbComment *, size_t, size_t, const GLineCursor *); /* Renseigne sur les propriétés liées à un générateur. */ -static BufferLineFlags g_db_comment_get_flags(const GDbComment *, size_t, size_t); +static BufferLineFlags g_db_comment_get_generator_flags(const GDbComment *, size_t, size_t); /* Imprime dans une ligne de rendu le contenu représenté. */ static void g_db_comment_print(GDbComment *, GBufferLine *, size_t, size_t, const GBinContent *); @@ -222,6 +213,8 @@ static void g_db_comment_class_init(GDbCommentClass *klass) item->feature = DBF_COMMENTS; + item->hash_key = (hash_db_item_key_fc)g_db_comment_hash_key; + item->cmp_key = (cmp_db_item_key_fc)g_db_comment_cmp_key; item->cmp = (cmp_db_item_fc)g_db_comment_cmp; item->unpack = (unpack_db_item_fc)g_db_comment_unpack; @@ -251,8 +244,12 @@ static void g_db_comment_class_init(GDbCommentClass *klass) static void g_db_comment_init(GDbComment *comment) { + init_vmpa(&comment->addr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); + + comment->type = CET_COUNT; + comment->flags = BLF_NONE; + comment->text = NULL; - comment->count = 0; } @@ -274,7 +271,7 @@ static void g_db_comment_interface_init(GLineGeneratorInterface *iface) iface->count = (linegen_count_lines_fc)g_db_comment_count_lines; iface->compute = (linegen_compute_fc)g_db_comment_compute_cursor; iface->contain = (linegen_contain_fc)g_db_comment_contain_cursor; - iface->get_flags = (linegen_get_flags_fc)g_db_comment_get_flags; + iface->get_flags = (linegen_get_flags_fc)g_db_comment_get_generator_flags; iface->print = (linegen_print_fc)g_db_comment_print; } @@ -294,13 +291,6 @@ static void g_db_comment_interface_init(GLineGeneratorInterface *iface) static void g_db_comment_dispose(GDbComment *comment) { - size_t i; /* Boucle de parcours */ - - g_clear_object(&comment->previous); - - for (i = 0; i < comment->old_count; i++) - g_clear_object(&comment->old_inlined[i]); - G_OBJECT_CLASS(g_db_comment_parent_class)->dispose(G_OBJECT(comment)); } @@ -340,9 +330,6 @@ static void g_db_comment_finalize(GDbComment *comment) unlock_flat_array(&comment->text); - if (comment->old_inlined != NULL) - free(comment->old_inlined); - G_OBJECT_CLASS(g_db_comment_parent_class)->finalize(G_OBJECT(comment)); } @@ -350,11 +337,12 @@ static void g_db_comment_finalize(GDbComment *comment) /****************************************************************************** * * -* Paramètres : addr = adresse inamovible localisant une position. * -* flags = indentifiants supplémentaires de ligne visée. * -* repeatable = repétition aux instructions liées ? * +* Paramètres : addr = adresse inamovible localisant une position. * +* type = type d'incrustation à respecter pour l'insertion. * +* flags = indentifiants supplémentaires de ligne visée. * +* text = contenu textuel associé au commentaire ou NULL. * * * -* Description : Crée une définition de commentaire dans une zone de texte. * +* Description : Crée une définition de commentaire textuel. * * * * Retour : Commentaire mis en place ou NULL en cas d'erreur. * * * @@ -362,19 +350,59 @@ static void g_db_comment_finalize(GDbComment *comment) * * ******************************************************************************/ -GDbComment *g_db_comment_new_inlined(const vmpa2t *addr, BufferLineFlags flags, bool repeatable) +GDbComment *g_db_comment_new(const vmpa2t *addr, CommentEmbeddingType type, BufferLineFlags flags, const char *text) { - GDbComment *result; /* Instance à retourner */ + GDbComment *result; /* Instance à retourner */ + bool status; /* Bilan de l'initialisation */ result = g_object_new(G_TYPE_DB_COMMENT, NULL); - copy_vmpa(&result->addr, addr); + status = g_db_comment_fill(result, addr, type, flags, text); + if (!status) goto error; + + return result; + + error: + + g_object_unref(G_OBJECT(result)); + + return NULL; + +} + - result->flags = flags; +/****************************************************************************** +* * +* Paramètres : addr = adresse inamovible localisant une position. * +* type = type d'incrustation à respecter pour l'insertion. * +* flags = indentifiants supplémentaires de ligne visée. * +* text = contenu textuel associé au commentaire ou NULL. * +* * +* Description : Initialise la définition d'un commentaire à incruster. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ - result->inlined = true; +bool g_db_comment_fill(GDbComment *comment, const vmpa2t *addr, CommentEmbeddingType type, BufferLineFlags flags, const char *text) +{ + bool result; /* Bilan à retourner */ - result->repeatable = repeatable; + /** + * Cette fonction est principalement destinée aux initialisations + * depuis l'extension Python. + */ + + result = true; + + copy_vmpa(&comment->addr, addr); + + comment->type = type; + comment->flags = flags; + + g_db_comment_define_text_lines(comment, text); return result; @@ -383,34 +411,98 @@ GDbComment *g_db_comment_new_inlined(const vmpa2t *addr, BufferLineFlags flags, /****************************************************************************** * * -* Paramètres : addr = adresse inamovible localisant une position. * -* flags = indentifiants supplémentaires de ligne visée. * -* text = commentaire construit ou NULL. * -* before = précision quant à la position de la zone à définir. * +* Paramètres : comment = commentaire dont les lignes sont à constituer. * +* text = contenu textuel associé au commentaire ou NULL. * * * -* Description : Crée une définition de commentaire dans une zone de texte. * +* Description : Constitue un ensemble de lignes pour un commentaire. * * * -* Retour : Commentaire mis en place ou NULL en cas d'erreur. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -GDbComment *g_db_comment_new_area(const vmpa2t *addr, BufferLineFlags flags, const char *text, bool before) +static void g_db_comment_define_text_lines(GDbComment *comment, const char *text) { - GDbComment *result; /* Instance à retourner */ + char *tmp; /* Zone de travail modifiable */ + char **lines; /* Lignes du texte découpé */ + size_t count; /* Quantité de ces lignes */ + size_t i; /* Boucle de parcours */ + rle_string string; /* Fragment de texte à ajouter */ - result = g_object_new(G_TYPE_DB_COMMENT, NULL); + if (text != NULL) + { + tmp = strdup(text); + + tmp = strrpl(tmp, "\r", ""); + + lines = strtoka(tmp, "\n", &count); + + lock_flat_array(&comment->text); + + for (i = 0; i < count; i++) + { + init_dynamic_rle_string(&string, lines[i]); + + add_item_to_flat_array(&comment->text, &string, sizeof(rle_string)); + + } + + unlock_flat_array(&comment->text); + + free(lines); + + free(tmp); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : comment = élément de collection à consulter. * +* * +* Description : Calcule le condensat associé à l'élément vu comme clef. * +* * +* Retour : Condensat associé à l'élément. * +* * +* Remarques : - * +* * +******************************************************************************/ - copy_vmpa(&result->addr, addr); +static guint g_db_comment_hash_key(const GDbComment *comment) +{ + guint result; /* Valeur "unique" à renvoyer */ - result->flags = flags; + result = hash_vmpa(&comment->addr); - g_db_comment_add_dynamic_text(result, strdup(text)); + return result; - result->inlined = false; +} - result->before = before; + +/****************************************************************************** +* * +* Paramètres : a = premier élément de collection à consulter. * +* b = second élément de collection à consulter. * +* * +* Description : Compare deux éléments en tant que clefs. * +* * +* Retour : Bilan de la comparaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean g_db_comment_cmp_key(const GDbComment *a, const GDbComment *b) +{ + gboolean result; /* Bilan à retourner */ + int ret; /* Bilan intermédiaire */ + + ret = cmp_vmpa(&a->addr, &b->addr); + + result = (ret == 0); return result; @@ -440,8 +532,8 @@ static gint g_db_comment_cmp(const GDbComment *a, const GDbComment *b) if (result == 0) { - string_a = g_db_comment_get_text(a); - string_b = g_db_comment_get_text(b); + string_a = g_db_comment_get_text((GDbComment *)a); + string_b = g_db_comment_get_text((GDbComment *)b); if (string_a == NULL && string_b == NULL) result = 0; @@ -481,9 +573,9 @@ static gint g_db_comment_cmp(const GDbComment *a, const GDbComment *b) static bool g_db_comment_unpack(GDbComment *comment, packed_buffer *pbuf) { bool result; /* Bilan à retourner */ - uint32_t tmp32; /* Valeur sur 32 bits */ - rle_string string; /* Texte brut récupéré */ uint8_t tmp8; /* Valeur sur 8 bits */ + uint32_t tmp32; /* Valeur sur 32 bits */ + rle_string text; /* Texte brut récupéré */ result = G_DB_ITEM_CLASS(g_db_comment_parent_class)->unpack(G_DB_ITEM(comment), pbuf); @@ -492,29 +584,25 @@ static bool g_db_comment_unpack(GDbComment *comment, packed_buffer *pbuf) if (result) { - result = extract_packed_buffer(pbuf, &tmp32, sizeof(uint32_t), true); - comment->flags = tmp32; + result = extract_packed_buffer(pbuf, &tmp8, sizeof(uint8_t), true); + comment->type = tmp8; } if (result) { - result = unpack_rle_string(&string, pbuf); - - if (!is_rle_string_empty(&string) > 0) - g_db_comment_add_rle_string(comment, &string); - + result = extract_packed_buffer(pbuf, &tmp32, sizeof(uint32_t), true); + comment->flags = tmp32; } if (result) { - result = extract_packed_buffer(pbuf, &tmp8, sizeof(uint8_t), true); - comment->inlined = tmp8; - } + setup_empty_rle_string(&text); + result = unpack_rle_string(&text, pbuf); + + g_db_comment_define_text_lines(comment, get_rle_string(&text)); + + exit_rle_string(&text); - if (result) - { - result = extract_packed_buffer(pbuf, &tmp8, sizeof(uint8_t), true); - comment->repeatable = tmp8; } return result; @@ -546,6 +634,9 @@ static bool g_db_comment_pack(GDbComment *comment, packed_buffer *pbuf) result = pack_vmpa(&comment->addr, pbuf); if (result) + result = extend_packed_buffer(pbuf, (uint8_t []) { comment->type }, sizeof(uint8_t), true); + + if (result) result = extend_packed_buffer(pbuf, (uint32_t []) { comment->flags }, sizeof(uint32_t), true); if (result) @@ -555,12 +646,6 @@ static bool g_db_comment_pack(GDbComment *comment, packed_buffer *pbuf) exit_rle_string(&text); } - if (result) - result = extend_packed_buffer(pbuf, (uint8_t []) { comment->inlined }, sizeof(uint8_t), true); - - if (result) - result = extend_packed_buffer(pbuf, (uint8_t []) { comment->repeatable }, sizeof(uint8_t), true); - return result; } @@ -580,28 +665,40 @@ static bool g_db_comment_pack(GDbComment *comment, packed_buffer *pbuf) static char *g_db_comment_build_label(GDbComment *comment) { -#if 0 - VMPA_BUFFER(loc); /* Indication de position */ - size_t count; /* Nombre d'éléments textuels */ + char *result; /* Description à retourner */ + DbItemFlags flags; /* Propriétés de l'élément */ + const char *text; /* Commentaire associé */ + const char *prefix; /* Préfixe à ajouter */ - vmpa2_to_string(&comment->addr, MDS_UNDEFINED, loc, NULL); + flags = g_db_item_get_flags(G_DB_ITEM(comment)); - lock_flat_array(&comment->text); - count = count_flat_array_items(comment->text); - unlock_flat_array(&comment->text); + if (flags & DIF_ERASER) + asprintf(&result, _("Removed comment")); + + else if (flags & DIF_UPDATED) + { + text = "...";//get_rle_string(&comment->text); - if (count == 0) - asprintf(&G_DB_ITEM(comment)->label, _("Delete comment at %s"), loc); + if (text != NULL) + asprintf(&result, _("Updated comment: \"%s\""), text); + else + asprintf(&result, _("Reset comment")); + } else { - if (comment->inlined) - asprintf(&G_DB_ITEM(comment)->label, _("Enter inlined comment at %s"), loc); + prefix = _("Created"); + + text = "...";//get_rle_string(&comment->text); + + if (text != NULL) + asprintf(&result, _("%s comment \"%s\""), prefix, text); else - asprintf(&G_DB_ITEM(comment)->label, _("Enter comment area at %s"), loc); + asprintf(&result, _("%s empty comment"), prefix); + } -#endif - return NULL; + + return result; } @@ -638,46 +735,30 @@ static bool g_db_comment_run(GDbComment *comment, GLoadedBinary *binary, bool ap cache = g_loaded_binary_get_disassembly_cache(binary); - cursor = g_binary_cursor_new(); - g_binary_cursor_update(G_BINARY_CURSOR(cursor), &comment->addr); + g_buffer_cache_lock(cache); - index = g_buffer_cache_find_index_by_cursor(cache, cursor, true); + switch (comment->type) + { + case CET_INLINED: - g_object_unref(G_OBJECT(cursor)); + cursor = g_binary_cursor_new(); + g_binary_cursor_update(G_BINARY_CURSOR(cursor), &comment->addr); - index = g_buffer_cache_look_for_flag(cache, index, BLF_HAS_CODE); + index = g_buffer_cache_find_index_by_cursor(cache, cursor, true); - if (comment->inlined) - { + g_object_unref(G_OBJECT(cursor)); -#define RUN_INLINED_COMMENT(idx, new, old) \ - if (apply) \ - { \ - old = g_buffer_cache_delete_type_at(cache, idx, G_TYPE_DB_COMMENT, false, false); \ - \ - g_buffer_cache_insert_at(cache, idx, G_LINE_GENERATOR(new), BLF_NONE, false, false); \ - \ - } \ - else \ - { \ - g_buffer_cache_delete_type_at(cache, idx, G_TYPE_DB_COMMENT, false, false); \ - \ - if (old != NULL) \ - { \ - g_buffer_cache_insert_at(cache, idx, old, BLF_NONE, false, false); \ - g_object_unref(G_OBJECT(old)); \ - } \ - \ - } + index = g_buffer_cache_look_for_flag(cache, index, BLF_HAS_CODE); - /* Commentaire principal */ + g_buffer_cache_delete_type_at(cache, index, G_TYPE_DB_COMMENT, false, false); - RUN_INLINED_COMMENT(index, comment, comment->previous); + if (apply) + g_buffer_cache_insert_at(cache, index, G_LINE_GENERATOR(comment), BLF_NONE, false, false); - /* Renvois répétés */ + break; + + case CET_REPEATED: - if (comment->repeatable) - { proc = g_loaded_binary_get_processor(binary); instr = g_arch_processor_find_instr_by_address(proc, &comment->addr); @@ -685,12 +766,6 @@ static bool g_db_comment_run(GDbComment *comment, GLoadedBinary *binary, bool ap scount = g_arch_instruction_count_sources(instr); - if (apply) - { - comment->old_count = scount; - comment->old_inlined = realloc(comment->old_inlined, comment->old_count * sizeof(GLineGenerator *)); - } - for (i = 0; i < scount && result; i++) { source = g_arch_instruction_get_source(instr, i); @@ -713,202 +788,37 @@ static bool g_db_comment_run(GDbComment *comment, GLoadedBinary *binary, bool ap linked = g_buffer_cache_look_for_flag(cache, linked, BLF_HAS_CODE | BLF_IS_LABEL); - RUN_INLINED_COMMENT(linked, comment, comment->old_inlined[i]); - - unref_instr_link(source); - - } + g_buffer_cache_delete_type_at(cache, linked, G_TYPE_DB_COMMENT, false, false); - if (!apply) - { - free(comment->old_inlined); + if (apply) + g_buffer_cache_insert_at(cache, linked, G_LINE_GENERATOR(comment), BLF_NONE, false, false); - comment->old_inlined = NULL; - comment->old_count = 0; + unref_instr_link(source); } g_object_unref(G_OBJECT(proc)); + break; - } - - - - } - - else - { - - - - - - + case CET_BEFORE: + break; + case CET_AFTER: + break; + case CET_COUNT: + assert(false); + result = false; + break; } - - //void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator *generator, bool before, bool after) - - //GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *cache, size_t index, GType type, bool before, bool after) - - - + g_buffer_cache_unlock(cache); g_object_unref(G_OBJECT(cache)); return result; - - - -#if 0 - - bool result; /* Bilan à faire remonter */ - GCodeBuffer *buffer; /* Tampon de lignes à traiter */ - GBufferLine *line; /* Ligne de tampon à marquer */ - GArchProcessor *proc; /* Propriétaire d'instructions */ - GArchInstruction *instr; /* Instruction à traiter */ - instr_link_t *sources; /* Instructions diverses liées */ - size_t scount; /* Nbre de sources affichées */ - size_t i; /* Boucle de parcours */ - const mrange_t *range; /* Emplacement d'instruction */ - GBufferLine *linked; /* Ligne liée à traiter */ - GDbComment *old; /* Ancien élément à restaurer */ - - result = true; - - /* Recherche de la ligne visée */ - - buffer = g_loaded_binary_get_disassembled_buffer(binary); - - line = g_code_buffer_find_line_by_addr(buffer, &comment->addr, comment->flags, NULL); - if (line == NULL) - { - result = false; - goto exit_gui; - } - - /* Détermination de l'imprimeur précédent */ - - if (apply) - { - assert(comment->old_count == 0); - - comment->old_count = 1; - comment->oldies = calloc(comment->old_count, sizeof(GDbComment *)); - - } - - /* Applications globales finales */ - -#define g_code_buffer_update_inlined_comment_dummy(b, l, c, d, o) \ - g_code_buffer_update_inlined_comment(b, l, c, o) - - /** - * Note : on part du principe qu'un commentaire intégré ne peut remplacer qu'un - * commentaire intégré. Et pareil pour les commentaires en blocs. - */ - -#define RUN_COMMENT_ON(ln, idx, func) \ - if (apply) \ - { \ - comment->oldies[idx] = (GDbComment *)g_code_buffer_get_comment_creator(buffer, ln); \ - assert(comment->oldies[idx] == NULL || G_IS_DB_COMMENT(comment->oldies[idx])); \ - assert(comment->oldies[idx] == NULL || comment->oldies[idx]->inlined == comment->inlined); \ - \ - if (is_rle_string_empty(&comment->text)) \ - result = g_code_buffer_delete_lines_comment(buffer, ln); \ - else \ - result = func(buffer, ln, get_rle_string(&comment->text), \ - comment->before, G_OBJECT(comment)); \ - } \ - else \ - { \ - old = comment->oldies[idx]; \ - \ - if (old == NULL) \ - { \ - if (!is_rle_string_empty(&comment->text)) \ - result = g_code_buffer_delete_lines_comment(buffer, ln); \ - else \ - result = true; \ - } \ - else \ - { \ - if (is_rle_string_empty(&old->text)) \ - result = g_code_buffer_delete_lines_comment(buffer, ln); \ - else \ - result = func(buffer, ln, get_rle_string(&old->text), \ - old->before, G_OBJECT(old)); \ - } \ - \ - } - - if (comment->inlined) - { - /* Traitement d'un commentaire inscrusté */ - - RUN_COMMENT_ON(line, 0, g_code_buffer_update_inlined_comment_dummy); - - /* Traitement des répétitions ? */ - - if (comment->repeatable/* && result*/) - { - proc = g_loaded_binary_get_processor(binary); - - range = g_buffer_line_get_range(line); - - instr = g_arch_processor_find_instr_by_address(proc, get_mrange_addr(range)); - assert(instr != NULL); - - scount = g_arch_instruction_get_sources(instr, &sources); - - if (apply) - { - comment->old_count += scount; - comment->oldies = realloc(comment->oldies, comment->old_count * sizeof(GDbComment *)); - } - - for (i = 0; i < scount && result; i++) - { - range = g_arch_instruction_get_range(sources[i].linked); - - /** - * On recherche ici une ligne potentiellement BLF_HAS_CODE ou BLF_IS_LABEL. - * Comme on ne peut pas traiter les deux cas, on prend la première qui vient - * avec BLF_NONE. - */ - linked = g_code_buffer_find_line_by_addr(buffer, get_mrange_addr(range), BLF_NONE, NULL); - assert(linked != NULL); - - RUN_COMMENT_ON(linked, 1 + i, g_code_buffer_update_inlined_comment_dummy); - - } - - g_object_unref(G_OBJECT(instr)); - - g_object_unref(G_OBJECT(proc)); - - } - - } - - else - { - RUN_COMMENT_ON(line, 0, g_code_buffer_update_comment_area); - } - - g_object_unref(G_OBJECT(line)); - - exit_gui: - - /* TODO g_object_unref(G_OBJECT(buffer));*/ - - return result; -#endif } @@ -982,40 +892,38 @@ static bool g_db_comment_load(GDbComment *comment, const bound_value *values, si result = G_DB_ITEM_CLASS(g_db_comment_parent_class)->load(G_DB_ITEM(comment), values, count); - result &= load_vmpa(&comment->addr, NULL, values, count); + if (result) + result = load_vmpa(&comment->addr, NULL, values, count); if (result) { - value = find_bound_value(values, count, "lflags"); + value = find_bound_value(values, count, "type"); result = (value != NULL && value->type == SQLITE_INTEGER); if (result) - comment->flags = value->integer; + comment->type = value->integer; } - result &= load_rle_string(&string, "text", values, count); - - if (result) - g_db_comment_add_rle_string(comment, &string); - if (result) { - value = find_bound_value(values, count, "inlined"); - result = (value != NULL && value->type == SQLITE_BOOLEAN); + value = find_bound_value(values, count, "line_flags"); + result = (value != NULL && value->type == SQLITE_INTEGER); if (result) - comment->inlined = value->boolean; + comment->flags = value->integer; } if (result) { - value = find_bound_value(values, count, "repeatable"); - result = (value != NULL && value->type == SQLITE_BOOLEAN); + result = load_rle_string(&string, "text", values, count); if (result) - comment->repeatable = value->boolean; + { + g_db_comment_define_text_lines(comment, get_rle_string(&string)); + exit_rle_string(&string); + } } @@ -1063,7 +971,7 @@ static bool g_db_comment_store(GDbComment *comment, bound_value **values, size_t value = &(*values)[*count - 1]; - value->cname = "lflags"; + value->cname = "type"; value->built_name = false; value->type = SQLITE_INTEGER; @@ -1071,50 +979,39 @@ static bool g_db_comment_store(GDbComment *comment, bound_value **values, size_t if (value->has_value) { - value->integer = comment->flags; + value->integer = comment->type; value->delete = 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; + *count += 1; *values = realloc(*values, *count * sizeof(bound_value)); - value = &(*values)[*count - 2]; + value = &(*values)[*count - 1]; - value->cname = "inlined"; + value->cname = "line_flags"; value->built_name = false; - value->type = SQLITE_BOOLEAN; + value->type = SQLITE_INTEGER; value->has_value = (comment != NULL); if (value->has_value) { - value->boolean = comment->inlined; + value->integer = comment->flags; value->delete = NULL; } - value = &(*values)[*count - 1]; - - value->cname = "repeatable"; - value->built_name = false; - value->type = SQLITE_BOOLEAN; - - value->has_value = (comment != NULL); + if (comment == NULL) + status = store_rle_string(NULL, "text", values, count); - if (value->has_value) + else { - value->boolean = comment->repeatable; - value->delete = NULL; + 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; + return true; } @@ -1122,19 +1019,27 @@ static bool g_db_comment_store(GDbComment *comment, bound_value **values, size_t /****************************************************************************** * * -* Paramètres : comment = informations à consulter. * +* Paramètres : key = clef de comparaison sous forme de localisation. * +* comment = informations de commentaire à consulter. * * * -* Description : Fournit l'adresse associée à un commentaire. * +* Description : Etablit la comparaison d'une adresse avec un commentaire. * * * -* Retour : Adresse mémoire. * +* Retour : Bilan de la comparaison. * * * * Remarques : - * * * ******************************************************************************/ -const vmpa2t *g_db_comment_get_address(const GDbComment *comment) +int compare_comment_by_addr(const vmpa2t *key, const GDbComment * const *comment) { - return &comment->addr; + int result; /* Bilan à retourner */ + const vmpa2t *addr; /* Position du commentaire */ + + addr = g_db_comment_get_address(*comment); + + result = cmp_vmpa(key, addr); + + return result; } @@ -1143,38 +1048,19 @@ const vmpa2t *g_db_comment_get_address(const GDbComment *comment) * * * Paramètres : comment = informations à consulter. * * * -* Description : Fournit le commentaire associé à un commentaire. * +* Description : Fournit l'adresse associée à un commentaire. * * * -* Retour : Commentaire existant à libérer après usage ou NULL. * +* Retour : Adresse mémoire. * * * * Remarques : - * * * ******************************************************************************/ -char *g_db_comment_get_text(GDbComment *comment) +const vmpa2t *g_db_comment_get_address(const GDbComment *comment) { - char *result; /* Chaîne constituée à renvoyer*/ - size_t count; /* Nombre d'éléments textuels */ - size_t i; /* Boucle de parcours */ - rle_string *string; /* Chaîne à consulter */ + const vmpa2t *result; /* Localisation à retourner */ - result = NULL; - - lock_flat_array(&comment->text); - - count = count_flat_array_items(comment->text); - - for (i = 0; i < count; i++) - { - string = get_flat_array_item(comment->text, i, sizeof(rle_string)); - - assert(!is_rle_string_empty(string)); - - result = stradd(result, get_rle_string(string)); - - } - - unlock_flat_array(&comment->text); + result = &comment->addr; return result; @@ -1184,30 +1070,22 @@ char *g_db_comment_get_text(GDbComment *comment) /****************************************************************************** * * * Paramètres : comment = informations à consulter. * -* text = commentaire construit ou NULL. * * * -* Description : Associe un contenu supplémentaire à un commentaire. * +* Description : Indique le type d'incrustation prévue pour un commentaire. * * * -* Retour : - * +* Retour : Incrustation associée au commentaire. * * * * Remarques : - * * * ******************************************************************************/ -void g_db_comment_add_dynamic_text(GDbComment *comment, char *text) +CommentEmbeddingType g_db_comment_get_embedding_type(const GDbComment *comment) { - rle_string string; /* Fragment de texte à ajouter */ - - if (text != NULL) - { - init_dynamic_rle_string(&string, text); + CommentEmbeddingType result; /* Type à renvoyer */ - g_db_comment_add_rle_string(comment, &string); + result = comment->type; - } - - else - g_db_comment_update_count_lines(comment); + return result; } @@ -1215,30 +1093,22 @@ void g_db_comment_add_dynamic_text(GDbComment *comment, char *text) /****************************************************************************** * * * Paramètres : comment = informations à consulter. * -* text = commentaire construit ou NULL. * * * -* Description : Associe un contenu statique supplémentaire à un commentaire. * +* Description : Fournit les particularités d'accroche liées à un commentaire.* * * -* Retour : - * +* Retour : Particularités éventuelles pour l'accroche. * * * * Remarques : - * * * ******************************************************************************/ -void g_db_comment_add_static_text(GDbComment *comment, const char *text) +BufferLineFlags g_db_comment_get_flags(const GDbComment *comment) { - rle_string string; /* Fragment de texte à ajouter */ + BufferLineFlags result; /* Type à renvoyer */ - if (text != NULL) - { - init_static_rle_string(&string, text); + result = comment->flags; - g_db_comment_add_rle_string(comment, &string); - - } - - else - g_db_comment_update_count_lines(comment); + return result; } @@ -1246,29 +1116,41 @@ void g_db_comment_add_static_text(GDbComment *comment, const char *text) /****************************************************************************** * * * Paramètres : comment = informations à consulter. * -* string = commentaire établi à inétgrer. * * * -* Description : Associe un contenu formaté supplémentaire à un commentaire. * +* Description : Fournit le commentaire associé à un commentaire. * * * -* Retour : - * +* Retour : Commentaire existant à libérer après usage ou NULL. * * * * Remarques : - * * * ******************************************************************************/ -static void g_db_comment_add_rle_string(GDbComment *comment, const rle_string *string) +char *g_db_comment_get_text(GDbComment *comment) { - /* Extension du contenu */ + char *result; /* Chaîne constituée à renvoyer*/ + size_t count; /* Nombre d'éléments textuels */ + size_t i; /* Boucle de parcours */ + rle_string *string; /* Chaîne à consulter */ + + result = NULL; lock_flat_array(&comment->text); - add_item_to_flat_array(&comment->text, string, sizeof(rle_string)); + count = count_flat_array_items(comment->text); - unlock_flat_array(&comment->text); + for (i = 0; i < count; i++) + { + string = get_flat_array_item(comment->text, i, sizeof(rle_string)); - /* Mise à jour de la taille de rendu */ + assert(!is_rle_string_empty(string)); - g_db_comment_update_count_lines(comment); + result = stradd(result, get_rle_string(string)); + + } + + unlock_flat_array(&comment->text); + + return result; } @@ -1281,64 +1163,27 @@ static void g_db_comment_add_rle_string(GDbComment *comment, const rle_string *s /****************************************************************************** * * -* Paramètres : comment = informations à réactualiser. * +* Paramètres : comment = générateur à consulter. * * * -* Description : Calcule le nombre de lignes suite à un changement de contenu.* +* Description : Indique le nombre de ligne prêtes à être générées. * * * -* Retour : - * +* Retour : Nombre de lignes devant apparaître au final. * * * * Remarques : - * * * ******************************************************************************/ -static void g_db_comment_update_count_lines(GDbComment *comment) +static size_t g_db_comment_count_lines(GDbComment *comment) { - char *full; /* Contenu textuel complet */ - char **lines; /* Lignes brutes à représenter */ - GCodingLanguage *lang; /* Langage de sortie préféré */ - size_t i; /* Boucle de parcours */ + size_t result; /* Quantité à retourner */ - full = g_db_comment_get_text(comment); - - if (full == NULL) - comment->count = 0; - - else - { - lines = strtoka(full, "\n", &comment->count); - - lang = g_asm_language_new(); - g_coding_language_encapsulate_comments(lang, &lines, &comment->count); - g_object_unref(G_OBJECT(lang)); - - for (i = 0; i < comment->count; i++) - free(lines[i]); - - if (lines != NULL) - free(lines); - - free(full); - - } - -} + lock_flat_array(&comment->text); + result = count_flat_array_items(comment->text); -/****************************************************************************** -* * -* Paramètres : comment = générateur à consulter. * -* * -* Description : Indique le nombre de ligne prêtes à être générées. * -* * -* Retour : Nombre de lignes devant apparaître au final. * -* * -* Remarques : - * -* * -******************************************************************************/ + unlock_flat_array(&comment->text); -static size_t g_db_comment_count_lines(const GDbComment *comment) -{ - return comment->count; + return result; } @@ -1413,7 +1258,7 @@ static int g_db_comment_contain_cursor(const GDbComment *comment, size_t index, * * ******************************************************************************/ -static BufferLineFlags g_db_comment_get_flags(const GDbComment *comment, size_t index, size_t repeat) +static BufferLineFlags g_db_comment_get_generator_flags(const GDbComment *comment, size_t index, size_t repeat) { return BLF_NONE; @@ -1454,11 +1299,6 @@ static void g_db_comment_print(GDbComment *comment, GBufferLine *line, size_t in g_coding_language_encapsulate_comments(lang, &lines, &count); g_object_unref(G_OBJECT(lang)); - if (count != comment->count) - printf("full=%s\n", full); - - assert(count == comment->count); - g_buffer_line_append_text(line, DLC_COMMENTS, SL(lines[repeat]), RTT_COMMENT, NULL); for (i = 0; i < count; i++) @@ -1616,13 +1456,12 @@ static bool g_comment_collection_create_db_table(const GCommentCollection *colle char *msg; /* Message d'erreur */ int ret; /* Bilan de la création */ - sql = "CREATE TABLE Comments (" \ - SQLITE_DB_ITEM_CREATE ", " \ - "%s, " \ - "lflags INTEGER, " \ - SQLITE_RLESTR_CREATE("text") ", " \ - "inlined INTEGER, " \ - "repeatable INTEGER" \ + sql = "CREATE TABLE Comments (" \ + SQLITE_DB_ITEM_CREATE ", " \ + "%s, " \ + "type INTEGER, " \ + "line_flags INTEGER, " \ + SQLITE_RLESTR_CREATE("text") \ ");"; addr_fields = create_vmpa_db_table(NULL); diff --git a/src/analysis/db/items/comment.h b/src/analysis/db/items/comment.h index 7049b28..fa1644f 100644 --- a/src/analysis/db/items/comment.h +++ b/src/analysis/db/items/comment.h @@ -37,12 +37,25 @@ /* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */ -#define G_TYPE_DB_COMMENT g_db_comment_get_type() -#define G_DB_COMMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_comment_get_type(), GDbComment)) -#define G_IS_DB_COMMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_comment_get_type())) -#define G_DB_COMMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DB_COMMENT, GDbCommentClass)) -#define G_IS_DB_COMMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DB_COMMENT)) -#define G_DB_COMMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DB_COMMENT, GDbCommentClass)) +/* Incrustations possibles pour un commentaire */ +typedef enum _CommentEmbeddingType +{ + CET_INLINED, /* En bout de ligne */ + CET_REPEATED, /* Reproduit à chaque référence*/ + CET_BEFORE, /* Placé sur une ligne avant */ + CET_AFTER, /* Placé sur une ligne après */ + + CET_COUNT + +} CommentEmbeddingType; + + +#define G_TYPE_DB_COMMENT g_db_comment_get_type() +#define G_DB_COMMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DB_COMMENT, GDbComment)) +#define G_IS_DB_COMMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DB_COMMENT)) +#define G_DB_COMMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DB_COMMENT, GDbCommentClass)) +#define G_IS_DB_COMMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DB_COMMENT)) +#define G_DB_COMMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DB_COMMENT, GDbCommentClass)) /* Commentaire à placer dans du texte quelconque (instance) */ @@ -55,35 +68,38 @@ typedef struct _GDbCommentClass GDbCommentClass; /* Indique le type défini pour un commentaire à l'intérieur d'une zone de texte. */ GType g_db_comment_get_type(void); -/* Crée une définition de commentaire dans une zone de texte. */ -GDbComment *g_db_comment_new_inlined(const vmpa2t *, BufferLineFlags, bool); +/* Crée une définition de commentaire textuel. */ +GDbComment *g_db_comment_new(const vmpa2t *, CommentEmbeddingType, BufferLineFlags, const char *); + +/* Initialise la définition d'un commentaire à incruster. */ +bool g_db_comment_fill(GDbComment *, const vmpa2t *, CommentEmbeddingType, BufferLineFlags, const char *); -/* Crée une définition de commentaire dans une zone de texte. */ -GDbComment *g_db_comment_new_area(const vmpa2t *, BufferLineFlags, const char *, bool); +/* Etablit la comparaison d'une adresse avec un commentaire. */ +int compare_comment_by_addr(const vmpa2t *, const GDbComment * const *); /* Fournit l'adresse associée à un commentaire. */ const vmpa2t *g_db_comment_get_address(const GDbComment *); -/* Fournit le commentaire associé à un commentaire. */ -char *g_db_comment_get_text(GDbComment *); +/* Indique le type d'incrustation prévue pour un commentaire. */ +CommentEmbeddingType g_db_comment_get_embedding_type(const GDbComment *); -/* Associe un contenu supplémentaire à un commentaire. */ -void g_db_comment_add_dynamic_text(GDbComment *, char *); +/* Fournit les particularités d'accroche liées à un commentaire. */ +BufferLineFlags g_db_comment_get_flags(const GDbComment *); -/* Associe un contenu statique supplémentaire à un commentaire. */ -void g_db_comment_add_static_text(GDbComment *, const char *); +/* Fournit le commentaire associé à un commentaire. */ +char *g_db_comment_get_text(GDbComment *); /* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ -#define G_TYPE_COMMENT_COLLECTION g_comment_collection_get_type() -#define G_COMMENT_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_comment_collection_get_type(), GCommentCollection)) -#define G_IS_COMMENT_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_comment_collection_get_type())) -#define G_COMMENT_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_COMMENT_COLLECTION, GCommentCollectionClass)) -#define G_IS_COMMENT_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_COMMENT_COLLECTION)) -#define G_COMMENT_COLLECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_COMMENT_COLLECTION, GCommentCollectionClass)) +#define G_TYPE_COMMENT_COLLECTION g_comment_collection_get_type() +#define G_COMMENT_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_COMMENT_COLLECTION, GCommentCollection)) +#define G_IS_COMMENT_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_COMMENT_COLLECTION)) +#define G_COMMENT_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_COMMENT_COLLECTION, GCommentCollectionClass)) +#define G_IS_COMMENT_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_COMMENT_COLLECTION)) +#define G_COMMENT_COLLECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_COMMENT_COLLECTION, GCommentCollectionClass)) /* Collection dédiée aux commentaires textuels (instance) */ diff --git a/src/core/collections.c b/src/core/collections.c index f5bccd7..660c981 100644 --- a/src/core/collections.c +++ b/src/core/collections.c @@ -114,7 +114,7 @@ bool load_hard_coded_collection_definitions(void) REGISTER_COLLECTION(G_TYPE_BM_COLLECTION, DBF_BOOKMARKS); - //REGISTER_COLLECTION(G_TYPE_COMMENT_COLLECTION, DBF_COMMENTS); + REGISTER_COLLECTION(G_TYPE_COMMENT_COLLECTION, DBF_COMMENTS); //REGISTER_COLLECTION(G_TYPE_MOVE_COLLECTION, DBF_MOVES); diff --git a/src/format/preload.c b/src/format/preload.c index dc254b2..c36db93 100644 --- a/src/format/preload.c +++ b/src/format/preload.c @@ -24,6 +24,9 @@ #include "preload.h" +#include <assert.h> + + #include "preload-int.h" @@ -629,7 +632,7 @@ void _g_preload_info_add_comment(GPreloadInfo *info, GDbComment *comment) * * * Description : Recherche un commentaire dans des préchargements. * * * -* Retour : Eventuel commenaire retrouvé ou NULL. * +* Retour : Eventuel commentaire retrouvé ou NULL. * * * * Remarques : - * * * @@ -640,23 +643,52 @@ GDbComment *_g_preload_info_find_comment_at(GPreloadInfo *info, const vmpa2t *ad GDbComment *result; /* Trouvaille à retourner */ GDbComment **ptr; /* Adresse dans le tableau */ - int cmp_comment_by_addr(const vmpa2t *key, const GDbComment * const *comment) + ptr = find_item_in_flat_array(info->comments, sizeof(GDbComment *), + (__compar_fn_t)compare_comment_by_addr, addr); + + if (ptr != NULL) { - const vmpa2t *caddr; /* Position du commentaire */ + result = *ptr; + g_object_ref(G_OBJECT(result)); + } + else + result = NULL; - caddr = g_db_comment_get_address(*comment); + return result; - return cmp_vmpa(key, caddr); +} - } + +/****************************************************************************** +* * +* Paramètres : info = instance à mettre à consulter. * +* addr = localisation du commentaire recherché. * +* index = indice du commentaire retrouvé ou NULL. [OUT] * +* * +* Description : Recherche un commentaire dans des préchargements. * +* * +* Retour : Eventuel commentaire retrouvé ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbComment *g_preload_info_find_comment_at(GPreloadInfo *info, const vmpa2t *addr, size_t *index) +{ + GDbComment *result; /* Trouvaille à retourner */ + GDbComment **ptr; /* Adresse dans le tableau */ ptr = find_item_in_flat_array(info->comments, sizeof(GDbComment *), - (__compar_fn_t)cmp_comment_by_addr, addr); + (__compar_fn_t)compare_comment_by_addr, addr); if (ptr != NULL) { result = *ptr; g_object_ref(G_OBJECT(result)); + + if (index != NULL) + *index = ((void **)ptr - info->comments); + } else result = NULL; @@ -668,6 +700,37 @@ GDbComment *_g_preload_info_find_comment_at(GPreloadInfo *info, const vmpa2t *ad /****************************************************************************** * * +* Paramètres : info = instance à mettre à jour. * +* index = indice du commentaire à remplacer. * +* comment = commentaire à venir associer. * +* * +* Description : Remplace un commentaire par un autre à un emplacement donné. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_preload_info_replace_comment_at(GPreloadInfo *info, size_t index, GDbComment *comment) +{ +#ifndef NDEBUG + GDbComment **current; /* Commentaire à remplacer */ +#endif + +#ifndef NDEBUG + current = get_flat_array_item(info->comments, index, sizeof(GDbComment *)); + + assert(cmp_vmpa(g_db_comment_get_address(*current), g_db_comment_get_address(comment))); +#endif + + rpl_item_in_flat_array(info->comments, index, &comment, sizeof(GDbComment *)); + +} + + +/****************************************************************************** +* * * Paramètres : info = instance à consulter. * * * * Description : Indique la quantité de commentaires préchargés disponibles. * diff --git a/src/format/preload.h b/src/format/preload.h index 5557253..587c35d 100644 --- a/src/format/preload.h +++ b/src/format/preload.h @@ -102,6 +102,12 @@ void _g_preload_info_add_comment(GPreloadInfo *, GDbComment *); /* Recherche un commentaire dans des préchargements. */ GDbComment *_g_preload_info_find_comment_at(GPreloadInfo *, const vmpa2t *); +/* Recherche un commentaire dans des préchargements. */ +GDbComment *g_preload_info_find_comment_at(GPreloadInfo *, const vmpa2t *, size_t *); + +/* Remplace un commentaire par un autre à un emplacement donné. */ +void g_preload_info_replace_comment_at(GPreloadInfo *, size_t, GDbComment *); + /* Indique la quantité de commentaires préchargés disponibles. */ size_t _g_preload_info_count_comments(const GPreloadInfo *); |