diff --git a/src/hdf5_hl.d.ts b/src/hdf5_hl.d.ts index 5f659b0..d1aa40b 100644 --- a/src/hdf5_hl.d.ts +++ b/src/hdf5_hl.d.ts @@ -154,6 +154,8 @@ export declare class DatasetRegion { private _metadata?; constructor(source_dataset: Dataset, region_reference: RegionReference); get metadata(): Metadata; + get value(): OutputData; + _value_getter(json_compatible?: boolean): OutputData; } export declare const h5wasm: { File: typeof File; diff --git a/src/hdf5_hl.ts b/src/hdf5_hl.ts index a659c40..e95481e 100644 --- a/src/hdf5_hl.ts +++ b/src/hdf5_hl.ts @@ -1050,6 +1050,29 @@ export class DatasetRegion { } return this._metadata; } + + get value() { + return this._value_getter(false); + } + + _value_getter(json_compatible=false) { + let metadata = this.metadata; + // if auto_refresh is on, getting the metadata has triggered a refresh of the dataset_id; + let nbytes = metadata.size * metadata.total_size; + let data_ptr = Module._malloc(nbytes); + let processed: OutputData; + try { + Module.get_region_data(this.source_dataset.file_id, this.region_reference.ref_data, BigInt(data_ptr)); + let data = Module.HEAPU8.slice(data_ptr, data_ptr + nbytes); + processed = process_data(data, metadata, json_compatible); + } finally { + if (metadata.vlen) { + Module.reclaim_vlen_memory(this.source_dataset.file_id, this.source_dataset.path, "", BigInt(data_ptr)); + } + Module._free(data_ptr); + } + return processed; + } } function create_nested_array(value: JSONCompatibleOutputData[], shape: number[]) { diff --git a/src/hdf5_util.cc b/src/hdf5_util.cc index 359cc5d..37753d8 100644 --- a/src/hdf5_util.cc +++ b/src/hdf5_util.cc @@ -1114,7 +1114,7 @@ val get_region_metadata(hid_t loc_id, const val ref_data_in) hid_t dcpl; herr_t status; const std::vector ref_data_vec = convertJSArrayToNumberVector(ref_data_in); - const hobj_ref_t *ref_ptr = (hobj_ref_t *)ref_data_vec.data(); + const hdset_reg_ref_t *ref_ptr = (hdset_reg_ref_t *)ref_data_vec.data(); hid_t ds_id = H5Rdereference2(loc_id, H5P_DEFAULT, H5R_DATASET_REGION, ref_ptr); dtype = H5Dget_type(ds_id); @@ -1150,6 +1150,57 @@ val get_region_metadata(hid_t loc_id, const val ref_data_in) return metadata; } +int get_region_data(hid_t loc_id, val ref_data_in, uint64_t rdata_uint64) +{ + hid_t ds_id; + hid_t dspace; + hid_t dtype; + hid_t memtype; + hid_t memspace; + herr_t status; + void *rdata = (void *)rdata_uint64; + const std::vector ref_data_vec = convertJSArrayToNumberVector(ref_data_in); + const hdset_reg_ref_t *ref_ptr = (hdset_reg_ref_t *)ref_data_vec.data(); + ds_id = H5Rdereference2(loc_id, H5P_DEFAULT, H5R_DATASET_REGION, ref_ptr); + dspace = H5Rget_region(ds_id, H5R_DATASET_REGION, ref_ptr); + dtype = H5Dget_type(ds_id); + // assumes that data to write will match type of dataset (exept endianness) + memtype = H5Tcopy(dtype); + // inputs and outputs from javascript will always be little-endian + H5T_order_t dorder = H5Tget_order(dtype); + if (dorder == H5T_ORDER_BE || dorder == H5T_ORDER_VAX) + { + status = H5Tset_order(memtype, H5T_ORDER_LE); + } + int rank = H5Sget_simple_extent_ndims(dspace); + htri_t is_regular = H5Sis_regular_hyperslab(dspace); + if (is_regular > 0) + { + std::vector count(rank); + std::vector block(rank); + std::vector shape_out(rank); + htri_t success = H5Sget_regular_hyperslab(dspace, nullptr, nullptr, count.data(), block.data()); + for (int d = 0; d < rank; d++) + { + int blocksize = (block.at(d) == NULL) ? 1 : block.at(d); + shape_out.at(d) = (count.at(d) * blocksize); + } + memspace = H5Screate_simple(shape_out.size(), &shape_out[0], nullptr); + } + else + { + hsize_t total_size = H5Sget_select_npoints(dspace); + memspace = H5Screate_simple(1, &total_size, nullptr); + } + status = H5Dread(ds_id, memtype, memspace, dspace, H5P_DEFAULT, rdata); + H5Dclose(ds_id); + H5Sclose(dspace); + H5Sclose(memspace); + H5Tclose(dtype); + H5Tclose(memtype); + return (int)status; +} + EMSCRIPTEN_BINDINGS(hdf5) { function("get_keys", &get_keys_vector); @@ -1192,6 +1243,7 @@ EMSCRIPTEN_BINDINGS(hdf5) function("create_region_reference", &create_region_reference); function("get_referenced_name", &get_referenced_name); function("get_region_metadata", &get_region_metadata); + function("get_region_data", &get_region_data); class_("H5L_info2_t") .constructor<>() diff --git a/src/hdf5_util_helpers.d.ts b/src/hdf5_util_helpers.d.ts index 0461720..8bba65e 100644 --- a/src/hdf5_util_helpers.d.ts +++ b/src/hdf5_util_helpers.d.ts @@ -121,6 +121,7 @@ export interface H5Module extends EmscriptenModule { create_region_reference(file_id: bigint, path: string, count: bigint[] | null, offset: bigint[] | null, strides: bigint[] | null): Uint8Array, get_referenced_name(loc_id: bigint, ref_ptr: Uint8Array, is_object: boolean): string; get_region_metadata(loc_id: bigint, ref_ptr: Uint8Array): Metadata; + get_region_data(loc_id: bigint, ref_data: Uint8Array, rdata_ptr: bigint): number; } export declare type Filter = {