/* * * Purpose: A library for displaying the values of a dataset or an attribute * in a human readable format. * * Note: h5dumputil is a modification of h5tools.c */ #include #include #include #include #include #include /* * The output functions need a temporary buffer to hold a piece of the * dataset while it's being printed. This constant sets the limit on the * size of that temporary buffer in bytes. For efficiency's sake, choose the * largest value suitable for your machine (for testing use a small value). */ #if 0 #define H5DUMP_BUFSIZE (1024*1024) #else #define H5DUMP_BUFSIZE (1024) #endif #define MIN(X,Y) ((X)<(Y)?(X):(Y)) #define NELMTS(X) (sizeof(X)/sizeof(*X)) #define ALIGN(A,Z) ((((A)+(Z)-1)/(Z))*(Z)) extern int indent; extern void indentation(int); int compound_data=0; int print_data(hid_t , hid_t , int); /*------------------------------------------------------------------------- * Function: h5dump_sprint * * Purpose: Prints the value pointed to by VP into the string S assuming * the data type of VP is TYPE. * * Return: void * * Modifications: * *------------------------------------------------------------------------- */ static void h5dump_sprint(char *s/*out*/, hid_t type, void *vp) { size_t i, n; char temp[1024]; int j; H5T_str_t str_pad; if (H5Tequal(type, H5T_NATIVE_DOUBLE)) { sprintf(s, "%g", *((double*)vp)); } else if (H5Tequal(type, H5T_NATIVE_FLOAT)) { sprintf(s, "%g", *((float*)vp)); } else if (H5Tequal(type, H5T_NATIVE_SHORT)) { sprintf(s, "%d", *((short*)vp)); } else if (H5Tequal(type, H5T_NATIVE_USHORT)) { sprintf(s, "%u", *((unsigned short*)vp)); } else if (H5Tequal(type, H5T_NATIVE_INT)) { sprintf(s, "%d", *((int*)vp)); } else if (H5Tequal(type, H5T_NATIVE_UINT)) { sprintf(s, "%u", *((unsigned*)vp)); } else if (H5Tequal(type, H5T_NATIVE_LONG)) { sprintf(s, "%ld", *((long*)vp)); } else if (H5Tequal(type, H5T_NATIVE_ULONG)) { sprintf(s, "%lu", *((unsigned long*)vp)); } else if (H5Tequal(type, H5T_NATIVE_SCHAR)) { sprintf(s, "%d", *((signed char*)vp)); } else if (H5Tequal(type, H5T_NATIVE_UCHAR)) { sprintf(s, "%u", *((unsigned char*)vp)); } else if (H5T_STRING==H5Tget_class(type)) { str_pad = H5Tget_strpad(type) ; j = 0; for (i = 0; i < H5Tget_size(type); i++) { switch (*((char*)vp+i)) { case '"': strcpy(s+j, "\\\""); j += strlen("\\\""); break; case '\\': strcpy(s+j, "\\\\"); j += strlen("\\\\"); break; case '\b': strcpy(s+j, "\\b"); j += strlen("\\b"); break; case '\f': strcpy(s+j, "\\f"); j += strlen("\\f"); break; case '\n': strcpy(s+j, "\\n"); j += strlen("\\n"); break; case '\r': strcpy(s+j, "\\r"); j += strlen("\\r"); break; case '\t': strcpy(s+j, "\\t"); j += strlen("\\t"); break; default: if (isprint(*((char*)vp+i))){ sprintf(s+j, "%c", *((char*)vp+i)); j += strlen(s+j); } else { if (str_pad == H5T_STR_NULLTERM && *((unsigned char*)vp+i) == '\0' ) { sprintf(s+j, "%c", *((unsigned char*)vp+i)); i = H5Tget_size(type); } else { sprintf(s+j, "\\%03o", *((unsigned char*)vp+i)); j += strlen(s+j); } } break; } } } else { strcpy(temp, "0x"); n = H5Tget_size(type); for (i=0; i ncols) indent = 0; for (i=0; i (ncols-indent-col)) { /* first row of member */ if (compound_data && (elmtno+i+1) == dim_n_size) printf("%s\n", out_buf); else { indentation(indent+col); printf("%s\n", out_buf); } strcpy(out_buf, p_buf); if ((elmtno+i+1) % dim_n_size) strcat(out_buf, ", "); else { /* end of a row, flush out_buf */ indentation(indent+col); printf("%s", out_buf); if ((elmtno+i+1) != p_nelmts) /* not last element */ printf(",\n"); else if (compound_data) { /* last element of member data*/ if ((ncols-strlen(out_buf)-indent-col) < 2) { /* 2 for space and ] */ printf("\n"); indentation(indent+col-3); } } else printf("\n"); /* last row */ *out_buf = '\0'; } } else { strcat(out_buf, p_buf); if ((elmtno+i+1) % dim_n_size) { if ((ncols-strlen(out_buf)-indent-col-1) > 0) strcat(out_buf, ", "); else strcat(out_buf, ","); } else { /* end of a row */ /* 1st row of member data */ if (compound_data && (elmtno+i+1) == dim_n_size) printf("%s", out_buf); else { indentation(indent+col); printf("%s", out_buf); } /* if it's the last element */ if ((elmtno+i+1) != p_nelmts) printf(",\n"); else if (compound_data) { /* last row of member data*/ /* 2 for space and ] */ if ((ncols-strlen(out_buf)-indent-col) < 2) { printf("\n"); indentation(indent+col-3); } } else printf("\n"); /* last row */ *out_buf = '\0'; } } } } /*------------------------------------------------------------------------- * Function: display_string * * Purpose: Display string in ddl format * * Return: void * * Comment: concatenator operator : '//' * separator between elements: ',' * * Modifications: * *------------------------------------------------------------------------- */ static void display_string (hsize_t hs_nelmts, hid_t p_type, unsigned char *sm_buf, size_t p_type_nbytes, hsize_t p_nelmts, hsize_t dim_n_size, hsize_t elmtno) { hsize_t i, row_size=0; int j, m, x, y, z, first_row=1; int free_space, long_string = 0; char p_buf[256], out_buf[ncols]; out_buf[0] = '\0'; if ((indent+col) > ncols) indent = 0; for (i=0; i free_space) long_string = 1; } else /* 3 for double quotes and one comma */ if (((int)strlen(p_buf) + 3) > free_space) long_string = 1; if (long_string) { if (free_space < 5) { /* 5 for double quotes, one space and two '/'s */ /* flush out_buf */ if (compound_data && first_row) { printf("%s\n", out_buf); first_row = 0; } else { indentation(indent+col); printf("%s\n", out_buf); } out_buf[0] = '\0'; x = 0 ; } else { x = free_space - 5; if (compound_data && first_row) { printf("%s\"", out_buf); strncpy(out_buf, p_buf, x); out_buf[x] = '\0'; printf("%s\" //\n", out_buf); first_row = 0; } else { indentation(indent+col); printf("%s\"", out_buf); strncpy(out_buf, p_buf, x); out_buf[x] = '\0'; printf("%s\" //\n", out_buf); } out_buf[0] = '\0'; } y = ncols - indent -col - 5; m = (strlen(p_buf) - x)/y; z = (strlen(p_buf) - x) % y; for (j = 0; j < m - 1 ; j++) { indentation(indent+col); strncpy(out_buf, p_buf+x+j*y, y); out_buf[y] = '\0'; printf("\"%s\" //\n", out_buf); } if ((elmtno+i+1) == p_nelmts) { /* last element */ if ((int)strlen(p_buf+x+j*y) > (ncols - indent - col -2)) { /* 2 for double quotes */ indentation(indent+col); strncpy(out_buf, p_buf+x+j*y, y); out_buf[y] = '\0'; printf("\"%s\" //\n", out_buf); indentation(indent+col); printf("\"%s\"", p_buf+x+m*y); if (compound_data) { if ((ncols-strlen(out_buf)-indent-col) < 2) { printf("\n"); indentation(indent+col-3); } } else printf("\n"); } else { indentation(indent+col); printf("\"%s\"", p_buf+x+j*y); if (compound_data) { if ((ncols-strlen(out_buf)-indent-col) < 2) { printf("\n"); indentation(indent+col-3); } } else printf("\n"); } out_buf[0] = '\0'; } else if ( row_size == dim_n_size) { if ((int)strlen(p_buf+x+j*y) > (ncols - indent - col -3)) { /* 3 for 2 "'s and 1 , */ indentation(indent+col); strncpy(out_buf, p_buf+x+j*y, y); out_buf[y] = '\0'; printf("\"%s\" //\n", out_buf); indentation(indent+col); printf("\"%s\",\n", p_buf+x+m*y); } else { indentation(indent+col); printf("\"%s\",\n", p_buf+x+j*y); } out_buf[0] = '\0'; row_size = 0; } else { if ((int)strlen(p_buf+x+j*y) > (ncols - indent - col -3)) { /* 3 for 2 "'s and 1 , */ indentation(indent+col); strncpy(out_buf, p_buf+x+j*y, y); out_buf[y] = '\0'; printf("\"%s\" //\n", out_buf); strcpy(out_buf, "\""); strcat(out_buf, p_buf+x+m*y); strcat(out_buf, "\","); if ((int)strlen(out_buf) < (ncols-indent-col)) strcat(out_buf, " "); } else { strcpy(out_buf, "\""); strcat (out_buf, p_buf+x+j*y); strcat(out_buf, "\","); if ((int)strlen(out_buf) < (ncols-indent-col)) strcat(out_buf, " "); } } long_string = 0; } else { /* flush out_buf if it's end of a row */ if (row_size == dim_n_size) { if (compound_data && (elmtno+i+1) == dim_n_size) { /* 1st row */ printf("%s\"%s\"", out_buf, p_buf); first_row = 0; } else { indentation(indent+col); printf("%s\"%s\"", out_buf, p_buf); } if ((elmtno+i+1) != p_nelmts) printf(",\n"); else if (compound_data) { if ((ncols-strlen(out_buf)-strlen(p_buf)-indent-col) < 2) { /* 2 for space and ] */ printf("\n"); indentation(indent+col-3); } } else printf("\n"); out_buf[0] = '\0'; row_size = 0; } else { strcat(out_buf, "\""); strcat(out_buf, p_buf); strcat(out_buf, "\","); if ((int)strlen(out_buf) < (ncols-indent-col)) strcat(out_buf, " "); } } } } /*------------------------------------------------------------------------- * Function: display_compound_data * * Purpose: Display compound data in ddl format * * Return: void * * Modifications: * *------------------------------------------------------------------------- */ static void display_compound_data (hsize_t hs_nelmts, hid_t p_type, unsigned char *sm_buf, size_t p_type_nbytes, hsize_t p_nelmts, hsize_t elmtno) { size_t offset, size, dims[4]; hsize_t nelmts, dim_n_size=0; hid_t memb; int nmembs, i, j, k, ndims, perm[4]; if ((indent+col) > ncols) indent = 0; for (i=0; i<(int)hs_nelmts && (elmtno+i) < p_nelmts; i++) { nmembs = H5Tget_nmembers(p_type); indentation(indent+col); printf("{\n"); indent+= col; for (j=0; j 0) dim_n_size = dims[ndims-1]; else dim_n_size = 1; for (k=0, nelmts=1; kNELMTS(sm_size)) return -1; /* Assume entire data space to be printed */ for (i=0; i<(hsize_t)ndims; i++) p_min_idx[i] = 0; H5Sget_simple_extent_dims(f_space, p_max_idx, NULL); for (i=0, p_nelmts=1; i<(hsize_t)ndims; i++) { p_nelmts *= p_max_idx[i]-p_min_idx[i]; } if (0==p_nelmts) return 0; /*nothing to print*/ /* * Determine the strip mine size and allocate a buffer. The strip mine is * a hyperslab whose size is manageable. */ p_type_nbytes = H5Tget_size(p_type); for (i=ndims, sm_nbytes=p_type_nbytes; i>0; --i) { sm_size[i-1] = MIN (p_max_idx[i-1]-p_min_idx[i-1], H5DUMP_BUFSIZE/sm_nbytes); sm_nbytes *= sm_size[i-1]; assert(sm_nbytes>0); } sm_buf = malloc(sm_nbytes); sm_nelmts = sm_nbytes/p_type_nbytes; sm_space = H5Screate_simple(1, &sm_nelmts, NULL); /* The stripmine loop */ memset(hs_offset, 0, sizeof hs_offset); memset(zero, 0, sizeof zero); for (elmtno=0; elmtno 0) { for (i=0, hs_nelmts=1; i<(hsize_t)ndims; i++) { hs_size[i] = MIN(sm_size[i], p_max_idx[i]-hs_offset[i]); hs_nelmts *= hs_size[i]; } H5Sselect_hyperslab(f_space, H5S_SELECT_SET, hs_offset, NULL, hs_size, NULL); H5Sselect_hyperslab(sm_space, H5S_SELECT_SET, zero, NULL, &hs_nelmts, NULL); dim_n_size = p_max_idx[ndims-1]; } else { H5Sselect_all(f_space); H5Sselect_all(sm_space); hs_nelmts = 1; dim_n_size = 1; } if (obj_data == DATASET_DATA) { if (H5Dread(oid, p_type, sm_space, f_space, H5P_DEFAULT, sm_buf) <0) return -1; } else { if (H5Aread(oid, p_type, sm_buf) < 0) return -1; } /* Print the data */ switch (H5Tget_class(p_type)) { case H5T_INTEGER: display_numeric_data (hs_nelmts, p_type, sm_buf, p_type_nbytes, p_nelmts, dim_n_size, elmtno); break; case H5T_FLOAT: display_numeric_data (hs_nelmts, p_type, sm_buf, p_type_nbytes, p_nelmts, dim_n_size, elmtno); break; case H5T_TIME: break; case H5T_STRING: display_string (hs_nelmts, p_type, sm_buf, p_type_nbytes, p_nelmts, dim_n_size, elmtno); break; case H5T_BITFIELD: break; case H5T_OPAQUE: break; case H5T_COMPOUND: compound_data = 1; display_compound_data (hs_nelmts, p_type, sm_buf, p_type_nbytes, p_nelmts, elmtno); compound_data = 0; break; default: break; } } H5Sclose(sm_space); H5Sclose(f_space); return 0; } /*------------------------------------------------------------------------- * Function: h5dump_fixtype * * Purpose: Given a file data type choose a memory data type which is * appropriate for printing the data. * * Return: Success: Memory data type * * Failure: FAIL * * Programmer: Robb Matzke * Thursday, July 23, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static hid_t h5dump_fixtype(hid_t f_type) { hid_t m_type=-1, f_memb; hid_t *memb=NULL; char **name=NULL; int nmembs=0, i, j, *ndims=NULL, perm[4]; size_t size, offset, *dims=NULL, nelmts; H5T_str_t strpad; size = H5Tget_size(f_type); switch (H5Tget_class(f_type)) { case H5T_INTEGER: /* * Use the smallest native integer type of the same sign as the file * such that the memory type is at least as large as the file type. * If there is no memory type large enough then use the largest * memory type available. */ if (size<=sizeof(char)) { m_type = H5Tcopy(H5T_NATIVE_SCHAR); } else if (size<=sizeof(short)) { m_type = H5Tcopy(H5T_NATIVE_SHORT); } else if (size<=sizeof(int)) { m_type = H5Tcopy(H5T_NATIVE_INT); } else if (size<=sizeof(long)) { m_type = H5Tcopy(H5T_NATIVE_LONG); } else { m_type = H5Tcopy(H5T_NATIVE_LLONG); } H5Tset_sign(m_type, H5Tget_sign(f_type)); break; case H5T_FLOAT: /* * Use the smallest native floating point type available such that * its size is at least as large as the file type. If there is not * native type large enough then use the largest native type. */ if (size<=sizeof(float)) { m_type = H5Tcopy(H5T_NATIVE_FLOAT); } else if (size<=sizeof(double)) { m_type = H5Tcopy(H5T_NATIVE_DOUBLE); } else { m_type = H5Tcopy(H5T_NATIVE_LDOUBLE); } break; case H5T_COMPOUND: /* * We have to do this in two steps. The first step scans the file * type and converts the members to native types and remembers all * their names and sizes, computing the size of the memory compound * type at the same time. Then we create the memory compound type * and add the members. */ nmembs = H5Tget_nmembers(f_type); memb = calloc(nmembs, sizeof(hid_t)); name = calloc(nmembs, sizeof(char*)); ndims = calloc(nmembs, sizeof(int)); dims = calloc(nmembs*4, sizeof(size_t)); for (i=0, size=0; i=0 && ndims[i]<=4); for (j=0, nelmts=1; j=0) H5Tclose(memb[i]); if (name[i]) free(name[i]); } free(memb); free(name); free(ndims); free(dims); } return m_type; } /*------------------------------------------------------------------------- * Function: print_data * * Purpose: Print some values from a dataset or an attribute to the * file STREAM after converting all types to P_TYPE (which * should be a native type). If P_TYPE is a negative value * then it will be computed from the dataset/attribute type * using only native types. * * Return: Success: 0 * * Failure: -1 * * Modifications: * *------------------------------------------------------------------------- */ int print_data(hid_t oid, hid_t _p_type, int obj_data) { hid_t f_space; hid_t p_type = _p_type; hid_t f_type; int status = -1; if (p_type < 0) { if (obj_data == DATASET_DATA) f_type = H5Dget_type(oid); else f_type = H5Aget_type(oid); if (f_type < 0) return status; p_type = h5dump_fixtype(f_type); H5Tclose(f_type); if (p_type < 0) return status; } /* Check the data space */ if (obj_data == DATASET_DATA) f_space = H5Dget_space(oid); else f_space = H5Aget_space(oid); if (f_space < 0) return status; if (H5Sis_simple(f_space) >= 0) status = h5dump_simple(oid, p_type, obj_data); H5Sclose(f_space); if (p_type != _p_type) H5Tclose(p_type); return status; }