Rev 1892 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1892 | Rev 3959 | ||
---|---|---|---|
Line -... | Line 1... | ||
- | 1 | /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ |
|
1 | /* cairo - a vector graphics library with display and print output |
2 | /* cairo - a vector graphics library with display and print output |
2 | * |
3 | * |
3 | * Copyright © 2004 Red Hat, Inc |
4 | * Copyright © 2004 Red Hat, Inc |
4 | * |
5 | * |
5 | * This library is free software; you can redistribute it and/or |
6 | * This library is free software; you can redistribute it and/or |
Line 34... | Line 35... | ||
34 | * Kristian Høgsberg |
35 | * Kristian Høgsberg |
35 | * Carl Worth |
36 | * Carl Worth |
36 | */ |
37 | */ |
Line 37... | Line 38... | ||
37 | 38 | ||
- | 39 | #include "cairoint.h" |
|
38 | #include "cairoint.h" |
40 | #include "cairo-array-private.h" |
Line 39... | Line 41... | ||
39 | #include "cairo-error-private.h" |
41 | #include "cairo-error-private.h" |
40 | 42 | ||
41 | /** |
43 | /** |
Line 51... | Line 53... | ||
51 | * |
53 | * |
52 | * When finished using the array, _cairo_array_fini() should be |
54 | * When finished using the array, _cairo_array_fini() should be |
53 | * called to free resources allocated during use of the array. |
55 | * called to free resources allocated during use of the array. |
54 | **/ |
56 | **/ |
55 | void |
57 | void |
56 | _cairo_array_init (cairo_array_t *array, int element_size) |
58 | _cairo_array_init (cairo_array_t *array, unsigned int element_size) |
57 | { |
59 | { |
58 | array->size = 0; |
60 | array->size = 0; |
59 | array->num_elements = 0; |
61 | array->num_elements = 0; |
60 | array->element_size = element_size; |
62 | array->element_size = element_size; |
61 | array->elements = NULL; |
63 | array->elements = NULL; |
62 | - | ||
63 | array->is_snapshot = FALSE; |
- | |
64 | } |
- | |
65 | - | ||
66 | /** |
- | |
67 | * _cairo_array_init_snapshot: |
- | |
68 | * @array: A #cairo_array_t to be initialized as a snapshot |
- | |
69 | * @other: The #cairo_array_t from which to create the snapshot |
- | |
70 | * |
- | |
71 | * Initialize @array as an immutable copy of @other. It is an error to |
- | |
72 | * call an array-modifying function (other than _cairo_array_fini) on |
- | |
73 | * @array after calling this function. |
- | |
74 | **/ |
- | |
75 | void |
- | |
76 | _cairo_array_init_snapshot (cairo_array_t *array, |
- | |
77 | const cairo_array_t *other) |
- | |
78 | { |
- | |
79 | array->size = other->size; |
- | |
80 | array->num_elements = other->num_elements; |
- | |
81 | array->element_size = other->element_size; |
- | |
82 | array->elements = other->elements; |
- | |
83 | - | ||
84 | array->is_snapshot = TRUE; |
- | |
85 | } |
64 | } |
Line 86... | Line 65... | ||
86 | 65 | ||
87 | /** |
66 | /** |
88 | * _cairo_array_fini: |
67 | * _cairo_array_fini: |
Line 93... | Line 72... | ||
93 | * _cairo_array_init() again first. |
72 | * _cairo_array_init() again first. |
94 | **/ |
73 | **/ |
95 | void |
74 | void |
96 | _cairo_array_fini (cairo_array_t *array) |
75 | _cairo_array_fini (cairo_array_t *array) |
97 | { |
76 | { |
98 | if (array->is_snapshot) |
- | |
99 | return; |
- | |
100 | - | ||
101 | if (array->elements) { |
- | |
102 | free (* array->elements); |
- | |
103 | free (array->elements); |
77 | free (array->elements); |
104 | } |
78 | } |
105 | } |
- | |
Line 106... | Line 79... | ||
106 | 79 | ||
107 | /** |
80 | /** |
108 | * _cairo_array_grow_by: |
81 | * _cairo_array_grow_by: |
109 | * @array: a #cairo_array_t |
82 | * @array: a #cairo_array_t |
Line 118... | Line 91... | ||
118 | char *new_elements; |
91 | char *new_elements; |
119 | unsigned int old_size = array->size; |
92 | unsigned int old_size = array->size; |
120 | unsigned int required_size = array->num_elements + additional; |
93 | unsigned int required_size = array->num_elements + additional; |
121 | unsigned int new_size; |
94 | unsigned int new_size; |
Line 122... | Line -... | ||
122 | - | ||
123 | assert (! array->is_snapshot); |
- | |
124 | 95 | ||
125 | /* check for integer overflow */ |
96 | /* check for integer overflow */ |
126 | if (required_size > INT_MAX || required_size < array->num_elements) |
97 | if (required_size > INT_MAX || required_size < array->num_elements) |
Line 127... | Line 98... | ||
127 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
98 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
Line 138... | Line 109... | ||
138 | new_size = old_size * 2; |
109 | new_size = old_size * 2; |
Line 139... | Line 110... | ||
139 | 110 | ||
140 | while (new_size < required_size) |
111 | while (new_size < required_size) |
Line 141... | Line -... | ||
141 | new_size = new_size * 2; |
- | |
142 | - | ||
143 | if (array->elements == NULL) { |
- | |
144 | array->elements = malloc (sizeof (char *)); |
- | |
145 | if (unlikely (array->elements == NULL)) |
- | |
146 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
147 | - | ||
148 | *array->elements = NULL; |
- | |
149 | } |
112 | new_size = new_size * 2; |
150 | 113 | ||
151 | array->size = new_size; |
114 | array->size = new_size; |
Line 152... | Line 115... | ||
152 | new_elements = _cairo_realloc_ab (*array->elements, |
115 | new_elements = _cairo_realloc_ab (array->elements, |
153 | array->size, array->element_size); |
116 | array->size, array->element_size); |
154 | 117 | ||
155 | if (unlikely (new_elements == NULL)) { |
118 | if (unlikely (new_elements == NULL)) { |
Line 156... | Line 119... | ||
156 | array->size = old_size; |
119 | array->size = old_size; |
Line 157... | Line 120... | ||
157 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
120 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
158 | } |
121 | } |
Line 159... | Line 122... | ||
159 | 122 | ||
Line 171... | Line 134... | ||
171 | * beyond @num_elements are simply "forgotten". |
134 | * beyond @num_elements are simply "forgotten". |
172 | **/ |
135 | **/ |
173 | void |
136 | void |
174 | _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements) |
137 | _cairo_array_truncate (cairo_array_t *array, unsigned int num_elements) |
175 | { |
138 | { |
176 | assert (! array->is_snapshot); |
- | |
177 | - | ||
178 | if (num_elements < array->num_elements) |
139 | if (num_elements < array->num_elements) |
179 | array->num_elements = num_elements; |
140 | array->num_elements = num_elements; |
180 | } |
141 | } |
Line 181... | Line 142... | ||
181 | 142 | ||
Line 205... | Line 166... | ||
205 | _cairo_array_index (cairo_array_t *array, unsigned int index) |
166 | _cairo_array_index (cairo_array_t *array, unsigned int index) |
206 | { |
167 | { |
207 | /* We allow an index of 0 for the no-elements case. |
168 | /* We allow an index of 0 for the no-elements case. |
208 | * This makes for cleaner calling code which will often look like: |
169 | * This makes for cleaner calling code which will often look like: |
209 | * |
170 | * |
210 | * elements = _cairo_array_index (array, num_elements); |
171 | * elements = _cairo_array_index (array, 0); |
211 | * for (i=0; i < num_elements; i++) { |
172 | * for (i=0; i < num_elements; i++) { |
212 | * ... use elements[i] here ... |
173 | * ... use elements[i] here ... |
213 | * } |
174 | * } |
214 | * |
175 | * |
215 | * which in the num_elements==0 case gets the NULL pointer here, |
176 | * which in the num_elements==0 case gets the NULL pointer here, |
Line 218... | Line 179... | ||
218 | if (index == 0 && array->num_elements == 0) |
179 | if (index == 0 && array->num_elements == 0) |
219 | return NULL; |
180 | return NULL; |
Line 220... | Line 181... | ||
220 | 181 | ||
Line -... | Line 182... | ||
- | 182 | assert (index < array->num_elements); |
|
- | 183 | ||
- | 184 | return array->elements + index * array->element_size; |
|
- | 185 | } |
|
- | 186 | ||
- | 187 | /** |
|
- | 188 | * _cairo_array_index_const: |
|
- | 189 | * @array: a #cairo_array_t |
|
- | 190 | * Returns: A pointer to the object stored at @index. |
|
- | 191 | * |
|
- | 192 | * If the resulting value is assigned to a pointer to an object of the same |
|
- | 193 | * element_size as initially passed to _cairo_array_init() then that |
|
- | 194 | * pointer may be used for further direct indexing with []. For |
|
- | 195 | * example: |
|
- | 196 | * |
|
- | 197 | * |
|
- | 198 | * cairo_array_t array; |
|
- | 199 | * const double *values; |
|
- | 200 | * |
|
- | 201 | * _cairo_array_init (&array, sizeof(double)); |
|
- | 202 | * ... calls to _cairo_array_append() here ... |
|
- | 203 | * |
|
- | 204 | * values = _cairo_array_index_const (&array, 0); |
|
- | 205 | * for (i = 0; i < _cairo_array_num_elements (&array); i++) |
|
- | 206 | * ... read values[i] here ... |
|
- | 207 | * |
|
- | 208 | **/ |
|
- | 209 | const void * |
|
- | 210 | _cairo_array_index_const (const cairo_array_t *array, unsigned int index) |
|
- | 211 | { |
|
- | 212 | /* We allow an index of 0 for the no-elements case. |
|
- | 213 | * This makes for cleaner calling code which will often look like: |
|
- | 214 | * |
|
- | 215 | * elements = _cairo_array_index_const (array, 0); |
|
- | 216 | * for (i=0; i < num_elements; i++) { |
|
- | 217 | * ... read elements[i] here ... |
|
- | 218 | * } |
|
- | 219 | * |
|
- | 220 | * which in the num_elements==0 case gets the NULL pointer here, |
|
- | 221 | * but never dereferences it. |
|
- | 222 | */ |
|
- | 223 | if (index == 0 && array->num_elements == 0) |
|
- | 224 | return NULL; |
|
- | 225 | ||
221 | assert (index < array->num_elements); |
226 | assert (index < array->num_elements); |
222 | 227 | ||
Line 223... | Line 228... | ||
223 | return (void *) &(*array->elements)[index * array->element_size]; |
228 | return array->elements + index * array->element_size; |
224 | } |
229 | } |
225 | 230 | ||
226 | /** |
231 | /** |
227 | * _cairo_array_copy_element: |
232 | * _cairo_array_copy_element: |
228 | * @array: a #cairo_array_t |
233 | * @array: a #cairo_array_t |
229 | * |
234 | * |
230 | * Copy a single element out of the array from index @index into the |
235 | * Copy a single element out of the array from index @index into the |
231 | * location pointed to by @dst. |
236 | * location pointed to by @dst. |
- | 237 | **/ |
|
- | 238 | void |
|
232 | **/ |
239 | _cairo_array_copy_element (const cairo_array_t *array, |
233 | void |
240 | unsigned int index, |
234 | _cairo_array_copy_element (cairo_array_t *array, int index, void *dst) |
241 | void *dst) |
Line 235... | Line 242... | ||
235 | { |
242 | { |
236 | memcpy (dst, _cairo_array_index (array, index), array->element_size); |
243 | memcpy (dst, _cairo_array_index_const (array, index), array->element_size); |
237 | } |
244 | } |
Line 253... | Line 260... | ||
253 | **/ |
260 | **/ |
254 | cairo_status_t |
261 | cairo_status_t |
255 | _cairo_array_append (cairo_array_t *array, |
262 | _cairo_array_append (cairo_array_t *array, |
256 | const void *element) |
263 | const void *element) |
257 | { |
264 | { |
258 | assert (! array->is_snapshot); |
- | |
259 | - | ||
260 | return _cairo_array_append_multiple (array, element, 1); |
265 | return _cairo_array_append_multiple (array, element, 1); |
261 | } |
266 | } |
Line 262... | Line 267... | ||
262 | 267 | ||
263 | /** |
268 | /** |
Line 273... | Line 278... | ||
273 | * operation. |
278 | * operation. |
274 | **/ |
279 | **/ |
275 | cairo_status_t |
280 | cairo_status_t |
276 | _cairo_array_append_multiple (cairo_array_t *array, |
281 | _cairo_array_append_multiple (cairo_array_t *array, |
277 | const void *elements, |
282 | const void *elements, |
278 | int num_elements) |
283 | unsigned int num_elements) |
279 | { |
284 | { |
280 | cairo_status_t status; |
285 | cairo_status_t status; |
281 | void *dest; |
286 | void *dest; |
Line 282... | Line -... | ||
282 | - | ||
283 | assert (! array->is_snapshot); |
- | |
284 | 287 | ||
285 | status = _cairo_array_allocate (array, num_elements, &dest); |
288 | status = _cairo_array_allocate (array, num_elements, &dest); |
286 | if (unlikely (status)) |
289 | if (unlikely (status)) |
Line 287... | Line 290... | ||
287 | return status; |
290 | return status; |
Line 309... | Line 312... | ||
309 | unsigned int num_elements, |
312 | unsigned int num_elements, |
310 | void **elements) |
313 | void **elements) |
311 | { |
314 | { |
312 | cairo_status_t status; |
315 | cairo_status_t status; |
Line 313... | Line -... | ||
313 | - | ||
314 | assert (! array->is_snapshot); |
- | |
315 | 316 | ||
316 | status = _cairo_array_grow_by (array, num_elements); |
317 | status = _cairo_array_grow_by (array, num_elements); |
317 | if (unlikely (status)) |
318 | if (unlikely (status)) |
Line 318... | Line 319... | ||
318 | return status; |
319 | return status; |
Line 319... | Line 320... | ||
319 | 320 | ||
Line 320... | Line 321... | ||
320 | assert (array->num_elements + num_elements <= array->size); |
321 | assert (array->num_elements + num_elements <= array->size); |
Line 321... | Line 322... | ||
321 | 322 | ||
322 | *elements = &(*array->elements)[array->num_elements * array->element_size]; |
323 | *elements = array->elements + array->num_elements * array->element_size; |
Line 331... | Line 332... | ||
331 | * @array: a #cairo_array_t |
332 | * @array: a #cairo_array_t |
332 | * Returns: The number of elements stored in @array. |
333 | * Returns: The number of elements stored in @array. |
333 | * |
334 | * |
334 | * This space was left intentionally blank, but gtk-doc filled it. |
335 | * This space was left intentionally blank, but gtk-doc filled it. |
335 | **/ |
336 | **/ |
336 | int |
337 | unsigned int |
337 | _cairo_array_num_elements (cairo_array_t *array) |
338 | _cairo_array_num_elements (const cairo_array_t *array) |
338 | { |
339 | { |
339 | return array->num_elements; |
340 | return array->num_elements; |
340 | } |
341 | } |
Line 341... | Line 342... | ||
341 | 342 | ||
Line 345... | Line 346... | ||
345 | * Returns: The number of elements for which there is currently space |
346 | * Returns: The number of elements for which there is currently space |
346 | * allocated in @array. |
347 | * allocated in @array. |
347 | * |
348 | * |
348 | * This space was left intentionally blank, but gtk-doc filled it. |
349 | * This space was left intentionally blank, but gtk-doc filled it. |
349 | **/ |
350 | **/ |
350 | int |
351 | unsigned int |
351 | _cairo_array_size (cairo_array_t *array) |
352 | _cairo_array_size (const cairo_array_t *array) |
352 | { |
353 | { |
353 | return array->size; |
354 | return array->size; |
354 | } |
355 | } |
Line 355... | Line 356... | ||
355 | 356 | ||
Line 383... | Line 384... | ||
383 | num_slots = array->num_elements; |
384 | num_slots = array->num_elements; |
384 | if (num_slots) { |
385 | if (num_slots) { |
385 | cairo_user_data_slot_t *slots; |
386 | cairo_user_data_slot_t *slots; |
Line 386... | Line 387... | ||
386 | 387 | ||
387 | slots = _cairo_array_index (array, 0); |
388 | slots = _cairo_array_index (array, 0); |
- | 389 | while (num_slots--) { |
|
388 | do { |
390 | cairo_user_data_slot_t *s = &slots[num_slots]; |
389 | if (slots->user_data != NULL && slots->destroy != NULL) |
391 | if (s->user_data != NULL && s->destroy != NULL) |
390 | slots->destroy (slots->user_data); |
392 | s->destroy (s->user_data); |
391 | slots++; |
- | |
392 | } while (--num_slots); |
393 | } |
Line 393... | Line 394... | ||
393 | } |
394 | } |
394 | 395 | ||
Line 491... | Line 492... | ||
491 | return CAIRO_STATUS_SUCCESS; |
492 | return CAIRO_STATUS_SUCCESS; |
492 | } |
493 | } |
Line 493... | Line 494... | ||
493 | 494 | ||
494 | cairo_status_t |
495 | cairo_status_t |
495 | _cairo_user_data_array_copy (cairo_user_data_array_t *dst, |
496 | _cairo_user_data_array_copy (cairo_user_data_array_t *dst, |
496 | cairo_user_data_array_t *src) |
497 | const cairo_user_data_array_t *src) |
497 | { |
498 | { |
498 | /* discard any existing user-data */ |
499 | /* discard any existing user-data */ |
499 | if (dst->num_elements != 0) { |
500 | if (dst->num_elements != 0) { |
500 | _cairo_user_data_array_fini (dst); |
501 | _cairo_user_data_array_fini (dst); |
501 | _cairo_user_data_array_init (dst); |
502 | _cairo_user_data_array_init (dst); |
Line 502... | Line -... | ||
502 | } |
- | |
503 | - | ||
504 | if (src->num_elements == 0) |
- | |
505 | return CAIRO_STATUS_SUCCESS; |
503 | } |
506 | 504 | ||
507 | return _cairo_array_append_multiple (dst, |
505 | return _cairo_array_append_multiple (dst, |
508 | _cairo_array_index (src, 0), |
506 | _cairo_array_index_const (src, 0), |
Line 509... | Line 507... | ||
509 | src->num_elements); |
507 | src->num_elements); |
510 | } |
508 | } |