]> mj.ucw.cz Git - libucw.git/blob - ucw/gary.c
Mainloop: Fixed +1 error in heap usage.
[libucw.git] / ucw / gary.c
1 /*
2  *      UCW Library -- A simple growing array of an arbitrary type
3  *
4  *      (c) 2010--2012 Martin Mares <mj@ucw.cz>
5  */
6
7 #undef LOCAL_DEBUG
8
9 #include <ucw/lib.h>
10 #include <ucw/gary.h>
11
12 #include <string.h>
13
14 void *
15 gary_init(size_t elt_size, size_t num_elts, int zeroed)
16 {
17   DBG("GARY: Init to %zd elements", num_elts);
18   struct gary_hdr *h = xmalloc(GARY_HDR_SIZE + elt_size * num_elts);
19   h->num_elts = h->have_space = num_elts;
20   h->elt_size = elt_size;
21   h->zeroed = zeroed;
22   if (zeroed)
23     bzero(GARY_BODY(h), elt_size * num_elts);
24   return GARY_BODY(h);
25 }
26
27 void
28 gary_free(void *array)
29 {
30   xfree(GARY_HDR(array));
31 }
32
33 static struct gary_hdr *
34 gary_realloc(struct gary_hdr *h, size_t n)
35 {
36   size_t old_size = h->have_space;
37   if (n > 2*h->have_space)
38     h->have_space = n;
39   else
40     h->have_space *= 2;
41   DBG("GARY: Resize from %zd to %zd elements (need %zd)", old_size, h->have_space, n);
42   h = xrealloc(h, GARY_HDR_SIZE + h->have_space * h->elt_size);
43   if (h->zeroed)
44     bzero(GARY_BODY(h) + h->elt_size * old_size, h->elt_size * (h->have_space - old_size));
45   return h;
46 }
47
48 void *
49 gary_set_size(void *array, size_t n)
50 {
51   struct gary_hdr *h = GARY_HDR(array);
52   h->num_elts = n;
53   if (n <= h->have_space)
54     return array;
55
56   h = gary_realloc(h, n);
57   return GARY_BODY(h);
58 }
59
60 void *
61 gary_push_helper(void *array, size_t n, byte **cptr)
62 {
63   struct gary_hdr *h = GARY_HDR(array);
64   h = gary_realloc(h, h->num_elts);
65   *cptr = GARY_BODY(h) + (h->num_elts - n) * h->elt_size;
66   return GARY_BODY(h);
67 }
68
69 void *
70 gary_fix(void *array)
71 {
72   struct gary_hdr *h = GARY_HDR(array);
73   if (h->num_elts != h->have_space)
74     {
75       h = xrealloc(h, GARY_HDR_SIZE + h->num_elts * h->elt_size);
76       h->have_space = h->num_elts;
77     }
78   return GARY_BODY(h);
79 }
80
81 #ifdef TEST
82
83 #include <stdio.h>
84
85 int main(void)
86 {
87   int *a;
88   GARY_INIT_ZERO(a, 5);
89
90   for (int i=0; i<5; i++)
91     {
92       ASSERT(!a[i]);
93       a[i] = i+1;
94     }
95
96   GARY_PUSH(a, 1);
97   *GARY_PUSH(a, 1) = 10;
98   *GARY_PUSH(a, 1) = 20;
99   *GARY_PUSH(a, 1) = 30;
100   GARY_POP(a, 1);
101   GARY_FIX(a);
102
103   for (int i=0; i<(int)GARY_SIZE(a); i++)
104     printf("%d\n", a[i]);
105
106   GARY_FREE(a);
107   return 0;
108 }
109
110 #endif