codec: jpeg: fix sanity checks
[vlc.git] / src / misc / objres.c
blob1afaccb7003db961bfae58f461778f319022a9e0
1 /*****************************************************************************
2 * objres.c: vlc_object_t resources
3 *****************************************************************************
4 * Copyright (C) 2017 RĂ©mi Denis-Courmont
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
25 #include <assert.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <stdalign.h>
30 #include <vlc_common.h>
32 #include "libvlc.h"
33 #include "variables.h"
35 struct vlc_res
37 struct vlc_res *prev;
38 void (*release)(void *);
39 max_align_t payload[];
42 static struct vlc_res **vlc_obj_res(vlc_object_t *obj)
44 return &vlc_internals(obj)->resources;
47 void *vlc_objres_new(size_t size, void (*release)(void *))
49 if (unlikely(size > SIZE_MAX - sizeof (struct vlc_res)))
51 errno = ENOMEM;
52 return NULL;
55 struct vlc_res *res = malloc(sizeof (*res) + size);
56 if (unlikely(res == NULL))
57 return NULL;
59 res->release = release;
60 return res->payload;
63 void vlc_objres_push(vlc_object_t *obj, void *data)
65 struct vlc_res **restrict pp = vlc_obj_res(obj);
66 struct vlc_res *res = container_of(data, struct vlc_res, payload);
68 res->prev = *pp;
69 *pp = res;
72 static void *vlc_objres_pop(vlc_object_t *obj)
74 struct vlc_res **restrict pp = vlc_obj_res(obj);
75 struct vlc_res *res = *pp;
77 if (res == NULL)
78 return NULL;
79 *pp = res->prev;
80 return res->payload;
83 void vlc_objres_clear(vlc_object_t *obj)
85 void *data;
87 while ((data = vlc_objres_pop(obj)) != NULL)
89 struct vlc_res *res = container_of(data, struct vlc_res, payload);
91 res->release(res->payload);
92 free(res);
96 void vlc_objres_remove(vlc_object_t *obj, void *data,
97 bool (*match)(void *, void *))
99 struct vlc_res **restrict pp = vlc_obj_res(obj);
101 /* With a doubly-linked list, this function could have constant complexity.
102 * But that would require one more pointer per resource.
104 * Any given list should contain a fairly small number of resources,
105 * and in most cases, the resources are destroyed implicitly by
106 * vlc_objres_clear().
108 for (;;)
110 struct vlc_res *res = *pp;
112 assert(res != NULL); /* invalid free? */
114 if (match(res->payload, data))
116 *pp = res->prev;
117 res->release(res->payload);
118 free(res);
119 return;
122 pp = &res->prev;
126 static void dummy_release(void *data)
128 (void) data;
131 static bool ptrcmp(void *a, void *b)
133 return a == b;
136 void *vlc_malloc(vlc_object_t *obj, size_t size)
138 void *ptr = vlc_objres_new(size, dummy_release);
139 if (likely(ptr != NULL))
140 vlc_objres_push(obj, ptr);
141 return ptr;
144 void *vlc_calloc(vlc_object_t *obj, size_t nmemb, size_t size)
146 size_t tabsize = nmemb * size;
148 if (unlikely(tabsize < nmemb))
150 errno = ENOMEM;
151 return NULL;
154 void *ptr = vlc_objres_new(tabsize, dummy_release);
155 if (likely(ptr != NULL))
157 memset(ptr, 0, tabsize);
158 vlc_objres_push(obj, ptr);
160 return ptr;
163 void vlc_free(vlc_object_t *obj, void *ptr)
165 vlc_objres_remove(obj, ptr, ptrcmp);