Merge branch 'mh/reflife'
Define memory ownership and lifetime rules for what for-each-ref feeds to its callbacks (in short, "you do not own it, so make a copy if you want to keep it"). * mh/reflife: (25 commits) refs: document the lifetime of the args passed to each_ref_fn register_ref(): make a copy of the bad reference SHA-1 exclude_existing(): set existing_refs.strdup_strings string_list_add_refs_by_glob(): add a comment about memory management string_list_add_one_ref(): rename first parameter to "refname" show_head_ref(): rename first parameter to "refname" show_head_ref(): do not shadow name of argument add_existing(): do not retain a reference to sha1 do_fetch(): clean up existing_refs before exiting do_fetch(): reduce scope of peer_item object_array_entry: fix memory handling of the name field find_first_merges(): remove unnecessary code find_first_merges(): initialize merges variable using initializer fsck: don't put a void*-shaped peg in a char*-shaped hole object_array_remove_duplicates(): rewrite to reduce copying revision: use object_array_filter() in implementation of gc_boundary() object_array: add function object_array_filter() revision: split some overly-long lines cmd_diff(): make it obvious which cases are exclusive of each other cmd_diff(): rename local variable "list" -> "entry" ...
This commit is contained in:
74
object.c
74
object.c
@ -270,11 +270,18 @@ void add_object_array(struct object *obj, const char *name, struct object_array
|
||||
add_object_array_with_mode(obj, name, array, S_IFINVALID);
|
||||
}
|
||||
|
||||
/*
|
||||
* A zero-length string to which object_array_entry::name can be
|
||||
* initialized without requiring a malloc/free.
|
||||
*/
|
||||
static char object_array_slopbuf[1];
|
||||
|
||||
void add_object_array_with_mode(struct object *obj, const char *name, struct object_array *array, unsigned mode)
|
||||
{
|
||||
unsigned nr = array->nr;
|
||||
unsigned alloc = array->alloc;
|
||||
struct object_array_entry *objects = array->objects;
|
||||
struct object_array_entry *entry;
|
||||
|
||||
if (nr >= alloc) {
|
||||
alloc = (alloc + 32) * 2;
|
||||
@ -282,28 +289,67 @@ void add_object_array_with_mode(struct object *obj, const char *name, struct obj
|
||||
array->alloc = alloc;
|
||||
array->objects = objects;
|
||||
}
|
||||
objects[nr].item = obj;
|
||||
objects[nr].name = name;
|
||||
objects[nr].mode = mode;
|
||||
entry = &objects[nr];
|
||||
entry->item = obj;
|
||||
if (!name)
|
||||
entry->name = NULL;
|
||||
else if (!*name)
|
||||
/* Use our own empty string instead of allocating one: */
|
||||
entry->name = object_array_slopbuf;
|
||||
else
|
||||
entry->name = xstrdup(name);
|
||||
entry->mode = mode;
|
||||
array->nr = ++nr;
|
||||
}
|
||||
|
||||
void object_array_filter(struct object_array *array,
|
||||
object_array_each_func_t want, void *cb_data)
|
||||
{
|
||||
unsigned nr = array->nr, src, dst;
|
||||
struct object_array_entry *objects = array->objects;
|
||||
|
||||
for (src = dst = 0; src < nr; src++) {
|
||||
if (want(&objects[src], cb_data)) {
|
||||
if (src != dst)
|
||||
objects[dst] = objects[src];
|
||||
dst++;
|
||||
} else {
|
||||
if (objects[src].name != object_array_slopbuf)
|
||||
free(objects[src].name);
|
||||
}
|
||||
}
|
||||
array->nr = dst;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true iff array already contains an entry with name.
|
||||
*/
|
||||
static int contains_name(struct object_array *array, const char *name)
|
||||
{
|
||||
unsigned nr = array->nr, i;
|
||||
struct object_array_entry *object = array->objects;
|
||||
|
||||
for (i = 0; i < nr; i++, object++)
|
||||
if (!strcmp(object->name, name))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void object_array_remove_duplicates(struct object_array *array)
|
||||
{
|
||||
unsigned int ref, src, dst;
|
||||
unsigned nr = array->nr, src;
|
||||
struct object_array_entry *objects = array->objects;
|
||||
|
||||
for (ref = 0; ref + 1 < array->nr; ref++) {
|
||||
for (src = ref + 1, dst = src;
|
||||
src < array->nr;
|
||||
src++) {
|
||||
if (!strcmp(objects[ref].name, objects[src].name))
|
||||
continue;
|
||||
if (src != dst)
|
||||
objects[dst] = objects[src];
|
||||
dst++;
|
||||
array->nr = 0;
|
||||
for (src = 0; src < nr; src++) {
|
||||
if (!contains_name(array, objects[src].name)) {
|
||||
if (src != array->nr)
|
||||
objects[array->nr] = objects[src];
|
||||
array->nr++;
|
||||
} else {
|
||||
if (objects[src].name != object_array_slopbuf)
|
||||
free(objects[src].name);
|
||||
}
|
||||
array->nr = dst;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user