File: | tests/suite/ecore/src/lib/eina_rectangle.c |
Location: | line 569, column 4 |
Description: | Dereference of null pointer |
1 | /* EINA - EFL data type library | ||||
2 | * Copyright (C) 2007-2008 Cedric BAIL, Carsten Haitzler | ||||
3 | * | ||||
4 | * This library is free software; you can redistribute it and/or | ||||
5 | * modify it under the terms of the GNU Lesser General Public | ||||
6 | * License as published by the Free Software Foundation; either | ||||
7 | * version 2.1 of the License, or (at your option) any later version. | ||||
8 | * | ||||
9 | * This library is distributed in the hope that it will be useful, | ||||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
12 | * Lesser General Public License for more details. | ||||
13 | * | ||||
14 | * You should have received a copy of the GNU Lesser General Public | ||||
15 | * License along with this library; | ||||
16 | * if not, see <http://www.gnu.org/licenses/>. | ||||
17 | */ | ||||
18 | |||||
19 | #ifdef HAVE_CONFIG_H1 | ||||
20 | # include "config.h" | ||||
21 | #endif | ||||
22 | |||||
23 | #include <stdio.h> | ||||
24 | #include <stdlib.h> | ||||
25 | |||||
26 | #ifdef HAVE_EVIL | ||||
27 | # include <Evil.h> | ||||
28 | #endif | ||||
29 | |||||
30 | #include "eina_config.h" | ||||
31 | #include "eina_private.h" | ||||
32 | #include "eina_magic.h" | ||||
33 | #include "eina_inlist.h" | ||||
34 | #include "eina_mempool.h" | ||||
35 | #include "eina_list.h" | ||||
36 | #include "eina_trash.h" | ||||
37 | #include "eina_log.h" | ||||
38 | |||||
39 | /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ | ||||
40 | #include "eina_safety_checks.h" | ||||
41 | #include "eina_rectangle.h" | ||||
42 | |||||
43 | /*============================================================================* | ||||
44 | * Local * | ||||
45 | *============================================================================*/ | ||||
46 | |||||
47 | /** | ||||
48 | * @cond LOCAL | ||||
49 | */ | ||||
50 | |||||
51 | #define EINA_RECTANGLE_POOL_MAGIC0x1578FCB0 0x1578FCB0 | ||||
52 | #define EINA_RECTANGLE_ALLOC_MAGIC0x1578FCB1 0x1578FCB1 | ||||
53 | |||||
54 | #define BUCKET_THRESHOLD110 110 | ||||
55 | |||||
56 | typedef struct _Eina_Rectangle_Alloc Eina_Rectangle_Alloc; | ||||
57 | |||||
58 | struct _Eina_Rectangle_Pool | ||||
59 | { | ||||
60 | Eina_Inlist *head; | ||||
61 | Eina_List *empty; | ||||
62 | void *data; | ||||
63 | |||||
64 | Eina_Trash *bucket; | ||||
65 | unsigned int bucket_count; | ||||
66 | |||||
67 | unsigned int references; | ||||
68 | int w; | ||||
69 | int h; | ||||
70 | |||||
71 | Eina_Bool sorted; | ||||
72 | EINA_MAGICEina_Magic __magic; | ||||
73 | }; | ||||
74 | |||||
75 | struct _Eina_Rectangle_Alloc | ||||
76 | { | ||||
77 | EINA_INLISTEina_Inlist __in_list; | ||||
78 | Eina_Rectangle_Pool *pool; | ||||
79 | EINA_MAGICEina_Magic __magic; | ||||
80 | }; | ||||
81 | |||||
82 | #define EINA_MAGIC_CHECK_RECTANGLE_POOL(d)do { if (!(((d)) && (((d))->__magic == (0x1578FCB0 )))) { eina_magic_fail((void *)((d)), ((d)) ? ((d))->__magic : 0, (0x1578FCB0), "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 82);; } } while (0) \ | ||||
83 | do { \ | ||||
84 | if (!EINA_MAGIC_CHECK((d), EINA_RECTANGLE_POOL_MAGIC)(((d)) && (((d))->__magic == (0x1578FCB0)))) { \ | ||||
85 | EINA_MAGIC_FAIL((d), EINA_RECTANGLE_POOL_MAGIC)eina_magic_fail((void *)((d)), ((d)) ? ((d))->__magic : 0, (0x1578FCB0), "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 85);; } \ | ||||
86 | } while (0) | ||||
87 | |||||
88 | #define EINA_MAGIC_CHECK_RECTANGLE_ALLOC(d)do { if (!(((d)) && (((d))->__magic == (0x1578FCB1 )))) { eina_magic_fail((void *)((d)), ((d)) ? ((d))->__magic : 0, (0x1578FCB1), "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 88);; } } while (0) \ | ||||
89 | do { \ | ||||
90 | if (!EINA_MAGIC_CHECK((d), EINA_RECTANGLE_ALLOC_MAGIC)(((d)) && (((d))->__magic == (0x1578FCB1)))) { \ | ||||
91 | EINA_MAGIC_FAIL((d), EINA_RECTANGLE_ALLOC_MAGIC)eina_magic_fail((void *)((d)), ((d)) ? ((d))->__magic : 0, (0x1578FCB1), "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 91);; } \ | ||||
92 | } while (0) | ||||
93 | |||||
94 | static Eina_Mempool *_eina_rectangle_alloc_mp = NULL((void*)0); | ||||
95 | static Eina_Mempool *_eina_rectangle_mp = NULL((void*)0); | ||||
96 | |||||
97 | static Eina_Trash *_eina_rectangles = NULL((void*)0); | ||||
98 | static unsigned int _eina_rectangles_count = 0; | ||||
99 | static int _eina_rectangle_log_dom = -1; | ||||
100 | |||||
101 | #ifdef ERR | ||||
102 | #undef ERR | ||||
103 | #endif | ||||
104 | #define ERR(...)eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_ERR, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 104, ...) EINA_LOG_DOM_ERR(_eina_rectangle_log_dom, __VA_ARGS__)eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_ERR, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 104, __VA_ARGS__) | ||||
105 | |||||
106 | #ifdef DBG | ||||
107 | #undef DBG | ||||
108 | #endif | ||||
109 | #define DBG(...)eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_DBG, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 109, ...) EINA_LOG_DOM_DBG(_eina_rectangle_log_dom, __VA_ARGS__)eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_DBG, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 109, __VA_ARGS__) | ||||
110 | |||||
111 | static int | ||||
112 | _eina_rectangle_cmp(const Eina_Rectangle *r1, const Eina_Rectangle *r2) | ||||
113 | { | ||||
114 | return (r2->w * r2->h) - (r1->w * r1->h); | ||||
115 | } | ||||
116 | |||||
117 | static Eina_List * | ||||
118 | _eina_rectangle_merge_list(Eina_List *empty, Eina_Rectangle *r) | ||||
119 | { | ||||
120 | Eina_Rectangle *match; | ||||
121 | Eina_List *l; | ||||
122 | int xw; | ||||
123 | int yh; | ||||
124 | |||||
125 | if (r->w == 0 || r->h == 0) | ||||
126 | { | ||||
127 | eina_rectangle_free(r); | ||||
128 | return empty; | ||||
129 | } | ||||
130 | |||||
131 | start_again: | ||||
132 | xw = r->x + r->w; | ||||
133 | yh = r->y + r->h; | ||||
134 | |||||
135 | EINA_LIST_FOREACH(empty, l, match)for (l = empty, match = eina_list_data_get(l); l; l = eina_list_next (l), match = eina_list_data_get(l)) | ||||
136 | { | ||||
137 | if (match->x == r->x && match->w == r->w | ||||
138 | && (match->y == yh || r->y == match->y + match->h)) | ||||
139 | { | ||||
140 | if (match->y > r->y) | ||||
141 | match->y = r->y; | ||||
142 | |||||
143 | match->h += r->h; | ||||
144 | |||||
145 | eina_rectangle_free(r); | ||||
146 | |||||
147 | empty = eina_list_remove_list(empty, l); | ||||
148 | |||||
149 | r = match; | ||||
150 | |||||
151 | goto start_again; | ||||
152 | } | ||||
153 | else if (match->y == r->y && match->h == r->h | ||||
154 | && (match->x == xw || r->x == match->x + match->w)) | ||||
155 | { | ||||
156 | if (match->x > r->x) | ||||
157 | match->x = r->x; | ||||
158 | |||||
159 | match->w += r->w; | ||||
160 | |||||
161 | eina_rectangle_free(r); | ||||
162 | |||||
163 | empty = eina_list_remove_list(empty, l); | ||||
164 | |||||
165 | r = match; | ||||
166 | |||||
167 | goto start_again; | ||||
168 | } | ||||
169 | } | ||||
170 | |||||
171 | return eina_list_append(empty, r); | ||||
172 | } | ||||
173 | |||||
174 | static Eina_List * | ||||
175 | _eina_rectangle_empty_space_find(Eina_List *empty, int w, int h, int *x, int *y) | ||||
176 | { | ||||
177 | Eina_Rectangle *r; | ||||
178 | Eina_List *l; | ||||
179 | |||||
180 | EINA_LIST_FOREACH(empty, l, r)for (l = empty, r = eina_list_data_get(l); l; l = eina_list_next (l), r = eina_list_data_get(l)) | ||||
181 | { | ||||
182 | if (r->w >= w && r->h >= h) | ||||
183 | { | ||||
184 | /* Remove l from empty */ | ||||
185 | empty = eina_list_remove_list(empty, l); | ||||
186 | /* Remember x and y */ | ||||
187 | *x = r->x; | ||||
188 | *y = r->y; | ||||
189 | /* Split r in 2 rectangle if needed (only the empty one) and insert them */ | ||||
190 | if (r->w == w) | ||||
191 | { | ||||
192 | r->y += h; | ||||
193 | r->h -= h; | ||||
194 | } | ||||
195 | else if (r->h == h) | ||||
196 | { | ||||
197 | r->x += w; | ||||
198 | r->w -= w; | ||||
199 | } | ||||
200 | else | ||||
201 | { | ||||
202 | int rx1, ry1, rw1, rh1; | ||||
203 | int x2, y2, w2, h2; | ||||
204 | |||||
205 | rx1 = r->x + w; | ||||
206 | ry1 = r->y; | ||||
207 | rw1 = r->w - w; | ||||
208 | /* h1 could be h or r->h */ | ||||
209 | x2 = r->x; | ||||
210 | y2 = r->y + h; | ||||
211 | /* w2 could be w or r->w */ | ||||
212 | h2 = r->h - h; | ||||
213 | |||||
214 | if (rw1 * r->h > h2 * r->w) | ||||
215 | { | ||||
216 | rh1 = r->h; | ||||
217 | w2 = w; | ||||
218 | } | ||||
219 | else | ||||
220 | { | ||||
221 | rh1 = h; | ||||
222 | w2 = r->w; | ||||
223 | } | ||||
224 | |||||
225 | EINA_RECTANGLE_SET(r, rx1, ry1, rw1, rh1)(r)->x = rx1; (r)->y = ry1; (r)->w = rw1; (r)->h = rh1;; | ||||
226 | empty = _eina_rectangle_merge_list(empty, r); | ||||
227 | |||||
228 | r = eina_rectangle_new(x2, y2, w2, h2); | ||||
229 | } | ||||
230 | |||||
231 | if (r) | ||||
232 | { | ||||
233 | empty = _eina_rectangle_merge_list(empty, r); /* Return empty */ | ||||
234 | |||||
235 | } | ||||
236 | |||||
237 | return empty; | ||||
238 | } | ||||
239 | } | ||||
240 | |||||
241 | *x = -1; | ||||
242 | *y = -1; | ||||
243 | return empty; | ||||
244 | } | ||||
245 | |||||
246 | /** | ||||
247 | * @endcond | ||||
248 | */ | ||||
249 | |||||
250 | /*============================================================================* | ||||
251 | * Global * | ||||
252 | *============================================================================*/ | ||||
253 | |||||
254 | Eina_Bool | ||||
255 | eina_rectangle_init(void) | ||||
256 | { | ||||
257 | const char *choice, *tmp; | ||||
258 | |||||
259 | _eina_rectangle_log_dom = eina_log_domain_register("eina_rectangle", | ||||
260 | EINA_LOG_COLOR_DEFAULT"\033[36m"); | ||||
261 | if (_eina_rectangle_log_dom < 0) | ||||
262 | { | ||||
263 | EINA_LOG_ERR("Could not register log domain: eina_rectangle")eina_log_print(EINA_LOG_DOMAIN_GLOBAL, EINA_LOG_LEVEL_ERR, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 263, "Could not register log domain: eina_rectangle" ); | ||||
264 | return EINA_FALSE((Eina_Bool)0); | ||||
265 | } | ||||
266 | |||||
267 | #ifdef EINA_DEFAULT_MEMPOOL | ||||
268 | choice = "pass_through"; | ||||
269 | #else | ||||
270 | choice = "chained_mempool"; | ||||
271 | #endif | ||||
272 | tmp = getenv("EINA_MEMPOOL"); | ||||
273 | if (tmp && tmp[0]) | ||||
274 | choice = tmp; | ||||
275 | |||||
276 | _eina_rectangle_alloc_mp = eina_mempool_add | ||||
277 | (choice, "rectangle-alloc", NULL((void*)0), | ||||
278 | sizeof(Eina_Rectangle_Alloc) + sizeof(Eina_Rectangle), 1024); | ||||
279 | if (!_eina_rectangle_alloc_mp) | ||||
280 | { | ||||
281 | ERR("Mempool for rectangle cannot be allocated in rectangle init.")eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_ERR, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 281, "Mempool for rectangle cannot be allocated in rectangle init." ); | ||||
282 | goto init_error; | ||||
283 | } | ||||
284 | |||||
285 | _eina_rectangle_mp = eina_mempool_add | ||||
286 | (choice, "rectangle", NULL((void*)0), sizeof(Eina_Rectangle), 256); | ||||
287 | if (!_eina_rectangle_mp) | ||||
288 | { | ||||
289 | ERR("Mempool for rectangle cannot be allocated in rectangle init.")eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_ERR, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 289, "Mempool for rectangle cannot be allocated in rectangle init." ); | ||||
290 | goto init_error; | ||||
291 | } | ||||
292 | |||||
293 | return EINA_TRUE((Eina_Bool)1); | ||||
294 | |||||
295 | init_error: | ||||
296 | eina_log_domain_unregister(_eina_rectangle_log_dom); | ||||
297 | _eina_rectangle_log_dom = -1; | ||||
298 | |||||
299 | return EINA_FALSE((Eina_Bool)0); | ||||
300 | } | ||||
301 | |||||
302 | Eina_Bool | ||||
303 | eina_rectangle_shutdown(void) | ||||
304 | { | ||||
305 | Eina_Rectangle *del; | ||||
306 | |||||
307 | while ((del = eina_trash_pop(&_eina_rectangles))) | ||||
308 | eina_mempool_free(_eina_rectangle_mp, del); | ||||
309 | _eina_rectangles_count = 0; | ||||
310 | |||||
311 | eina_mempool_del(_eina_rectangle_alloc_mp); | ||||
312 | eina_mempool_del(_eina_rectangle_mp); | ||||
313 | |||||
314 | eina_log_domain_unregister(_eina_rectangle_log_dom); | ||||
315 | _eina_rectangle_log_dom = -1; | ||||
316 | |||||
317 | return EINA_TRUE((Eina_Bool)1); | ||||
318 | } | ||||
319 | |||||
320 | /*============================================================================* | ||||
321 | * API * | ||||
322 | *============================================================================*/ | ||||
323 | |||||
324 | /** | ||||
325 | * @addtogroup Eina_Rectangle_Group Rectangle | ||||
326 | * | ||||
327 | * @brief These functions provide rectangle management. | ||||
328 | * | ||||
329 | * @{ | ||||
330 | */ | ||||
331 | |||||
332 | /** | ||||
333 | * @brief Create a new rectangle. | ||||
334 | * | ||||
335 | * @param x The X coordinate of the top left corner of the rectangle. | ||||
336 | * @param y The Y coordinate of the top left corner of the rectangle. | ||||
337 | * @param w The width of the rectangle. | ||||
338 | * @param h The height of the rectangle. | ||||
339 | * @return The new rectangle on success, @ NULL otherwise. | ||||
340 | * | ||||
341 | * This function creates a rectangle which top left corner has the | ||||
342 | * coordinates (@p x, @p y), with height @p w and height @p h and adds | ||||
343 | * it to the rectangles pool. No check is done on @p w and @p h. This | ||||
344 | * function returns a new rectangle on success, @c NULL otherwhise. | ||||
345 | */ | ||||
346 | EAPI__attribute__ ((visibility("default"))) Eina_Rectangle * | ||||
347 | eina_rectangle_new(int x, int y, int w, int h) | ||||
348 | { | ||||
349 | Eina_Rectangle *rect; | ||||
350 | |||||
351 | if (_eina_rectangles) | ||||
352 | { | ||||
353 | rect = eina_trash_pop(&_eina_rectangles); | ||||
354 | _eina_rectangles_count--; | ||||
355 | } | ||||
356 | else | ||||
357 | rect = eina_mempool_malloc(_eina_rectangle_mp, sizeof (Eina_Rectangle)); | ||||
358 | |||||
359 | if (!rect) | ||||
360 | return NULL((void*)0); | ||||
361 | |||||
362 | EINA_RECTANGLE_SET(rect, x, y, w, h)(rect)->x = x; (rect)->y = y; (rect)->w = w; (rect)-> h = h;; | ||||
363 | |||||
364 | return rect; | ||||
365 | } | ||||
366 | |||||
367 | /** | ||||
368 | * @brief Free the given rectangle. | ||||
369 | * | ||||
370 | * @param rect The rectangle to free. | ||||
371 | * | ||||
372 | * This function removes @p rect from the rectangles pool. | ||||
373 | */ | ||||
374 | EAPI__attribute__ ((visibility("default"))) void | ||||
375 | eina_rectangle_free(Eina_Rectangle *rect) | ||||
376 | { | ||||
377 | EINA_SAFETY_ON_NULL_RETURN(rect)do { if (__builtin_expect(((rect) == ((void*)0)), 0)) { eina_error_set (EINA_ERROR_SAFETY_FAILED); eina_log_print(EINA_LOG_DOMAIN_GLOBAL , EINA_LOG_LEVEL_ERR, "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 377, "%s", "safety check failed: " "rect" " == NULL"); return ; } } while (0); | ||||
378 | |||||
379 | if (_eina_rectangles_count > BUCKET_THRESHOLD110) | ||||
380 | eina_mempool_free(_eina_rectangle_mp, rect); | ||||
381 | else | ||||
382 | { | ||||
383 | eina_trash_push(&_eina_rectangles, rect); | ||||
384 | _eina_rectangles_count++; | ||||
385 | } | ||||
386 | } | ||||
387 | |||||
388 | /** | ||||
389 | * @brief Add a rectangle in a new pool. | ||||
390 | * | ||||
391 | * @param w The width of the rectangle. | ||||
392 | * @param h The height of the rectangle. | ||||
393 | * @return A newly allocated pool on success, @c NULL otherwise. | ||||
394 | * | ||||
395 | * This function adds the rectangle of size (@p width, @p height) to a | ||||
396 | * new pool. If the pool can not be created, @c NULL is | ||||
397 | * returned. Otherwise the newly allocated pool is returned. | ||||
398 | */ | ||||
399 | EAPI__attribute__ ((visibility("default"))) Eina_Rectangle_Pool * | ||||
400 | eina_rectangle_pool_new(int w, int h) | ||||
401 | { | ||||
402 | Eina_Rectangle_Pool *new; | ||||
403 | |||||
404 | new = malloc(sizeof (Eina_Rectangle_Pool)); | ||||
405 | if (!new) | ||||
406 | return NULL((void*)0); | ||||
407 | |||||
408 | new->head = NULL((void*)0); | ||||
409 | new->empty = eina_list_append(NULL((void*)0), eina_rectangle_new(0, 0, w, h)); | ||||
410 | new->references = 0; | ||||
411 | new->sorted = EINA_FALSE((Eina_Bool)0); | ||||
412 | new->w = w; | ||||
413 | new->h = h; | ||||
414 | new->bucket = NULL((void*)0); | ||||
415 | new->bucket_count = 0; | ||||
416 | |||||
417 | EINA_MAGIC_SET(new, EINA_RECTANGLE_POOL_MAGIC)(new)->__magic = (0x1578FCB0); | ||||
418 | DBG("pool=%p, size=(%d, %d)", new, w, h)eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_DBG, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 418, "pool=%p, size=(%d, %d)", new, w, h); | ||||
419 | |||||
420 | return new; | ||||
421 | } | ||||
422 | |||||
423 | /** | ||||
424 | * @brief Free the given pool. | ||||
425 | * | ||||
426 | * @param pool The pool to free. | ||||
427 | * | ||||
428 | * This function frees the allocated data of @p pool. If @p pool is | ||||
429 | * @c NULL, ths function returned immediately. | ||||
430 | */ | ||||
431 | EAPI__attribute__ ((visibility("default"))) void | ||||
432 | eina_rectangle_pool_free(Eina_Rectangle_Pool *pool) | ||||
433 | { | ||||
434 | Eina_Rectangle_Alloc *del; | ||||
435 | |||||
436 | EINA_SAFETY_ON_NULL_RETURN(pool)do { if (__builtin_expect(((pool) == ((void*)0)), 0)) { eina_error_set (EINA_ERROR_SAFETY_FAILED); eina_log_print(EINA_LOG_DOMAIN_GLOBAL , EINA_LOG_LEVEL_ERR, "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 436, "%s", "safety check failed: " "pool" " == NULL"); return ; } } while (0); | ||||
437 | DBG("pool=%p, size=(%d, %d), references=%u",eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_DBG, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 438, "pool=%p, size=(%d, %d), references=%u", pool, pool->w, pool->h, pool->references) | ||||
438 | pool, pool->w, pool->h, pool->references)eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_DBG, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 438, "pool=%p, size=(%d, %d), references=%u", pool, pool->w, pool->h, pool->references); | ||||
439 | while (pool->head) | ||||
440 | { | ||||
441 | del = (Eina_Rectangle_Alloc *)pool->head; | ||||
442 | |||||
443 | pool->head = (EINA_INLIST_GET(del)(& ((del)->__in_list)))->next; | ||||
444 | |||||
445 | EINA_MAGIC_SET(del, EINA_MAGIC_NONE)(del)->__magic = (0x1234fedc); | ||||
446 | eina_mempool_free(_eina_rectangle_alloc_mp, del); | ||||
447 | } | ||||
448 | |||||
449 | while (pool->bucket) | ||||
450 | { | ||||
451 | del = eina_trash_pop(&pool->bucket); | ||||
452 | eina_mempool_free(_eina_rectangle_alloc_mp, del); | ||||
453 | } | ||||
454 | |||||
455 | MAGIC_FREE(pool)do { if (pool) { (pool)->__magic = (0x1234fedc); do { free (pool); pool = ((void*)0); } while(0);; } } while(0);; | ||||
456 | } | ||||
457 | |||||
458 | /** | ||||
459 | * @brief Return the number of rectangles in the given pool. | ||||
460 | * | ||||
461 | * @param pool The pool. | ||||
462 | * @return The number of rectangles in the pool. | ||||
463 | * | ||||
464 | * This function returns the number of rectangles in @p pool. | ||||
465 | */ | ||||
466 | EAPI__attribute__ ((visibility("default"))) int | ||||
467 | eina_rectangle_pool_count(Eina_Rectangle_Pool *pool) | ||||
468 | { | ||||
469 | EINA_SAFETY_ON_NULL_RETURN_VAL(pool, 0)do { if (__builtin_expect(((pool) == ((void*)0)), 0)) { eina_error_set (EINA_ERROR_SAFETY_FAILED); eina_log_print(EINA_LOG_DOMAIN_GLOBAL , EINA_LOG_LEVEL_ERR, "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 469, "%s", "safety check failed: " "pool" " == NULL"); return (0); } } while (0); | ||||
470 | return pool->references; | ||||
471 | } | ||||
472 | |||||
473 | /** | ||||
474 | * @brief Request a rectangle of given size in the given pool. | ||||
475 | * | ||||
476 | * @param pool The pool. | ||||
477 | * @param w The width of the rectangle to request. | ||||
478 | * @param h The height of the rectangle to request. | ||||
479 | * @return The requested rectangle on success, @c NULL otherwise. | ||||
480 | * | ||||
481 | * This function retrieve from @p pool the rectangle of width @p w and | ||||
482 | * height @p h. If @p pool is @c NULL, or @p w or @p h are non-positive, | ||||
483 | * the function returns @c NULL. If @p w or @p h are greater than the | ||||
484 | * pool size, the function returns @c NULL. On success, the function | ||||
485 | * returns the rectangle which matches the size (@p w, @p h). | ||||
486 | * Otherwise it returns @c NULL. | ||||
487 | */ | ||||
488 | EAPI__attribute__ ((visibility("default"))) Eina_Rectangle * | ||||
489 | eina_rectangle_pool_request(Eina_Rectangle_Pool *pool, int w, int h) | ||||
490 | { | ||||
491 | Eina_Rectangle_Alloc *new; | ||||
492 | Eina_Rectangle *rect; | ||||
493 | int x; | ||||
494 | int y; | ||||
495 | |||||
496 | EINA_SAFETY_ON_NULL_RETURN_VAL(pool, NULL)do { if (__builtin_expect(((pool) == ((void*)0)), 0)) { eina_error_set (EINA_ERROR_SAFETY_FAILED); eina_log_print(EINA_LOG_DOMAIN_GLOBAL , EINA_LOG_LEVEL_ERR, "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 496, "%s", "safety check failed: " "pool" " == NULL"); return (((void*)0)); } } while (0); | ||||
497 | |||||
498 | DBG("pool=%p, size=(%d, %d), references=%u",eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_DBG, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 499, "pool=%p, size=(%d, %d), references=%u", pool, pool->w, pool->h, pool->references) | ||||
499 | pool, pool->w, pool->h, pool->references)eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_DBG, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 499, "pool=%p, size=(%d, %d), references=%u", pool, pool->w, pool->h, pool->references); | ||||
500 | |||||
501 | if (w <= 0 || h <= 0) | ||||
502 | return NULL((void*)0); | ||||
503 | |||||
504 | if (w > pool->w || h > pool->h) | ||||
505 | return NULL((void*)0); | ||||
506 | |||||
507 | /* Sort empty if dirty */ | ||||
508 | if (pool->sorted) | ||||
509 | { | ||||
510 | pool->empty = | ||||
511 | eina_list_sort(pool->empty, 0, EINA_COMPARE_CB(_eina_rectangle_cmp)((Eina_Compare_Cb)_eina_rectangle_cmp)); | ||||
512 | pool->sorted = EINA_TRUE((Eina_Bool)1); | ||||
513 | } | ||||
514 | |||||
515 | pool->empty = _eina_rectangle_empty_space_find(pool->empty, w, h, &x, &y); | ||||
516 | if (x == -1) | ||||
517 | return NULL((void*)0); | ||||
518 | |||||
519 | pool->sorted = EINA_FALSE((Eina_Bool)0); | ||||
520 | |||||
521 | if (pool->bucket_count > 0) | ||||
522 | { | ||||
523 | new = eina_trash_pop(&pool->bucket); | ||||
524 | pool->bucket_count--; | ||||
525 | } | ||||
526 | else | ||||
527 | new = eina_mempool_malloc(_eina_rectangle_alloc_mp, | ||||
528 | sizeof (Eina_Rectangle_Alloc) + | ||||
529 | sizeof (Eina_Rectangle)); | ||||
530 | |||||
531 | if (!new) | ||||
532 | return NULL((void*)0); | ||||
533 | |||||
534 | rect = (Eina_Rectangle *)(new + 1); | ||||
535 | eina_rectangle_coords_from(rect, x, y, w, h); | ||||
536 | |||||
537 | pool->head = eina_inlist_prepend(pool->head, EINA_INLIST_GET(new)(& ((new)->__in_list))); | ||||
538 | pool->references++; | ||||
539 | |||||
540 | new->pool = pool; | ||||
541 | |||||
542 | EINA_MAGIC_SET(new, EINA_RECTANGLE_ALLOC_MAGIC)(new)->__magic = (0x1578FCB1); | ||||
543 | DBG("rect=%p pool=%p, size=(%d, %d), references=%u",eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_DBG, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 544, "rect=%p pool=%p, size=(%d, %d), references=%u" , rect, pool, pool->w, pool->h, pool->references) | ||||
544 | rect, pool, pool->w, pool->h, pool->references)eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_DBG, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 544, "rect=%p pool=%p, size=(%d, %d), references=%u" , rect, pool, pool->w, pool->h, pool->references); | ||||
545 | |||||
546 | return rect; | ||||
547 | } | ||||
548 | |||||
549 | /** | ||||
550 | * @brief Remove the given rectangle from the pool. | ||||
551 | * | ||||
552 | * @param rect The rectangle to remove from the pool. | ||||
553 | * | ||||
554 | * This function removes @p rect from the pool. If @p rect is | ||||
555 | * @c NULL, the function returns immediately. Otherwise it remoes @p | ||||
556 | * rect from the pool. | ||||
557 | */ | ||||
558 | EAPI__attribute__ ((visibility("default"))) void | ||||
559 | eina_rectangle_pool_release(Eina_Rectangle *rect) | ||||
560 | { | ||||
561 | Eina_Rectangle_Alloc *era = ((Eina_Rectangle_Alloc *)rect) - 1; | ||||
562 | Eina_Rectangle *r; | ||||
563 | |||||
564 | EINA_SAFETY_ON_NULL_RETURN(rect)do { if (__builtin_expect(((rect) == ((void*)0)), 0)) { eina_error_set (EINA_ERROR_SAFETY_FAILED); eina_log_print(EINA_LOG_DOMAIN_GLOBAL , EINA_LOG_LEVEL_ERR, "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 564, "%s", "safety check failed: " "rect" " == NULL"); return ; } } while (0); | ||||
565 | |||||
566 | EINA_MAGIC_CHECK_RECTANGLE_ALLOC(era)do { if (!(((era)) && (((era))->__magic == (0x1578FCB1 )))) { eina_magic_fail((void *)((era)), ((era)) ? ((era))-> __magic : 0, (0x1578FCB1), "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 566);; } } while (0); | ||||
567 | EINA_MAGIC_CHECK_RECTANGLE_POOL(era->pool)do { if (!(((era->pool)) && (((era->pool))-> __magic == (0x1578FCB0)))) { eina_magic_fail((void *)((era-> pool)), ((era->pool)) ? ((era->pool))->__magic : 0, ( 0x1578FCB0), "ecore/src/lib/eina_rectangle.c", __FUNCTION__, 567 );; } } while (0); | ||||
| |||||
568 | |||||
569 | DBG("rect=%p pool=%p, size=(%d, %d), references=%u",eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_DBG, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 570, "rect=%p pool=%p, size=(%d, %d), references=%u" , rect, era->pool, era->pool->w, era->pool->h, era->pool->references) | ||||
| |||||
570 | rect, era->pool, era->pool->w, era->pool->h, era->pool->references)eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_DBG, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 570, "rect=%p pool=%p, size=(%d, %d), references=%u" , rect, era->pool, era->pool->w, era->pool->h, era->pool->references); | ||||
571 | |||||
572 | era->pool->references--; | ||||
573 | era->pool->head = eina_inlist_remove(era->pool->head, EINA_INLIST_GET(era)(& ((era)->__in_list))); | ||||
574 | |||||
575 | r = eina_rectangle_new(rect->x, rect->y, rect->w, rect->h); | ||||
576 | if (r) | ||||
577 | { | ||||
578 | era->pool->empty = _eina_rectangle_merge_list(era->pool->empty, r); | ||||
579 | era->pool->sorted = EINA_FALSE((Eina_Bool)0); | ||||
580 | } | ||||
581 | |||||
582 | if (era->pool->bucket_count < BUCKET_THRESHOLD110) | ||||
583 | { | ||||
584 | Eina_Rectangle_Pool *pool; | ||||
585 | |||||
586 | pool = era->pool; | ||||
587 | |||||
588 | pool->bucket_count++; | ||||
589 | eina_trash_push(&pool->bucket, era); | ||||
590 | } | ||||
591 | else | ||||
592 | { | ||||
593 | EINA_MAGIC_SET(era, EINA_MAGIC_NONE)(era)->__magic = (0x1234fedc); | ||||
594 | eina_mempool_free(_eina_rectangle_alloc_mp, era); | ||||
595 | } | ||||
596 | } | ||||
597 | |||||
598 | /** | ||||
599 | * @brief Return the pool of the given rectangle. | ||||
600 | * | ||||
601 | * @param rect The rectangle. | ||||
602 | * @return The pool of the given rectangle. | ||||
603 | * | ||||
604 | * This function returns the pool in which @p rect is. If @p rect is | ||||
605 | * @c NULL, @c NULL is returned. | ||||
606 | */ | ||||
607 | EAPI__attribute__ ((visibility("default"))) Eina_Rectangle_Pool * | ||||
608 | eina_rectangle_pool_get(Eina_Rectangle *rect) | ||||
609 | { | ||||
610 | Eina_Rectangle_Alloc *era = ((Eina_Rectangle_Alloc *)rect) - 1; | ||||
611 | |||||
612 | EINA_SAFETY_ON_NULL_RETURN_VAL(rect, NULL)do { if (__builtin_expect(((rect) == ((void*)0)), 0)) { eina_error_set (EINA_ERROR_SAFETY_FAILED); eina_log_print(EINA_LOG_DOMAIN_GLOBAL , EINA_LOG_LEVEL_ERR, "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 612, "%s", "safety check failed: " "rect" " == NULL"); return (((void*)0)); } } while (0); | ||||
613 | |||||
614 | EINA_MAGIC_CHECK_RECTANGLE_ALLOC(era)do { if (!(((era)) && (((era))->__magic == (0x1578FCB1 )))) { eina_magic_fail((void *)((era)), ((era)) ? ((era))-> __magic : 0, (0x1578FCB1), "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 614);; } } while (0); | ||||
615 | EINA_MAGIC_CHECK_RECTANGLE_POOL(era->pool)do { if (!(((era->pool)) && (((era->pool))-> __magic == (0x1578FCB0)))) { eina_magic_fail((void *)((era-> pool)), ((era->pool)) ? ((era->pool))->__magic : 0, ( 0x1578FCB0), "ecore/src/lib/eina_rectangle.c", __FUNCTION__, 615 );; } } while (0); | ||||
616 | |||||
617 | return era->pool; | ||||
618 | } | ||||
619 | |||||
620 | /** | ||||
621 | * @brief Set the data to the given pool. | ||||
622 | * | ||||
623 | * @param pool The pool. | ||||
624 | * @param data The data to set. | ||||
625 | * | ||||
626 | * This function sets @p data to @p pool. If @p pool is @c NULL, this | ||||
627 | * function does nothing. | ||||
628 | */ | ||||
629 | EAPI__attribute__ ((visibility("default"))) void | ||||
630 | eina_rectangle_pool_data_set(Eina_Rectangle_Pool *pool, const void *data) | ||||
631 | { | ||||
632 | EINA_MAGIC_CHECK_RECTANGLE_POOL(pool)do { if (!(((pool)) && (((pool))->__magic == (0x1578FCB0 )))) { eina_magic_fail((void *)((pool)), ((pool)) ? ((pool))-> __magic : 0, (0x1578FCB0), "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 632);; } } while (0); | ||||
633 | EINA_SAFETY_ON_NULL_RETURN(pool)do { if (__builtin_expect(((pool) == ((void*)0)), 0)) { eina_error_set (EINA_ERROR_SAFETY_FAILED); eina_log_print(EINA_LOG_DOMAIN_GLOBAL , EINA_LOG_LEVEL_ERR, "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 633, "%s", "safety check failed: " "pool" " == NULL"); return ; } } while (0); | ||||
634 | |||||
635 | DBG("data=%p pool=%p, size=(%d, %d), references=%u",eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_DBG, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 636, "data=%p pool=%p, size=(%d, %d), references=%u" , data, pool, pool->w, pool->h, pool->references) | ||||
636 | data, pool, pool->w, pool->h, pool->references)eina_log_print(_eina_rectangle_log_dom, EINA_LOG_LEVEL_DBG, "ecore/src/lib/eina_rectangle.c" , __FUNCTION__, 636, "data=%p pool=%p, size=(%d, %d), references=%u" , data, pool, pool->w, pool->h, pool->references); | ||||
637 | |||||
638 | pool->data = (void *)data; | ||||
639 | } | ||||
640 | |||||
641 | /** | ||||
642 | * @brief Get the data from the given pool. | ||||
643 | * | ||||
644 | * @param pool The pool. | ||||
645 | * @return The returned data. | ||||
646 | * | ||||
647 | * This function gets the data from @p pool set by | ||||
648 | * eina_rectangle_pool_data_set(). If @p pool is @c NULL, this | ||||
649 | * function returns @c NULL. | ||||
650 | */ | ||||
651 | EAPI__attribute__ ((visibility("default"))) void * | ||||
652 | eina_rectangle_pool_data_get(Eina_Rectangle_Pool *pool) | ||||
653 | { | ||||
654 | EINA_MAGIC_CHECK_RECTANGLE_POOL(pool)do { if (!(((pool)) && (((pool))->__magic == (0x1578FCB0 )))) { eina_magic_fail((void *)((pool)), ((pool)) ? ((pool))-> __magic : 0, (0x1578FCB0), "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 654);; } } while (0); | ||||
655 | EINA_SAFETY_ON_NULL_RETURN_VAL(pool, NULL)do { if (__builtin_expect(((pool) == ((void*)0)), 0)) { eina_error_set (EINA_ERROR_SAFETY_FAILED); eina_log_print(EINA_LOG_DOMAIN_GLOBAL , EINA_LOG_LEVEL_ERR, "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 655, "%s", "safety check failed: " "pool" " == NULL"); return (((void*)0)); } } while (0); | ||||
656 | |||||
657 | return pool->data; | ||||
658 | } | ||||
659 | |||||
660 | /** | ||||
661 | * @brief Return the width and height of the given pool. | ||||
662 | * | ||||
663 | * @param pool The pool. | ||||
664 | * @param w The returned width. | ||||
665 | * @param h The returned height. | ||||
666 | * @return #EINA_TRUE on success, #EINA_FALSE otherwise. | ||||
667 | * | ||||
668 | * This function returns the width and height of @p pool and store | ||||
669 | * them in respectively @p w and @p h if they are not @c NULL. If | ||||
670 | * @p pool is @c NULL, #EINA_FALSE is returned. Otherwise #EINA_TRUE is | ||||
671 | * returned. | ||||
672 | */ | ||||
673 | EAPI__attribute__ ((visibility("default"))) Eina_Bool | ||||
674 | eina_rectangle_pool_geometry_get(Eina_Rectangle_Pool *pool, int *w, int *h) | ||||
675 | { | ||||
676 | if (!pool) | ||||
677 | return EINA_FALSE((Eina_Bool)0); | ||||
678 | |||||
679 | EINA_MAGIC_CHECK_RECTANGLE_POOL(pool)do { if (!(((pool)) && (((pool))->__magic == (0x1578FCB0 )))) { eina_magic_fail((void *)((pool)), ((pool)) ? ((pool))-> __magic : 0, (0x1578FCB0), "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 679);; } } while (0); | ||||
680 | EINA_SAFETY_ON_NULL_RETURN_VAL(pool, EINA_FALSE)do { if (__builtin_expect(((pool) == ((void*)0)), 0)) { eina_error_set (EINA_ERROR_SAFETY_FAILED); eina_log_print(EINA_LOG_DOMAIN_GLOBAL , EINA_LOG_LEVEL_ERR, "ecore/src/lib/eina_rectangle.c", __FUNCTION__ , 680, "%s", "safety check failed: " "pool" " == NULL"); return (((Eina_Bool)0)); } } while (0); | ||||
681 | |||||
682 | if (w) | ||||
683 | *w = pool->w; | ||||
684 | |||||
685 | if (h) | ||||
686 | *h = pool->h; | ||||
687 | |||||
688 | return EINA_TRUE((Eina_Bool)1); | ||||
689 | } | ||||
690 | |||||
691 | /** | ||||
692 | * @} | ||||
693 | */ |