1 /*
2 ** SPDX-License-Identifier: BSD-3-Clause
3 ** Copyright Contributors to the OpenEXR Project.
4 */
5
6 #include "internal_attr.h"
7
8 #include "internal_constants.h"
9 #include "internal_structs.h"
10
11 #include <string.h>
12
13 /**************************************/
14
15 int
exr_attr_opaquedata_init(exr_context_t ctxt,exr_attr_opaquedata_t * u,size_t b)16 exr_attr_opaquedata_init (
17 exr_context_t ctxt, exr_attr_opaquedata_t* u, size_t b)
18 {
19 exr_attr_opaquedata_t nil = { 0 };
20
21 INTERN_EXR_PROMOTE_CONTEXT_OR_ERROR (ctxt);
22
23 if (!u)
24 return pctxt->report_error (
25 pctxt,
26 EXR_ERR_INVALID_ARGUMENT,
27 "Invalid reference to opaque data object to initialize");
28
29 if (b > (size_t) INT32_MAX)
30 return pctxt->print_error (
31 pctxt,
32 EXR_ERR_INVALID_ARGUMENT,
33 "Invalid size for opaque data (%" PRIu64
34 " bytes, must be <= INT32_MAX)",
35 (uint64_t) b);
36
37 *u = nil;
38 if (b > 0)
39 {
40
41 u->packed_data = pctxt->alloc_fn (b);
42 if (!u->packed_data)
43 return pctxt->standard_error (pctxt, EXR_ERR_OUT_OF_MEMORY);
44 }
45 u->size = (int32_t) b;
46 u->packed_alloc_size = (int32_t) b;
47 return EXR_ERR_SUCCESS;
48 }
49
50 /**************************************/
51
52 exr_result_t
exr_attr_opaquedata_create(exr_context_t ctxt,exr_attr_opaquedata_t * u,size_t b,const void * d)53 exr_attr_opaquedata_create (
54 exr_context_t ctxt, exr_attr_opaquedata_t* u, size_t b, const void* d)
55 {
56 exr_result_t rv = exr_attr_opaquedata_init (ctxt, u, b);
57 if (rv == EXR_ERR_SUCCESS)
58 {
59 if (d) memcpy ((void*) u->packed_data, d, b);
60 }
61
62 return rv;
63 }
64
65 /**************************************/
66
67 exr_result_t
exr_attr_opaquedata_destroy(exr_context_t ctxt,exr_attr_opaquedata_t * ud)68 exr_attr_opaquedata_destroy (exr_context_t ctxt, exr_attr_opaquedata_t* ud)
69 {
70 INTERN_EXR_PROMOTE_CONTEXT_OR_ERROR (ctxt);
71
72 if (ud)
73 {
74 exr_attr_opaquedata_t nil = { 0 };
75 if (ud->packed_data && ud->packed_alloc_size > 0)
76 pctxt->free_fn (ud->packed_data);
77
78 if (ud->unpacked_data && ud->destroy_unpacked_func_ptr)
79 ud->destroy_unpacked_func_ptr (
80 ctxt, ud->unpacked_data, ud->unpacked_size);
81 *ud = nil;
82 }
83 return EXR_ERR_SUCCESS;
84 }
85
86 /**************************************/
87
88 exr_result_t
exr_attr_opaquedata_copy(exr_context_t ctxt,exr_attr_opaquedata_t * ud,const exr_attr_opaquedata_t * srcud)89 exr_attr_opaquedata_copy (
90 exr_context_t ctxt,
91 exr_attr_opaquedata_t* ud,
92 const exr_attr_opaquedata_t* srcud)
93 {
94 exr_result_t rv;
95 if (!srcud) return EXR_ERR_INVALID_ARGUMENT;
96 if (srcud->packed_data)
97 return exr_attr_opaquedata_create (
98 ctxt, ud, (size_t) srcud->size, srcud->packed_data);
99 rv = exr_attr_opaquedata_init (ctxt, ud, 0);
100 if (rv == EXR_ERR_SUCCESS)
101 rv = exr_attr_opaquedata_set_unpacked (
102 ctxt, ud, srcud->unpacked_data, srcud->unpacked_size);
103 return rv;
104 }
105
106 /**************************************/
107
108 exr_result_t
exr_attr_opaquedata_unpack(exr_context_t ctxt,exr_attr_opaquedata_t * u,int32_t * sz,void ** unpacked)109 exr_attr_opaquedata_unpack (
110 exr_context_t ctxt, exr_attr_opaquedata_t* u, int32_t* sz, void** unpacked)
111 {
112 exr_result_t rv;
113 int32_t tmpusz;
114 void *tmpuptr;
115
116 INTERN_EXR_PROMOTE_CONTEXT_OR_ERROR (ctxt);
117
118 if (sz) *sz = 0;
119 if (unpacked) *unpacked = NULL;
120
121 if (!u)
122 return pctxt->report_error (
123 pctxt,
124 EXR_ERR_INVALID_ARGUMENT,
125 "Invalid reference to opaque data object to initialize");
126
127 if (u->unpacked_data)
128 {
129 if (sz) *sz = u->unpacked_size;
130 if (unpacked) *unpacked = u->unpacked_data;
131 return EXR_ERR_SUCCESS;
132 }
133
134 if (!u->unpack_func_ptr)
135 return pctxt->report_error (
136 pctxt,
137 EXR_ERR_INVALID_ARGUMENT,
138 "No unpack provider specified for opaque data");
139 rv = u->unpack_func_ptr (
140 ctxt,
141 u->packed_data,
142 u->size,
143 &(tmpusz),
144 &(tmpuptr));
145 if (rv == EXR_ERR_SUCCESS)
146 {
147 u->unpacked_size = tmpusz;
148 u->unpacked_data = tmpuptr;
149 if (sz) *sz = tmpusz;
150 if (unpacked) *unpacked = tmpuptr;
151 }
152
153 return rv;
154 }
155
156 /**************************************/
157
158 exr_result_t
exr_attr_opaquedata_pack(exr_context_t ctxt,exr_attr_opaquedata_t * u,int32_t * sz,void ** packed)159 exr_attr_opaquedata_pack (
160 exr_context_t ctxt, exr_attr_opaquedata_t* u, int32_t* sz, void** packed)
161 {
162 exr_result_t rv;
163 int32_t nsize = 0;
164 void* tmpptr = NULL;
165
166 INTERN_EXR_PROMOTE_CONTEXT_OR_ERROR (ctxt);
167
168 if (sz) *sz = 0;
169 if (packed) *packed = NULL;
170
171 if (!u)
172 return pctxt->report_error (
173 pctxt,
174 EXR_ERR_INVALID_ARGUMENT,
175 "Invalid reference to opaque data object to initialize");
176
177 if (u->packed_data)
178 {
179 if (sz) *sz = u->size;
180 if (packed) *packed = u->packed_data;
181 return EXR_ERR_SUCCESS;
182 }
183
184 if (!u->pack_func_ptr)
185 return pctxt->report_error (
186 pctxt,
187 EXR_ERR_INVALID_ARGUMENT,
188 "No pack provider specified for opaque data");
189
190 rv = u->pack_func_ptr (
191 ctxt, u->unpacked_data, u->unpacked_size, &nsize, NULL);
192 if (rv != EXR_ERR_SUCCESS)
193 return pctxt->print_error (
194 pctxt,
195 rv,
196 "Pack function failed finding pack buffer size, unpacked size %d",
197 u->unpacked_size);
198
199 if (nsize > 0)
200 {
201 tmpptr = pctxt->alloc_fn ((size_t) nsize);
202 if (tmpptr == NULL)
203 return pctxt->standard_error (pctxt, EXR_ERR_OUT_OF_MEMORY);
204
205 u->packed_alloc_size = nsize;
206
207 rv = u->pack_func_ptr (
208 ctxt, u->unpacked_data, u->unpacked_size, &nsize, tmpptr);
209 if (rv != EXR_ERR_SUCCESS)
210 {
211 pctxt->free_fn (tmpptr);
212 nsize = u->packed_alloc_size;
213 u->packed_alloc_size = 0;
214 return pctxt->print_error (
215 pctxt,
216 rv,
217 "Pack function failed to pack data, unpacked size %d, packed buffer size %d",
218 u->unpacked_size,
219 nsize);
220 }
221 u->size = nsize;
222 u->packed_data = tmpptr;
223 if (sz) *sz = nsize;
224 if (packed) *packed = tmpptr;
225
226 if (u->destroy_unpacked_func_ptr)
227 u->destroy_unpacked_func_ptr (
228 ctxt, u->unpacked_data, u->unpacked_size);
229 u->unpacked_data = NULL;
230 u->unpacked_size = 0;
231 }
232 return rv;
233 }
234
235 /**************************************/
236
237 exr_result_t
exr_attr_opaquedata_set_unpacked(exr_context_t ctxt,exr_attr_opaquedata_t * u,void * unpacked,int32_t sz)238 exr_attr_opaquedata_set_unpacked (
239 exr_context_t ctxt, exr_attr_opaquedata_t* u, void* unpacked, int32_t sz)
240 {
241 INTERN_EXR_PROMOTE_CONTEXT_OR_ERROR (ctxt);
242
243 if (!u) return pctxt->standard_error (pctxt, EXR_ERR_INVALID_ARGUMENT);
244
245 /* TODO: do we care if the incoming unpacked data is null? */
246 if (sz < 0)
247 return pctxt->print_error (
248 pctxt,
249 EXR_ERR_INVALID_ARGUMENT,
250 "Opaque data given invalid negative size (%d)",
251 sz);
252
253 if (u->unpacked_data)
254 {
255 if (u->destroy_unpacked_func_ptr)
256 u->destroy_unpacked_func_ptr (
257 ctxt, u->unpacked_data, u->unpacked_size);
258 }
259 u->unpacked_data = unpacked;
260 u->unpacked_size = sz;
261
262 if (u->packed_data)
263 {
264 if (u->packed_alloc_size > 0) pctxt->free_fn (u->packed_data);
265 u->packed_data = NULL;
266 u->size = 0;
267 u->packed_alloc_size = 0;
268 }
269 return EXR_ERR_SUCCESS;
270 }
271
272 /**************************************/
273
274 exr_result_t
exr_attr_opaquedata_set_packed(exr_context_t ctxt,exr_attr_opaquedata_t * u,const void * packed,int32_t sz)275 exr_attr_opaquedata_set_packed (
276 exr_context_t ctxt,
277 exr_attr_opaquedata_t* u,
278 const void* packed,
279 int32_t sz)
280 {
281 void* nmem;
282 INTERN_EXR_PROMOTE_CONTEXT_OR_ERROR (ctxt);
283
284 if (!u) return pctxt->standard_error (pctxt, EXR_ERR_INVALID_ARGUMENT);
285
286 /* TODO: do we care if the incoming unpacked data is null? */
287 if (sz < 0)
288 return pctxt->print_error (
289 pctxt,
290 EXR_ERR_INVALID_ARGUMENT,
291 "Opaque data given invalid negative size (%d)",
292 sz);
293
294 nmem = pctxt->alloc_fn ((size_t)sz);
295 if (!nmem) return pctxt->standard_error (pctxt, EXR_ERR_OUT_OF_MEMORY);
296
297 if (u->unpacked_data)
298 {
299 if (u->destroy_unpacked_func_ptr)
300 u->destroy_unpacked_func_ptr (
301 ctxt, u->unpacked_data, u->unpacked_size);
302 }
303 u->unpacked_data = NULL;
304 u->unpacked_size = 0;
305
306 if (u->packed_data)
307 {
308 if (u->packed_alloc_size > 0) pctxt->free_fn (u->packed_data);
309 u->packed_data = NULL;
310 u->size = 0;
311 u->packed_alloc_size = 0;
312 }
313
314 u->packed_data = nmem;
315 u->size = sz;
316 u->packed_alloc_size = sz;
317 if (packed) memcpy ((void*) u->packed_data, packed, (size_t)sz);
318
319 return EXR_ERR_SUCCESS;
320 }
321