On 03/17/2014 07:33 AM, Junio C Hamano wrote: > Junio C Hamano <gitster@xxxxxxxxx> writes: > >> Would it make sense to go one step further to introduce two macros >> to make this kind of screw-up less likely? >> ... >> After letting my eyes coast over hits from "git grep memmove", there >> do seem to be some places that these would help readability, but not >> very many. > > I see quite a many hits that follow this pattern > > memmove(array + pos, array + pos + 1, sizeof(*array) * (nr - pos)) > > to make a single slot in a middle of array available, which would be > good candidates to use MOVE_DOWN(). Just to show a few: > > builtin/mv.c:226: memmove(source + i, source + i + 1, > builtin/mv.c-227- (argc - i) * sizeof(char *)); > builtin/mv.c:228: memmove(destination + i, > builtin/mv.c-229- destination + i + 1, > builtin/mv.c-230- (argc - i) * sizeof(char *)); > cache-tree.c:92: memmove(it->down + pos + 1, > cache-tree.c-93- it->down + pos, > cache-tree.c-94- sizeof(down) * (it->subtree_nr - pos - 1)); > > > Perhaps something like this patch to start off; I am not sure > MOVE_DOWN_BOUNDED is needed, though. > > cache.h | 33 +++++++++++++++++++++++++++++++++ > 1 file changed, 33 insertions(+) > > diff --git a/cache.h b/cache.h > index b66cb49..b2615ab 100644 > --- a/cache.h > +++ b/cache.h > @@ -455,6 +455,39 @@ extern int daemonize(void); > } \ > } while (0) > > +/* > + * With an array "array" that currently holds "nr" elements, move > + * elements at "at" and later down by "count" elements to make room to > + * add in new elements. The caller is responsible for making sure > + * that the array has enough room to hold "nr" + "count" slots. > + */ > +#define MOVE_DOWN(array, nr, at, count) \ > + memmove((array) + (at) + (count), \ > + (array) + (at), \ > + sizeof((array)[0]) * ((nr) - (at))) > + > +/* > + * With an array "array" that has enough memory to hold "alloc" > + * elements allocated and currently holds "nr" elements, move elements > + * at "at" and later down by "count" elements to make room to add in > + * new elements. > + */ > +#define MOVE_DOWN_BOUNDED(array, nr, at, count, alloc) \ > + do { \ > + if ((alloc) <= (nr) + (count)) \ > + BUG("MOVE_DOWN beyond the end of an array"); \ > + MOVE_DOWN((array), (nr), (at), (count)); \ > + } while (0) > + > +/* > + * With an array "array" that curently holds "nr" elements, move elements > + * at "at" + "count" and later down by "count" elements, removing the > + * elements between "at" and "at" + "count". > + */ > +#define MOVE_UP(array, nr, at, count) \ > + memmove((array) + (at), (array) + (at) + (count), \ > + sizeof((array)[0]) * ((nr) - ((at) + (count)))) > + > /* Initialize and use the cache information */ > extern int read_index(struct index_state *); > extern int read_index_preload(struct index_state *, const struct pathspec *pathspec); I had recently been thinking along the same lines. In many of the potential callers that I noticed, ALLOC_GROW() was used immediately before making space in the array for a new element. So I suggest something more like +#define MOVE_DOWN(array, nr, at, count) \ + memmove((array) + (at) + (count), \ + (array) + (at), \ + sizeof((array)[0]) * ((nr) - (at))) +#define ALLOC_INSERT_GAP(array, nr, at, count, alloc) \ + do { \ + ALLOC_GROW((array), (nr) + (count), (alloc)); \ + MOVE_DOWN((array), (nr), (at), (count)); \ + } while (0) Also, count==1 is so frequent that this special case might deserve its own macro pair. I'm not inspired by these macro names, though. Michael -- Michael Haggerty mhagger@xxxxxxxxxxxx http://softwareswirl.blogspot.com/ -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html