1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 
11 
12 ngx_array_t *
ngx_array_create(ngx_pool_t * p,ngx_uint_t n,size_t size)13 ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size)
14 {
15     ngx_array_t *a;
16 
17     a = ngx_palloc(p, sizeof(ngx_array_t));
18     if (a == NULL) {
19         return NULL;
20     }
21 
22     if (ngx_array_init(a, p, n, size) != NGX_OK) {
23         return NULL;
24     }
25 
26     return a;
27 }
28 
29 
30 void
ngx_array_destroy(ngx_array_t * a)31 ngx_array_destroy(ngx_array_t *a)
32 {
33     ngx_pool_t  *p;
34 
35     p = a->pool;
36 
37     if ((u_char *) a->elts + a->size * a->nalloc == p->d.last) {
38         p->d.last -= a->size * a->nalloc;
39     }
40 
41     if ((u_char *) a + sizeof(ngx_array_t) == p->d.last) {
42         p->d.last = (u_char *) a;
43     }
44 }
45 
46 
47 void *
ngx_array_push(ngx_array_t * a)48 ngx_array_push(ngx_array_t *a)
49 {
50     void        *elt, *new;
51     size_t       size;
52     ngx_pool_t  *p;
53 
54     if (a->nelts == a->nalloc) {
55 
56         /* the array is full */
57 
58         size = a->size * a->nalloc;
59 
60         p = a->pool;
61 
62         if ((u_char *) a->elts + size == p->d.last
63             && p->d.last + a->size <= p->d.end)
64         {
65             /*
66              * the array allocation is the last in the pool
67              * and there is space for new allocation
68              */
69 
70             p->d.last += a->size;
71             a->nalloc++;
72 
73         } else {
74             /* allocate a new array */
75 
76             new = ngx_palloc(p, 2 * size);
77             if (new == NULL) {
78                 return NULL;
79             }
80 
81             ngx_memcpy(new, a->elts, size);
82             a->elts = new;
83             a->nalloc *= 2;
84         }
85     }
86 
87     elt = (u_char *) a->elts + a->size * a->nelts;
88     a->nelts++;
89 
90     return elt;
91 }
92 
93 
94 void *
ngx_array_push_n(ngx_array_t * a,ngx_uint_t n)95 ngx_array_push_n(ngx_array_t *a, ngx_uint_t n)
96 {
97     void        *elt, *new;
98     size_t       size;
99     ngx_uint_t   nalloc;
100     ngx_pool_t  *p;
101 
102     size = n * a->size;
103 
104     if (a->nelts + n > a->nalloc) {
105 
106         /* the array is full */
107 
108         p = a->pool;
109 
110         if ((u_char *) a->elts + a->size * a->nalloc == p->d.last
111             && p->d.last + size <= p->d.end)
112         {
113             /*
114              * the array allocation is the last in the pool
115              * and there is space for new allocation
116              */
117 
118             p->d.last += size;
119             a->nalloc += n;
120 
121         } else {
122             /* allocate a new array */
123 
124             nalloc = 2 * ((n >= a->nalloc) ? n : a->nalloc);
125 
126             new = ngx_palloc(p, nalloc * a->size);
127             if (new == NULL) {
128                 return NULL;
129             }
130 
131             ngx_memcpy(new, a->elts, a->nelts * a->size);
132             a->elts = new;
133             a->nalloc = nalloc;
134         }
135     }
136 
137     elt = (u_char *) a->elts + a->size * a->nelts;
138     a->nelts += n;
139 
140     return elt;
141 }
142