Line | Count | Source |
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 | | * Module Info: This module contains the functionality for enumerated datatypes |
15 | | * in the H5T interface. |
16 | | */ |
17 | | |
18 | | #include "H5Tmodule.h" /* This source code file is part of the H5T module */ |
19 | | |
20 | | #include "H5private.h" /*generic functions */ |
21 | | #include "H5Eprivate.h" /*error handling */ |
22 | | #include "H5Iprivate.h" /*ID functions */ |
23 | | #include "H5MMprivate.h" /*memory management */ |
24 | | #include "H5Tpkg.h" /*data-type functions */ |
25 | | |
26 | | /* Static local functions */ |
27 | | static char *H5T__enum_nameof(const H5T_t *dt, const void *value, char *name /*out*/, size_t size); |
28 | | static herr_t H5T__enum_valueof(const H5T_t *dt, const char *name, void *value /*out*/); |
29 | | |
30 | | /*------------------------------------------------------------------------- |
31 | | * Function: H5Tenum_create |
32 | | * |
33 | | * Purpose: Create a new enumeration data type based on the specified |
34 | | * TYPE, which must be an integer type. |
35 | | * |
36 | | * Return: Success: ID of new enumeration data type |
37 | | * |
38 | | * Failure: Negative |
39 | | * |
40 | | *------------------------------------------------------------------------- |
41 | | */ |
42 | | hid_t |
43 | | H5Tenum_create(hid_t parent_id) |
44 | 0 | { |
45 | 0 | H5T_t *parent = NULL; /*base integer data type */ |
46 | 0 | H5T_t *dt = NULL; /*new enumeration data type */ |
47 | 0 | hid_t ret_value; /*return value */ |
48 | |
|
49 | 0 | FUNC_ENTER_API(H5I_INVALID_HID) |
50 | | |
51 | | /* Check args */ |
52 | 0 | if (NULL == (parent = (H5T_t *)H5I_object_verify(parent_id, H5I_DATATYPE)) || |
53 | 0 | H5T_INTEGER != parent->shared->type) |
54 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not an integer data type"); |
55 | | |
56 | | /* Build new type */ |
57 | 0 | if (NULL == (dt = H5T__enum_create(parent))) |
58 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5I_INVALID_HID, "cannot create enum type"); |
59 | | |
60 | | /* Register the type */ |
61 | 0 | if ((ret_value = H5I_register(H5I_DATATYPE, dt, true)) < 0) |
62 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register data type ID"); |
63 | | |
64 | 0 | done: |
65 | 0 | FUNC_LEAVE_API(ret_value) |
66 | 0 | } /* end H5Tenum_create() */ |
67 | | |
68 | | /*------------------------------------------------------------------------- |
69 | | * Function: H5T__enum_create |
70 | | * |
71 | | * Purpose: Private function for H5Tenum_create. Create a new |
72 | | * enumeration data type based on the specified |
73 | | * TYPE, which must be an integer type. |
74 | | * |
75 | | * Return: Success: new enumeration data type |
76 | | * Failure: NULL |
77 | | * |
78 | | *------------------------------------------------------------------------- |
79 | | */ |
80 | | H5T_t * |
81 | | H5T__enum_create(const H5T_t *parent) |
82 | 0 | { |
83 | 0 | H5T_t *ret_value = NULL; /* New enumeration data type */ |
84 | |
|
85 | 0 | FUNC_ENTER_PACKAGE |
86 | |
|
87 | 0 | assert(parent); |
88 | | |
89 | | /* Build new type */ |
90 | 0 | if (NULL == (ret_value = H5T__alloc())) |
91 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
92 | 0 | ret_value->shared->type = H5T_ENUM; |
93 | |
|
94 | 0 | if (NULL == (ret_value->shared->parent = H5T_copy(parent, H5T_COPY_ALL))) |
95 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "unable to copy base datatype for enum"); |
96 | | |
97 | 0 | ret_value->shared->size = ret_value->shared->parent->shared->size; |
98 | |
|
99 | 0 | done: |
100 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
101 | 0 | } |
102 | | |
103 | | /*------------------------------------------------------------------------- |
104 | | * Function: H5Tenum_insert |
105 | | * |
106 | | * Purpose: Insert a new enumeration data type member into an enumeration |
107 | | * type. TYPE is the enumeration type, NAME is the name of the |
108 | | * new member, and VALUE points to the value of the new member. |
109 | | * The NAME and VALUE must both be unique within the TYPE. VALUE |
110 | | * points to data which is of the data type defined when the |
111 | | * enumeration type was created. |
112 | | * |
113 | | * Return: Success: non-negative |
114 | | * |
115 | | * Failure: negative |
116 | | * |
117 | | *------------------------------------------------------------------------- |
118 | | */ |
119 | | herr_t |
120 | | H5Tenum_insert(hid_t type, const char *name, const void *value) |
121 | 0 | { |
122 | 0 | H5T_t *dt = NULL; |
123 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
124 | |
|
125 | 0 | FUNC_ENTER_API(FAIL) |
126 | | |
127 | | /* Check args */ |
128 | 0 | if (NULL == (dt = (H5T_t *)H5I_object_verify(type, H5I_DATATYPE))) |
129 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); |
130 | 0 | if (H5T_ENUM != dt->shared->type) |
131 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an enumeration data type"); |
132 | 0 | if (!name || !*name) |
133 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified"); |
134 | 0 | if (!value) |
135 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no value specified"); |
136 | | |
137 | | /* Do work */ |
138 | 0 | if (H5T__enum_insert(dt, name, value) < 0) |
139 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to insert new enumeration member"); |
140 | | |
141 | 0 | done: |
142 | 0 | FUNC_LEAVE_API(ret_value) |
143 | 0 | } |
144 | | |
145 | | /*------------------------------------------------------------------------- |
146 | | * Function: H5T__enum_insert |
147 | | * |
148 | | * Purpose: Insert a new member having a NAME and VALUE into an |
149 | | * enumeration data TYPE. The NAME and VALUE must both be |
150 | | * unique. The VALUE points to data of the data type defined for |
151 | | * the enumeration base type. |
152 | | * |
153 | | * Return: Success: non-negative |
154 | | * |
155 | | * Failure: negative |
156 | | * |
157 | | *------------------------------------------------------------------------- |
158 | | */ |
159 | | herr_t |
160 | | H5T__enum_insert(const H5T_t *dt, const char *name, const void *value) |
161 | 0 | { |
162 | 0 | unsigned i; |
163 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
164 | |
|
165 | 0 | FUNC_ENTER_PACKAGE |
166 | |
|
167 | 0 | assert(dt); |
168 | 0 | assert(name && *name); |
169 | 0 | assert(value); |
170 | | |
171 | | /* The name and value had better not already exist */ |
172 | 0 | for (i = 0; i < dt->shared->u.enumer.nmembs; i++) { |
173 | 0 | if (!strcmp(dt->shared->u.enumer.name[i], name)) |
174 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "name redefinition"); |
175 | 0 | if (!memcmp((uint8_t *)dt->shared->u.enumer.value + (i * dt->shared->size), value, dt->shared->size)) |
176 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "value redefinition"); |
177 | 0 | } |
178 | | |
179 | | /* Increase table sizes */ |
180 | 0 | if (dt->shared->u.enumer.nmembs >= dt->shared->u.enumer.nalloc) { |
181 | 0 | char **names; |
182 | 0 | uint8_t *values; |
183 | 0 | unsigned n = MAX(32, 2 * dt->shared->u.enumer.nalloc); |
184 | |
|
185 | 0 | if (NULL == (names = (char **)H5MM_realloc(dt->shared->u.enumer.name, n * sizeof(char *)))) |
186 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); |
187 | 0 | dt->shared->u.enumer.name = names; |
188 | |
|
189 | 0 | if (NULL == (values = (uint8_t *)H5MM_realloc(dt->shared->u.enumer.value, n * dt->shared->size))) |
190 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); |
191 | 0 | dt->shared->u.enumer.value = values; |
192 | 0 | dt->shared->u.enumer.nalloc = n; |
193 | 0 | } |
194 | | |
195 | | /* Insert new member at end of member arrays */ |
196 | 0 | dt->shared->u.enumer.sorted = H5T_SORT_NONE; |
197 | 0 | i = dt->shared->u.enumer.nmembs++; |
198 | 0 | dt->shared->u.enumer.name[i] = H5MM_xstrdup(name); |
199 | 0 | H5MM_memcpy((uint8_t *)dt->shared->u.enumer.value + (i * dt->shared->size), value, dt->shared->size); |
200 | |
|
201 | 0 | done: |
202 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
203 | 0 | } |
204 | | |
205 | | /*------------------------------------------------------------------------- |
206 | | * Function: H5Tget_member_value |
207 | | * |
208 | | * Purpose: Return the value for an enumeration data type member. |
209 | | * |
210 | | * Return: Success: non-negative with the member value copied |
211 | | * into the memory pointed to by VALUE. |
212 | | * |
213 | | * Failure: negative, VALUE memory is undefined. |
214 | | * |
215 | | *------------------------------------------------------------------------- |
216 | | */ |
217 | | herr_t |
218 | | H5Tget_member_value(hid_t type, unsigned membno, void *value /*out*/) |
219 | 0 | { |
220 | 0 | H5T_t *dt = NULL; |
221 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
222 | |
|
223 | 0 | FUNC_ENTER_API(FAIL) |
224 | |
|
225 | 0 | if (NULL == (dt = (H5T_t *)H5I_object_verify(type, H5I_DATATYPE))) |
226 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); |
227 | 0 | if (H5T_ENUM != dt->shared->type) |
228 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for data type class"); |
229 | 0 | if (membno >= dt->shared->u.enumer.nmembs) |
230 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid member number"); |
231 | 0 | if (!value) |
232 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "null value buffer"); |
233 | | |
234 | 0 | if (H5T__get_member_value(dt, membno, value) < 0) |
235 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get member value"); |
236 | 0 | done: |
237 | 0 | FUNC_LEAVE_API(ret_value) |
238 | 0 | } |
239 | | |
240 | | /*------------------------------------------------------------------------- |
241 | | * Function: H5T__get_member_value |
242 | | * |
243 | | * Purpose: Private function for H5T__get_member_value. Return the |
244 | | * value for an enumeration data type member. |
245 | | * |
246 | | * Return: Success: non-negative with the member value copied |
247 | | * into the memory pointed to by VALUE. |
248 | | * |
249 | | * Failure: negative, VALUE memory is undefined. |
250 | | * |
251 | | *------------------------------------------------------------------------- |
252 | | */ |
253 | | herr_t |
254 | | H5T__get_member_value(const H5T_t *dt, unsigned membno, void *value /*out*/) |
255 | 0 | { |
256 | 0 | FUNC_ENTER_PACKAGE_NOERR |
257 | |
|
258 | 0 | assert(dt); |
259 | 0 | assert(value); |
260 | |
|
261 | 0 | H5MM_memcpy(value, (uint8_t *)dt->shared->u.enumer.value + (membno * dt->shared->size), dt->shared->size); |
262 | |
|
263 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
264 | 0 | } |
265 | | |
266 | | /*------------------------------------------------------------------------- |
267 | | * Function: H5Tenum_nameof |
268 | | * |
269 | | * Purpose: Finds the symbol name that corresponds to the specified VALUE |
270 | | * of an enumeration data type TYPE. At most SIZE characters of |
271 | | * the symbol name are copied into the NAME buffer. If the |
272 | | * entire symbol anem and null terminator do not fit in the NAME |
273 | | * buffer then as many characters as possible are copied (not |
274 | | * null terminated) and the function fails. |
275 | | * |
276 | | * Return: Success: Non-negative. |
277 | | * |
278 | | * Failure: Negative, first character of NAME is set to |
279 | | * null if SIZE allows it. |
280 | | * |
281 | | *------------------------------------------------------------------------- |
282 | | */ |
283 | | herr_t |
284 | | H5Tenum_nameof(hid_t type, const void *value, char *name /*out*/, size_t size) |
285 | 0 | { |
286 | 0 | H5T_t *dt = NULL; |
287 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
288 | |
|
289 | 0 | FUNC_ENTER_API(FAIL) |
290 | | |
291 | | /* Check args */ |
292 | 0 | if (NULL == (dt = (H5T_t *)H5I_object_verify(type, H5I_DATATYPE))) |
293 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); |
294 | 0 | if (H5T_ENUM != dt->shared->type) |
295 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an enumeration data type"); |
296 | 0 | if (!value) |
297 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no value supplied"); |
298 | 0 | if (!name) |
299 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name buffer supplied"); |
300 | | |
301 | 0 | if (NULL == H5T__enum_nameof(dt, value, name, size)) |
302 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "nameof query failed"); |
303 | | |
304 | 0 | done: |
305 | 0 | FUNC_LEAVE_API(ret_value) |
306 | 0 | } |
307 | | |
308 | | /*------------------------------------------------------------------------- |
309 | | * Function: H5T__enum_nameof |
310 | | * |
311 | | * Purpose: Finds the symbol name that corresponds to the specified |
312 | | * VALUE of an enumeration data type DT. At most SIZE characters |
313 | | * of the symbol name are copied into the NAME buffer. If the |
314 | | * entire symbol name and null terminator do not fit in the NAME |
315 | | * buffer then as many characters as possible are copied and the |
316 | | * function returns failure. |
317 | | * |
318 | | * If NAME is the null pointer and SIZE is zero then enough |
319 | | * space is allocated to hold the result and a pointer to that |
320 | | * memory is returned. |
321 | | * |
322 | | * Return: Success: Pointer to NAME |
323 | | * |
324 | | * Failure: NULL, name[0] is set to null. |
325 | | * |
326 | | *------------------------------------------------------------------------- |
327 | | */ |
328 | | static char * |
329 | | H5T__enum_nameof(const H5T_t *dt, const void *value, char *name /*out*/, size_t size) |
330 | 0 | { |
331 | 0 | H5T_t *copied_dt = NULL; /* Do sorting in copied datatype */ |
332 | 0 | unsigned lt, md = 0, rt; /* Indices for binary search */ |
333 | 0 | int cmp = (-1); /* Comparison result */ |
334 | 0 | bool alloc_name = false; /* Whether name has been allocated */ |
335 | 0 | char *ret_value = NULL; /* Return value */ |
336 | |
|
337 | 0 | FUNC_ENTER_PACKAGE |
338 | | |
339 | | /* Check args */ |
340 | 0 | assert(dt && H5T_ENUM == dt->shared->type); |
341 | 0 | assert(value); |
342 | 0 | assert(name || 0 == size); |
343 | |
|
344 | 0 | if (name && size > 0) |
345 | 0 | *name = '\0'; |
346 | | |
347 | | /* Sanity check */ |
348 | 0 | if (dt->shared->u.enumer.nmembs == 0) |
349 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "datatype has no members"); |
350 | | |
351 | | /* Do a binary search over the values to find the correct one. Do sorting |
352 | | * and search on the copied datatype to protect the original order. */ |
353 | 0 | if (NULL == (copied_dt = H5T_copy(dt, H5T_COPY_ALL))) |
354 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to copy data type"); |
355 | 0 | if (H5T__sort_value(copied_dt, NULL) < 0) |
356 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOMPARE, NULL, "value sort failed"); |
357 | | |
358 | 0 | lt = 0; |
359 | 0 | rt = copied_dt->shared->u.enumer.nmembs; |
360 | 0 | while (lt < rt) { |
361 | 0 | md = (lt + rt) / 2; |
362 | 0 | cmp = memcmp(value, (uint8_t *)copied_dt->shared->u.enumer.value + (md * copied_dt->shared->size), |
363 | 0 | copied_dt->shared->size); |
364 | 0 | if (cmp < 0) |
365 | 0 | rt = md; |
366 | 0 | else if (cmp > 0) |
367 | 0 | lt = md + 1; |
368 | 0 | else |
369 | 0 | break; |
370 | 0 | } /* end while */ |
371 | | |
372 | | /* Value was not yet defined. This fixes bug # 774, 2002/06/05 EIP */ |
373 | 0 | if (cmp != 0) |
374 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "value is currently not defined"); |
375 | | |
376 | | /* Save result name */ |
377 | 0 | if (!name) { |
378 | 0 | if (NULL == (name = (char *)H5MM_malloc(strlen(copied_dt->shared->u.enumer.name[md]) + 1))) |
379 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
380 | 0 | alloc_name = true; |
381 | 0 | } /* end if */ |
382 | 0 | strncpy(name, copied_dt->shared->u.enumer.name[md], size); |
383 | 0 | if (strlen(copied_dt->shared->u.enumer.name[md]) >= size) |
384 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, NULL, "name has been truncated"); |
385 | | |
386 | | /* Set return value */ |
387 | 0 | ret_value = name; |
388 | |
|
389 | 0 | done: |
390 | 0 | if (copied_dt) |
391 | 0 | if (H5T_close_real(copied_dt) < 0) |
392 | 0 | HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "unable to close data type"); |
393 | 0 | if (!ret_value && alloc_name) |
394 | 0 | H5MM_free(name); |
395 | |
|
396 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
397 | 0 | } /* end H5T__enum_nameof() */ |
398 | | |
399 | | /*------------------------------------------------------------------------- |
400 | | * Function: H5Tenum_valueof |
401 | | * |
402 | | * Purpose: Finds the value that corresponds to the specified NAME f an |
403 | | * enumeration TYPE. The VALUE argument should be at least as |
404 | | * large as the value of H5Tget_size(type) in order to hold the |
405 | | * result. |
406 | | * |
407 | | * Return: Success: Non-negative |
408 | | * |
409 | | * Failure: Negative |
410 | | * |
411 | | *------------------------------------------------------------------------- |
412 | | */ |
413 | | herr_t |
414 | | H5Tenum_valueof(hid_t type, const char *name, void *value /*out*/) |
415 | 0 | { |
416 | 0 | H5T_t *dt; |
417 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
418 | |
|
419 | 0 | FUNC_ENTER_API(FAIL) |
420 | | |
421 | | /* Check args */ |
422 | 0 | if (NULL == (dt = (H5T_t *)H5I_object_verify(type, H5I_DATATYPE))) |
423 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); |
424 | 0 | if (H5T_ENUM != dt->shared->type) |
425 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an enumeration data type"); |
426 | 0 | if (!name || !*name) |
427 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name"); |
428 | 0 | if (!value) |
429 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no value buffer"); |
430 | | |
431 | 0 | if (H5T__enum_valueof(dt, name, value) < 0) |
432 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "valueof query failed"); |
433 | | |
434 | 0 | done: |
435 | 0 | FUNC_LEAVE_API(ret_value) |
436 | 0 | } /* H5Tenum_valueof() */ |
437 | | |
438 | | /*------------------------------------------------------------------------- |
439 | | * Function: H5T__enum_valueof |
440 | | * |
441 | | * Purpose: Finds the value that corresponds to the specified symbol |
442 | | * NAME of an enumeration data type DT and copy it to the VALUE |
443 | | * result buffer. The VALUE should be allocated by the caller to |
444 | | * be large enough for the result. |
445 | | * |
446 | | * Return: Success: Non-negative, value stored in VALUE. |
447 | | * |
448 | | * Failure: Negative, VALUE is undefined. |
449 | | * |
450 | | *------------------------------------------------------------------------- |
451 | | */ |
452 | | static herr_t |
453 | | H5T__enum_valueof(const H5T_t *dt, const char *name, void *value /*out*/) |
454 | 0 | { |
455 | 0 | unsigned lt, md = 0, rt; /*indices for binary search */ |
456 | 0 | int cmp = (-1); /*comparison result */ |
457 | 0 | H5T_t *copied_dt = NULL; /*do sorting in copied datatype */ |
458 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
459 | |
|
460 | 0 | FUNC_ENTER_PACKAGE |
461 | | |
462 | | /* Check args */ |
463 | 0 | assert(dt && H5T_ENUM == dt->shared->type); |
464 | 0 | assert(name && *name); |
465 | 0 | assert(value); |
466 | | |
467 | | /* Sanity check */ |
468 | 0 | if (dt->shared->u.enumer.nmembs == 0) |
469 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "datatype has no members"); |
470 | | |
471 | | /* Do a binary search over the names to find the correct one. Do sorting |
472 | | * and search on the copied datatype to protect the original order. */ |
473 | 0 | if (NULL == (copied_dt = H5T_copy(dt, H5T_COPY_ALL))) |
474 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy data type"); |
475 | 0 | if (H5T__sort_name(copied_dt, NULL) < 0) |
476 | 0 | HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOMPARE, FAIL, "value sort failed"); |
477 | | |
478 | 0 | lt = 0; |
479 | 0 | rt = copied_dt->shared->u.enumer.nmembs; |
480 | |
|
481 | 0 | while (lt < rt) { |
482 | 0 | md = (lt + rt) / 2; |
483 | 0 | cmp = strcmp(name, copied_dt->shared->u.enumer.name[md]); |
484 | 0 | if (cmp < 0) { |
485 | 0 | rt = md; |
486 | 0 | } |
487 | 0 | else if (cmp > 0) { |
488 | 0 | lt = md + 1; |
489 | 0 | } |
490 | 0 | else { |
491 | 0 | break; |
492 | 0 | } |
493 | 0 | } |
494 | | /* Value was not yet defined. This fixes bug # 774, 2002/06/05 EIP */ |
495 | 0 | if (cmp != 0) |
496 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "string doesn't exist in the enumeration type"); |
497 | | |
498 | 0 | H5MM_memcpy(value, (uint8_t *)copied_dt->shared->u.enumer.value + (md * copied_dt->shared->size), |
499 | 0 | copied_dt->shared->size); |
500 | |
|
501 | 0 | done: |
502 | 0 | if (copied_dt) |
503 | 0 | if (H5T_close_real(copied_dt) < 0) |
504 | 0 | HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "unable to close data type"); |
505 | |
|
506 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
507 | 0 | } |