1 /*
2 * Copyright (C) 2009 Citrix Ltd.
3 * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published
7 * by the Free Software Foundation; version 2.1 only. with the special
8 * exception on linking described in file LICENSE.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 */
15
16 #include "libxl_internal.h"
17 #include <stdarg.h>
18
19 /*
20 * It is safe to store gc in the struct because:
21 * - If it an actual gc, then the flexarray should not be used after the gc
22 * have been freed.
23 * - If it is a NOGC, then this point to a structure embedded in libxl_ctx,
24 * therefore will survive across several libxl calls.
25 */
26
flexarray_make(libxl__gc * gc,int size,int autogrow)27 flexarray_t *flexarray_make(libxl__gc *gc, int size, int autogrow)
28 {
29 flexarray_t *array;
30
31 GCNEW(array);
32 array->size = size;
33 array->autogrow = autogrow;
34 array->count = 0;
35 array->gc = gc;
36 GCNEW_ARRAY(array->data, size);
37
38 return array;
39 }
40
flexarray_free(flexarray_t * array)41 void flexarray_free(flexarray_t *array)
42 {
43 assert(!libxl__gc_is_real(array->gc));
44 free(array->data);
45 free(array);
46 }
47
flexarray_grow(flexarray_t * array,int extents)48 void flexarray_grow(flexarray_t *array, int extents)
49 {
50 int newsize;
51 libxl__gc *gc = array->gc;
52
53 newsize = array->size + extents;
54 GCREALLOC_ARRAY(array->data, newsize);
55 array->size += extents;
56 }
57
flexarray_set(flexarray_t * array,unsigned int idx,void * ptr)58 int flexarray_set(flexarray_t *array, unsigned int idx, void *ptr)
59 {
60 if (idx >= array->size) {
61 int newsize;
62 if (!array->autogrow)
63 return 1;
64 newsize = (array->size * 2 < idx) ? idx + 1 : array->size * 2;
65 flexarray_grow(array, newsize - array->size);
66 }
67 if ( idx + 1 > array->count )
68 array->count = idx + 1;
69 array->data[idx] = ptr;
70 return 0;
71 }
72
flexarray_append(flexarray_t * array,void * ptr)73 int flexarray_append(flexarray_t *array, void *ptr)
74 {
75 return flexarray_set(array, array->count, ptr);
76 }
77
flexarray_append_pair(flexarray_t * array,void * ptr1,void * ptr2)78 int flexarray_append_pair(flexarray_t *array, void *ptr1, void *ptr2)
79 {
80 int rc = flexarray_append(array, ptr1);
81 if (!rc)
82 rc = flexarray_append(array, ptr2);
83 return rc;
84 }
85
flexarray_vappend(flexarray_t * array,...)86 int flexarray_vappend(flexarray_t *array, ...)
87 {
88 va_list va;
89 void *ptr;
90 int ret;
91
92 va_start(va, array);
93 for(ret = 0; (ptr = va_arg(va, void *)); ret++) {
94 if ( flexarray_append(array, ptr) )
95 break;
96 }
97 va_end(va);
98 return ret;
99 }
100
flexarray_get(flexarray_t * array,int idx,void ** ptr)101 int flexarray_get(flexarray_t *array, int idx, void **ptr)
102 {
103 if (idx >= array->size)
104 return 1;
105 *ptr = array->data[idx];
106 return 0;
107 }
108
flexarray_contents(flexarray_t * array)109 void **flexarray_contents(flexarray_t *array)
110 {
111 void **data;
112 data = array->data;
113 if (!libxl__gc_is_real(array->gc))
114 free(array);
115 return data;
116 }
117
118 /*
119 * Local variables:
120 * mode: C
121 * c-basic-offset: 4
122 * indent-tabs-mode: nil
123 * End:
124 */
125