Line | Count | Source (jump to first uncovered line) |
1 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | | * Copyright by The HDF Group. * |
3 | | * All rights reserved. * |
4 | | * * |
5 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
6 | | * terms governing use, modification, and redistribution, is contained in * |
7 | | * the LICENSE file, which can be found at the root of the source code * |
8 | | * distribution tree, or in https://www.hdfgroup.org/licenses. * |
9 | | * If you do not have access to either file, you may request a copy from * |
10 | | * help@hdfgroup.org. * |
11 | | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
12 | | |
13 | | /*------------------------------------------------------------------------- |
14 | | * |
15 | | * Created: H5WB.c |
16 | | * |
17 | | * Purpose: Implements the "wrapped buffer" code for wrapping |
18 | | * an existing [statically sized] buffer, in order to |
19 | | * avoid lots of memory allocation calls. |
20 | | * |
21 | | *------------------------------------------------------------------------- |
22 | | */ |
23 | | |
24 | | /****************/ |
25 | | /* Module Setup */ |
26 | | /****************/ |
27 | | |
28 | | /***********/ |
29 | | /* Headers */ |
30 | | /***********/ |
31 | | #include "H5private.h" /* Generic Functions */ |
32 | | #include "H5Eprivate.h" /* Error handling */ |
33 | | #include "H5FLprivate.h" /* Free Lists */ |
34 | | #include "H5WBprivate.h" /* Wrapped Buffers */ |
35 | | |
36 | | /****************/ |
37 | | /* Local Macros */ |
38 | | /****************/ |
39 | | |
40 | | /******************/ |
41 | | /* Local Typedefs */ |
42 | | /******************/ |
43 | | |
44 | | /********************/ |
45 | | /* Package Typedefs */ |
46 | | /********************/ |
47 | | |
48 | | /* Typedef for buffer wrapper */ |
49 | | struct H5WB_t { |
50 | | void *wrapped_buf; /* Pointer to wrapped buffer */ |
51 | | size_t wrapped_size; /* Size of wrapped buffer */ |
52 | | void *actual_buf; /* Pointer to actual buffer */ |
53 | | size_t actual_size; /* Size of actual buffer used */ |
54 | | size_t alloc_size; /* Size of actual buffer allocated */ |
55 | | }; |
56 | | |
57 | | /********************/ |
58 | | /* Local Prototypes */ |
59 | | /********************/ |
60 | | |
61 | | /*********************/ |
62 | | /* Package Variables */ |
63 | | /*********************/ |
64 | | |
65 | | /*****************************/ |
66 | | /* Library Private Variables */ |
67 | | /*****************************/ |
68 | | |
69 | | /*******************/ |
70 | | /* Local Variables */ |
71 | | /*******************/ |
72 | | |
73 | | /* Declare a free list to manage the H5WB_t struct */ |
74 | | H5FL_DEFINE_STATIC(H5WB_t); |
75 | | |
76 | | /* Declare a free list to manage the extra buffer information */ |
77 | | H5FL_BLK_DEFINE_STATIC(extra_buf); |
78 | | |
79 | | /*------------------------------------------------------------------------- |
80 | | * Function: H5WB_wrap |
81 | | * |
82 | | * Purpose: Wraps an existing [possibly static] buffer |
83 | | * |
84 | | * Return: Pointer to buffer wrapper info on success |
85 | | * NULL on failure |
86 | | * |
87 | | *------------------------------------------------------------------------- |
88 | | */ |
89 | | H5WB_t * |
90 | | H5WB_wrap(void *buf, size_t buf_size) |
91 | 1.76k | { |
92 | 1.76k | H5WB_t *wb = NULL; /* Wrapped buffer info */ |
93 | 1.76k | H5WB_t *ret_value; /* Return value */ |
94 | | |
95 | 1.76k | FUNC_ENTER_NOAPI(NULL) |
96 | | |
97 | | /* |
98 | | * Check arguments. |
99 | | */ |
100 | 1.76k | assert(buf); |
101 | 1.76k | assert(buf_size); |
102 | | |
103 | | /* Create wrapped buffer info */ |
104 | 1.76k | if (NULL == (wb = H5FL_MALLOC(H5WB_t))) |
105 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for wrapped buffer info"); |
106 | | |
107 | | /* Wrap buffer given */ |
108 | 1.76k | wb->wrapped_buf = buf; |
109 | 1.76k | wb->wrapped_size = buf_size; |
110 | | |
111 | | /* No actual buffer yet */ |
112 | 1.76k | wb->actual_buf = NULL; |
113 | 1.76k | wb->actual_size = 0; |
114 | 1.76k | wb->alloc_size = 0; |
115 | | |
116 | | /* Set the return value */ |
117 | 1.76k | ret_value = wb; |
118 | | |
119 | 1.76k | done: |
120 | | /* Release resources on error */ |
121 | 1.76k | if (!ret_value && wb) |
122 | 0 | wb = H5FL_FREE(H5WB_t, wb); |
123 | | |
124 | 1.76k | FUNC_LEAVE_NOAPI(ret_value) |
125 | 1.76k | } /* end H5WB_wrap() */ |
126 | | |
127 | | /*------------------------------------------------------------------------- |
128 | | * Function: H5WB_actual |
129 | | * |
130 | | * Purpose: Get the pointer to an "actual" buffer, of at least a certain |
131 | | * size. |
132 | | * |
133 | | * Return: Pointer to buffer pointer on success |
134 | | * NULL on failure |
135 | | * |
136 | | *------------------------------------------------------------------------- |
137 | | */ |
138 | | void * |
139 | | H5WB_actual(H5WB_t *wb, size_t need) |
140 | 1.76k | { |
141 | 1.76k | void *ret_value; /* Return value */ |
142 | | |
143 | 1.76k | FUNC_ENTER_NOAPI(NULL) |
144 | | |
145 | | /* |
146 | | * Check arguments. |
147 | | */ |
148 | 1.76k | assert(wb); |
149 | 1.76k | assert(wb->wrapped_buf); |
150 | | |
151 | | /* Check for previously allocated buffer */ |
152 | 1.76k | if (wb->actual_buf && wb->actual_buf != wb->wrapped_buf) { |
153 | | /* Sanity check */ |
154 | 0 | assert(wb->actual_size > wb->wrapped_size); |
155 | | |
156 | | /* Check if we can reuse existing buffer */ |
157 | 0 | if (need <= wb->alloc_size) |
158 | 0 | HGOTO_DONE(wb->actual_buf); |
159 | | /* Can't reuse existing buffer, free it and proceed */ |
160 | 0 | else |
161 | 0 | wb->actual_buf = H5FL_BLK_FREE(extra_buf, wb->actual_buf); |
162 | 0 | } /* end if */ |
163 | | |
164 | | /* Check if size needed can be fulfilled with wrapped buffer */ |
165 | 1.76k | if (need > wb->wrapped_size) { |
166 | | /* Need to allocate new buffer */ |
167 | 0 | if (NULL == (wb->actual_buf = H5FL_BLK_MALLOC(extra_buf, need))) |
168 | 0 | HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, NULL, "memory allocation failed"); |
169 | | |
170 | | /* Remember size of buffer allocated */ |
171 | 0 | wb->alloc_size = need; |
172 | 0 | } /* end if */ |
173 | 1.76k | else { |
174 | | /* Don't have to allocate a new buffer, use the wrapped one */ |
175 | 1.76k | wb->actual_buf = wb->wrapped_buf; |
176 | 1.76k | wb->alloc_size = 0; |
177 | 1.76k | } /* end else */ |
178 | | |
179 | | /* Set the return value */ |
180 | 1.76k | ret_value = wb->actual_buf; |
181 | | |
182 | 1.76k | done: |
183 | | /* Remember size of buffer used, if we were successful */ |
184 | 1.76k | if (ret_value) |
185 | 1.76k | wb->actual_size = need; |
186 | | |
187 | 1.76k | FUNC_LEAVE_NOAPI(ret_value) |
188 | 1.76k | } /* end H5WB_actual() */ |
189 | | |
190 | | /*------------------------------------------------------------------------- |
191 | | * Function: H5WB_actual_clear |
192 | | * |
193 | | * Purpose: Get the pointer to an "actual" buffer, of at least a certain |
194 | | * size. Also, clear actual buffer to zeros. |
195 | | * |
196 | | * Return: Pointer to buffer pointer on success |
197 | | * NULL on failure |
198 | | * |
199 | | *------------------------------------------------------------------------- |
200 | | */ |
201 | | void * |
202 | | H5WB_actual_clear(H5WB_t *wb, size_t need) |
203 | 0 | { |
204 | 0 | void *ret_value; /* Return value */ |
205 | |
|
206 | 0 | FUNC_ENTER_NOAPI(NULL) |
207 | | |
208 | | /* |
209 | | * Check arguments. |
210 | | */ |
211 | 0 | assert(wb); |
212 | 0 | assert(wb->wrapped_buf); |
213 | | |
214 | | /* Get a pointer to an actual buffer */ |
215 | 0 | if (NULL == (ret_value = H5WB_actual(wb, need))) |
216 | 0 | HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, NULL, "memory allocation failed"); |
217 | | |
218 | | /* Clear the buffer */ |
219 | 0 | memset(ret_value, 0, need); |
220 | |
|
221 | 0 | done: |
222 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
223 | 0 | } /* end H5WB_actual_clear() */ |
224 | | |
225 | | /*------------------------------------------------------------------------- |
226 | | * Function: H5WB_unwrap |
227 | | * |
228 | | * Purpose: "unwrap" a wrapped buffer, releasing all resources used |
229 | | * |
230 | | * Return: SUCCEED/FAIL |
231 | | * |
232 | | *------------------------------------------------------------------------- |
233 | | */ |
234 | | herr_t |
235 | | H5WB_unwrap(H5WB_t *wb) |
236 | 1.76k | { |
237 | 1.76k | FUNC_ENTER_NOAPI_NOINIT_NOERR |
238 | | |
239 | | /* |
240 | | * Check arguments. |
241 | | */ |
242 | 1.76k | assert(wb); |
243 | 1.76k | assert(wb->wrapped_buf); |
244 | | |
245 | | /* Release any extra buffers allocated */ |
246 | 1.76k | if (wb->actual_buf && wb->actual_buf != wb->wrapped_buf) { |
247 | | /* Sanity check */ |
248 | 0 | assert(wb->actual_size > wb->wrapped_size); |
249 | |
|
250 | 0 | wb->actual_buf = H5FL_BLK_FREE(extra_buf, wb->actual_buf); |
251 | 0 | } /* end if */ |
252 | | |
253 | | /* Release the buffer wrapper info */ |
254 | 1.76k | wb = H5FL_FREE(H5WB_t, wb); |
255 | | |
256 | 1.76k | FUNC_LEAVE_NOAPI(SUCCEED) |
257 | 1.76k | } /* end H5WB_unwrap() */ |