pack-objects.con commit Merge branch 'jk/avoid-unbounded-alloca' into maint (1f5d429)
   1#include "cache.h"
   2#include "object.h"
   3#include "pack.h"
   4#include "pack-objects.h"
   5
   6static uint32_t locate_object_entry_hash(struct packing_data *pdata,
   7                                         const unsigned char *sha1,
   8                                         int *found)
   9{
  10        uint32_t i, mask = (pdata->index_size - 1);
  11
  12        i = sha1hash(sha1) & mask;
  13
  14        while (pdata->index[i] > 0) {
  15                uint32_t pos = pdata->index[i] - 1;
  16
  17                if (!hashcmp(sha1, pdata->objects[pos].idx.sha1)) {
  18                        *found = 1;
  19                        return i;
  20                }
  21
  22                i = (i + 1) & mask;
  23        }
  24
  25        *found = 0;
  26        return i;
  27}
  28
  29static inline uint32_t closest_pow2(uint32_t v)
  30{
  31        v = v - 1;
  32        v |= v >> 1;
  33        v |= v >> 2;
  34        v |= v >> 4;
  35        v |= v >> 8;
  36        v |= v >> 16;
  37        return v + 1;
  38}
  39
  40static void rehash_objects(struct packing_data *pdata)
  41{
  42        uint32_t i;
  43        struct object_entry *entry;
  44
  45        pdata->index_size = closest_pow2(pdata->nr_objects * 3);
  46        if (pdata->index_size < 1024)
  47                pdata->index_size = 1024;
  48
  49        free(pdata->index);
  50        pdata->index = xcalloc(pdata->index_size, sizeof(*pdata->index));
  51
  52        entry = pdata->objects;
  53
  54        for (i = 0; i < pdata->nr_objects; i++) {
  55                int found;
  56                uint32_t ix = locate_object_entry_hash(pdata, entry->idx.sha1, &found);
  57
  58                if (found)
  59                        die("BUG: Duplicate object in hash");
  60
  61                pdata->index[ix] = i + 1;
  62                entry++;
  63        }
  64}
  65
  66struct object_entry *packlist_find(struct packing_data *pdata,
  67                                   const unsigned char *sha1,
  68                                   uint32_t *index_pos)
  69{
  70        uint32_t i;
  71        int found;
  72
  73        if (!pdata->index_size)
  74                return NULL;
  75
  76        i = locate_object_entry_hash(pdata, sha1, &found);
  77
  78        if (index_pos)
  79                *index_pos = i;
  80
  81        if (!found)
  82                return NULL;
  83
  84        return &pdata->objects[pdata->index[i] - 1];
  85}
  86
  87struct object_entry *packlist_alloc(struct packing_data *pdata,
  88                                    const unsigned char *sha1,
  89                                    uint32_t index_pos)
  90{
  91        struct object_entry *new_entry;
  92
  93        if (pdata->nr_objects >= pdata->nr_alloc) {
  94                pdata->nr_alloc = (pdata->nr_alloc  + 1024) * 3 / 2;
  95                REALLOC_ARRAY(pdata->objects, pdata->nr_alloc);
  96        }
  97
  98        new_entry = pdata->objects + pdata->nr_objects++;
  99
 100        memset(new_entry, 0, sizeof(*new_entry));
 101        hashcpy(new_entry->idx.sha1, sha1);
 102
 103        if (pdata->index_size * 3 <= pdata->nr_objects * 4)
 104                rehash_objects(pdata);
 105        else
 106                pdata->index[index_pos] = pdata->nr_objects;
 107
 108        return new_entry;
 109}