#include "hdf5.h" #include "api.h" #include "buffer.h" #include #include #include #ifdef _WIN32 #pragma warning(disable: 4018) #pragma warning(disable: 4244) #endif #define HDF_TYPE 'H5' #define BUFF_SIZE 1024 ///////////////////////////////////////////////////////////////////// class zsHDF { size_t size; public: zsHDF() : fid(-1), gid(-1), did(-1), tid(-1), flag(false), ndim(0), size(0), ptr(0) { } ~zsHDF() { if (tid > 0) H5Tclose(tid); if (did > 0) H5Dclose(did); if (gid > 0) H5Gclose(gid); if (fid > 0) H5Fclose(fid); if (ptr) free(ptr); } void checksize(size_t size) { if (this->size < size || this->size > 2*size) { if (ptr) { free(ptr); ptr = 0; } ptr = malloc(size); this->size = size; } } hid_t fid, gid, did, tid; hsize_t dims[H5S_MAX_RANK]; size_t ndim, dsize, tsize; bool flag; // true if dataset is the target; otherwise group is the target. int type; void *ptr; }; enum { HDF_CHAR, HDF_UCHAR, HDF_SHORT, HDF_USHORT, HDF_INT, HDF_UINT, HDF_FLOAT, HDF_DOUBLE }; ///////////////////////////////////////////////////////////////////// void check_dataset(void* ctx, zsHDF *o) { if (!o->flag) api_runtime_error(ctx, "dataset not specified"); } void type_error(void* ctx) { api_runtime_error(ctx, "unsupported variable/attibute type"); } void hdf_destroy(void *ptr) { delete (zsHDF*)ptr; ptr = 0; } herr_t hdf_error(void *data) { H5Eclear(); return 1; } ///////////////////////////////////////////////////////////////////// void* hdf_open(void *ctx, int nargs, void** args) { if (nargs < 1) api_input_error(ctx); const char *fname = api_get_string(ctx, args[0]); zsHDF *o = new zsHDF; H5Eset_auto(hdf_error, o); if (nargs > 1) { const char *s = api_get_string(ctx, args[1]); if (s[0] == 'w' || s[0] == 'W') { o->fid = H5Fopen(fname, H5F_ACC_RDWR, H5P_DEFAULT); if (o->fid < 0) { o->fid = H5Fcreate(fname, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT); } } else if (s[0] == 'c' || s[0] == 'C') { o->fid = H5Fcreate(fname, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT); } else { o->fid = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT); } } else { o->fid = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT); } if (o->fid < 0) { return 0; // api_runtime_error2(ctx, "failed to open or create HDF file: ", fname); } o->gid = H5Gopen(o->fid, "/"); if (o->gid < 0) o->gid = H5Gcreate(o->fid, "/", 1); if (o->gid < 0) api_runtime_error(ctx, "failed to open or create group"); return api_create_user(ctx, o, 0, hdf_destroy, HDF_TYPE); } void* hdf_version(void *ctx, int nargs, void** args) { unsigned v1, v2, v3; H5get_libversion(&v1, &v2, &v3); static char buf[64]; sprintf(buf, "version-%d.%d.%d", v1, v2, v3); return api_create_string(ctx, buf); } void* hdf_group(void *ctx, int nargs, void** args) { if (nargs < 2) api_input_error(ctx); zsHDF *o = (zsHDF*)api_get_user(ctx, args[0], HDF_TYPE); const char *name = api_get_string(ctx, args[1]); if (o->gid >= 0) H5Gclose(o->gid); o->gid = H5Gopen(o->fid, name); if (o->gid < 0) o->gid = H5Gcreate(o->fid, name, strlen(name)); if (o->gid < 0) api_runtime_error(ctx, "failed to open/create group"); o->flag = false; return 0; } void* hdf_dataset(void *ctx, int nargs, void** args) { if (nargs < 2) api_input_error(ctx); zsHDF *o = (zsHDF*)api_get_user(ctx, args[0], HDF_TYPE); const char *name = api_get_string(ctx, args[1]); if (nargs == 2) { // set dataset target if (o->did >= 0) H5Dclose(o->did); o->did = H5Dopen(o->gid, name); if (o->did < 0) return api_create_integer(ctx, 0); hid_t dspace = H5Dget_space(o->did); if (dspace < 0) api_runtime_error(ctx, "failed to get dataset space"); o->ndim = H5Sget_simple_extent_dims(dspace, o->dims, 0); H5Sclose(dspace); if (o->tid >= 0) H5Tclose(o->tid); o->tid = H5Dget_type(o->did); if (H5Tequal(o->tid, H5T_NATIVE_CHAR) > 0) { o->tsize = sizeof(char); o->type = HDF_CHAR; } else if (H5Tequal(o->tid, H5T_NATIVE_UCHAR) > 0) { o->tsize = sizeof(unsigned char); o->type = HDF_UCHAR; } else if (H5Tequal(o->tid, H5T_NATIVE_SHORT) > 0) { o->tsize = sizeof(short); o->type = HDF_SHORT; } else if (H5Tequal(o->tid, H5T_NATIVE_USHORT) > 0) { o->tsize = sizeof(unsigned short); o->type = HDF_USHORT; } else if (H5Tequal(o->tid, H5T_NATIVE_INT) > 0) { o->tsize = sizeof(int); o->type = HDF_INT; } else if (H5Tequal(o->tid, H5T_NATIVE_UINT) > 0) { o->tsize = sizeof(unsigned int); o->type = HDF_UINT; } else if (H5Tequal(o->tid, H5T_NATIVE_FLOAT) > 0) { o->tsize = sizeof(float); o->type = HDF_FLOAT; } else if (H5Tequal(o->tid, H5T_NATIVE_DOUBLE) > 0) { o->tsize = sizeof(double); o->type = HDF_DOUBLE; } else { type_error(ctx); } o->flag = true; o->dsize = 1; for (size_t i = 0; i < o->ndim; i++) o->dsize *= o->dims[i]; return api_create_integer(ctx, 1); } // define dataset if (nargs < 4) api_input_error(ctx); const char *type = api_get_string(ctx, args[2]); if (o->tid >= 0) H5Tclose(o->tid); if (!strcmp(type, "char")) { o->tid = H5Tcopy(H5T_NATIVE_CHAR); o->tsize = sizeof(char); o->type = HDF_CHAR; } else if (!strcmp(type, "uchar")) { o->tid = H5Tcopy(H5T_NATIVE_UCHAR); o->tsize = sizeof(unsigned char); o->type = HDF_UCHAR; } else if (!strcmp(type, "short")) { o->tid = H5Tcopy(H5T_NATIVE_SHORT); o->tsize = sizeof(short); o->type = HDF_SHORT; } else if (!strcmp(type, "ushort")) { o->tid = H5Tcopy(H5T_NATIVE_USHORT); o->tsize = sizeof(unsigned short); o->type = HDF_USHORT; } else if (!strcmp(type, "int")) { o->tid = H5Tcopy(H5T_NATIVE_INT); o->tsize = sizeof(int); o->type = HDF_INT; } else if (!strcmp(type, "uint")) { o->tid = H5Tcopy(H5T_NATIVE_UINT); o->tsize = sizeof(unsigned int); o->type = HDF_UINT; } else if (!strcmp(type, "float")) { o->tid = H5Tcopy(H5T_NATIVE_FLOAT); o->tsize = sizeof(float); o->type = HDF_FLOAT; } else if (!strcmp(type, "double")) { o->tid = H5Tcopy(H5T_NATIVE_DOUBLE); o->tsize = sizeof(double); o->type = HDF_DOUBLE; } else { api_input_error(ctx); } o->ndim = 0; o->dsize = 1; for (int i = 3; i < nargs && o->ndim < H5S_MAX_RANK; i++) { integer_t n = api_get_integer(ctx, args[i]); if (n <= 0) api_input_error(ctx); o->dims[o->ndim] = n; o->dsize *= n; o->ndim++; } hid_t dspace = H5Screate_simple(nargs-3, o->dims, 0); if (dspace < 0) api_runtime_error(ctx, "failed to create data space"); if (o->did >= 0) H5Dclose(o->did); o->did = H5Dcreate(o->gid, name, o->tid, dspace, H5P_DEFAULT); H5Sclose(dspace); if (o->did < 0) api_runtime_error(ctx, "failed to create dataset"); o->flag = true; return 0; } void* hdf_size(void *ctx, int nargs, void** args) { if (nargs < 1) api_input_error(ctx); zsHDF *o = (zsHDF*)api_get_user(ctx, args[0], HDF_TYPE); check_dataset(ctx, o); void *arr = api_create_array(ctx, 3); api_set_array_object(ctx, arr, "0", api_create_integer(0, o->dsize)); api_set_array_object(ctx, arr, "1", api_create_integer(0, o->tsize)); switch (o->type) { case HDF_CHAR: api_set_array_object(ctx, arr, "2", api_create_string(0, "char")); break; case HDF_UCHAR: api_set_array_object(ctx, arr, "2", api_create_string(0, "uchar")); break; case HDF_SHORT: api_set_array_object(ctx, arr, "2", api_create_string(0, "short")); break; case HDF_USHORT: api_set_array_object(ctx, arr, "2", api_create_string(0, "ushort")); break; case HDF_INT: api_set_array_object(ctx, arr, "2", api_create_string(0, "int")); break; case HDF_UINT: api_set_array_object(ctx, arr, "2", api_create_string(0, "uint")); break; case HDF_FLOAT: api_set_array_object(ctx, arr, "2", api_create_string(0, "float")); break; case HDF_DOUBLE: api_set_array_object(ctx, arr, "2", api_create_string(0, "double")); break; default: type_error(ctx); } return arr; } void* hdf_dims(void *ctx, int nargs, void** args) { if (nargs < 1) api_input_error(ctx); zsHDF *o = (zsHDF*)api_get_user(ctx, args[0], HDF_TYPE); check_dataset(ctx, o); void *arr = api_create_array(ctx, o->ndim); for (int i = 0; i < o->ndim; i++) api_set_array_object2(ctx, arr, i, api_create_integer(0, o->dims[i])); return arr; } void* hdf_getatt(void *ctx, int nargs, void** args) { if (nargs < 2) api_input_error(ctx); zsHDF *o = (zsHDF*)api_get_user(ctx, args[0], HDF_TYPE); const char *name = api_get_string(ctx, args[1]); hid_t id = o->did; if (!o->flag) id = o->gid; hid_t att_id = H5Aopen_name(id, name); if (att_id < 0) return 0; // return null if the attribute does not exist. hid_t att_type = H5Aget_type(att_id); if (att_type < 0) { H5Aclose(att_id); return 0; } hid_t att_space = H5Aget_space(att_id); if (att_space < 0) { H5Aclose(att_id); H5Sclose(att_space); return 0; } void *ret = 0; int ndim = H5Sget_simple_extent_ndims(att_space); if (ndim == 0) { switch (H5Tget_class(att_type)) { case H5T_INTEGER: { int value; if (H5Aread(att_id, H5T_NATIVE_INT, &value) >= 0) ret = api_create_integer(ctx, value); } break; case H5T_FLOAT: { double value; if (H5Aread(att_id, H5T_NATIVE_DOUBLE, &value) >= 0) ret = api_create_real(ctx, value); } break; case H5T_STRING: { zsBuffer buf(1024); hid_t atype = H5Tcopy(H5T_C_S1); H5Tset_size(atype, 1023); if (H5Aread(att_id, atype, buf.u.pchar) >= 0) { buf.u.pchar[1023] = 0; ret = api_create_string(ctx, buf.u.pchar); } H5Tclose(atype); } break; default: type_error(ctx); break; } } else if (ndim == 1) { hsize_t dims[1]; if (H5Sget_simple_extent_dims(att_space, dims, NULL) == 1) { switch (H5Tget_class(att_type)) { case H5T_INTEGER: { zsBuffer buf(dims[0]*sizeof(int)); if (H5Aread(att_id, H5T_NATIVE_INT, buf.u.ptr) >= 0) { ret = api_create_array(ctx, dims[0]); for (int i = 0; i < dims[0]; i++) { api_set_array_object2(ctx, ret, i, api_create_integer(0, buf.u.pint[i])); } } } break; case H5T_FLOAT: { zsBuffer buf(dims[0]*sizeof(double)); if (H5Aread(att_id, H5T_NATIVE_DOUBLE, buf.u.ptr) >= 0) { ret = api_create_array(ctx, dims[0]); for (int i = 0; i < dims[0]; i++) { api_set_array_object2(ctx, ret, i, api_create_real(0, buf.u.pdouble[i])); } } } break; default: type_error(ctx); } } } H5Aclose(att_id); H5Tclose(att_type); H5Sclose(att_space); return ret; } void* hdf_putatt(void *ctx, int nargs, void** args) { if (nargs < 3) api_input_error(ctx); zsHDF *o = (zsHDF*)api_get_user(ctx, args[0], HDF_TYPE); const char *name = api_get_string(ctx, args[1]); hid_t id = o->did; if (!o->flag) id = o->gid; H5Adelete(id, name); hid_t status = -1; if (api_is_real(args[2])) { // e.g., hdf.name = 1.23; double value = api_get_real(ctx, args[2]); hid_t space = H5Screate(H5S_SCALAR); hid_t aid = H5Acreate(id, name, H5T_NATIVE_DOUBLE, space, H5P_DEFAULT); if (aid > 0) { status = H5Awrite(aid, H5T_NATIVE_DOUBLE, &value); H5Aclose(aid); } H5Sclose(space); } else if (api_is_integer(args[2])) { // e.g., hdf.name = 123; int value = api_get_integer(ctx, args[2]); hid_t space = H5Screate(H5S_SCALAR); hid_t aid = H5Acreate(id, name, H5T_NATIVE_INT, space, H5P_DEFAULT); if (aid > 0) { status = H5Awrite(aid, H5T_NATIVE_INT, &value); H5Aclose(aid); } H5Sclose(space); } else if (api_is_string(args[2])) { // e.g., hdf.name = "my property"; const char *ptr = api_get_string(ctx, args[2]); hid_t space = H5Screate(H5S_SCALAR); hid_t type = H5Tcopy(H5T_C_S1); H5Tset_size(type, strlen(ptr)); hid_t aid = H5Acreate(id, name, type, space, H5P_DEFAULT); if (aid > 0) { status = H5Awrite(aid, type, ptr); H5Aclose(aid); } H5Sclose(space); H5Tclose(type); } else if (api_is_array(args[2])) { // e.g., hdf.name = [1, 2.0, 3.3]; hsize_t dims[1] = { api_get_array_size(ctx, args[2]) }; if (dims[0] == 0 || dims[0] > 256) api_runtime_error(ctx, "unexpected number of attributes"); zsBuffer br(dims[0]*sizeof(double)), bi(dims[0]*sizeof(int)); bool real_flag = false; for (int i = 0; i < dims[0]; i++) { void *o = api_get_array_object2(ctx, args[2], i); if (api_is_real(o)) { br.u.pdouble[i] = api_get_real(ctx, o); real_flag = true; } else { bi.u.pint[i] = api_get_integer(ctx, o); br.u.pdouble[i] = bi.u.pint[i]; } } if (real_flag) { hid_t space = H5Screate_simple(1, dims, NULL); hid_t aid = H5Acreate(id, name, H5T_NATIVE_DOUBLE, space, 0); if (aid > 0) { status = H5Awrite(aid, H5T_NATIVE_DOUBLE, br.u.pdouble); H5Aclose(aid); } H5Sclose(space); } else { hid_t space = H5Screate_simple(1, dims, NULL); hid_t aid = H5Acreate(id, name, H5T_NATIVE_INT, space, 0); if (aid > 0) { status = H5Awrite(aid, H5T_NATIVE_INT, bi.u.pint); H5Aclose(aid); } H5Sclose(space); } } if (status < 0) api_runtime_error(ctx, "failed to write attribute"); return 0; } void hdf_check_index(void *ctx, int nargs, void** args, zsHDF *o, hsize_t mcount[], hsize_t dstart[], hsize_t dcount[]) { if (nargs-1 > o->ndim) api_runtime_error(ctx, "too many dimension specifiers"); for (size_t k = 0; k < o->ndim; k++) { dstart[k] = 0; dcount[k] = o->dims[k]; mcount[0] *= o->dims[k]; } for (int i = 1; i < nargs; i++) { int k = i - 1; if (!api_is_null(args[i])) { mcount[0] /= o->dims[k]; if (api_is_integer(args[i])) { dstart[k] = api_get_integer(ctx, args[i]); dcount[k] = 1; } else { dstart[k] = api_get_integer(ctx, api_get_array_object(ctx, args[i], "0")); void *a1 = api_get_array_object(ctx, args[i], "1"); if (api_is_null(a1)) { dcount[k] = dcount[k] - 1; } else { dcount[k] = api_get_integer(ctx, a1); } if (dcount[k] < dstart[k]) api_runtime_error(ctx, "invalid range specifiers"); dcount[k] = dcount[k] - dstart[k] + 1; mcount[0] *= dcount[k]; } } } } void* hdf_get(void *ctx, int nargs, void** args) { if (nargs < 2) api_input_error(ctx); if (api_is_string(args[1])) { // hdf.name return hdf_getatt(ctx, nargs, args); } // hdf[...] hsize_t mstart[1] = { 0 }, mcount[1] = { 1 }, dstart[H5S_MAX_RANK], dcount[H5S_MAX_RANK]; zsHDF *o = (zsHDF*)api_get_user(ctx, args[0], HDF_TYPE); check_dataset(ctx, o); hdf_check_index(ctx, nargs, args, o, mcount, dstart, dcount); o->checksize(mcount[0]*o->tsize); hid_t dspace = H5Dget_space(o->did); hid_t mspace = H5Screate_simple(1, mcount, NULL); if (H5Sselect_hyperslab(dspace, H5S_SELECT_SET, dstart, NULL, dcount, NULL) < 0 || H5Sselect_hyperslab(mspace, H5S_SELECT_SET, mstart, NULL, mcount, NULL) < 0 || H5Dread(o->did, o->tid, mspace, dspace, H5P_DEFAULT, o->ptr) < 0) { api_runtime_error(ctx, "failed to read data"); } H5Sclose(mspace); H5Sclose(dspace); if (mcount[0] == 1) { switch (o->type) { case HDF_CHAR: return api_create_integer(ctx, ((char*)o->ptr)[0]); case HDF_UCHAR: return api_create_integer(ctx, ((unsigned char*)o->ptr)[0]); case HDF_SHORT: return api_create_integer(ctx, ((short*)o->ptr)[0]); case HDF_USHORT: return api_create_integer(ctx, ((unsigned short*)o->ptr)[0]); case HDF_INT: return api_create_integer(ctx, ((int*)o->ptr)[0]); case HDF_UINT: return api_create_integer(ctx, ((unsigned int*)o->ptr)[0]); case HDF_FLOAT: return api_create_real(ctx, ((float*)o->ptr)[0]); case HDF_DOUBLE: return api_create_integer(ctx, ((double*)o->ptr)[0]); default: type_error(ctx); } } return api_create_user(ctx, o->ptr, 0, 0, 0); } void* hdf_set(void *ctx, int nargs, void** args) { if (nargs < 3) api_input_error(ctx); if (api_is_string(args[1])) { // hdf.name = attribute return hdf_putatt(ctx, nargs, args); } // hdf[...] hsize_t mstart[1] = { 0 }, mcount[1] = { 1 }, dstart[H5S_MAX_RANK], dcount[H5S_MAX_RANK]; zsHDF *o = (zsHDF*)api_get_user(ctx, args[0], HDF_TYPE); check_dataset(ctx, o); hdf_check_index(ctx, nargs-1, args, o, mcount, dstart, dcount); hid_t status = -1; hid_t dspace = H5Dget_space(o->did); hid_t mspace = H5Screate_simple(1, mcount, NULL); if (H5Sselect_hyperslab(dspace, H5S_SELECT_SET, dstart, NULL, dcount, NULL) >= 0 && H5Sselect_hyperslab(mspace, H5S_SELECT_SET, mstart, NULL, mcount, NULL) >= 0) { if (api_is_user(args[nargs-1])) { void *ptr = api_get_ptr(ctx, args[nargs-1]); status = H5Dwrite(o->did, o->tid, mspace, dspace, H5P_DEFAULT, ptr); } else { zsBuffer buf(mcount[0]*o->tsize); real_t value = api_get_number(ctx, args[nargs-1]); hsize_t k; switch (o->type) { case HDF_CHAR: for (k = 0; k < mcount[0]; k++) buf.u.pchar[k] = char(value); break; case HDF_UCHAR: for (k = 0; k < mcount[0]; k++) buf.u.puchar[k] = unsigned char(value); break; case HDF_SHORT: for (k = 0; k < mcount[0]; k++) buf.u.pshort[k] = short(value); break; case HDF_USHORT: for (k = 0; k < mcount[0]; k++) buf.u.pushort[k] = unsigned short(value); break; case HDF_INT: for (k = 0; k < mcount[0]; k++) buf.u.pint[k] = int(value); break; case HDF_UINT: for (k = 0; k < mcount[0]; k++) buf.u.puint[k] = unsigned int(value); break; case HDF_FLOAT: for (k = 0; k < mcount[0]; k++) buf.u.pfloat[k] = float(value); break; case HDF_DOUBLE: for (k = 0; k < mcount[0]; k++) buf.u.pdouble[k] = double(value); break; default: type_error(ctx); } status = H5Dwrite(o->did, o->tid, mspace, dspace, H5P_DEFAULT, buf.u.ptr); } } H5Sclose(mspace); H5Sclose(dspace); if (status < 0) api_runtime_error(ctx, "failed to write to dataset"); return 0; } void* hdf_cmm(void *ctx, int nargs, void** args) { if (nargs < 1) api_input_error(ctx); zsHDF *o = (zsHDF*)api_get_user(ctx, args[0], HDF_TYPE); hid_t id = o->did; if (!o->flag) id = o->gid; if (nargs == 1) { zsBuffer buf(BUFF_SIZE); if (H5Gget_comment(id, ".", BUFF_SIZE-1, buf.u.pchar) < 0) api_runtime_error(ctx, "failed to read comment"); return api_create_string(ctx, buf.u.pchar); } if (H5Gset_comment(id, ".", api_get_string(ctx, args[1])) < 0) api_runtime_error(ctx, "failed to write comment"); return 0; } void write_space(FILE *fp, int n) { for (int k = 0; k < n; k++) fputc(' ', fp); } void list_attribute(hid_t id, FILE *fp, int nc) { zsBuffer buf(BUFF_SIZE); unsigned int k, n = H5Aget_num_attrs(id); for (k = 0; k < n; k++) { hid_t aid = H5Aopen_idx(id, k); if (aid < 0) continue; H5Aget_name(aid, BUFF_SIZE-1, buf.u.pchar); buf.u.pchar[BUFF_SIZE-1] = 0; write_space(fp, nc); fprintf(fp, "%s", buf.u.pchar); hid_t tid = H5Aget_type(aid); if (tid < 0) { H5Aclose(aid); fprintf(fp, "=...\n"); continue; } bool flag = false; hid_t sid = 0, atype = 0; switch (H5Tget_class(tid)) { case H5T_INTEGER: sid = H5Aget_space(aid); if (sid > 0) { int ndim = H5Sget_simple_extent_ndims(sid); if (ndim == 0) { int value; if (H5Aread(aid, H5T_NATIVE_INT, &value) >= 0) { fprintf(fp, "=%d\n", value); flag = true; } } } H5Sclose(sid); break; case H5T_FLOAT: sid = H5Aget_space(aid); if (sid > 0) { int ndim = H5Sget_simple_extent_ndims(sid); if (ndim == 0) { double value; if (H5Aread(aid, H5T_NATIVE_DOUBLE, &value) >= 0) fprintf(fp, "=%f\n", value); flag = true; } } H5Sclose(sid); break; case H5T_STRING: atype = H5Tcopy(H5T_C_S1); H5Tset_size(atype, BUFF_SIZE-1); if (H5Aread(aid, atype, buf.u.pchar) >= 0) { buf.u.pchar[BUFF_SIZE-1] = 0; fprintf(fp, "=%s\n", buf.u.pchar); flag = true; } H5Tclose(atype); break; } if (!flag) fprintf(fp, "=...\n"); H5Tclose(tid); H5Aclose(aid); } fflush(fp); } void list_dataset(hid_t gid, const char *name, FILE *fp, int nc) { hid_t did = H5Dopen(gid, name); if (did < 0) return; write_space(fp, nc); fprintf(fp, "%s(", name); hid_t sid = H5Dget_space(did); if (sid > 0) { hsize_t dims[H5S_MAX_RANK]; int k, ndim = H5Sget_simple_extent_dims(sid, dims, 0); for (k = 0; k < ndim; k++) { if (k == 0) fprintf(fp,"%d", dims[k]); else fprintf(fp,",%d", dims[k]); } } fprintf(fp, ")\n"); fflush(fp); H5Sclose(sid); list_attribute(did, fp, nc+4); H5Dclose(did); } void list_group(hid_t gid, const char *name, FILE *fp, int nc) { hsize_t k, n; zsBuffer buf(BUFF_SIZE); hid_t id = gid; if (name) { write_space(fp, nc); fprintf(fp, "%s\n", name); id = H5Gopen(gid, name); nc += 4; if (id < 0) return; } if (H5Gget_comment(id, ".", BUFF_SIZE-1, buf.u.pchar) > 0) { write_space(fp, nc); fprintf(fp, "comment: %s\n", buf.u.pchar); } H5Gget_num_objs(id, &n); for (k = 0; k < n; k++) { H5Gget_objname_by_idx(id, k, buf.u.pchar, BUFF_SIZE-1); buf.u.pchar[BUFF_SIZE-1] = 0; hid_t type = H5Gget_objtype_by_idx(id, k); switch(type) { case H5G_LINK: write_space(fp, nc); fprintf(fp, "%s is a link\n", buf.u.pchar); break; case H5G_GROUP: list_group(id, buf.u.pchar, fp, nc); break; case H5G_DATASET: list_dataset(id, buf.u.pchar, fp, nc); break; case H5G_TYPE: write_space(fp, nc); fprintf(fp, "%s is a datatype\n", buf.u.pchar); break; default: write_space(fp, nc); fprintf(fp, "%s is ?\n", buf.u.pchar); } H5Tclose(type); } list_attribute(id, fp, nc); if (name) H5Gclose(id); } void* hdf_list(void *ctx, int nargs, void** args) { if (nargs < 1) api_input_error(ctx); zsHDF *o = (zsHDF*)api_get_user(ctx, args[0], HDF_TYPE); list_group(o->gid, 0, stdout, 0); return 0; } struct iter_s { void *ctx; void *func; const char *name; }; herr_t scan_group(hid_t loc_id, const char *name, void *opdata) { H5G_stat_t statbuf; H5Gget_objinfo(loc_id, name, 0, &statbuf); iter_s *iter = (iter_s*)opdata; void *p[3]; p[1] = api_create_string(iter->ctx, iter->name); p[2] = api_create_string(iter->ctx, name); switch (statbuf.type) { case H5G_GROUP: p[0] = api_create_string(iter->ctx, "GROUP"); break; case H5G_DATASET: p[0] = api_create_string(iter->ctx, "DATASET"); break; default: p[0] = api_create_string(iter->ctx, "DEFAULT"); } void *ret = api_call_func(iter->ctx, iter->func, 3, p); if (api_is_integer(ret)) { return !api_get_integer(iter->ctx, ret); } return 0; } void* hdf_scan(void *ctx, int nargs, void** args) { if (nargs < 3) api_input_error(ctx); zsHDF *o = (zsHDF*)api_get_user(ctx, args[0], HDF_TYPE); const char *fname = api_get_string(ctx,args[1]); const char *gname = api_get_string(ctx,args[2]); iter_s iter = { ctx, api_get_func(ctx,fname), gname }; int idx = 0; H5Giterate(o->fid, gname, &idx, scan_group, &iter); return 0; } ///////////////////////////////////////////////////////////////////// class zsRegPrimitive { public: zsRegPrimitive() { api_add_primitive("hdf", 0, hdf_open); api_add_primitive("version", HDF_TYPE, hdf_version); api_add_primitive("group", HDF_TYPE, hdf_group); api_add_primitive("dataset", HDF_TYPE, hdf_dataset); api_add_primitive("size", HDF_TYPE, hdf_size); api_add_primitive("dims", HDF_TYPE, hdf_dims); api_add_primitive("__get", HDF_TYPE, hdf_get); api_add_primitive("__set", HDF_TYPE, hdf_set); api_add_primitive("cmm", HDF_TYPE, hdf_cmm); api_add_primitive("list", HDF_TYPE, hdf_list); api_add_primitive("scan", HDF_TYPE, hdf_scan); } ~zsRegPrimitive() { } }; zsRegPrimitive hdf_register;