commit-slab-impl.hon commit tree-walk: add a strbuf wrapper for make_traverse_path() (c43ab06)
   1#ifndef COMMIT_SLAB_IMPL_H
   2#define COMMIT_SLAB_IMPL_H
   3
   4#include "git-compat-util.h"
   5
   6#define implement_static_commit_slab(slabname, elemtype) \
   7        implement_commit_slab(slabname, elemtype, MAYBE_UNUSED static)
   8
   9#define implement_shared_commit_slab(slabname, elemtype) \
  10        implement_commit_slab(slabname, elemtype, )
  11
  12#define implement_commit_slab(slabname, elemtype, scope)                \
  13                                                                        \
  14scope void init_ ##slabname## _with_stride(struct slabname *s,          \
  15                                                   unsigned stride)     \
  16{                                                                       \
  17        unsigned int elem_size;                                         \
  18        if (!stride)                                                    \
  19                stride = 1;                                             \
  20        s->stride = stride;                                             \
  21        elem_size = sizeof(elemtype) * stride;                          \
  22        s->slab_size = COMMIT_SLAB_SIZE / elem_size;                    \
  23        s->slab_count = 0;                                              \
  24        s->slab = NULL;                                                 \
  25}                                                                       \
  26                                                                        \
  27scope void init_ ##slabname(struct slabname *s)                         \
  28{                                                                       \
  29        init_ ##slabname## _with_stride(s, 1);                          \
  30}                                                                       \
  31                                                                        \
  32scope void clear_ ##slabname(struct slabname *s)                        \
  33{                                                                       \
  34        unsigned int i;                                                 \
  35        for (i = 0; i < s->slab_count; i++)                             \
  36                free(s->slab[i]);                                       \
  37        s->slab_count = 0;                                              \
  38        FREE_AND_NULL(s->slab);                                         \
  39}                                                                       \
  40                                                                        \
  41scope elemtype *slabname## _at_peek(struct slabname *s,                 \
  42                                                  const struct commit *c, \
  43                                                  int add_if_missing)   \
  44{                                                                       \
  45        unsigned int nth_slab, nth_slot;                                \
  46                                                                        \
  47        nth_slab = c->index / s->slab_size;                             \
  48        nth_slot = c->index % s->slab_size;                             \
  49                                                                        \
  50        if (s->slab_count <= nth_slab) {                                \
  51                unsigned int i;                                         \
  52                if (!add_if_missing)                                    \
  53                        return NULL;                                    \
  54                REALLOC_ARRAY(s->slab, nth_slab + 1);                   \
  55                for (i = s->slab_count; i <= nth_slab; i++)             \
  56                        s->slab[i] = NULL;                              \
  57                s->slab_count = nth_slab + 1;                           \
  58        }                                                               \
  59        if (!s->slab[nth_slab]) {                                       \
  60                if (!add_if_missing)                                    \
  61                        return NULL;                                    \
  62                s->slab[nth_slab] = xcalloc(s->slab_size,               \
  63                                            sizeof(**s->slab) * s->stride);             \
  64        }                                                               \
  65        return &s->slab[nth_slab][nth_slot * s->stride];                \
  66}                                                                       \
  67                                                                        \
  68scope elemtype *slabname## _at(struct slabname *s,                      \
  69                                             const struct commit *c)    \
  70{                                                                       \
  71        return slabname##_at_peek(s, c, 1);                             \
  72}                                                                       \
  73                                                                        \
  74scope elemtype *slabname## _peek(struct slabname *s,                    \
  75                                             const struct commit *c)    \
  76{                                                                       \
  77        return slabname##_at_peek(s, c, 0);                             \
  78}                                                                       \
  79                                                                        \
  80struct slabname
  81
  82/*
  83 * Note that this redundant forward declaration is required
  84 * to allow a terminating semicolon, which makes instantiations look
  85 * like function declarations.  I.e., the expansion of
  86 *
  87 *    implement_commit_slab(indegree, int, static);
  88 *
  89 * ends in 'struct indegree;'.  This would otherwise
  90 * be a syntax error according (at least) to ISO C.  It's hard to
  91 * catch because GCC silently parses it by default.
  92 */
  93
  94#endif  /* COMMIT_SLAB_IMPL_H */