Introduce a new macro ALLOC_GROW_BY which automatically zeros the added
array elements and takes care of updating the nr value. Use the macro in
code introduced earlier in this patchset.

Signed-off-by: Matthew DeVore <matv...@google.com>
---
 cache.h                       | 22 ++++++++++++++++++++++
 list-objects-filter-options.c | 17 +++++++----------
 2 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/cache.h b/cache.h
index fa8ede9a2d..847fbdeff0 100644
--- a/cache.h
+++ b/cache.h
@@ -652,33 +652,55 @@ int init_db(const char *git_dir, const char *real_git_dir,
 void sanitize_stdfds(void);
 int daemonize(void);
 
 #define alloc_nr(x) (((x)+16)*3/2)
 
 /*
  * Realloc the buffer pointed at by variable 'x' so that it can hold
  * at least 'nr' entries; the number of entries currently allocated
  * is 'alloc', using the standard growing factor alloc_nr() macro.
  *
+ * Consider using ALLOC_GROW_BY instead of ALLOC_GROW as it has some
+ * added niceties.
+ *
  * DO NOT USE any expression with side-effect for 'x', 'nr', or 'alloc'.
  */
 #define ALLOC_GROW(x, nr, alloc) \
        do { \
                if ((nr) > alloc) { \
                        if (alloc_nr(alloc) < (nr)) \
                                alloc = (nr); \
                        else \
                                alloc = alloc_nr(alloc); \
                        REALLOC_ARRAY(x, alloc); \
                } \
        } while (0)
 
+/*
+ * Similar to ALLOC_GROW but handles updating of the nr value and
+ * zeroing the bytes of the newly-grown array elements.
+ *
+ * DO NOT USE any expression with side-effect for any of the
+ * arguments.
+ */
+#define ALLOC_GROW_BY(x, nr, increase, alloc) \
+       do { \
+               if (increase) { \
+                       size_t new_nr = nr + (increase); \
+                       if (new_nr < nr) \
+                               BUG("negative growth in ALLOC_GROW_BY"); \
+                       ALLOC_GROW(x, new_nr, alloc); \
+                       memset((x) + nr, 0, sizeof(*(x)) * (increase)); \
+                       nr = new_nr; \
+               } \
+       } while (0)
+
 /* Initialize and use the cache information */
 struct lock_file;
 void preload_index(struct index_state *index,
                   const struct pathspec *pathspec,
                   unsigned int refresh_flags);
 int do_read_index(struct index_state *istate, const char *path,
                  int must_exist); /* for testting only! */
 int read_index_from(struct index_state *, const char *path,
                    const char *gitdir);
 int is_index_unborn(struct index_state *);
diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c
index 5e98e4a309..d8abe6cfcf 100644
--- a/list-objects-filter-options.c
+++ b/list-objects-filter-options.c
@@ -142,26 +142,24 @@ static int has_reserved_character(
        }
 
        return 0;
 }
 
 static int parse_combine_subfilter(
        struct list_objects_filter_options *filter_options,
        struct strbuf *subspec,
        struct strbuf *errbuf)
 {
-       size_t new_index = filter_options->sub_nr++;
+       size_t new_index = filter_options->sub_nr;
 
-       ALLOC_GROW(filter_options->sub, filter_options->sub_nr,
-                  filter_options->sub_alloc);
-       memset(&filter_options->sub[new_index], 0,
-              sizeof(*filter_options->sub));
+       ALLOC_GROW_BY(filter_options->sub, filter_options->sub_nr, 1,
+                     filter_options->sub_alloc);
 
        return has_reserved_character(subspec, errbuf) ||
                url_decode(subspec, errbuf) ||
                gently_parse_list_objects_filter(
                        &filter_options->sub[new_index], subspec->buf, errbuf);
 }
 
 static int parse_combine_filter(
        struct list_objects_filter_options *filter_options,
        const char *arg,
@@ -273,27 +271,26 @@ int parse_list_objects_filter(
                /*
                 * Make filter_options an LOFC_COMBINE spec so we can trivially
                 * add subspecs to it.
                 */
                transform_to_combine_type(filter_options);
 
                strbuf_addstr(&filter_options->filter_spec, "+");
                add_url_encoded(&filter_options->filter_spec, arg);
                trace_printf("Generated composite filter-spec: %s\n",
                             filter_options->filter_spec.buf);
-               ALLOC_GROW(filter_options->sub, filter_options->sub_nr + 1,
-                          filter_options->sub_alloc);
-               filter_options = &filter_options->sub[filter_options->sub_nr++];
-               memset(filter_options, 0, sizeof(*filter_options));
+               ALLOC_GROW_BY(filter_options->sub, filter_options->sub_nr, 1,
+                             filter_options->sub_alloc);
 
                parse_error = gently_parse_list_objects_filter(
-                       filter_options, arg, &errbuf);
+                       &filter_options->sub[filter_options->sub_nr - 1], arg,
+                       &errbuf);
        }
        if (parse_error)
                die("%s", errbuf.buf);
        return 0;
 }
 
 int opt_parse_list_objects_filter(const struct option *opt,
                                  const char *arg, int unset)
 {
        struct list_objects_filter_options *filter_options = opt->value;
-- 
2.17.1

Reply via email to