From e59544bb61b0043d82946918ece144cae2749d53 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 6 Aug 2018 19:38:09 +0200 Subject: Fixed many bugs in the code cache and the width tracker objects. --- src/analysis/db/items/comment.c | 36 +++++++------- src/glibext/gbuffercache.c | 102 ++++++++++++++++++++++++++++++---------- src/glibext/gbuffercache.h | 5 +- src/glibext/gwidthtracker.c | 67 +++++++++++++++----------- 4 files changed, 138 insertions(+), 72 deletions(-) diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c index 8155fc5..b879d08 100644 --- a/src/analysis/db/items/comment.c +++ b/src/analysis/db/items/comment.c @@ -654,24 +654,24 @@ static bool g_db_comment_run(GDbComment *comment, GLoadedBinary *binary, bool ap if (comment->inlined) { -#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), 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, false, false); \ - g_object_unref(G_OBJECT(old)); \ - } \ - \ +#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)); \ + } \ + \ } /* Commentaire principal */ diff --git a/src/glibext/gbuffercache.c b/src/glibext/gbuffercache.c index 7293e7c..866d696 100644 --- a/src/glibext/gbuffercache.c +++ b/src/glibext/gbuffercache.c @@ -72,7 +72,7 @@ static void init_cache_info(cache_info *, GLineGenerator *, size_t, BufferLineFl static void release_cache_info(cache_info *); /* Ajoute un générateur aux informations sur une ligne. */ -static void extend_cache_info(cache_info *, GLineGenerator *); +static void extend_cache_info(cache_info *, GLineGenerator *, BufferLineFlags); /* Retire un générateur aux informations d'une ligne. */ static void remove_from_cache_info(cache_info *, GLineGenerator *); @@ -217,6 +217,7 @@ static void release_cache_info(cache_info *info) * * * Paramètres : info = informations concernant une ligne à actualiser. * * generator = générateur à associer à toutes les lignes. * +* flags = propriétés supplémentaires à associer à la ligne.* * * * Description : Ajoute un générateur aux informations sur une ligne. * * * @@ -226,7 +227,7 @@ static void release_cache_info(cache_info *info) * * ******************************************************************************/ -static void extend_cache_info(cache_info *info, GLineGenerator *generator) +static void extend_cache_info(cache_info *info, GLineGenerator *generator, BufferLineFlags flags) { generator_link first; /* Générateur déjà en place */ generator_link *new; /* Nouveau générateur placé */ @@ -259,6 +260,17 @@ static void extend_cache_info(cache_info *info, GLineGenerator *generator) reset_cache_info_line(info); + /** + * On peut rajouter des indications, mais, en cas de retrait d'un générateur, + * on ne saura pas forcément lesquelles retirer puisque qu'on ne trace pas + * leur origine. + * + * On considère donc que seul le premier générateur (le principal) a le + * droit de poser des fanions. + */ + + assert(flags == BLF_NONE); + } @@ -319,6 +331,8 @@ static void remove_from_cache_info(cache_info *info, GLineGenerator *generator) info->generators = (generator_link *)realloc(info->generators, --info->count * sizeof(generator_link)); + g_object_unref(G_OBJECT(generator)); + break; } @@ -592,7 +606,7 @@ static void g_buffer_cache_init(GBufferCache *cache) static void g_buffer_cache_dispose(GBufferCache *cache) { size_t i; /* Boucle de parcours #1 */ - cache_info *info; /* Accès directe à une ligne */ + cache_info *info; /* Accès direct à une ligne */ size_t j; /* Boucle de parcours #2 */ if (cache->content != NULL) @@ -636,7 +650,7 @@ static void g_buffer_cache_dispose(GBufferCache *cache) static void g_buffer_cache_finalize(GBufferCache *cache) { size_t i; /* Boucle de parcours */ - cache_info *info; /* Accès directe à une ligne */ + cache_info *info; /* Accès direct à une ligne */ for (i = 0; i < cache->used; i++) { @@ -817,7 +831,7 @@ GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *cache) static size_t g_buffer_cache_compute_repetition(GBufferCache *cache, size_t index, GLineGenerator *generator) { size_t result; /* Compteur à retourner */ - cache_info *info; /* Accès directe à une ligne */ + cache_info *info; /* Accès direct à une ligne */ size_t i; /* Boucle de parcours */ result = 0; @@ -853,6 +867,7 @@ static size_t g_buffer_cache_compute_repetition(GBufferCache *cache, size_t inde * Paramètres : cache = instance GLib à modifier. * * index = point d'insertion, puis de sauvegarde. * * generator = générateur à insérer dans les lignes. * +* flags = propriétés supplémentaires à associer à la ligne.* * before = précise l'emplacement final des nouvelles lignes.* * after = précise l'emplacement final des nouvelles lignes.* * * @@ -864,7 +879,7 @@ static size_t g_buffer_cache_compute_repetition(GBufferCache *cache, size_t inde * * ******************************************************************************/ -void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator *generator, bool before, bool after) +void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator *generator, BufferLineFlags flags, bool before, bool after) { #ifndef NDEBUG GLineCursor *gen_cursor; /* Position du générateur */ @@ -880,26 +895,27 @@ void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator #ifndef NDEBUG - g_line_generator_compute_cursor(generator, 0, index, 0, &gen_cursor); + if (!before && !after) + { + g_line_generator_compute_cursor(generator, 0, index, 0, &gen_cursor); - get_cache_info_cursor(&cache->lines[index], index, 0, &line_cursor); + get_cache_info_cursor(&cache->lines[index], index, 0, &line_cursor); - ret = g_line_cursor_compare(gen_cursor, line_cursor); + ret = g_line_cursor_compare(gen_cursor, line_cursor); - g_object_unref(G_OBJECT(gen_cursor)); - g_object_unref(G_OBJECT(line_cursor)); + g_object_unref(G_OBJECT(gen_cursor)); + g_object_unref(G_OBJECT(line_cursor)); - /////////////////////////////////////// - if (ret != 0) return; + assert(ret == 0); - assert(ret == 0); + } #endif /* Cas particulier d'ajout en fin de cache... */ if (after && (index + 1) == cache->used) { - g_buffer_cache_append(cache, generator, BLF_NONE); + g_buffer_cache_append(cache, generator, flags); goto gbcia_done; } @@ -932,10 +948,10 @@ void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator if (before || after) { - memmove(&cache->lines[index], &cache->lines[index + needed], (cache->used - index) * sizeof(cache_info)); + memmove(&cache->lines[index + needed], &cache->lines[index], (cache->used - index) * sizeof(cache_info)); for (i = 0; i < needed; i++) - init_cache_info(&cache->lines[index + i], generator, i, BLF_NONE); + init_cache_info(&cache->lines[index + i], generator, i, flags); cache->used += needed; @@ -947,7 +963,7 @@ void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator else { - extend_cache_info(&cache->lines[index], generator); + extend_cache_info(&cache->lines[index], generator, flags); g_width_tracker_update(cache->tracker, index); @@ -980,6 +996,42 @@ void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator /****************************************************************************** * * +* Paramètres : cache = instance GLib à modifier. * +* index = point de suppression. * +* * +* Description : Retire une ligne du tampon. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_buffer_cache_delete_at(GBufferCache *cache, size_t index) +{ + cache_info *info; /* Accès direct à une ligne */ + + assert(index < cache->used); + + info = &cache->lines[index]; + + release_cache_info(info); + + if ((index + 1) < cache->used) + memmove(&cache->lines[index], &cache->lines[index + 1], + (cache->used - index - 1) * sizeof(cache_info)); + + cache->used--; + + g_width_tracker_update_deleted(cache->tracker, index, index); + + g_signal_emit_by_name(cache, "size-changed", false, index, 1); + +} + + +/****************************************************************************** +* * * Paramètres : cache = instance GLib à modifier. * * index = point d'insertion, puis de sauvegarde. * * type = type de générateurs à retirer des lignes visées. * @@ -997,7 +1049,7 @@ void g_buffer_cache_insert_at(GBufferCache *cache, size_t index, GLineGenerator GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *cache, size_t index, GType type, bool before, bool after) { GLineGenerator *result; /* Prédécesseur à retourner */ - cache_info *info; /* Accès directe à une ligne */ + cache_info *info; /* Accès direct à une ligne */ generator_link *link; /* Accès simplifié */ size_t i; /* Boucle de parcours */ size_t count; /* Emplacements occupés */ @@ -1122,7 +1174,7 @@ void g_buffer_cache_append(GBufferCache *cache, GLineGenerator *generator, Buffe size_t count; /* Nombre de lignes générées */ size_t index; /* Point d'insertion */ size_t i; /* Boucle de parcours */ - cache_info *info; /* Accès directe à une ligne */ + cache_info *info; /* Accès direct à une ligne */ count = g_line_generator_count_lines(generator); @@ -1157,8 +1209,6 @@ void g_buffer_cache_append(GBufferCache *cache, GLineGenerator *generator, Buffe cache->used += count; - g_object_unref(G_OBJECT(generator)); - g_width_tracker_update_added(cache->tracker, index, count); g_signal_emit_by_name(cache, "size-changed", true, index, count); @@ -1184,7 +1234,7 @@ void g_buffer_cache_extend_with(GBufferCache *cache, size_t count, GLineGenerato { size_t index; /* Point d'insertion */ size_t i; /* Boucle de parcours */ - cache_info *info; /* Accès directe à une ligne */ + cache_info *info; /* Accès direct à une ligne */ size_t added; /* Nombre d'ajouts effectués */ assert(count >= cache->used); @@ -1245,7 +1295,7 @@ void g_buffer_cache_extend_with(GBufferCache *cache, size_t count, GLineGenerato void g_buffer_cache_truncate(GBufferCache *cache, size_t max) { size_t i; /* Boucle de parcours #1 */ - cache_info *info; /* Accès directe à une ligne */ + cache_info *info; /* Accès direct à une ligne */ size_t j; /* Boucle de parcours #2 */ size_t removed; /* Nombre de retraits effectués*/ @@ -1326,7 +1376,7 @@ void g_buffer_cache_get_line_cursor(const GBufferCache *cache, size_t index, gin BufferLineFlags g_buffer_cache_get_line_flags(const GBufferCache *cache, size_t index) { BufferLineFlags result; /* Somme à renvoyer */ - cache_info *info; /* Accès directe à une ligne */ + cache_info *info; /* Accès direct à une ligne */ const generator_link *generator; /* Générateur retenu */ size_t i; /* Boucle de parcours */ @@ -1433,7 +1483,7 @@ void g_buffer_cache_draw(const GBufferCache *cache, cairo_t *cr, size_t first, s gint y; /* Point de départ en ordonnée */ bool wait_selection; /* Sélection déjà passée ? */ size_t i; /* Boucle de parcours */ - cache_info *info; /* Accès directe à une ligne */ + cache_info *info; /* Accès direct à une ligne */ line_width_summary summary; /* Résumé concis des largeurs */ GBufferLine *line; /* Ligne à venir dessiner */ diff --git a/src/glibext/gbuffercache.h b/src/glibext/gbuffercache.h index 7a0d250..077c5f9 100644 --- a/src/glibext/gbuffercache.h +++ b/src/glibext/gbuffercache.h @@ -76,7 +76,10 @@ size_t g_buffer_cache_count_lines(const GBufferCache *); GWidthTracker *g_buffer_cache_get_width_tracker(const GBufferCache *); /* Insère un générateur dans des lignes à une position donnée. */ -void g_buffer_cache_insert_at(GBufferCache *, size_t, GLineGenerator *, bool, bool); +void g_buffer_cache_insert_at(GBufferCache *, size_t, GLineGenerator *, BufferLineFlags, bool, bool); + +/* Retire une ligne du tampon. */ +void g_buffer_cache_delete_at(GBufferCache *, size_t); /* Retire un type de générateur de lignes. */ GLineGenerator *g_buffer_cache_delete_type_at(GBufferCache *, size_t, GType, bool, bool); diff --git a/src/glibext/gwidthtracker.c b/src/glibext/gwidthtracker.c index 44a7ff0..e116a85 100644 --- a/src/glibext/gwidthtracker.c +++ b/src/glibext/gwidthtracker.c @@ -613,8 +613,14 @@ static void g_width_tracker_update_ranges(GWidthTracker *tracker, size_t start, for (i = start; i < tracker->count; i++) { +#ifndef NDEBUG + if ((i + 1) < tracker->count) + assert((tracker->portions[i].last + 1) == tracker->portions[i + 1].first); +#endif + tracker->portions[i].first += diff; tracker->portions[i].last += diff; + } } @@ -746,7 +752,6 @@ void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t c { size_t current; /* Indice de portion visée */ common_metrics *portion; /* Portion sélectionnée */ - size_t next; /* Prochaine portion à décaller*/ size_t i; /* Boucle de parcours */ size_t dest; /* Destination d'une recopie */ size_t src; /* Source d'une recopie */ @@ -786,7 +791,9 @@ void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t c g_width_tracker_reset_widths(tracker, current); - next = current + 1; + /* Suite impérative : accroître les indices ! */ + + g_width_tracker_update_ranges(tracker, current + 1, count); /* Un découpage s'impose-t-il quelque part ? */ @@ -810,14 +817,12 @@ void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t c memmove(&tracker->portions[dest], &tracker->portions[src], (tracker->count - src - 1) * sizeof(common_metrics)); - next++; - /* Insertion au début */ if (i == portion->first) { assert(i == index); - tracker->portions[current + 1].first = portion->first + 1; + tracker->portions[current + 1].first = i + 1; tracker->portions[current + 1].last = portion->last; tracker->portions[current + 1].cached = false; @@ -839,6 +844,8 @@ void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t c } + assert((tracker->portions[current].last + 1) == tracker->portions[current + 1].first); + /* Mise à jour des largeurs */ g_width_tracker_reset_widths(tracker, current); @@ -849,10 +856,6 @@ void g_width_tracker_update_added(GWidthTracker *tracker, size_t index, size_t c } - /* Suite impérative : accroître les indices ! */ - - g_width_tracker_update_ranges(tracker, next, 1); - } @@ -879,6 +882,7 @@ void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t size_t dest; /* Destination du transfert */ bool keep_last; /* Conservation de portion #2 */ size_t src; /* Source du transfert */ + size_t update; /* Début de la série en rafale */ first = g_width_tracker_find_metrics(tracker, start); assert(first < tracker->count); @@ -890,18 +894,19 @@ void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t /* Suppression de portions inutiles ? */ - keep_first = (tracker->portions[first].first < start || end < tracker->portions[first].last); + keep_first = (tracker->portions[first].first < start); dest = (keep_first ? first + 1 : first); - keep_last = (tracker->portions[last].first < start || end < tracker->portions[last].last); + keep_last = (end < tracker->portions[last].last); src = (keep_last ? last : last + 1); if (src > dest) { - memmove(&tracker->portions[dest], &tracker->portions[src], - (tracker->count - src) * sizeof(common_metrics)); + if (src < tracker->count) + memmove(&tracker->portions[dest], &tracker->portions[src], + (tracker->count - src) * sizeof(common_metrics)); tracker->count -= (src - dest); @@ -914,10 +919,11 @@ void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t if (keep_first && keep_last && last != first) { - tracker->portions[first].last = tracker->portions[dest].last; + tracker->portions[first].last = tracker->portions[first + 1].last; - memmove(&tracker->portions[first + 1], &tracker->portions[first + 2], - (tracker->count - first - 2) * sizeof(common_metrics)); + if ((first - 2) < tracker->count) + memmove(&tracker->portions[first + 1], &tracker->portions[first + 2], + (tracker->count - first - 2) * sizeof(common_metrics)); tracker->count--; @@ -930,29 +936,36 @@ void g_width_tracker_update_deleted(GWidthTracker *tracker, size_t start, size_t /* Avant toute chose : faire décroître les indices ! */ - if (keep_first) + if (keep_first && keep_last) { - if (end < tracker->portions[first].last) - tracker->portions[first].last -= diff; - else - tracker->portions[first].last = start - 1; + tracker->portions[first].last -= diff; + update = first + 1; } - if (keep_last && last != first) + else { - tracker->portions[dest].first = end + 1; - tracker->portions[dest].last -= diff; + if (keep_first) + { + tracker->portions[first].last = start - 1; + update = first + 1; + } + else + update = first; + + if (keep_last) + tracker->portions[update].first = end + 1; + } - g_width_tracker_update_ranges(tracker, keep_last ? dest + 1 : dest, -diff); + g_width_tracker_update_ranges(tracker, update, -diff); /* Mise à jour des largeurs aux extrémités */ if (keep_first) g_width_tracker_reset_widths(tracker, first); - if (keep_last && last != first) - g_width_tracker_reset_widths(tracker, dest); + if (keep_last && !keep_first) + g_width_tracker_reset_widths(tracker, update); } -- cgit v0.11.2-87-g4458