X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fgit-merge-changelog.c;h=1911c08e5ca78b0932e239548651ada0e1bb09ed;hb=35dda7458879acb367f2cba0aaf7856cd98f5b63;hp=022ac5c2da7f3694db2033da1c2bb4f26a5f8c88;hpb=29b57c22fecb5bc0978937d6f557b7eff1897d56;p=gnulib.git diff --git a/lib/git-merge-changelog.c b/lib/git-merge-changelog.c index 022ac5c2d..1911c08e5 100644 --- a/lib/git-merge-changelog.c +++ b/lib/git-merge-changelog.c @@ -160,8 +160,24 @@ struct entry { char *string; size_t length; + /* Cache for the hash code. */ + bool hashcode_cached; + size_t hashcode; }; +/* Create an entry. + The memory region passed by the caller must of indefinite extent. It is + *not* copied here. */ +static struct entry * +entry_create (char *string, size_t length) +{ + struct entry *result = XMALLOC (struct entry); + result->string = string; + result->length = length; + result->hashcode_cached = false; + return result; +} + /* Compare two entries for equality. */ static bool entry_equals (const void *elt1, const void *elt2) @@ -176,16 +192,21 @@ entry_equals (const void *elt1, const void *elt2) static size_t entry_hashcode (const void *elt) { - const struct entry *entry = (const struct entry *) elt; - /* See http://www.haible.de/bruno/hashfunc.html. */ - const char *s; - size_t n; - size_t h = 0; + struct entry *entry = (struct entry *) elt; + if (!entry->hashcode_cached) + { + /* See http://www.haible.de/bruno/hashfunc.html. */ + const char *s; + size_t n; + size_t h = 0; - for (s = entry->string, n = entry->length; n > 0; s++, n--) - h = (unsigned char) *s + ((h << 9) | (h >> (sizeof (size_t) * CHAR_BIT - 9))); + for (s = entry->string, n = entry->length; n > 0; s++, n--) + h = (unsigned char) *s + ((h << 9) | (h >> (sizeof (size_t) * CHAR_BIT - 9))); - return h; + entry->hashcode = h; + entry->hashcode_cached = true; + } + return entry->hashcode; } /* Perform a fuzzy comparison of two ChangeLog entries. @@ -282,9 +303,7 @@ read_changelog_file (const char *filename, struct changelog_file *result) } } - curr = XMALLOC (struct entry); - curr->string = start; - curr->length = ptr - start; + curr = entry_create (start, ptr - start); gl_list_add_last (result->entries_list, curr); gl_list_add_first (result->entries_reversed, curr); @@ -735,19 +754,15 @@ try_split_merged_entry (const struct entry *old_entry, if (best_similarity < FSTRCMP_STRICTER_THRESHOLD) return false; - new_split[0] = XMALLOC (struct entry); - new_split[0]->string = new_entry->string; - new_split[0]->length = best_split_offset + 1; + new_split[0] = entry_create (new_entry->string, best_split_offset + 1); - new_split[1] = XMALLOC (struct entry); { size_t len1 = new_title_len; size_t len2 = new_entry->length - best_split_offset; char *combined = XNMALLOC (len1 + len2, char); memcpy (combined, new_entry->string, len1); memcpy (combined + len1, new_entry->string + best_split_offset, len2); - new_split[1]->string = combined; - new_split[1]->length = len1 + len2; + new_split[1] = entry_create (combined, len1 + len2); } return true; @@ -1242,7 +1257,8 @@ There is NO WARRANTY, to the extent permitted by law.\n\ result_entries_pointers[k], changed_entry); } - else + else if (!entry_equals (ancestor_file.entries[i], + changed_entry)) { struct conflict *c = XMALLOC (struct conflict); c->num_old_entries = 1; @@ -1322,7 +1338,10 @@ There is NO WARRANTY, to the extent permitted by law.\n\ } else { - struct conflict *c = XMALLOC (struct conflict); + struct conflict *c; + ASSERT (!entry_equals (ancestor_file.entries[i], + changed_entry)); + c = XMALLOC (struct conflict); c->num_old_entries = 1; c->old_entries = XNMALLOC (c->num_old_entries, struct entry *); @@ -1384,7 +1403,10 @@ There is NO WARRANTY, to the extent permitted by law.\n\ } else { - struct conflict *c = XMALLOC (struct conflict); + struct conflict *c; + ASSERT (!entry_equals (ancestor_file.entries[i], + changed_entry)); + c = XMALLOC (struct conflict); c->num_old_entries = 1; c->old_entries = XNMALLOC (c->num_old_entries, struct entry *); @@ -1490,11 +1512,14 @@ There is NO WARRANTY, to the extent permitted by law.\n\ for (i = 0; i < n; i++) conflict_write (fp, (struct conflict *) gl_list_get_at (result_conflicts, i)); } + /* Output the modified and unmodified entries, in order. */ { - size_t n = gl_list_size (result_entries); - size_t i; - for (i = 0; i < n; i++) - entry_write (fp, (struct entry *) gl_list_get_at (result_entries, i)); + gl_list_iterator_t iter = gl_list_iterator (result_entries); + const void *elt; + gl_list_node_t node; + while (gl_list_iterator_next (&iter, &elt, &node)) + entry_write (fp, (struct entry *) elt); + gl_list_iterator_free (&iter); } if (fwriteerror (fp))