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: H5Tdbg.c |
16 | | * |
17 | | * Purpose: Dump debugging information about a datatype |
18 | | * |
19 | | *------------------------------------------------------------------------- |
20 | | */ |
21 | | |
22 | | /****************/ |
23 | | /* Module Setup */ |
24 | | /****************/ |
25 | | |
26 | | #include "H5Tmodule.h" /* This source code file is part of the H5T module */ |
27 | | |
28 | | /***********/ |
29 | | /* Headers */ |
30 | | /***********/ |
31 | | #include "H5private.h" /* Generic Functions */ |
32 | | #include "H5Eprivate.h" /* Error handling */ |
33 | | #include "H5Tpkg.h" /* Datatypes */ |
34 | | |
35 | | /****************/ |
36 | | /* Local Macros */ |
37 | | /****************/ |
38 | | |
39 | | /******************/ |
40 | | /* Local Typedefs */ |
41 | | /******************/ |
42 | | |
43 | | /********************/ |
44 | | /* Package Typedefs */ |
45 | | /********************/ |
46 | | |
47 | | /********************/ |
48 | | /* Local Prototypes */ |
49 | | /********************/ |
50 | | |
51 | | /*********************/ |
52 | | /* Package Variables */ |
53 | | /*********************/ |
54 | | |
55 | | /*****************************/ |
56 | | /* Library Private Variables */ |
57 | | /*****************************/ |
58 | | |
59 | | /*******************/ |
60 | | /* Local Variables */ |
61 | | /*******************/ |
62 | | |
63 | | /*------------------------------------------------------------------------- |
64 | | * Function: H5T__print_path_stats |
65 | | * |
66 | | * Purpose: Print statistics about a conversion path. Statistics are |
67 | | * printed only if all the following conditions are true: |
68 | | * |
69 | | * 1. The library was compiled with H5T_DEBUG defined. |
70 | | * 2. Data type debugging is turned on at run time. |
71 | | * 3. The path was called at least one time. |
72 | | * |
73 | | * The optional NPRINT argument keeps track of the number of |
74 | | * conversions paths for which statistics have been shown. If |
75 | | * its value is zero then table headers are printed before the |
76 | | * first line of output. |
77 | | * |
78 | | * Return: SUCCEED/FAIL |
79 | | * |
80 | | *------------------------------------------------------------------------- |
81 | | */ |
82 | | herr_t |
83 | | H5T__print_path_stats(H5T_path_t H5_ATTR_UNUSED *path, int H5_ATTR_UNUSED *nprint /*in,out*/) |
84 | 183 | { |
85 | 183 | FUNC_ENTER_PACKAGE_NOERR |
86 | | |
87 | | #ifdef H5T_DEBUG |
88 | | if (H5DEBUG(T) && path->stats.ncalls > 0) { |
89 | | hsize_t nbytes; |
90 | | char bandwidth[32]; |
91 | | struct { |
92 | | char *user; |
93 | | char *system; |
94 | | char *elapsed; |
95 | | } timestrs = {H5_timer_get_time_string(path->stats.times.user), |
96 | | H5_timer_get_time_string(path->stats.times.system), |
97 | | H5_timer_get_time_string(path->stats.times.elapsed)}; |
98 | | |
99 | | if (nprint && 0 == (*nprint)++) { |
100 | | fprintf(H5DEBUG(T), "H5T: type conversion statistics:\n"); |
101 | | fprintf(H5DEBUG(T), " %-16s %10s %10s %8s %8s %8s %10s\n", "Conversion", "Elmts", "Calls", |
102 | | "User", "System", "Elapsed", "Bandwidth"); |
103 | | fprintf(H5DEBUG(T), " %-16s %10s %10s %8s %8s %8s %10s\n", "----------", "-----", "-----", |
104 | | "----", "------", "-------", "---------"); |
105 | | } /* end if */ |
106 | | |
107 | | if (path->src && path->dst) |
108 | | nbytes = MAX(H5T_get_size(path->src), H5T_get_size(path->dst)); |
109 | | else if (path->src) |
110 | | nbytes = H5T_get_size(path->src); |
111 | | else if (path->dst) |
112 | | nbytes = H5T_get_size(path->dst); |
113 | | else |
114 | | nbytes = 0; |
115 | | nbytes *= path->stats.nelmts; |
116 | | H5_bandwidth(bandwidth, sizeof(bandwidth), (double)nbytes, path->stats.times.elapsed); |
117 | | fprintf(H5DEBUG(T), " %-16s %10" PRIdHSIZE " %10u %8s %8s %8s %10s\n", path->name, |
118 | | path->stats.nelmts, path->stats.ncalls, timestrs.user, timestrs.system, timestrs.elapsed, |
119 | | bandwidth); |
120 | | free(timestrs.user); |
121 | | free(timestrs.system); |
122 | | free(timestrs.elapsed); |
123 | | } |
124 | | #endif |
125 | | |
126 | 183 | FUNC_LEAVE_NOAPI(SUCCEED) |
127 | 183 | } /* end H5T__print_path_stats() */ |
128 | | |
129 | | /*------------------------------------------------------------------------- |
130 | | * Function: H5T_debug |
131 | | * |
132 | | * Purpose: Prints information about a data type. |
133 | | * |
134 | | * Return: SUCCEED/FAIL |
135 | | * |
136 | | *------------------------------------------------------------------------- |
137 | | */ |
138 | | herr_t |
139 | | H5T_debug(const H5T_t *dt, FILE *stream) |
140 | 0 | { |
141 | 0 | const char *s1 = ""; |
142 | 0 | const char *s2 = ""; |
143 | 0 | unsigned i; |
144 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
145 | |
|
146 | 0 | FUNC_ENTER_NOAPI_NOINIT |
147 | | |
148 | | /* Check args */ |
149 | 0 | assert(dt); |
150 | 0 | assert(stream); |
151 | |
|
152 | 0 | switch (dt->shared->type) { |
153 | 0 | case H5T_NO_CLASS: |
154 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "no class"); |
155 | 0 | break; |
156 | | |
157 | 0 | case H5T_INTEGER: |
158 | 0 | s1 = "int"; |
159 | 0 | break; |
160 | | |
161 | 0 | case H5T_FLOAT: |
162 | 0 | s1 = "float"; |
163 | 0 | break; |
164 | | |
165 | 0 | case H5T_TIME: |
166 | 0 | s1 = "time"; |
167 | 0 | break; |
168 | | |
169 | 0 | case H5T_STRING: |
170 | 0 | s1 = "str"; |
171 | 0 | break; |
172 | | |
173 | 0 | case H5T_BITFIELD: |
174 | 0 | s1 = "bits"; |
175 | 0 | break; |
176 | | |
177 | 0 | case H5T_OPAQUE: |
178 | 0 | s1 = "opaque"; |
179 | 0 | break; |
180 | | |
181 | 0 | case H5T_COMPOUND: |
182 | 0 | s1 = "struct"; |
183 | 0 | break; |
184 | | |
185 | 0 | case H5T_REFERENCE: |
186 | 0 | switch (dt->shared->u.atomic.u.r.rtype) { |
187 | 0 | case H5R_OBJECT1: |
188 | 0 | s1 = "object reference (old)"; |
189 | 0 | break; |
190 | 0 | case H5R_OBJECT2: |
191 | 0 | s1 = "object reference (new)"; |
192 | 0 | break; |
193 | 0 | case H5R_DATASET_REGION1: |
194 | 0 | s1 = "region reference (old)"; |
195 | 0 | break; |
196 | 0 | case H5R_DATASET_REGION2: |
197 | 0 | s1 = "region reference (new)"; |
198 | 0 | break; |
199 | 0 | case H5R_ATTR: |
200 | 0 | s1 = "attribute reference"; |
201 | 0 | break; |
202 | 0 | case H5R_BADTYPE: |
203 | 0 | case H5R_MAXTYPE: |
204 | 0 | default: |
205 | 0 | s1 = "invalid reference"; |
206 | 0 | break; |
207 | 0 | } |
208 | 0 | break; |
209 | | |
210 | 0 | case H5T_ENUM: |
211 | 0 | s1 = "enum"; |
212 | 0 | break; |
213 | | |
214 | 0 | case H5T_VLEN: |
215 | 0 | if (H5T_IS_VL_STRING(dt->shared)) |
216 | 0 | s1 = "str"; |
217 | 0 | else |
218 | 0 | s1 = "vlen"; |
219 | 0 | break; |
220 | | |
221 | 0 | case H5T_ARRAY: |
222 | 0 | s1 = "array"; |
223 | 0 | break; |
224 | | |
225 | 0 | case H5T_COMPLEX: |
226 | 0 | s1 = "complex number"; |
227 | 0 | break; |
228 | | |
229 | 0 | case H5T_NCLASSES: |
230 | 0 | default: |
231 | 0 | s1 = ""; |
232 | 0 | break; |
233 | 0 | } /* end switch */ |
234 | | |
235 | 0 | switch (dt->shared->state) { |
236 | 0 | case H5T_STATE_TRANSIENT: |
237 | 0 | s2 = "[transient]"; |
238 | 0 | break; |
239 | | |
240 | 0 | case H5T_STATE_RDONLY: |
241 | 0 | s2 = "[constant]"; |
242 | 0 | break; |
243 | | |
244 | 0 | case H5T_STATE_IMMUTABLE: |
245 | 0 | s2 = "[predefined]"; |
246 | 0 | break; |
247 | | |
248 | 0 | case H5T_STATE_NAMED: |
249 | 0 | s2 = "[named,closed]"; |
250 | 0 | break; |
251 | | |
252 | 0 | case H5T_STATE_OPEN: |
253 | 0 | s2 = "[named,open]"; |
254 | 0 | break; |
255 | 0 | default: |
256 | 0 | assert(0 && "This Should never be executed!"); |
257 | 0 | } /* end switch */ |
258 | | |
259 | 0 | fprintf(stream, "%s%s {nbytes=%lu", s1, s2, (unsigned long)(dt->shared->size)); |
260 | |
|
261 | 0 | if (H5T_IS_ATOMIC(dt->shared)) { |
262 | 0 | uint64_t tmp; |
263 | |
|
264 | 0 | switch (dt->shared->u.atomic.order) { |
265 | 0 | case H5T_ORDER_ERROR: |
266 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "order error"); |
267 | 0 | break; |
268 | | |
269 | 0 | case H5T_ORDER_BE: |
270 | 0 | s1 = "BE"; |
271 | 0 | break; |
272 | | |
273 | 0 | case H5T_ORDER_LE: |
274 | 0 | s1 = "LE"; |
275 | 0 | break; |
276 | | |
277 | 0 | case H5T_ORDER_VAX: |
278 | 0 | s1 = "VAX"; |
279 | 0 | break; |
280 | | |
281 | 0 | case H5T_ORDER_NONE: |
282 | 0 | s1 = "NONE"; |
283 | 0 | break; |
284 | | |
285 | 0 | case H5T_ORDER_MIXED: |
286 | 0 | default: |
287 | 0 | s1 = "order?"; |
288 | 0 | break; |
289 | 0 | } /* end switch */ |
290 | | |
291 | 0 | fprintf(stream, ", %s", s1); |
292 | |
|
293 | 0 | if (dt->shared->u.atomic.offset) |
294 | 0 | fprintf(stream, ", offset=%lu", (unsigned long)(dt->shared->u.atomic.offset)); |
295 | 0 | if (dt->shared->u.atomic.prec != 8 * dt->shared->size) |
296 | 0 | fprintf(stream, ", prec=%lu", (unsigned long)(dt->shared->u.atomic.prec)); |
297 | |
|
298 | 0 | switch (dt->shared->type) { |
299 | 0 | case H5T_NO_CLASS: |
300 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "no class"); |
301 | 0 | break; |
302 | | |
303 | 0 | case H5T_INTEGER: |
304 | 0 | switch (dt->shared->u.atomic.u.i.sign) { |
305 | 0 | case H5T_SGN_ERROR: |
306 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "sign error"); |
307 | 0 | break; |
308 | | |
309 | 0 | case H5T_SGN_NONE: |
310 | 0 | s1 = "unsigned"; |
311 | 0 | break; |
312 | | |
313 | 0 | case H5T_SGN_2: |
314 | 0 | s1 = NULL; |
315 | 0 | break; |
316 | | |
317 | 0 | case H5T_NSGN: |
318 | 0 | default: |
319 | 0 | s1 = "sign?"; |
320 | 0 | break; |
321 | |
|
322 | 0 | } /* end switch */ |
323 | 0 | if (s1) |
324 | 0 | fprintf(stream, ", %s", s1); |
325 | 0 | break; |
326 | | |
327 | 0 | case H5T_FLOAT: |
328 | 0 | switch (dt->shared->u.atomic.u.f.norm) { |
329 | 0 | case H5T_NORM_ERROR: |
330 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "norm error"); |
331 | 0 | break; |
332 | | |
333 | 0 | case H5T_NORM_IMPLIED: |
334 | 0 | s1 = "implied"; |
335 | 0 | break; |
336 | | |
337 | 0 | case H5T_NORM_MSBSET: |
338 | 0 | s1 = "msbset"; |
339 | 0 | break; |
340 | | |
341 | 0 | case H5T_NORM_NONE: |
342 | 0 | s1 = "no-norm"; |
343 | 0 | break; |
344 | | |
345 | 0 | default: |
346 | 0 | s1 = "norm?"; |
347 | 0 | break; |
348 | 0 | } /* end switch */ |
349 | | |
350 | 0 | fprintf(stream, ", sign=%lu+1", (unsigned long)(dt->shared->u.atomic.u.f.sign)); |
351 | 0 | fprintf(stream, ", mant=%lu+%lu (%s)", (unsigned long)(dt->shared->u.atomic.u.f.mpos), |
352 | 0 | (unsigned long)(dt->shared->u.atomic.u.f.msize), s1); |
353 | 0 | fprintf(stream, ", exp=%lu+%lu", (unsigned long)(dt->shared->u.atomic.u.f.epos), |
354 | 0 | (unsigned long)(dt->shared->u.atomic.u.f.esize)); |
355 | 0 | tmp = dt->shared->u.atomic.u.f.ebias >> 32; |
356 | 0 | if (tmp) { |
357 | 0 | size_t hi = (size_t)tmp; |
358 | 0 | size_t lo = (size_t)(dt->shared->u.atomic.u.f.ebias & 0xffffffff); |
359 | 0 | fprintf(stream, " bias=0x%08lx%08lx", (unsigned long)hi, (unsigned long)lo); |
360 | 0 | } |
361 | 0 | else { |
362 | 0 | size_t lo = (size_t)(dt->shared->u.atomic.u.f.ebias & 0xffffffff); |
363 | 0 | fprintf(stream, " bias=0x%08lx", (unsigned long)lo); |
364 | 0 | } |
365 | 0 | break; |
366 | | |
367 | 0 | case H5T_TIME: |
368 | 0 | case H5T_STRING: |
369 | 0 | case H5T_BITFIELD: |
370 | 0 | case H5T_OPAQUE: |
371 | 0 | case H5T_COMPOUND: |
372 | 0 | case H5T_REFERENCE: |
373 | 0 | case H5T_ENUM: |
374 | 0 | case H5T_VLEN: |
375 | 0 | case H5T_ARRAY: |
376 | 0 | case H5T_COMPLEX: |
377 | 0 | case H5T_NCLASSES: |
378 | 0 | default: |
379 | | /* No additional info */ |
380 | 0 | break; |
381 | 0 | } /* end switch */ |
382 | 0 | } |
383 | 0 | else if (H5T_COMPOUND == dt->shared->type) { |
384 | | /* Compound data type */ |
385 | 0 | for (i = 0; i < dt->shared->u.compnd.nmembs; i++) { |
386 | 0 | fprintf(stream, "\n\"%s\" @%lu", dt->shared->u.compnd.memb[i].name, |
387 | 0 | (unsigned long)(dt->shared->u.compnd.memb[i].offset)); |
388 | 0 | fprintf(stream, " "); |
389 | 0 | H5T_debug(dt->shared->u.compnd.memb[i].type, stream); |
390 | 0 | } /* end for */ |
391 | 0 | fprintf(stream, "\n"); |
392 | 0 | } |
393 | 0 | else if (H5T_VLEN == dt->shared->type) { |
394 | 0 | switch (dt->shared->u.vlen.loc) { |
395 | 0 | case H5T_LOC_BADLOC: |
396 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "invalid datatype location"); |
397 | 0 | break; |
398 | | |
399 | 0 | case H5T_LOC_MEMORY: |
400 | 0 | fprintf(stream, ", loc=memory"); |
401 | 0 | break; |
402 | | |
403 | 0 | case H5T_LOC_DISK: |
404 | 0 | fprintf(stream, ", loc=disk"); |
405 | 0 | break; |
406 | | |
407 | 0 | case H5T_LOC_MAXLOC: |
408 | 0 | default: |
409 | 0 | fprintf(stream, ", loc=UNKNOWN"); |
410 | 0 | break; |
411 | 0 | } /* end switch */ |
412 | | |
413 | 0 | if (H5T_IS_VL_STRING(dt->shared)) |
414 | | /* Variable length string datatype */ |
415 | 0 | fprintf(stream, ", variable-length"); |
416 | 0 | else { |
417 | | /* Variable length sequence datatype */ |
418 | 0 | fprintf(stream, " VLEN "); |
419 | 0 | H5T_debug(dt->shared->parent, stream); |
420 | 0 | fprintf(stream, "\n"); |
421 | 0 | } /* end else */ |
422 | 0 | } |
423 | 0 | else if (H5T_ENUM == dt->shared->type) { |
424 | 0 | size_t base_size; |
425 | | |
426 | | /* Enumeration data type */ |
427 | 0 | fprintf(stream, " "); |
428 | 0 | H5T_debug(dt->shared->parent, stream); |
429 | 0 | base_size = dt->shared->parent->shared->size; |
430 | 0 | for (i = 0; i < dt->shared->u.enumer.nmembs; i++) { |
431 | 0 | size_t k; |
432 | |
|
433 | 0 | fprintf(stream, "\n\"%s\" = 0x", dt->shared->u.enumer.name[i]); |
434 | 0 | for (k = 0; k < base_size; k++) |
435 | 0 | fprintf(stream, "%02" PRIx8, *((uint8_t *)dt->shared->u.enumer.value + (i * base_size) + k)); |
436 | 0 | } /* end for */ |
437 | 0 | fprintf(stream, "\n"); |
438 | 0 | } |
439 | 0 | else if (H5T_OPAQUE == dt->shared->type) { |
440 | 0 | fprintf(stream, ", tag=\"%s\"", dt->shared->u.opaque.tag); |
441 | 0 | } |
442 | 0 | else if (H5T_COMPLEX == dt->shared->type) { |
443 | 0 | fprintf(stream, ", homogeneous"); |
444 | 0 | switch (dt->shared->u.cplx.form) { |
445 | 0 | case H5T_COMPLEX_RECTANGULAR: |
446 | 0 | fprintf(stream, ", rectangular form"); |
447 | 0 | break; |
448 | 0 | case H5T_COMPLEX_POLAR: |
449 | 0 | fprintf(stream, ", polar form"); |
450 | 0 | break; |
451 | 0 | case H5T_COMPLEX_EXPONENTIAL: |
452 | 0 | fprintf(stream, ", exponential form"); |
453 | 0 | break; |
454 | 0 | default: |
455 | 0 | fprintf(stream, ", invalid form"); |
456 | 0 | break; |
457 | 0 | } |
458 | 0 | } |
459 | 0 | else { |
460 | | /* Unknown */ |
461 | 0 | fprintf(stream, "unknown class %d\n", (int)(dt->shared->type)); |
462 | 0 | } |
463 | 0 | fprintf(stream, "}"); |
464 | |
|
465 | 0 | done: |
466 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
467 | 0 | } /* end H5T_debug() */ |