diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 1998-07-06 21:01:13 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 1998-07-06 21:01:13 (GMT) |
commit | 43f13aeca28a722d6436d43dcd84a59918dc0950 (patch) | |
tree | 1ee94e4f1b64a7d027112d616d8617992c09520a /src | |
parent | d70e61b1dbd7ff16aa4ac5cad4a69bf87b84f208 (diff) | |
download | hdf5-43f13aeca28a722d6436d43dcd84a59918dc0950.zip hdf5-43f13aeca28a722d6436d43dcd84a59918dc0950.tar.gz hdf5-43f13aeca28a722d6436d43dcd84a59918dc0950.tar.bz2 |
[svn-r451] Completely tore out existing dataspace API and replaced with code to match
API defined in the html/Dataspaces.html document. This code does not include
support for strides, merging selections, or permutations of coordinates yet,
but it's a drop-in replacement for the existing API with the same features.
Diffstat (limited to 'src')
-rw-r--r-- | src/H5A.c | 2 | ||||
-rw-r--r-- | src/H5D.c | 414 | ||||
-rw-r--r-- | src/H5E.c | 1 | ||||
-rw-r--r-- | src/H5Epublic.h | 1 | ||||
-rw-r--r-- | src/H5Farray.c | 14 | ||||
-rw-r--r-- | src/H5Iprivate.h | 1 | ||||
-rw-r--r-- | src/H5Ipublic.h | 1 | ||||
-rw-r--r-- | src/H5Oattr.c | 10 | ||||
-rw-r--r-- | src/H5Osdspace.c | 26 | ||||
-rw-r--r-- | src/H5S.c | 1326 | ||||
-rw-r--r-- | src/H5Sall.c | 511 | ||||
-rw-r--r-- | src/H5Shyper.c | 1395 | ||||
-rw-r--r-- | src/H5Spoint.c | 455 | ||||
-rw-r--r-- | src/H5Sprivate.h | 263 | ||||
-rw-r--r-- | src/H5Spublic.h | 22 | ||||
-rw-r--r-- | src/H5Sselect.c | 386 | ||||
-rw-r--r-- | src/H5Ssimp.c | 272 | ||||
-rw-r--r-- | src/H5TB.c | 506 | ||||
-rw-r--r-- | src/H5TBprivate.h | 26 | ||||
-rw-r--r-- | src/H5V.c | 66 | ||||
-rw-r--r-- | src/H5Vprivate.h | 1 | ||||
-rw-r--r-- | src/H5public.h | 2 | ||||
-rw-r--r-- | src/Makefile.in | 15 |
23 files changed, 4666 insertions, 1050 deletions
@@ -262,7 +262,7 @@ H5A_create(const H5G_entry_t *ent, const char *name, const H5T_t *type, /* Compute the internal sizes */ attr->dt_size=(H5O_DTYPE[0].raw_size)(attr->ent.file,type); - attr->ds_size=(H5O_SDSPACE[0].raw_size)(attr->ent.file,&(space->u.simple)); + attr->ds_size=(H5O_SDSPACE[0].raw_size)(attr->ent.file,&(space->extent.u.simple)); attr->data_size=H5S_get_npoints(space)*H5T_get_size(type); /* Hold the symbol table entry (and file) open */ @@ -29,6 +29,8 @@ static char RcsId[] = "@(#)$Revision$"; #include <H5Pprivate.h> /* Property lists */ #include <H5Zprivate.h> /* Data compression */ +int qak_debug=0; + #define PABLO_MASK H5D_mask /* @@ -1221,8 +1223,10 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, uint8 *bkg_buf = NULL; /*background buffer */ H5T_conv_t tconv_func = NULL; /*conversion function */ hid_t src_id = -1, dst_id = -1;/*temporary type atoms */ - const H5S_conv_t *sconv_func = NULL; /*space conversion funcs*/ - H5S_number_t numbering; /*element numbering info*/ + H5S_conv_t sconv_func={NULL}; /*space conversion funcs*/ + H5S_sel_iter_t mem_iter, /* memory selection iteration information */ + bkg_iter, /* background iteration information */ + file_iter; /* file selection iteration information */ H5T_cdata_t *cdata = NULL; /*type conversion data */ herr_t ret_value = FAIL; herr_t status; @@ -1244,14 +1248,14 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, assert(xfer_parms); assert(buf); if (!file_space) { - if (NULL==(free_this_space=H5S_read (&(dataset->ent)))) { - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to read data space from dataset header"); - } - file_space = free_this_space; + if (NULL==(free_this_space=H5S_read (&(dataset->ent)))) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to read data space from dataset header"); + } + file_space = free_this_space; } if (!mem_space) mem_space = file_space; - nelmts = H5S_get_npoints(mem_space); + nelmts = H5S_select_npoints(mem_space); #ifdef HAVE_PARALLEL /* @@ -1278,27 +1282,31 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, * enough value in xfer_parms since turning off data type conversion also * turns off background preservation. */ - if (nelmts!=H5S_get_npoints (file_space)) { - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, +#ifdef QAK +printf("%s: check 1.0, nelmts=%d\n",FUNC,(int)nelmts); +#endif /* QAK */ + if (nelmts!=H5S_select_npoints (file_space)) { + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes"); } if (NULL == (tconv_func = H5T_find(dataset->type, mem_type, xfer_parms->need_bkg, &cdata))) { - HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types"); } else if (H5T_conv_noop!=tconv_func) { - if ((src_id=H5I_register(H5_DATATYPE, - H5T_copy(dataset->type, H5T_COPY_ALL)))<0 || - (dst_id=H5I_register(H5_DATATYPE, - H5T_copy(mem_type, H5T_COPY_ALL)))<0) { - HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, - "unable to register types for conversion"); - } - } - if (NULL==(sconv_func=H5S_find (mem_space, file_space))) { - HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, + if ((src_id=H5I_register(H5_DATATYPE, H5T_copy(dataset->type, H5T_COPY_ALL)))<0 || + (dst_id=H5I_register(H5_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL)))<0) { + HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, + "unable to register types for conversion"); + } + } + if (FAIL==H5S_find (&sconv_func, mem_space, file_space)) { + HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert from file to memory data space"); } +#ifdef QAK +printf("%s: check 1.0\n",FUNC); +#endif /* QAK */ #ifdef HAVE_PARALLEL /* @@ -1307,8 +1315,8 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, if (xfer_parms->xfer_mode == H5D_XFER_COLLECTIVE){ /* Supports only no conversion, type or space, for now. */ if (H5T_conv_noop==tconv_func && - NULL!=sconv_func->read) { - status = (sconv_func->read)(dataset->ent.file, &(dataset->layout), + NULL!=sconv_func.read) { + status = (sconv_func.read)(dataset->ent.file, &(dataset->layout), &(dataset->create_parms->compress), &(dataset->create_parms->efl), H5T_get_size (dataset->type), @@ -1326,22 +1334,24 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, * If there is no type conversion then try reading directly into the * application's buffer. This saves at least one mem-to-mem copy. */ - if (H5D_OPTIMIZE_PIPE && - H5T_conv_noop==tconv_func && - NULL!=sconv_func->read) { - status = (sconv_func->read)(dataset->ent.file, &(dataset->layout), + if (H5D_OPTIMIZE_PIPE && H5T_conv_noop==tconv_func && + NULL!=sconv_func.read) { + status = (sconv_func.read)(dataset->ent.file, &(dataset->layout), &(dataset->create_parms->compress), &(dataset->create_parms->efl), H5T_get_size (dataset->type), file_space, mem_space, xfer_parms->xfer_mode, buf/*out*/); - if (status>=0) goto succeed; + if (status>=0) goto succeed; #ifdef H5D_DEBUG - fprintf (stderr, "H5D: data space conversion could not be optimized " - "for this case (using general method instead)\n"); + fprintf (stderr, "H5D: data space conversion could not be optimized " + "for this case (using general method instead)\n"); #endif - H5E_clear (); + H5E_clear (); } +#ifdef QAK +printf("%s: check 2.0\n",FUNC); +#endif /* QAK */ /* @@ -1352,21 +1362,24 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, target_size = xfer_parms->buf_size; request_nelmts = target_size / MAX(src_type_size, dst_type_size); if (request_nelmts<=0) { - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small"); } - if (sconv_func->init) { - smine_nelmts = (sconv_func->init)(&(dataset->layout), mem_space, - file_space, request_nelmts, - &numbering/*out*/); - if (smine_nelmts<=0) { - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to initialize element numbering information"); - } - } else { - smine_nelmts = request_nelmts; - HDmemset (&numbering, 0, sizeof numbering); - } + if (FAIL == (sconv_func.finit)(&(dataset->layout), file_space, &file_iter)) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to initialize file selection information"); + } + if (FAIL == (sconv_func.minit)(&(dataset->layout), mem_space, &mem_iter)) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to initialize memory selection information"); + } + if (FAIL == (sconv_func.binit)(&(dataset->layout), mem_space, &bkg_iter)) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to initialize memory selection information"); + } +#ifdef QAK +printf("%s: check 3.0, request_nelmts=%d\n",FUNC,(int)request_nelmts); +#endif /* QAK */ /* * Get a temporary buffer for type conversion unless the app has already @@ -1376,9 +1389,9 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, * same size over and over. */ if (cdata->need_bkg) { - need_bkg = MAX (cdata->need_bkg, xfer_parms->need_bkg); + need_bkg = MAX (cdata->need_bkg, xfer_parms->need_bkg); } else { - need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/ + need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/ } if (NULL==(tconv_buf=xfer_parms->tconv_buf)) { if (NULL==(tconv_buf = H5MM_malloc (target_size))) { @@ -1387,7 +1400,7 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, } } if (need_bkg && NULL==(bkg_buf=xfer_parms->bkg_buf)) { - if (NULL==(bkg_buf = H5MM_malloc (smine_nelmts * dst_type_size))) { + if (NULL==(bkg_buf = H5MM_malloc (request_nelmts * dst_type_size))) { HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background buffer"); } @@ -1414,58 +1427,88 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, } #endif +#ifdef QAK +printf("%s: check 4.0, nelmts=%d, need_bkg=%d\n",FUNC,(int)nelmts,(int)need_bkg); +#endif /* QAK */ /* Start strip mining... */ for (smine_start=0; smine_start<nelmts; smine_start+=smine_nelmts) { - smine_nelmts = MIN (smine_nelmts, nelmts-smine_start); + /* Go figure out how many elements to read from the file */ + smine_nelmts = (sconv_func.favail)(file_space,&file_iter, + MIN(request_nelmts,(nelmts-smine_start))); +#ifdef QAK +printf("%s: check 5.0, nelmts=%d, smine_start=%d, smine_nelmts=%d\n",FUNC,(int)nelmts,(int)smine_start,(int)smine_nelmts); +#endif /* QAK */ - /* - * Gather the data from disk into the data type conversion - * buffer. Also gather data from application to background buffer - * if necessary. - */ - if ((sconv_func->fgath)(dataset->ent.file, &(dataset->layout), - &(dataset->create_parms->compress), - &(dataset->create_parms->efl), - H5T_get_size (dataset->type), file_space, - &numbering, smine_start, smine_nelmts, - xfer_parms->xfer_mode, - tconv_buf/*out*/)!=smine_nelmts) { - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed"); - } - if ((H5D_OPTIMIZE_PIPE && H5T_BKG_YES==need_bkg) || - (!H5D_OPTIMIZE_PIPE && need_bkg)) { - if ((sconv_func->mgath)(buf, H5T_get_size (mem_type), mem_space, - &numbering, smine_start, smine_nelmts, - bkg_buf/*out*/)!=smine_nelmts) { - HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "mem gather failed"); - } - } + /* + * Gather the data from disk into the data type conversion + * buffer. Also gather data from application to background buffer + * if necessary. + */ + if ((sconv_func.fgath)(dataset->ent.file, &(dataset->layout), + &(dataset->create_parms->compress), + &(dataset->create_parms->efl), + H5T_get_size (dataset->type), file_space, &file_iter, + smine_nelmts, xfer_parms->xfer_mode, + tconv_buf/*out*/)!=smine_nelmts) { + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed"); + } +#ifdef QAK +printf("%s: check 6.0\n",FUNC); +{ + int i; + int *b; - /* - * Perform data type conversion. - */ + if(qak_debug) { + b=tconv_buf; + printf("\ntconv_buf:"); + for (i=0; i<smine_nelmts; i++,b++) { + printf("(%d)%d ",i,*b); + } + printf("\n"); + } +} +#endif /* QAK */ + if ((H5D_OPTIMIZE_PIPE && H5T_BKG_YES==need_bkg) || + (!H5D_OPTIMIZE_PIPE && need_bkg)) { + if ((sconv_func.mgath)(buf, H5T_get_size (mem_type), mem_space, + &bkg_iter, smine_nelmts, bkg_buf/*out*/)!=smine_nelmts) { + HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "mem gather failed"); + } + } +#ifdef QAK +printf("%s: check 7.0\n",FUNC); +#endif /* QAK */ + + /* + * Perform data type conversion. + */ #ifdef H5T_DEBUG - H5T_timer_begin (&timer, cdata); + H5T_timer_begin (&timer, cdata); #endif - cdata->command = H5T_CONV_CONV; - status = (tconv_func)(src_id, dst_id, cdata, smine_nelmts, tconv_buf, + cdata->command = H5T_CONV_CONV; + status = (tconv_func)(src_id, dst_id, cdata, smine_nelmts, tconv_buf, bkg_buf); #ifdef H5T_DEBUG - H5T_timer_end (&timer, cdata, smine_nelmts); + H5T_timer_end (&timer, cdata, smine_nelmts); #endif - if (status<0) { - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "data type conversion failed"); - } - - /* - * Scatter the data into memory. - */ - if ((sconv_func->mscat)(tconv_buf, H5T_get_size (mem_type), mem_space, - &numbering, smine_start, smine_nelmts, - buf/*out*/)<0) { - HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "scatter failed"); - } + if (status<0) { + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, + "data type conversion failed"); + } + +#ifdef QAK +printf("%s: check 8.0\n",FUNC); +#endif /* QAK */ + /* + * Scatter the data into memory. + */ + if ((sconv_func.mscat)(tconv_buf, H5T_get_size (mem_type), mem_space, + &mem_iter, smine_nelmts, buf/*out*/)<0) { + HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "scatter failed"); + } +#ifdef QAK +printf("%s: check 9.0\n",FUNC); +#endif /* QAK */ } succeed: @@ -1516,8 +1559,10 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, uint8 *bkg_buf = NULL; /*background buffer */ H5T_conv_t tconv_func = NULL; /*conversion function */ hid_t src_id = -1, dst_id = -1;/*temporary type atoms */ - const H5S_conv_t *sconv_func = NULL; /*space conversion funcs*/ - H5S_number_t numbering; /*element numbering info*/ + H5S_conv_t sconv_func= {NULL}; /*space conversion funcs*/ + H5S_sel_iter_t mem_iter, /* memory selection iteration information */ + bkg_iter, /* background iteration information */ + file_iter; /* file selection iteration information */ H5T_cdata_t *cdata = NULL; /*type conversion data */ herr_t ret_value = FAIL, status; size_t src_type_size; /*size of source type */ @@ -1545,7 +1590,7 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, file_space = free_this_space; } if (!mem_space) mem_space = file_space; - nelmts = H5S_get_npoints(mem_space); + nelmts = H5S_select_npoints(mem_space); #ifdef HAVE_PARALLEL /* @@ -1572,7 +1617,7 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, * enough value in xfer_parms since turning off data type conversion also * turns off background preservation. */ - if (nelmts!=H5S_get_npoints (file_space)) { + if (nelmts!=H5S_select_npoints (file_space)) { HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes"); } @@ -1589,10 +1634,13 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, "unable to register types for conversion"); } } - if (NULL==(sconv_func=H5S_find (mem_space, file_space))) { + if (FAIL==H5S_find (&sconv_func, mem_space, file_space)) { HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert from memory to file data space"); } +#ifdef QAK +printf("%s: check 1.0\n",FUNC); +#endif /* QAK */ #ifdef HAVE_PARALLEL /* @@ -1601,8 +1649,8 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, if (xfer_parms->xfer_mode == H5D_XFER_COLLECTIVE){ /* Supports only no conversion, type or space, for now. */ if (H5T_conv_noop==tconv_func && - NULL!=sconv_func->write) { - status = (sconv_func->write)(dataset->ent.file, + NULL!=sconv_func.write) { + status = (sconv_func.write)(dataset->ent.file, &(dataset->layout), &(dataset->create_parms->compress), &(dataset->create_parms->efl), @@ -1623,8 +1671,8 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, */ if (H5D_OPTIMIZE_PIPE && H5T_conv_noop==tconv_func && - NULL!=sconv_func->write) { - status = (sconv_func->write)(dataset->ent.file, &(dataset->layout), + NULL!=sconv_func.write) { + status = (sconv_func.write)(dataset->ent.file, &(dataset->layout), &(dataset->create_parms->compress), &(dataset->create_parms->efl), H5T_get_size (dataset->type), file_space, @@ -1636,6 +1684,9 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, #endif H5E_clear (); } +#ifdef QAK +printf("%s: check 2.0\n",FUNC); +#endif /* QAK */ /* @@ -1646,21 +1697,24 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, target_size = xfer_parms->buf_size; request_nelmts = target_size / MAX (src_type_size, dst_type_size); if (request_nelmts<=0) { - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small"); } - if (sconv_func->init) { - smine_nelmts = (sconv_func->init)(&(dataset->layout), mem_space, - file_space, request_nelmts, - &numbering/*out*/); - if (smine_nelmts<=0) { - HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, - "unable to initialize element numbering information"); - } - } else { - smine_nelmts = request_nelmts; - HDmemset (&numbering, 0, sizeof numbering); - } + if (FAIL == (sconv_func.finit)(&(dataset->layout), file_space, &file_iter)) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to initialize file selection information"); + } + if (FAIL == (sconv_func.minit)(&(dataset->layout), mem_space, &mem_iter)) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to initialize memory selection information"); + } + if (FAIL == (sconv_func.binit)(&(dataset->layout), mem_space, &bkg_iter)) { + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, + "unable to initialize memory selection information"); + } +#ifdef QAK +printf("%s: check 3.0, request_nelmts=%d\n",FUNC,(int)request_nelmts); +#endif /* QAK */ /* * Get a temporary buffer for type conversion unless the app has already @@ -1670,9 +1724,9 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, * same size over and over. */ if (cdata->need_bkg) { - need_bkg = MAX (cdata->need_bkg, xfer_parms->need_bkg); + need_bkg = MAX (cdata->need_bkg, xfer_parms->need_bkg); } else { - need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/ + need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/ } if (NULL==(tconv_buf=xfer_parms->tconv_buf)) { if (NULL==(tconv_buf = H5MM_malloc (target_size))) { @@ -1681,7 +1735,7 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, } } if (need_bkg && NULL==(bkg_buf=xfer_parms->bkg_buf)) { - if (NULL==(bkg_buf = H5MM_malloc (smine_nelmts * dst_type_size))) { + if (NULL==(bkg_buf = H5MM_malloc (request_nelmts * dst_type_size))) { HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background buffer"); } @@ -1707,65 +1761,93 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, } } #endif +#ifdef QAK +printf("%s: check 4.0, nelmts=%d, need_bkg=%d\n",FUNC,(int)nelmts,(int)need_bkg); +#endif /* QAK */ /* Start strip mining... */ for (smine_start=0; smine_start<nelmts; smine_start+=smine_nelmts) { - smine_nelmts = MIN (smine_nelmts, nelmts-smine_start); - - /* - * Gather data from application buffer into the data type conversion - * buffer. Also gather data from the file into the background buffer - * if necessary. - */ - if ((sconv_func->mgath)(buf, H5T_get_size (mem_type), mem_space, - &numbering, smine_start, smine_nelmts, - tconv_buf/*out*/)!=smine_nelmts) { - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed"); - } - if ((H5D_OPTIMIZE_PIPE && H5T_BKG_YES==need_bkg) || - (!H5D_OPTIMIZE_PIPE && need_bkg)) { - if ((sconv_func->fgath)(dataset->ent.file, &(dataset->layout), - &(dataset->create_parms->compress), - &(dataset->create_parms->efl), - H5T_get_size (dataset->type), file_space, - &numbering, smine_start, smine_nelmts, - xfer_parms->xfer_mode, - bkg_buf/*out*/)!=smine_nelmts) { - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, - "file gather failed"); - } - } - - /* - * Perform data type conversion. - */ + /* Go figure out how many elements to read from the file */ + smine_nelmts = (sconv_func.favail)(file_space,&file_iter, + MIN(request_nelmts,(nelmts-smine_start))); +#ifdef QAK +printf("%s: check 5.0, nelmts=%d, smine_start=%d, smine_nelmts=%d\n",FUNC,(int)nelmts,(int)smine_start,(int)smine_nelmts); +#endif /* QAK */ + + /* + * Gather data from application buffer into the data type conversion + * buffer. Also gather data from the file into the background buffer + * if necessary. + */ + if ((sconv_func.mgath)(buf, H5T_get_size (mem_type), mem_space, + &mem_iter, smine_nelmts, tconv_buf/*out*/)!=smine_nelmts) { + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed"); + } +#ifdef QAK +{ + int i; + int *b; + + if(qak_debug) { + b=buf; + b+=1430; + printf("buf:"); + for (i=0; i<smine_nelmts; i++,b++) { + printf("(%d)%d ",i,*b); + } + b=tconv_buf; + printf("\ntconv_buf:"); + for (i=0; i<smine_nelmts; i++,b++) { + printf("(%d)%d ",i,*b); + } + printf("\n"); + } +} +printf("%s: check 6.0\n",FUNC); +#endif /* QAK */ + if ((H5D_OPTIMIZE_PIPE && H5T_BKG_YES==need_bkg) || + (!H5D_OPTIMIZE_PIPE && need_bkg)) { + if ((sconv_func.fgath)(dataset->ent.file, &(dataset->layout), + &(dataset->create_parms->compress), + &(dataset->create_parms->efl), + H5T_get_size (dataset->type), file_space, + &bkg_iter, smine_nelmts, xfer_parms->xfer_mode, + bkg_buf/*out*/)!=smine_nelmts) { + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed"); + } + } + + /* + * Perform data type conversion. + */ #ifdef H5T_DEBUG - H5T_timer_begin (&timer, cdata); + H5T_timer_begin (&timer, cdata); #endif - cdata->command = H5T_CONV_CONV; - status = (tconv_func) (src_id, dst_id, cdata, smine_nelmts, tconv_buf, - bkg_buf); + cdata->command = H5T_CONV_CONV; + status = (tconv_func) (src_id, dst_id, cdata, smine_nelmts, tconv_buf, + bkg_buf); #ifdef H5T_DEBUG - H5T_timer_end (&timer, cdata, smine_nelmts); + H5T_timer_end (&timer, cdata, smine_nelmts); #endif - if (status<0) { - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, - "data type conversion failed"); - } + if (status<0) { + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, + "data type conversion failed"); + } - /* - * Scatter the data out to the file. - */ - if ((sconv_func->fscat)(dataset->ent.file, &(dataset->layout), - &(dataset->create_parms->compress), - &(dataset->create_parms->efl), - H5T_get_size (dataset->type), file_space, - &numbering, smine_start, smine_nelmts, - xfer_parms->xfer_mode, tconv_buf)<0) { - HGOTO_ERROR (H5E_DATASET, H5E_WRITEERROR, FAIL, "scatter failed"); - } + /* + * Scatter the data out to the file. + */ + if ((sconv_func.fscat)(dataset->ent.file, &(dataset->layout), + &(dataset->create_parms->compress), + &(dataset->create_parms->efl), + H5T_get_size (dataset->type), file_space, + &file_iter, smine_nelmts, + xfer_parms->xfer_mode, tconv_buf)<0) { + HGOTO_ERROR (H5E_DATASET, H5E_WRITEERROR, FAIL, "scatter failed"); + } } + succeed: ret_value = SUCCEED; @@ -1773,10 +1855,10 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, if (src_id >= 0) H5I_dec_ref(src_id); if (dst_id >= 0) H5I_dec_ref(dst_id); if (tconv_buf && NULL==xfer_parms->tconv_buf) { - H5MM_xfree(tconv_buf); + H5MM_xfree(tconv_buf); } if (bkg_buf && NULL==xfer_parms->bkg_buf) { - H5MM_xfree (bkg_buf); + H5MM_xfree (bkg_buf); } if (free_this_space) H5S_close (free_this_space); FUNC_LEAVE(ret_value); @@ -67,6 +67,7 @@ static const H5E_minor_mesg_t H5E_minor_mesg_g[] = { {H5E_BADRANGE, "Out of range"}, {H5E_BADVALUE, "Bad value"}, {H5E_NOSPACE, "No space available for allocation"}, + {H5E_CANTCOPY, "Unable to copy object"}, {H5E_FILEEXISTS, "File already exists"}, {H5E_FILEOPEN, "File already open"}, {H5E_CANTCREATE, "Unable to create file"}, diff --git a/src/H5Epublic.h b/src/H5Epublic.h index 4096179..d155e9a 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -89,6 +89,7 @@ typedef enum H5E_minor_t { /* Resource errors */ H5E_NOSPACE, /*no space available for allocation */ + H5E_CANTCOPY, /*unable to copy object */ /* File accessability errors */ H5E_FILEEXISTS, /*file already exists */ diff --git a/src/H5Farray.c b/src/H5Farray.c index 85df727..0a3d5ab 100644 --- a/src/H5Farray.c +++ b/src/H5Farray.c @@ -155,6 +155,13 @@ H5F_arr_read (H5F_t *f, const struct H5O_layout_t *layout, "supported yet"); } #endif +#ifdef QAK +{ + printf("%s: layout->ndims=%d\n",FUNC,(int)layout->ndims); + for(i=0; i<layout->ndims; i++) + printf("%s: %d: hslab_size=%d, mem_size=%d, mem_offset=%d, file_offset=%d\n",FUNC,i,(int)_hslab_size[i],(int)mem_size[i],(int)mem_offset[i],(int)file_offset[i]); +} +#endif /* QAK */ switch (layout->type) { case H5D_CONTIGUOUS: @@ -360,6 +367,13 @@ H5F_arr_write (H5F_t *f, const struct H5O_layout_t *layout, "collective access on non-contiguous datasets not supported yet"); } #endif +#ifdef QAK +{ + printf("%s: layout->ndims=%d\n",FUNC,(int)layout->ndims); + for(i=0; i<layout->ndims; i++) + printf("%s: %d: hslab_size=%d, mem_size=%d, mem_offset=%d, file_offset=%d\n",FUNC,i,(int)_hslab_size[i],(int)mem_size[i],(int)mem_offset[i],(int)file_offset[i]); +} +#endif /* QAK */ switch (layout->type) { case H5D_CONTIGUOUS: diff --git a/src/H5Iprivate.h b/src/H5Iprivate.h index 895128b..81c53d2 100644 --- a/src/H5Iprivate.h +++ b/src/H5Iprivate.h @@ -68,6 +68,7 @@ #define H5I_OID_HASHSIZE 64 #define H5I_GROUPID_HASHSIZE 64 #define H5I_ATTRID_HASHSIZE 64 +#define H5I_TEMPBUFID_HASHSIZE 64 /* Atom information structure used */ typedef struct H5I_id_info_t { diff --git a/src/H5Ipublic.h b/src/H5Ipublic.h index 96442a7..74b0bd8 100644 --- a/src/H5Ipublic.h +++ b/src/H5Ipublic.h @@ -40,6 +40,7 @@ typedef enum { H5_DATASPACE, /*group ID for Dataspace objects */ H5_DATASET, /*group ID for Dataset objects */ H5_ATTR, /*group ID for Attribute objects */ + H5_TEMPBUF, /*group ID for Temporary buffer objects */ MAXGROUP /*highest group in group_t (Invalid as true group)*/ } H5I_group_t; diff --git a/src/H5Oattr.c b/src/H5Oattr.c index 6a13a91..c71318f 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -115,13 +115,13 @@ H5O_attr_decode(H5F_t *f, const uint8 *p, H5O_shared_t __unused__ *sh) "memory allocation failed"); } if((simple=(H5O_SDSPACE->decode)(f,p,NULL))!=NULL) { - attr->ds->type = H5S_SIMPLE; - HDmemcpy(&(attr->ds->u.simple),simple, sizeof(H5S_simple_t)); + attr->ds->extent.type = H5S_SIMPLE; + HDmemcpy(&(attr->ds->extent.u.simple),simple, sizeof(H5S_simple_t)); H5MM_xfree(simple); } else { - attr->ds->type = H5S_SCALAR; + attr->ds->extent.type = H5S_SCALAR; } /* end else */ - attr->ds_size=(H5O_SDSPACE->raw_size)(f,&(attr->ds->u.simple)); + attr->ds_size=(H5O_SDSPACE->raw_size)(f,&(attr->ds->extent.u.simple)); p+=attr->ds_size; /* Compute the size of the data */ @@ -190,7 +190,7 @@ H5O_attr_encode(H5F_t *f, uint8 *p, const void *mesg) p+=attr->dt_size; /* encode the attribute dataspace */ - if((H5O_SDSPACE->encode)(f,p,&(attr->ds->u.simple))<0) { + if((H5O_SDSPACE->encode)(f,p,&(attr->ds->extent.u.simple))<0) { HRETURN_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute dataspace"); } diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c index a780af3..117dcf3 100644 --- a/src/H5Osdspace.c +++ b/src/H5Osdspace.c @@ -102,7 +102,7 @@ H5O_sdspace_decode(H5F_t *f, const uint8 *p, H5O_shared_t __unused__ *sh) for (u = 0; u < sdim->rank; u++) { H5F_decode_length (f, p, sdim->size[u]); } - if (flags & 0x01) { + if (flags & H5S_VALID_MAX) { if (NULL==(sdim->max=H5MM_malloc(sizeof(sdim->max[0])* sdim->rank))) { HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, @@ -112,7 +112,8 @@ H5O_sdspace_decode(H5F_t *f, const uint8 *p, H5O_shared_t __unused__ *sh) H5F_decode_length (f, p, sdim->max[u]); } } - if (flags & 0x02) { +#ifdef LATER + if (flags & H5S_VALID_PERM) { if (NULL==(sdim->perm=H5MM_malloc(sizeof(sdim->perm[0])* sdim->rank))) { HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, @@ -121,6 +122,7 @@ H5O_sdspace_decode(H5F_t *f, const uint8 *p, H5O_shared_t __unused__ *sh) for (u = 0; u < sdim->rank; u++) UINT32DECODE(p, sdim->perm[u]); } +#endif } } @@ -171,8 +173,10 @@ H5O_sdspace_encode(H5F_t *f, uint8 *p, const void *mesg) assert(sdim); /* set flags */ - if (sdim->max) flags |= 0x01; - if (sdim->perm) flags |= 0x02; + if (sdim->max) flags |= H5S_VALID_MAX; +#ifdef LATER + if (sdim->perm) flags |= H5S_VALID_PERM; +#endif /* encode */ UINT32ENCODE(p, sdim->rank); @@ -181,15 +185,17 @@ H5O_sdspace_encode(H5F_t *f, uint8 *p, const void *mesg) for (u = 0; u < sdim->rank; u++) { H5F_encode_length (f, p, sdim->size[u]); } - if (flags & 0x01) { + if (flags & H5S_VALID_MAX) { for (u = 0; u < sdim->rank; u++) { H5F_encode_length (f, p, sdim->max[u]); } } - if (flags & 0x02) { +#ifdef LATER + if (flags & H5S_VALID_PERM) { for (u = 0; u < sdim->rank; u++) UINT32ENCODE(p, sdim->perm[u]); } +#endif } FUNC_LEAVE(SUCCEED); } @@ -241,6 +247,7 @@ H5O_sdspace_copy(const void *mesg, void *dest) } HDmemcpy (dst->max, src->max, src->rank*sizeof(src->max[0])); } +#ifdef LATER if (src->perm) { if (NULL==(dst->perm=H5MM_calloc(src->rank*sizeof(src->perm[0])))) { HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, @@ -248,6 +255,7 @@ H5O_sdspace_copy(const void *mesg, void *dest) } HDmemcpy (dst->perm, src->perm, src->rank*sizeof(src->perm[0])); } +#endif FUNC_LEAVE((void *) dst); } @@ -278,7 +286,9 @@ H5O_sdspace_reset(void *_mesg) FUNC_ENTER (H5O_sdspace_reset, FAIL); mesg->size = H5MM_xfree (mesg->size); mesg->max = H5MM_xfree (mesg->max); +#ifdef LATER mesg->perm = H5MM_xfree (mesg->perm); +#endif FUNC_LEAVE (SUCCEED); } @@ -321,8 +331,10 @@ H5O_sdspace_size(H5F_t *f, const void *mesg) /* add in the space for the maximum dimensions, if they are present */ ret_value += sdim->max ? sdim->rank * H5F_SIZEOF_SIZE (f) : 0; +#ifdef LATER /* add in the space for the dimension permutations, if they are present */ ret_value += sdim->perm ? sdim->rank * 4 : 0; +#endif FUNC_LEAVE(ret_value); } @@ -386,6 +398,7 @@ H5O_sdspace_debug(H5F_t __unused__ *f, const void *mesg, HDfprintf (stream, "CONSTANT\n"); } +#ifdef LATER if (sdim->perm) { HDfprintf(stream, "%*s%-*s {", indent, "", fwidth, "Dim Perm:"); for (u = 0; u < sdim->rank; u++) { @@ -393,6 +406,7 @@ H5O_sdspace_debug(H5F_t __unused__ *f, const void *mesg, (unsigned long) (sdim->perm[u])); } } +#endif FUNC_LEAVE(SUCCEED); } @@ -20,7 +20,7 @@ static char RcsId[] = "@(#)$Revision$"; #include <H5Iprivate.h> /* ID Functions */ #include <H5Eprivate.h> /* Error handling */ #include <H5MMprivate.h> /* Memory Management functions */ -#include <H5Oprivate.h> /*object headers */ +#include <H5Oprivate.h> /* object headers */ #include <H5Sprivate.h> /* Data-space functions */ /* Interface initialization */ @@ -51,9 +51,8 @@ H5S_init_interface(void) /* Initialize the atom group for the file IDs */ if ((ret_value = H5I_init_group(H5_DATASPACE, H5I_DATASPACEID_HASHSIZE, - H5S_RESERVED_ATOMS, - (herr_t (*)(void *)) H5S_close)) != FAIL) { - ret_value = H5_add_exit(&H5S_term_interface); + H5S_RESERVED_ATOMS, (herr_t (*)(void *)) H5S_close)) != FAIL) { + ret_value = H5_add_exit(&H5S_term_interface); } FUNC_LEAVE(ret_value); } @@ -82,116 +81,97 @@ H5S_term_interface(void) H5I_destroy_group(H5_DATASPACE); } -/*------------------------------------------------------------------------- - * Function: H5Screate_simple - * - * Purpose: Creates a new simple data space object and opens it for - * access. The DIMS argument is the size of the simple dataset - * and the MAXDIMS argument is the upper limit on the size of - * the dataset. MAXDIMS may be the null pointer in which case - * the upper limit is the same as DIMS. If an element of - * MAXDIMS is H5S_UNLIMITED then the corresponding dimension is - * unlimited, otherwise no element of MAXDIMS should be smaller - * than the corresponding element of DIMS. - * - * Return: Success: The ID for the new simple data space object. - * - * Failure: FAIL - * - * Errors: - * - * Programmer: Quincey Koziol - * Tuesday, January 27, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -hid_t -H5Screate_simple (int rank, const hsize_t *dims, const hsize_t *maxdims) +/*-------------------------------------------------------------------------- + NAME + H5S_create + PURPOSE + Create empty, typed dataspace + USAGE + H5S_t *H5S_create(type) + H5S_type_t type; IN: Dataspace type to create + RETURNS + Pointer to dataspace on success, NULL on failure + DESCRIPTION + Creates a new dataspace of a given type. The extent & selection are + undefined + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5S_t *H5S_create(H5S_class_t type) { - H5S_t *ds = NULL; + H5S_t *ret_value = NULL; + + FUNC_ENTER(H5S_create, NULL); + + /* Create a new data space */ + if((ret_value = H5MM_calloc(sizeof(H5S_t)))!=NULL) + { + ret_value->extent.type = type; + ret_value->select.type = H5S_SEL_ALL; /* Entire extent selected by default */ + } + +#ifdef LATER +done: +#endif + FUNC_LEAVE(ret_value); +} /* end H5S_create() */ + +/*-------------------------------------------------------------------------- + NAME + H5Screate + PURPOSE + Create empty, typed dataspace + USAGE + hid_t H5Screate(type) + H5S_type_t type; IN: Dataspace type to create + RETURNS + Valid dataspace ID on success, negative on failure + DESCRIPTION + Creates a new dataspace of a given type. The extent & selection are + undefined + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hid_t H5Screate(H5S_class_t type) +{ + H5S_t *new_ds=NULL; hid_t ret_value = FAIL; - int i; FUNC_ENTER(H5Screate, FAIL); - H5TRACE3("i","Is*h*h",rank,dims,maxdims); - /* Check arguments */ - if (rank<0) { - HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, - "dimensionality cannot be negative"); - } - if (!dims && dims!=0) { - HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, - "no dimensions specified"); - } - if (maxdims) { - for (i=0; i<rank; i++) { - if (H5S_UNLIMITED!=maxdims[i] && maxdims[i]<dims[i]) { - HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, - "maxdims is smaller than dims"); - } - } - } + /* Check args */ + if(type<=H5S_NO_CLASS || type> H5S_SIMPLE) /* don't allow complex dataspace yet */ + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "invalid dataspace type"); - /* Create a new data space */ - if (NULL==(ds = H5MM_calloc(sizeof(H5S_t)))) { - HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, - "memory allocation failed"); + if (NULL==(new_ds=H5S_create(type))) { + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace"); } - if(rank>0) /* for creating simple dataspace */ - { - ds->type = H5S_SIMPLE; - ds->hslab_def = FALSE; /* no hyperslab defined currently */ - - /* Initialize rank and dimensions */ - ds->u.simple.rank = rank; - - if (NULL==(ds->u.simple.size = H5MM_calloc(1*rank*sizeof(hsize_t)))) { - HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, - "memory allocation failed"); - } - HDmemcpy(ds->u.simple.size, dims, rank*sizeof(hsize_t)); - - if (maxdims) { - if (NULL==(ds->u.simple.max=H5MM_calloc(rank*sizeof(hsize_t)))) { - HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, - "memory allocation failed"); - } - HDmemcpy (ds->u.simple.max, maxdims, rank*sizeof(hsize_t)); - } - } /* end if */ - else /* rank==0, for scalar data space */ - { - ds->type = H5S_SCALAR; - ds->u.simple.rank = 0; - } /* end else */ - - /* Register the new data space and get an ID for it */ - if ((ret_value = H5I_register(H5_DATASPACE, ds)) < 0) { - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, - "unable to register data space for ID"); + + /* Atomize */ + if ((ret_value=H5I_register (H5_DATASPACE, new_ds))<0) { + HGOTO_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space atom"); } - done: +done: if (ret_value < 0) { - H5MM_xfree(ds); } FUNC_LEAVE(ret_value); -} +} /* end H5Screate() */ /*------------------------------------------------------------------------- - * Function: H5Sclose + * Function: H5S_close * - * Purpose: Release access to a data space object. + * Purpose: Releases all memory associated with a data space. * * Return: Success: SUCCEED * * Failure: FAIL * - * Errors: - * * Programmer: Robb Matzke * Tuesday, December 9, 1997 * @@ -199,33 +179,55 @@ H5Screate_simple (int rank, const hsize_t *dims, const hsize_t *maxdims) * *------------------------------------------------------------------------- */ -herr_t -H5Sclose (hid_t space_id) +herr_t H5S_close(H5S_t *ds) { - FUNC_ENTER(H5Sclose, FAIL); - H5TRACE1("e","i",space_id); + FUNC_ENTER(H5S_close, FAIL); - /* Check args */ - if (H5_DATASPACE != H5I_group(space_id) || - NULL == H5I_object(space_id)) { - HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); - } - /* When the reference count reaches zero the resources are freed */ - if (H5I_dec_ref(space_id) < 0) { - HRETURN_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "problem freeing id"); + assert(ds); + + /* Release selection (this should come before the extent release) */ + H5S_select_release(ds); + + /* release extent */ + switch (ds->extent.type) { + case H5S_NO_CLASS: + /*nothing needed */ + break; + + case H5S_SCALAR: + /*nothing needed */ + break; + + case H5S_SIMPLE: + H5S_release_simple(&(ds->extent.u.simple)); + break; + + case H5S_COMPLEX: + /* nothing yet */ + break; + + default: + assert("unknown dataspace (extent) type" && 0); + break; } + + /* Release the main structure */ + H5MM_xfree(ds); + FUNC_LEAVE(SUCCEED); } /*------------------------------------------------------------------------- - * Function: H5S_close + * Function: H5Sclose * - * Purpose: Releases all memory associated with a data space. + * Purpose: Release access to a data space object. * * Return: Success: SUCCEED * * Failure: FAIL * + * Errors: + * * Programmer: Robb Matzke * Tuesday, December 9, 1997 * @@ -234,41 +236,25 @@ H5Sclose (hid_t space_id) *------------------------------------------------------------------------- */ herr_t -H5S_close(H5S_t *ds) +H5Sclose (hid_t space_id) { - FUNC_ENTER(H5S_close, FAIL); - - assert(ds); - - switch (ds->type) { - case H5S_SCALAR: - /*nothing needed */ - break; - - case H5S_SIMPLE: - H5S_close_simple(&(ds->u.simple)); - break; - - case H5S_COMPLEX: - /* nothing */ - break; + FUNC_ENTER(H5Sclose, FAIL); + H5TRACE1("e","i",space_id); - default: - assert("unknown data space type" && 0); - break; + /* Check args */ + if (H5_DATASPACE != H5I_group(space_id) || + NULL == H5I_object(space_id)) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + } + /* When the reference count reaches zero the resources are freed */ + if (H5I_dec_ref(space_id) < 0) { + HRETURN_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "problem freeing id"); } - if(ds->hslab_def==TRUE) { - H5MM_xfree(ds->h.start); - H5MM_xfree(ds->h.count); - H5MM_xfree(ds->h.stride); - } /* end if */ - H5MM_xfree(ds); - FUNC_LEAVE(SUCCEED); } /*------------------------------------------------------------------------- - * Function: H5S_close_simple + * Function: H5S_release_simple * * Purpose: Releases all memory associated with a simple data space. * (but doesn't free the simple space itself) @@ -284,16 +270,16 @@ H5S_close(H5S_t *ds) * *------------------------------------------------------------------------- */ -herr_t -H5S_close_simple(H5S_simple_t *simple) +herr_t H5S_release_simple(H5S_simple_t *simple) { - FUNC_ENTER(H5S_close_simple, FAIL); + FUNC_ENTER(H5S_release_simple, FAIL); assert(simple); - H5MM_xfree(simple->size); - H5MM_xfree(simple->max); - H5MM_xfree(simple->perm); + if(simple->size) + H5MM_xfree(simple->size); + if(simple->max) + H5MM_xfree(simple->max); FUNC_LEAVE(SUCCEED); } @@ -325,21 +311,18 @@ H5Scopy (hid_t space_id) H5TRACE1("i","i",space_id); /* Check args */ - if (H5_DATASPACE!=H5I_group (space_id) || - NULL==(src=H5I_object (space_id))) { - HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + if (H5_DATASPACE!=H5I_group (space_id) || NULL==(src=H5I_object (space_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); } /* Copy */ if (NULL==(dst=H5S_copy (src))) { - HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, - "unable to copy data space"); + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy data space"); } /* Atomize */ if ((ret_value=H5I_register (H5_DATASPACE, dst))<0) { - HRETURN_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, - "unable to register data space atom"); + HRETURN_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space atom"); } FUNC_LEAVE (ret_value); @@ -347,9 +330,67 @@ H5Scopy (hid_t space_id) /*------------------------------------------------------------------------- + * Function: H5S_extent_copy + * + * Purpose: Copies a dataspace extent + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * Wednesday, June 3, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t H5S_extent_copy(H5S_extent_t *dst, const H5S_extent_t *src) +{ + int i; + + FUNC_ENTER(H5S_extent_copy, NULL); + + /* Copy the regular fields */ + *dst=*src; + + switch (src->type) { + case H5S_SCALAR: + /*nothing needed */ + break; + + case H5S_SIMPLE: + if (src->u.simple.size) { + dst->u.simple.size = H5MM_malloc(src->u.simple.rank * + sizeof(src->u.simple.size[0])); + for (i = 0; i < src->u.simple.rank; i++) { + dst->u.simple.size[i] = src->u.simple.size[i]; + } + } + if (src->u.simple.max) { + dst->u.simple.max = H5MM_malloc(src->u.simple.rank * + sizeof(src->u.simple.max[0])); + for (i = 0; i < src->u.simple.rank; i++) { + dst->u.simple.max[i] = src->u.simple.max[i]; + } + } + break; + + case H5S_COMPLEX: + /*void */ + break; + + default: + assert("unknown data space type" && 0); + break; + } + + FUNC_LEAVE(SUCCEED); +} + +/*------------------------------------------------------------------------- * Function: H5S_copy * - * Purpose: Copies a data space. + * Purpose: Copies a data space, by copying the extent and selection through + * H5S_extent_copy and H5S_select_copy * * Return: Success: A pointer to a new copy of SRC * @@ -362,11 +403,9 @@ H5Scopy (hid_t space_id) * *------------------------------------------------------------------------- */ -H5S_t * -H5S_copy(const H5S_t *src) +H5S_t * H5S_copy(const H5S_t *src) { H5S_t *dst = NULL; - int i; FUNC_ENTER(H5S_copy, NULL); @@ -376,55 +415,13 @@ H5S_copy(const H5S_t *src) } *dst = *src; - switch (dst->type) { - case H5S_SCALAR: - /*nothing needed */ - break; - - case H5S_SIMPLE: - if (dst->u.simple.size) { - dst->u.simple.size = H5MM_malloc(dst->u.simple.rank * - sizeof(dst->u.simple.size[0])); - if (NULL==dst->u.simple.size) { - HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, - "memory allocation failed"); - } - for (i = 0; i < dst->u.simple.rank; i++) { - dst->u.simple.size[i] = src->u.simple.size[i]; - } - } - if (dst->u.simple.max) { - dst->u.simple.max = H5MM_malloc(dst->u.simple.rank * - sizeof(dst->u.simple.max[0])); - if (NULL==dst->u.simple.max) { - HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, - "memory allocation failed"); - } - for (i = 0; i < dst->u.simple.rank; i++) { - dst->u.simple.max[i] = src->u.simple.max[i]; - } - } - if (dst->u.simple.perm) { - dst->u.simple.perm = H5MM_malloc(dst->u.simple.rank * - sizeof(dst->u.simple.perm[0])); - if (NULL==dst->u.simple.perm) { - HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, - "memory allocation failed"); - } - for (i = 0; i < dst->u.simple.rank; i++) { - dst->u.simple.perm[i] = src->u.simple.perm[i]; - } - } - break; - - case H5S_COMPLEX: - /*void */ - break; - - default: - assert("unknown data space type" && 0); - break; - } + /* Copy the source dataspace's extent */ + if (H5S_extent_copy(&(dst->extent),&(src->extent))<0) + HRETURN_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy extent"); + + /* Copy the source dataspace's selection */ + if (H5S_select_copy(dst,src)<0) + HRETURN_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy select"); FUNC_LEAVE(dst); } @@ -455,9 +452,8 @@ H5Sget_npoints (hid_t space_id) H5TRACE1("h","i",space_id); /* Check args */ - if (H5_DATASPACE != H5I_group(space_id) || - NULL == (ds = H5I_object(space_id))) { - HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a data space"); + if (H5_DATASPACE != H5I_group(space_id) || NULL == (ds = H5I_object(space_id))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a data space"); } ret_value = H5S_get_npoints(ds); @@ -492,35 +488,25 @@ H5S_get_npoints(const H5S_t *ds) /* check args */ assert(ds); - switch (ds->type) { - case H5S_SCALAR: - ret_value = 1; - break; - - case H5S_SIMPLE: - /* - * Count the elements selected by the hypeslab if there is one, - * otherwise count all the elements. - */ - if (ds->hslab_def) { - for (ret_value=1, i=0; i<ds->u.simple.rank; i++) { - ret_value *= ds->h.count[i]; - } - } else { - for (ret_value=1, i=0; i<ds->u.simple.rank; i++) { - ret_value *= ds->u.simple.size[i]; - } - } - break; - - case H5S_COMPLEX: - HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0, - "complex data spaces are not supported yet"); - - default: - assert("unknown data space class" && 0); - HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0, - "internal error (unknown data space class)"); + switch (ds->extent.type) { + case H5S_SCALAR: + ret_value = 1; + break; + + case H5S_SIMPLE: + for (ret_value=1, i=0; i<ds->extent.u.simple.rank; i++) { + ret_value *= ds->extent.u.simple.size[i]; + } + break; + + case H5S_COMPLEX: + HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0, + "complex data spaces are not supported yet"); + + default: + assert("unknown data space class" && 0); + HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0, + "internal error (unknown data space class)"); } FUNC_LEAVE(ret_value); @@ -558,36 +544,36 @@ H5S_get_npoints_max(const H5S_t *ds) /* check args */ assert(ds); - switch (ds->type) { - case H5S_SCALAR: - ret_value = 1; - break; - - case H5S_SIMPLE: - if (ds->u.simple.max) { - for (ret_value=1, i=0; i<ds->u.simple.rank; i++) { - if (H5S_UNLIMITED==ds->u.simple.max[i]) { - ret_value = MAX_HSIZET; - break; - } else { - ret_value *= ds->u.simple.max[i]; - } - } - } else { - for (ret_value=1, i=0; i<ds->u.simple.rank; i++) { - ret_value *= ds->u.simple.size[i]; - } - } - break; - - case H5S_COMPLEX: - HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0, - "complex data spaces are not supported yet"); - - default: - assert("unknown data space class" && 0); - HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0, - "internal error (unknown data space class)"); + switch (ds->extent.type) { + case H5S_SCALAR: + ret_value = 1; + break; + + case H5S_SIMPLE: + if (ds->extent.u.simple.max) { + for (ret_value=1, i=0; i<ds->extent.u.simple.rank; i++) { + if (H5S_UNLIMITED==ds->extent.u.simple.max[i]) { + ret_value = MAX_HSIZET; + break; + } else { + ret_value *= ds->extent.u.simple.max[i]; + } + } + } else { + for (ret_value=1, i=0; i<ds->extent.u.simple.rank; i++) { + ret_value *= ds->extent.u.simple.size[i]; + } + } + break; + + case H5S_COMPLEX: + HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0, + "complex data spaces are not supported yet"); + + default: + assert("unknown data space class" && 0); + HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0, + "internal error (unknown data space class)"); } FUNC_LEAVE(ret_value); @@ -620,9 +606,8 @@ H5Sget_ndims (hid_t space_id) H5TRACE1("Is","i",space_id); /* Check args */ - if (H5_DATASPACE != H5I_group(space_id) || - NULL == (ds = H5I_object(space_id))) { - HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + if (H5_DATASPACE != H5I_group(space_id) || NULL == (ds = H5I_object(space_id))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); } ret_value = H5S_get_ndims(ds); @@ -656,23 +641,23 @@ H5S_get_ndims(const H5S_t *ds) /* check args */ assert(ds); - switch (ds->type) { - case H5S_SCALAR: - ret_value = 0; - break; + switch (ds->extent.type) { + case H5S_SCALAR: + ret_value = 0; + break; - case H5S_SIMPLE: - ret_value = ds->u.simple.rank; - break; + case H5S_SIMPLE: + ret_value = ds->extent.u.simple.rank; + break; - case H5S_COMPLEX: - HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, - "complex data spaces are not supported yet"); + case H5S_COMPLEX: + HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, + "complex data spaces are not supported yet"); - default: - assert("unknown data space class" && 0); - HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, - "internal error (unknown data space class)"); + default: + assert("unknown data space class" && 0); + HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, + "internal error (unknown data space class)"); } FUNC_LEAVE(ret_value); @@ -710,9 +695,8 @@ H5Sget_dims (hid_t space_id, hsize_t dims[]/*out*/, hsize_t maxdims[]/*out*/) H5TRACE1("Is","i",space_id); /* Check args */ - if (H5_DATASPACE != H5I_group(space_id) || - NULL == (ds = H5I_object(space_id))) { - HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + if (H5_DATASPACE != H5I_group(space_id) || NULL == (ds = H5I_object(space_id))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); } ret_value = H5S_get_dims(ds, dims, maxdims); @@ -746,35 +730,35 @@ H5S_get_dims(const H5S_t *ds, hsize_t dims[], hsize_t max_dims[]) /* check args */ assert(ds); - assert(dims); - - switch (ds->type) { - case H5S_SCALAR: - ret_value = 0; - break; - - case H5S_SIMPLE: - ret_value = ds->u.simple.rank; - for (i=0; i<ret_value; i++) { - if (dims) dims[i] = ds->u.simple.size[i]; - if (max_dims) { - if (ds->u.simple.max) { - max_dims[i] = ds->u.simple.max[i]; - } else { - max_dims[i] = ds->u.simple.size[i]; - } - } - } - break; - - case H5S_COMPLEX: - HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, - "complex data spaces are not supported yet"); - - default: - assert("unknown data space class" && 0); - HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, - "internal error (unknown data space class)"); + + switch (ds->extent.type) { + case H5S_SCALAR: + ret_value = 0; + break; + + case H5S_SIMPLE: + ret_value = ds->extent.u.simple.rank; + for (i=0; i<ret_value; i++) { + if (dims) + dims[i] = ds->extent.u.simple.size[i]; + if (max_dims) { + if (ds->extent.u.simple.max) { + max_dims[i] = ds->extent.u.simple.max[i]; + } else { + max_dims[i] = ds->extent.u.simple.size[i]; + } + } + } + break; + + case H5S_COMPLEX: + HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, + "complex data spaces are not supported yet"); + + default: + assert("unknown data space class" && 0); + HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, + "internal error (unknown data space class)"); } FUNC_LEAVE(ret_value); @@ -805,27 +789,22 @@ H5S_modify(H5G_entry_t *ent, const H5S_t *ds) assert(ent); assert(ds); - switch (ds->type) { - case H5S_SCALAR: -#ifdef OLD_WAY - HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, - "scalar data spaces are not implemented yet"); -#endif - - case H5S_SIMPLE: - if (H5O_modify(ent, H5O_SDSPACE, 0, 0, &(ds->u.simple)) < 0) { - HRETURN_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, - "can't update simple data space message"); - } - break; - - case H5S_COMPLEX: - HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, - "complex data spaces are not implemented yet"); - - default: - assert("unknown data space class" && 0); - break; + switch (ds->extent.type) { + case H5S_SCALAR: + case H5S_SIMPLE: + if (H5O_modify(ent, H5O_SDSPACE, 0, 0, &(ds->extent.u.simple)) < 0) { + HRETURN_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, + "can't update simple data space message"); + } + break; + + case H5S_COMPLEX: + HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, + "complex data spaces are not implemented yet"); + + default: + assert("unknown data space class" && 0); + break; } FUNC_LEAVE(SUCCEED); @@ -860,24 +839,26 @@ H5S_read(H5G_entry_t *ent) assert(ent); if (NULL==(ds = H5MM_calloc(sizeof(H5S_t)))) { - HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, + HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } - if (H5O_read(ent, H5O_SDSPACE, 0, &(ds->u.simple))) { - ds->type = H5S_SIMPLE; - + if (H5O_read(ent, H5O_SDSPACE, 0, &(ds->extent.u.simple))) { + ds->extent.type = H5S_SIMPLE; } else { - ds->type = H5S_SCALAR; + ds->extent.type = H5S_SCALAR; } + /* Default to entire dataspace being selected */ + ds->select.type=H5S_SEL_ALL; + FUNC_LEAVE(ds); } /*------------------------------------------------------------------------- * Function: H5S_cmp * - * Purpose: Compares two data spaces. + * Purpose: Compares two data space extents. * * Return: Success: 0 if DS1 and DS2 are the same. * <0 if DS1 is less than DS2. @@ -889,6 +870,7 @@ H5S_read(H5G_entry_t *ent) * Wednesday, December 10, 1997 * * Modifications: + * 6/9/98 Changed to only compare extents - QAK * *------------------------------------------------------------------------- */ @@ -904,61 +886,42 @@ H5S_cmp(const H5S_t *ds1, const H5S_t *ds2) assert(ds2); /* compare */ - if (ds1->type < ds2->type) - HRETURN(-1); - if (ds1->type > ds2->type) - HRETURN(1); - - switch (ds1->type) { - case H5S_SIMPLE: - if (ds1->u.simple.rank < ds2->u.simple.rank) - HRETURN(-1); - if (ds1->u.simple.rank > ds2->u.simple.rank) - HRETURN(1); - - for (i = 0; i < ds1->u.simple.rank; i++) { - if (ds1->u.simple.size[i] < ds2->u.simple.size[i]) - HRETURN(-1); - if (ds1->u.simple.size[i] > ds2->u.simple.size[i]) - HRETURN(1); - } - - /* don't compare max dimensions */ - - for (i = 0; i < ds1->u.simple.rank; i++) { - if ((ds1->u.simple.perm ? ds1->u.simple.perm[i] : i) < - (ds2->u.simple.perm ? ds2->u.simple.perm[i] : i)) - HRETURN(-1); - if ((ds1->u.simple.perm ? ds2->u.simple.perm[i] : i) > - (ds2->u.simple.perm ? ds2->u.simple.perm[i] : i)) - HRETURN(1); - } - - /* Check if we should compare hyperslab definitions */ - if(ds1->hslab_def==TRUE && ds2->hslab_def==TRUE) { - for (i = 0; i < ds1->u.simple.rank; i++) { - if (ds1->h.start[i] < ds2->h.start[i]) - HRETURN(-1); - if (ds1->h.start[i] > ds2->h.start[i]) - HRETURN(1); - if (ds1->h.count[i] < ds2->h.count[i]) - HRETURN(-1); - if (ds1->h.count[i] > ds2->h.count[i]) - HRETURN(1); - if (ds1->h.stride[i] < ds2->h.stride[i]) - HRETURN(-1); - if (ds1->h.stride[i] > ds2->h.stride[i]) - HRETURN(1); - } - } else { - if(ds1->hslab_def!=ds2->hslab_def) - HRETURN(ds1->hslab_def==TRUE ? 1 : -1); - } - - break; - - default: - assert("not implemented yet" && 0); + if (ds1->extent.type < ds2->extent.type) + HRETURN(-1); + if (ds1->extent.type > ds2->extent.type) + HRETURN(1); + + switch (ds1->extent.type) { + case H5S_SIMPLE: + if (ds1->extent.u.simple.rank < ds2->extent.u.simple.rank) + HRETURN(-1); + if (ds1->extent.u.simple.rank > ds2->extent.u.simple.rank) + HRETURN(1); + + for (i = 0; i < ds1->extent.u.simple.rank; i++) { + if (ds1->extent.u.simple.size[i] < ds2->extent.u.simple.size[i]) + HRETURN(-1); + if (ds1->extent.u.simple.size[i] > ds2->extent.u.simple.size[i]) + HRETURN(1); + } + + /* don't compare max dimensions */ + +#ifdef LATER + for (i = 0; i < ds1->extent.u.simple.rank; i++) { + if ((ds1->extent.u.simple.perm ? ds1->extent.u.simple.perm[i] : i) < + (ds2->extent.u.simple.perm ? ds2->extent.u.simple.perm[i] : i)) + HRETURN(-1); + if ((ds1->extent.u.simple.perm ? ds2->extent.u.simple.perm[i] : i) > + (ds2->extent.u.simple.perm ? ds2->extent.u.simple.perm[i] : i)) + HRETURN(1); + } +#endif + + break; + + default: + assert("not implemented yet" && 0); } FUNC_LEAVE(0); @@ -988,7 +951,7 @@ H5S_is_simple(const H5S_t *sdim) /* Check args and all the boring stuff. */ assert(sdim); - ret_value = sdim->type == H5S_SIMPLE ? TRUE : FALSE; /* Currently all dataspaces are simple, but check anyway */ + ret_value = sdim->extent.type == H5S_SIMPLE ? TRUE : FALSE; FUNC_LEAVE(ret_value); } @@ -1034,310 +997,108 @@ H5Sis_simple (hid_t sid) /*-------------------------------------------------------------------------- NAME - H5Sset_space + H5Sset_extent_simple PURPOSE - Determine the size of a dataspace + Sets the size of a simple dataspace USAGE - herr_t H5Sset_space(sid, rank, dims) - hid_t sid; IN: Dataspace object to query - intn rank; IN: # of dimensions for the dataspace - const size_t *dims; IN: Size of each dimension for the dataspace + herr_t H5Sset_extent_simple(sid, rank, dims, max) + hid_t sid; IN: Dataspace object to query + intn rank; IN: # of dimensions for the dataspace + const size_t *dims; IN: Size of each dimension for the dataspace + const size_t *max; IN: Maximum size of each dimension for the dataspace RETURNS SUCCEED/FAIL DESCRIPTION This function sets the number and size of each dimension in the - dataspace. Setting RANK to a value of zero allows scalar objects to be - created. Dimensions are specified from slowest to fastest changing in the - DIMS array (i.e. 'C' order). Setting the size of a dimension to zero - indicates that the dimension is of unlimited size and should be allowed to - expand. Currently, only the first dimension in the array (the slowest) may - be unlimited in size. + dataspace. Setting RANK to a value of zero converts the dataspace to a + scalar dataspace. Dimensions are specified from slowest to fastest changing + in the DIMS array (i.e. 'C' order). Setting the size of a dimension in the + MAX array to zero indicates that the dimension is of unlimited size and + should be allowed to expand. If MAX is NULL, the dimensions in the DIMS + array are used as the maximum dimensions. Currently, only the first + dimension in the array (the slowest) may be unlimited in size. --------------------------------------------------------------------------*/ herr_t -H5Sset_space (hid_t sid, int rank, const hsize_t *dims) +H5Sset_extent_simple (hid_t sid, int rank, const hsize_t *dims, const hsize_t *max) { H5S_t *space = NULL; /* dataspace to modify */ intn u; /* local counting variable */ herr_t ret_value = SUCCEED; - FUNC_ENTER(H5Sset_space, FAIL); - H5TRACE3("e","iIs*h",sid,rank,dims); + FUNC_ENTER(H5Sset_extent_simple, FAIL); /* Check args */ if ((space = H5I_object(sid)) == NULL) { - HRETURN_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a data space"); + HRETURN_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a data space"); } if (rank > 0 && dims == NULL) { - HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no dimensions specified"); + HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no dimensions specified"); } if (rank<0) { - HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid rank"); + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid rank"); } if (dims) { - for (u=0; u<rank; u++) { - if (dims[u]<=0) { - HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, - "invalid dimension size"); - } - } + for (u=0; u<rank; u++) { + if (((max!=NULL && max[u]!=H5S_UNLIMITED) || max==NULL) && dims[u]==0) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "invalid dimension size"); + } + } + } + if (max!=NULL) { + if(dims==NULL) + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "maximum dimension specified, but no current dimensions specified"); + for (u=0; u<rank; u++) { + if (max[u]!=H5S_UNLIMITED && max[u]<dims[u]) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "invalid maximum dimension size"); + } + } } /* shift out of the previous state to a "simple" dataspace */ - switch (space->type) { - case H5S_SCALAR: - case H5S_SIMPLE: - /* do nothing */ - break; - - case H5S_COMPLEX: - /* - * eventually this will destroy whatever "complex" dataspace info - * is retained, right now it's an error - */ - /* Fall through to report error */ - - default: - HRETURN_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, - "unknown data space class"); - } - space->type = H5S_SIMPLE; - - /* Reset hyperslab definition, if one is defined */ - if(space->hslab_def==TRUE) { - H5MM_xfree(space->h.start); - H5MM_xfree(space->h.count); - H5MM_xfree(space->h.stride); - space->hslab_def=FALSE; + switch (space->extent.type) { + case H5S_SCALAR: + /* do nothing */ + break; + + case H5S_SIMPLE: + H5S_release_simple(&(space->extent.u.simple)); + break; + + case H5S_COMPLEX: + /* + * eventually this will destroy whatever "complex" dataspace info + * is retained, right now it's an error + */ + /* Fall through to report error */ + + default: + HRETURN_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, + "unknown data space class"); } - /* Free the old space for now */ - if (space->u.simple.size != NULL) - space->u.simple.size = H5MM_xfree(space->u.simple.size); - if (space->u.simple.max != NULL) - space->u.simple.max = H5MM_xfree(space->u.simple.max); - if (space->u.simple.perm != NULL) - space->u.simple.max = H5MM_xfree(space->u.simple.perm); - if (rank == 0) { /* scalar variable */ - space->type = H5S_SCALAR; - space->u.simple.rank = 0; /* set to scalar rank */ + space->extent.type = H5S_SCALAR; + space->extent.u.simple.rank = 0; /* set to scalar rank */ } else { - /* Set the rank and copy the dims */ - space->u.simple.rank = rank; - if (NULL==(space->u.simple.size=H5MM_calloc(rank*sizeof(hsize_t)))) { - HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, - "memory allocation failed"); - } - HDmemcpy(space->u.simple.size, dims, sizeof(hsize_t) * rank); + space->extent.type = H5S_SIMPLE; + + /* Set the rank and copy the dims */ + space->extent.u.simple.rank = rank; + space->extent.u.simple.size = H5MM_malloc(rank*sizeof(hsize_t)); + HDmemcpy(space->extent.u.simple.size, dims, sizeof(hsize_t) * rank); + + /* Copy the maximum dimensions if specified */ + if(max!=NULL) { + space->extent.u.simple.max = H5MM_malloc(rank*sizeof(hsize_t)); + HDmemcpy(space->extent.u.simple.max, max, sizeof(hsize_t) * rank); + } /* end if */ } FUNC_LEAVE(ret_value); } -/*-------------------------------------------------------------------------- - NAME - H5Sset_hyperslab - PURPOSE - Select a hyperslab from a simple dataspace - USAGE - herr_t H5Sset_hyperslab(sid, start, count, stride) - hid_t sid; IN: Dataspace object to select hyperslab from - const int *start; IN: Starting location for hyperslab to select - const size_t *count; IN: Number of elements in hyperslab - const size_t *stride; IN: Packing of elements in hyperslab - RETURNS - SUCCEED/FAIL - DESCRIPTION - This function selects a hyperslab from a simple dataspace. The stride - array may be used to sub-sample the hyperslab chosen, a value of 1 in each - position of the stride array selects contiguous elements in the array, - a value of 2 selects every other element, etc. If the stride parameter is - set to NULL, a contiguous hyperslab is chosen. The values in the start and - count arrays may be negative, to allow for selecting hyperslabs in chunked - datasets which extend in arbitrary directions. ---------------------------------------------------------------------------*/ -herr_t -H5Sset_hyperslab (hid_t sid, const hssize_t *start, const hsize_t *count, - const hsize_t *stride) -{ - H5S_t *space = NULL; /* dataspace to modify */ - hsize_t *tmp_stride=NULL; /* temp. copy of stride */ - intn u; /* local counting variable */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER(H5Sset_hyperslab, FAIL); - H5TRACE4("e","i*Hs*h*h",sid,start,count,stride); - - /* Get the object */ - if (H5_DATASPACE != H5I_group(sid) || (space = H5I_object(sid)) == NULL) { - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a data space"); - } - if (start == NULL || count==NULL) { - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, - "invalid hyperslab selected"); - } - - /* We can't modify other types of dataspaces currently, so error out */ - if (space->type!=H5S_SIMPLE) { - HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, - "unknown dataspace type"); - } - - /* Set up stride values for later use */ - tmp_stride=H5MM_malloc(space->u.simple.rank*sizeof(tmp_stride[0])); - if (NULL==tmp_stride) { - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, - "memory allocation failed"); - } - for (u=0; u<space->u.simple.rank; u++) { - tmp_stride[u] = stride ? stride[u] : 1; - } - - /* Range check arguments */ - for (u=0; u<space->u.simple.rank; u++) { - if (start[u]<0 || (hsize_t)(start[u])>=space->u.simple.size[u]) { - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, - "hyperslab bounds out of range"); - } - if (start[u]<0 || - start[u]+(count[u]*tmp_stride[u])>space->u.simple.size[u]) { - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, - "hyperslab bounds out of range"); - } - } - - /* Allocate space for the hyperslab information */ - if (NULL==space->h.start) { - space->h.start=H5MM_calloc(space->u.simple.rank*sizeof(hsize_t)); - space->h.count=H5MM_calloc(space->u.simple.rank*sizeof(hsize_t)); - space->h.stride=H5MM_calloc(space->u.simple.rank*sizeof(hsize_t)); - if (NULL==space->h.start || - NULL==space->h.count || - NULL==space->h.stride) { - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, - "memory allocation failed"); - } - } - - /* Build hyperslab */ - for(u=0; u<space->u.simple.rank; u++) { - space->h.start[u] = start[u]; - space->h.count[u] = count[u]; - space->h.stride[u] = tmp_stride[u]; - } - space->hslab_def=TRUE; - -done: - if (ret_value == FAIL) { /* Error condition cleanup */ - - } /* end if */ - - /* Normal function cleanup */ - H5MM_xfree(tmp_stride); - FUNC_LEAVE(ret_value); -} - -/*------------------------------------------------------------------------- - * Function: H5Sget_hyperslab - * - * Purpose: Retrieves information about the hyperslab from a simple data - * space. If no hyperslab has been defined then the hyperslab - * is the same as the entire array. - * - * Return: Success: Hyperslab dimensionality. - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * Wednesday, January 28, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -int -H5Sget_hyperslab (hid_t sid, hssize_t offset[]/*out*/, hsize_t size[]/*out*/, - hsize_t stride[]/*out*/) -{ - const H5S_t *ds = NULL; - intn ret_value = FAIL; - - FUNC_ENTER (H5Sget_hyperslab, FAIL); - H5TRACE1("Is","i",sid); - - /* Check args */ - if (H5_DATASPACE!=H5I_group (sid) || NULL==(ds=H5I_object (sid))) { - HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); - } - - /* Get hyperslab info */ - if ((ret_value=H5S_get_hyperslab (ds, offset, size, stride))<0) { - HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, - "unable to retrieve hyperslab information"); - } - - FUNC_LEAVE (ret_value); -} - -/*------------------------------------------------------------------------- - * Function: H5S_get_hyperslab - * - * Purpose: Retrieves information about the hyperslab from a simple data - * space. If no hyperslab has been defined then the hyperslab - * is the same as the entire array. - * - * Return: Success: Hyperslab dimensionality. - * - * Failure: FAIL - * - * Programmer: Robb Matzke - * Wednesday, January 28, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -intn -H5S_get_hyperslab (const H5S_t *ds, hssize_t offset[]/*out*/, - hsize_t size[]/*out*/, hsize_t stride[]/*out*/) -{ - intn i; - intn ret_value = FAIL; - - FUNC_ENTER (H5S_get_hyperslab, FAIL); - - /* Check args */ - assert (ds); - switch (ds->type) { - case H5S_SCALAR: - break; - - case H5S_SIMPLE: - if (ds->hslab_def) { - for (i=0; i<ds->u.simple.rank; i++) { - if (offset) offset[i] = ds->h.start[i]; - if (size) size[i] = ds->h.count[i]; - if (stride) stride[i] = ds->h.stride[i]; - } - } else { - for (i=0; i<ds->u.simple.rank; i++) { - if (offset) offset[i] = 0; - if (size) size[i] = ds->u.simple.size[i]; - if (stride) stride[i] = 1; - } - } - ret_value = ds->u.simple.rank; - break; - - case H5S_COMPLEX: /*fall through*/ - default: - HRETURN_ERROR (H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, - "hyperslabs not supported for this type of space"); - } - - FUNC_LEAVE (ret_value); -} - - /*------------------------------------------------------------------------- * Function: H5S_find * @@ -1358,44 +1119,138 @@ H5S_get_hyperslab (const H5S_t *ds, hssize_t offset[]/*out*/, * *------------------------------------------------------------------------- */ -const H5S_conv_t * -H5S_find (const H5S_t *mem_space, const H5S_t *file_space) +herr_t +H5S_find (H5S_conv_t *conv, const H5S_t *mem_space, const H5S_t *file_space) { - static H5S_conv_t _conv; - static const H5S_conv_t *conv = NULL; - - FUNC_ENTER (H5S_find, NULL); + FUNC_ENTER (H5S_find, FAIL); /* Check args */ - assert (mem_space && (H5S_SIMPLE==mem_space->type || H5S_SCALAR==mem_space->type)); - assert (file_space && (H5S_SIMPLE==file_space->type || H5S_SCALAR==mem_space->type)); + assert (conv); + assert (mem_space && (H5S_SIMPLE==mem_space->extent.type || H5S_SCALAR==mem_space->extent.type)); + assert (file_space && (H5S_SIMPLE==file_space->extent.type || H5S_SCALAR==mem_space->extent.type)); /* * We can't do conversion if the source and destination select a * different number of data points. */ - if (H5S_get_npoints (mem_space) != H5S_get_npoints (file_space)) { - HRETURN_ERROR (H5E_DATASPACE, H5E_BADRANGE, NULL, + if (H5S_select_npoints (mem_space) != H5S_select_npoints (file_space)) { + HRETURN_ERROR (H5E_DATASPACE, H5E_BADRANGE, FAIL, "memory and file data spaces are different sizes"); } +#ifdef OLD_WAY /* * Initialize pointers. This will eventually be a table lookup based * on the source and destination data spaces, similar to H5T_find(), but * for now we only support simple data spaces. */ if (!conv) { - _conv.init = H5S_simp_init; - _conv.fgath = H5S_simp_fgath; - _conv.mscat = H5S_simp_mscat; - _conv.mgath = H5S_simp_mgath; - _conv.fscat = H5S_simp_fscat; - _conv.read = H5S_simp_read; - _conv.write = H5S_simp_write; - conv = &_conv; + _conv.init = H5S_simp_init; + _conv.fgath = H5S_simp_fgath; + _conv.mscat = H5S_simp_mscat; + _conv.mgath = H5S_simp_mgath; + _conv.fscat = H5S_simp_fscat; + _conv.read = H5S_simp_read; + _conv.write = H5S_simp_write; + conv = &_conv; } +#else + /* Set up the function pointers for file transfers */ + switch(file_space->select.type) { + case H5S_SEL_POINTS: +#ifdef QAK +printf("%s: file space has point selection\n",FUNC); +#endif /* QAK */ + conv->finit = H5S_point_init; + conv->favail = H5S_point_favail; + conv->fgath = H5S_point_fgath; + conv->fscat = H5S_point_fscat; + conv->read = NULL; + conv->write = NULL; + break; + + case H5S_SEL_ALL: +#ifdef QAK +printf("%s: file space has all selection\n",FUNC); +#endif /* QAK */ + conv->finit = H5S_all_init; + conv->favail = H5S_all_favail; + conv->fgath = H5S_all_fgath; + conv->fscat = H5S_all_fscat; + conv->read = NULL; + conv->write = NULL; + break; + + case H5S_SEL_HYPERSLABS: +#ifdef QAK +printf("%s: file space has hyperslab selection\n",FUNC); +#endif /* QAK */ + conv->finit = H5S_hyper_init; + conv->favail = H5S_hyper_favail; + conv->fgath = H5S_hyper_fgath; + conv->fscat = H5S_hyper_fscat; + conv->read = NULL; + conv->write = NULL; + break; + + case H5S_SEL_NONE: + default: +#ifdef QAK +printf("%s: file space has unknown selection\n",FUNC); +#endif /* QAK */ + HRETURN_ERROR (H5E_DATASPACE, H5E_BADVALUE, FAIL, + "invalid file dataspace selection type"); + } /* end switch */ + + /* Set up the function pointers for background & memory transfers */ + switch(mem_space->select.type) { + case H5S_SEL_POINTS: +#ifdef QAK +printf("%s: memory space has point selection\n",FUNC); +#endif /* QAK */ + conv->minit = H5S_point_init; + conv->binit = H5S_point_init; + conv->mgath = H5S_point_mgath; + conv->mscat = H5S_point_mscat; + conv->read = NULL; + conv->write = NULL; + break; + + case H5S_SEL_ALL: +#ifdef QAK +printf("%s: memory space has all selection\n",FUNC); +#endif /* QAK */ + conv->minit = H5S_all_init; + conv->binit = H5S_all_init; + conv->mgath = H5S_all_mgath; + conv->mscat = H5S_all_mscat; + conv->read = NULL; + conv->write = NULL; + break; + + case H5S_SEL_HYPERSLABS: +#ifdef QAK +printf("%s: memory space has hyperslab selection\n",FUNC); +#endif /* QAK */ + conv->minit = H5S_hyper_init; + conv->binit = H5S_hyper_init; + conv->mgath = H5S_hyper_mgath; + conv->mscat = H5S_hyper_mscat; + conv->read = NULL; + conv->write = NULL; + break; + + case H5S_SEL_NONE: + default: +#ifdef QAK +printf("%s: memory space has unknown selection\n",FUNC); +#endif /* QAK */ + HRETURN_ERROR (H5E_DATASPACE, H5E_BADVALUE, FAIL, + "invalid file dataspace selection type"); + } /* end switch */ +#endif /* OLD_WAY */ - FUNC_LEAVE (conv); + FUNC_LEAVE (SUCCEED); } /*------------------------------------------------------------------------- @@ -1422,30 +1277,97 @@ H5S_extend (H5S_t *space, const hsize_t *size) FUNC_ENTER (H5S_extend, FAIL); /* Check args */ - assert (space && H5S_SIMPLE==space->type); + assert (space && H5S_SIMPLE==space->extent.type); assert (size); - for (i=0; i<space->u.simple.rank; i++) { - if (space->u.simple.size[i]<size[i]) { - if (space->u.simple.max && - H5S_UNLIMITED!=space->u.simple.max[i] && - space->u.simple.max[i]<size[i]) { - HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, - "dimension cannot be increased"); - } - ret_value++; - } + for (i=0; i<space->extent.u.simple.rank; i++) { + if (space->extent.u.simple.size[i]<size[i]) { + if (space->extent.u.simple.max && + H5S_UNLIMITED!=space->extent.u.simple.max[i] && + space->extent.u.simple.max[i]<size[i]) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "dimension cannot be increased"); + } + ret_value++; + } } /* Update */ if (ret_value) { - for (i=0; i<space->u.simple.rank; i++) { - if (space->u.simple.size[i]<size[i]) { - space->u.simple.size[i] = size[i]; - } - } + for (i=0; i<space->extent.u.simple.rank; i++) { + if (space->extent.u.simple.size[i]<size[i]) { + space->extent.u.simple.size[i] = size[i]; + } + } } FUNC_LEAVE (ret_value); } + +/*------------------------------------------------------------------------- + * Function: H5Screate_simple + * + * Purpose: Creates a new simple data space object and opens it for + * access. The DIMS argument is the size of the simple dataset + * and the MAXDIMS argument is the upper limit on the size of + * the dataset. MAXDIMS may be the null pointer in which case + * the upper limit is the same as DIMS. If an element of + * MAXDIMS is H5S_UNLIMITED then the corresponding dimension is + * unlimited, otherwise no element of MAXDIMS should be smaller + * than the corresponding element of DIMS. + * + * Return: Success: The ID for the new simple data space object. + * + * Failure: FAIL + * + * Errors: + * + * Programmer: Quincey Koziol + * Tuesday, January 27, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5Screate_simple (int rank, const hsize_t *dims, const hsize_t *maxdims) +{ + hid_t ret_value = FAIL; + int i; + + FUNC_ENTER(H5Screate, FAIL); + + /* Check arguments */ + if (rank<0) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "dimensionality cannot be negative"); + } + if (!dims && dims!=0) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "no dimensions specified"); + } + if (maxdims) { + for (i=0; i<rank; i++) { + if (H5S_UNLIMITED!=maxdims[i] && maxdims[i]<dims[i]) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "maxdims is smaller than dims"); + } + } + } + + if((ret_value=H5Screate(H5S_SIMPLE))==FAIL) + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTCREATE, FAIL, + "can't create simple dataspace"); + + if(H5Sset_extent_simple(ret_value,rank,dims,maxdims)<0) { + H5Sclose(ret_value); + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, + "can't set dimensions"); + } /* end if */ + +done: + if (ret_value < 0) { + } + FUNC_LEAVE(ret_value); +} diff --git a/src/H5Sall.c b/src/H5Sall.c new file mode 100644 index 0000000..f35b23b --- /dev/null +++ b/src/H5Sall.c @@ -0,0 +1,511 @@ +/* + * Copyright (C) 1998 NCSA + * All rights reserved. + * + * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Tuesday, June 16, 1998 + * + * Purpose: "All" selection data space I/O functions. + */ +#include <H5private.h> +#include <H5Eprivate.h> +#include <H5Sprivate.h> +#include <H5Vprivate.h> + +/* Interface initialization */ +#define PABLO_MASK H5S_all_mask +#define INTERFACE_INIT NULL +static intn interface_initialize_g = FALSE; + +/*------------------------------------------------------------------------- + * Function: H5S_all_init + * + * Purpose: Initializes iteration information for all selection. + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_all_init (const struct H5O_layout_t __unused__ *layout, + const H5S_t *space, H5S_sel_iter_t *sel_iter) +{ + FUNC_ENTER (H5S_all_init, FAIL); + + /* Check args */ + assert (layout); + assert (space && H5S_SEL_ALL==space->select.type); + assert (sel_iter); + + /* Initialize the number of elements to iterate over */ + sel_iter->all.elmt_left=H5S_get_npoints(space); + + /* Start at the upper left location */ + sel_iter->all.offset=0; + + FUNC_LEAVE (SUCCEED); +} + +/*------------------------------------------------------------------------- + * Function: H5S_all_favail + * + * Purpose: Figure out the optimal number of elements to transfer to/from the file + * + * Return: non-negative number of elements on success, negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +size_t +H5S_all_favail (const H5S_t *space, const H5S_sel_iter_t *sel_iter, size_t max) +{ + hsize_t nelmts; + int m_ndims; /* file dimensionality */ + hsize_t size[H5O_LAYOUT_NDIMS]; /*size of selected hyperslab */ + hsize_t acc; + int i; + + FUNC_ENTER (H5S_all_favail, FAIL); + + /* Check args */ + assert (space && H5S_SEL_ALL==space->select.type); + assert (sel_iter); + + /* + * The stripmine size is such that only the slowest varying dimension can + * be split up. We choose the largest possible strip mine size which is + * not larger than the desired size. + */ + m_ndims = H5S_get_dims (space, size, NULL); + for (i=m_ndims-1, acc=1; i>0; --i) + acc *= size[i]; + nelmts = (max/acc) * acc; + if (nelmts<=0) { + HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, 0, + "strip mine buffer is too small"); + } + + FUNC_LEAVE (MIN(sel_iter->all.elmt_left,nelmts)); +} /* H5S_all_favail() */ + +/*------------------------------------------------------------------------- + * Function: H5S_all_fgath + * + * Purpose: Gathers data points from file F and accumulates them in the + * type conversion buffer BUF. The LAYOUT argument describes + * how the data is stored on disk and EFL describes how the data + * is organized in external files. ELMT_SIZE is the size in + * bytes of a datum which this function treats as opaque. + * FILE_SPACE describes the data space of the dataset on disk + * and the elements that have been selected for reading (via + * hyperslab, etc). This function will copy at most NELMTS elements. + * + * Return: Success: Number of elements copied. + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +size_t +H5S_all_fgath (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, + size_t elmt_size, const H5S_t *file_space, H5S_sel_iter_t *file_iter, + size_t nelmts, + const H5D_transfer_t xfer_mode, void *_buf/*out*/) +{ + hssize_t file_offset[H5O_LAYOUT_NDIMS]; /*offset of slab in file*/ + hsize_t hsize[H5O_LAYOUT_NDIMS]; /*size of hyperslab */ + hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero */ + uint8 *buf=(uint8 *)_buf; /* Alias for pointer arithmetic */ + hsize_t acc; /*accumulator */ + intn space_ndims; /*dimensionality of space*/ + intn i; /*counters */ + + FUNC_ENTER (H5S_all_fgath, 0); + + /* Check args */ + assert (f); + assert (layout); + assert (elmt_size>0); + assert (file_space); + assert (file_iter); + assert (nelmts>0); + assert (buf); + + /* + * Get hyperslab information to determine what elements are being + * selected (there might eventually be other selection methods too). + * We only support hyperslabs with unit sample because there's no way to + * currently pass sample information into H5F_arr_read() much less + * H5F_istore_read(). + */ + if ((space_ndims=H5S_get_dims (file_space, hsize, NULL))<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, 0, + "unable to retrieve hyperslab parameters"); + } + HDmemset(file_offset,0,sizeof(hssize_t)*space_ndims); + + /* Adjust the slowest varying dimension to take care of strip mining */ + for (i=1, acc=1; i<space_ndims; i++) + acc *= hsize[i]; + assert (0==file_iter->all.offset % acc); + assert (0==nelmts % acc); + file_offset[0] += file_iter->all.offset / acc; + hsize[0] = nelmts / acc; + + /* The fastest varying dimension is for the data point itself */ + file_offset[space_ndims] = 0; + hsize[space_ndims] = elmt_size; + HDmemset (zero, 0, layout->ndims*sizeof(*zero)); + + /* + * Gather from file. + */ + if (H5F_arr_read (f, layout, comp, efl, hsize, hsize, zero, file_offset, + xfer_mode, buf/*out*/)<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_READERROR, 0, "read error"); + } + + /* Advance iterator */ + file_iter->all.elmt_left--; + file_iter->all.offset+=nelmts; + + FUNC_LEAVE (nelmts); +} /* H5S_all_fgath() */ + +/*------------------------------------------------------------------------- + * Function: H5S_all_fscat + * + * Purpose: Scatters dataset elements from the type conversion buffer BUF + * to the file F where the data points are arranged according to + * the file data space FILE_SPACE and stored according to + * LAYOUT and EFL. Each element is ELMT_SIZE bytes. + * The caller is requesting that NELMTS elements are copied. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_all_fscat (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, + size_t elmt_size, const H5S_t *file_space, H5S_sel_iter_t *file_iter, + size_t nelmts, + const H5D_transfer_t xfer_mode, const void *_buf) +{ + hssize_t file_offset[H5O_LAYOUT_NDIMS]; /*offset of hyperslab */ + hsize_t hsize[H5O_LAYOUT_NDIMS]; /*size of hyperslab */ + hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero vector */ + const uint8 *buf=(const uint8 *)_buf; /* Alias for pointer arithmetic */ + hsize_t acc; /*accumulator */ + intn space_ndims; /*space dimensionality */ + intn i; /*counters */ + + FUNC_ENTER (H5S_all_fscat, FAIL); + + /* Check args */ + assert (f); + assert (layout); + assert (elmt_size>0); + assert (file_space); + assert (file_iter); + assert (nelmts>0); + assert (buf); + + /* + * Get information to determine what elements are being selected. + */ + if ((space_ndims=H5S_get_dims (file_space, hsize, NULL))<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, + "unable to retrieve hyperslab parameters"); + } + HDmemset(file_offset,0,sizeof(hssize_t)*space_ndims); + + /* Adjust the slowest varying dimension to account for strip mining */ + for (i=1, acc=1; i<space_ndims; i++) + acc *= hsize[i]; + assert (0==file_iter->all.offset % acc); + assert (0==nelmts % acc); + file_offset[0] += file_iter->all.offset / acc; + hsize[0] = nelmts / acc; + + /* The fastest varying dimension is for the data point itself */ + file_offset[space_ndims] = 0; + hsize[space_ndims] = elmt_size; + HDmemset (zero, 0, layout->ndims*sizeof(*zero)); + + /* + * Scatter to file. + */ + if (H5F_arr_write (f, layout, comp, efl, hsize, hsize, zero, + file_offset, xfer_mode, buf)<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error"); + } + + /* Advance iterator */ + file_iter->all.elmt_left--; + file_iter->all.offset+=nelmts; + + FUNC_LEAVE (SUCCEED); +} /* H5S_all_fscat() */ + +/*------------------------------------------------------------------------- + * Function: H5S_all_mgath + * + * Purpose: Gathers dataset elements from application memory BUF and + * copies them into the data type conversion buffer TCONV_BUF. + * Each element is ELMT_SIZE bytes and arranged in application + * memory according to MEM_SPACE. + * The caller is requesting that at most NELMTS be gathered. + * + * Return: Success: Number of elements copied. + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +size_t +H5S_all_mgath (const void *_buf, size_t elmt_size, + const H5S_t *mem_space, H5S_sel_iter_t *mem_iter, + size_t nelmts, void *_tconv_buf/*out*/) +{ + hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /*slab offset in app buf*/ + hsize_t mem_size[H5O_LAYOUT_NDIMS]; /*total size of app buf */ + hsize_t hsize[H5O_LAYOUT_NDIMS]; /*size of hyperslab */ + hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero */ + const uint8 *buf=(const uint8 *)_buf; /* Get local copies for address arithmetic */ + uint8 *tconv_buf=(uint8 *)_tconv_buf; + hsize_t acc; /*accumulator */ + intn space_ndims; /*dimensionality of space*/ + intn i; /*counters */ + + FUNC_ENTER (H5S_all_mgath, 0); + + /* Check args */ + assert (buf); + assert (elmt_size>0); + assert (mem_space && H5S_SEL_ALL==mem_space->select.type); + assert (mem_iter); + assert (nelmts>0); + assert (tconv_buf); + + /* + * Retrieve information to determine what elements are being selected. + */ + if ((space_ndims=H5S_get_dims (mem_space, hsize, NULL))<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, 0, + "unable to retrieve hyperslab parameters"); + } + HDmemset(mem_offset,0,sizeof(hssize_t)*space_ndims); + + if (H5S_get_dims (mem_space, mem_size, NULL)<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, 0, + "unable to retrieve data space dimensions"); + } + + /* Adjust the slowest varying dimension to account for strip mining */ + for (i=1, acc=1; i<space_ndims; i++) + acc *= hsize[i]; + assert (0==mem_iter->all.offset % acc); + assert (0==nelmts % acc); + mem_offset[0] += mem_iter->all.offset / acc; + hsize[0] = nelmts / acc; + + /* The fastest varying dimension is for the data point itself */ + mem_offset[space_ndims] = 0; + mem_size[space_ndims] = elmt_size; + hsize[space_ndims] = elmt_size; + HDmemset (zero, 0, (space_ndims+1)*sizeof(*zero)); + + /* + * Scatter from conversion buffer to application memory. + */ + if (H5V_hyper_copy (space_ndims+1, hsize, hsize, zero, tconv_buf, + mem_size, mem_offset, buf)<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, 0, + "unable to scatter data to memory"); + } + + /* Advance iterator */ + mem_iter->all.elmt_left--; + mem_iter->all.offset+=nelmts; + + FUNC_LEAVE (nelmts); +} /* H5S_all_mgath() */ + +/*------------------------------------------------------------------------- + * Function: H5S_all_mscat + * + * Purpose: Scatters NELMTS data points from the type conversion buffer + * TCONV_BUF to the application buffer BUF. Each element is + * ELMT_SIZE bytes and they are organized in application memory + * according to MEM_SPACE. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, June 17, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_all_mscat (const void *_tconv_buf, size_t elmt_size, + const H5S_t *mem_space, H5S_sel_iter_t *mem_iter, + size_t nelmts, void *_buf/*out*/) +{ + hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /*slab offset in app buf*/ + hsize_t mem_size[H5O_LAYOUT_NDIMS]; /*total size of app buf */ + hsize_t hsize[H5O_LAYOUT_NDIMS]; /*size of hyperslab */ + hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero */ + uint8 *buf=(uint8 *)_buf; /* Get local copies for address arithmetic */ + const uint8 *tconv_buf=(const uint8 *)_tconv_buf; + hsize_t acc; /*accumulator */ + intn space_ndims; /*dimensionality of space*/ + intn i; /*counters */ + + FUNC_ENTER (H5S_all_mscat, FAIL); + + /* Check args */ + assert (tconv_buf); + assert (elmt_size>0); + assert (mem_space && H5S_SEL_ALL==mem_space->select.type); + assert (mem_iter); + assert (nelmts>0); + assert (buf); + + /* + * Retrieve information to determine what elements are being selected. + */ + if ((space_ndims=H5S_get_dims (mem_space, hsize, NULL))<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, + "unable to retrieve hyperslab parameters"); + } + HDmemset(mem_offset,0,sizeof(hssize_t)*space_ndims); + + if (H5S_get_dims (mem_space, mem_size, NULL)<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, + "unable to retrieve data space dimensions"); + } + + /* Adjust the slowest varying dimension to take care of strip mining */ + for (i=1, acc=1; i<space_ndims; i++) + acc *= hsize[i]; + assert (0==mem_iter->all.offset % acc); + assert (0==nelmts % acc); + mem_offset[0] += mem_iter->all.offset / acc; + hsize[0] = nelmts / acc; + + /* The fastest varying dimension is for the data point itself */ + mem_offset[space_ndims] = 0; + mem_size[space_ndims] = elmt_size; + hsize[space_ndims] = elmt_size; + HDmemset (zero, 0, (space_ndims+1)*sizeof(*zero)); + + /* + * Scatter from conversion buffer to application memory. + */ + if (H5V_hyper_copy (space_ndims+1, hsize, mem_size, mem_offset, buf, + hsize, zero, tconv_buf)<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, + "unable to scatter data to memory"); + } + + /* Advance iterator */ + mem_iter->all.elmt_left--; + mem_iter->all.offset+=nelmts; + + FUNC_LEAVE (SUCCEED); +} /* H5S_all_mscat() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_all_release + PURPOSE + Release all selection information for a dataspace + USAGE + herr_t H5S_all_release(space) + H5S_t *space; IN: Pointer to dataspace + RETURNS + SUCCEED/FAIL + DESCRIPTION + Releases "all" selection information for a dataspace + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_all_release (H5S_t *space) +{ + FUNC_ENTER (H5S_all_release, FAIL); + + /* Check args */ + assert (space); + + FUNC_LEAVE (SUCCEED); +} /* H5S_all_release() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_all_npoints + PURPOSE + Compute number of elements in current selection + USAGE + hsize_t H5S_all_npoints(space) + H5S_t *space; IN: Pointer to dataspace + RETURNS + The number of elements in selection on success, 0 on failure + DESCRIPTION + Compute number of elements in current selection. For "all" selections, + this is the same as the number of points in the extent. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hsize_t +H5S_all_npoints (H5S_t *space) +{ + intn i; /* Counters */ + hsize_t ret_value; + + FUNC_ENTER (H5S_all_npoints, 0); + + /* Check args */ + assert (space); + + for(i=0, ret_value=1; i<space->extent.u.simple.rank; i++) + ret_value*=space->extent.u.simple.size[i]; + + FUNC_LEAVE (ret_value); +} /* H5S_all_npoints() */ diff --git a/src/H5Shyper.c b/src/H5Shyper.c new file mode 100644 index 0000000..e1d3109 --- /dev/null +++ b/src/H5Shyper.c @@ -0,0 +1,1395 @@ +/* + * Copyright (C) 1998 NCSA + * All rights reserved. + * + * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Thursday, June 18, 1998 + * + * Purpose: Hyperslab selection data space I/O functions. + */ +#include <H5private.h> +#include <H5Eprivate.h> +#include <H5Sprivate.h> +#include <H5Vprivate.h> +#include <H5MMprivate.h> + +/* Interface initialization */ +#define PABLO_MASK H5S_hyper_mask +#define INTERFACE_INIT NULL +static intn interface_initialize_g = FALSE; + +/* Local datatypes */ +/* Parameter block for H5S_hyper_fread & H5S_hyper_fwrite */ +typedef struct { + H5F_t *f; + const struct H5O_layout_t *layout; + const struct H5O_compress_t *comp; + const struct H5O_efl_t *efl; + size_t elmt_size; + const H5S_t *space; + H5S_sel_iter_t *iter; + size_t nelmts; + H5D_transfer_t xfer_mode; + void *_buf; + void *tconv_buf; + H5S_hyper_bound_t **lo_bounds; + H5S_hyper_bound_t **hi_bounds; +} H5S_hyper_fhyper_info_t; + +/* Static function prototypes */ +static intn H5S_hyper_bsearch(hssize_t size, H5S_hyper_bound_t *barr, size_t count); +static H5S_hyper_region_t *H5S_hyper_get_regions (size_t *num_regions, intn dim, + size_t bound_count, H5S_hyper_bound_t **lo_bounds, + H5S_hyper_bound_t **hi_bounds, hssize_t *pos); +static size_t H5S_hyper_fread (intn dim, H5S_hyper_fhyper_info_t *fhyper_info); +static size_t H5S_hyper_fwrite (intn dim, H5S_hyper_fhyper_info_t *fhyper_info); + + +/*------------------------------------------------------------------------- + * Function: H5S_hyper_init + * + * Purpose: Initializes iteration information for hyperslab selection. + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_hyper_init (const struct H5O_layout_t __unused__ *layout, + const H5S_t *space, H5S_sel_iter_t *sel_iter) +{ + FUNC_ENTER (H5S_hyper_init, FAIL); + + /* Check args */ + assert (layout); + assert (space && H5S_SEL_HYPERSLABS==space->select.type); + assert (sel_iter); + + /* Initialize the number of points to iterate over */ + sel_iter->hyp.elmt_left=space->select.num_elem; + + /* Start at the origin of the array */ + sel_iter->hyp.pos = H5MM_calloc(space->extent.u.simple.rank*sizeof(hssize_t)); + + FUNC_LEAVE (SUCCEED); +} /* H5S_hyper_init() */ + +/*------------------------------------------------------------------------- + * Function: H5S_hyper_favail + * + * Purpose: Figure out the optimal number of elements to transfer to/from the file + * + * Return: non-negative number of elements on success, negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +size_t +H5S_hyper_favail (const H5S_t __unused__ *space, const H5S_sel_iter_t *sel_iter, size_t max) +{ + FUNC_ENTER (H5S_hyper_favail, FAIL); + + /* Check args */ + assert (space && H5S_SEL_HYPERSLABS==space->select.type); + assert (sel_iter); + + FUNC_LEAVE (MIN(sel_iter->hyp.elmt_left,max)); +} /* H5S_hyper_favail() */ + +/*------------------------------------------------------------------------- + * Function: H5S_hyper_get_regions + * + * Purpose: Builds a sorted array of the overlaps in a dimension + * + * Return: Success: Pointer to valid array (num_regions parameter set to + * array size) + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Monday, June 29, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5S_hyper_region_t * +H5S_hyper_get_regions (size_t *num_regions, intn dim, size_t bound_count, + H5S_hyper_bound_t **lo_bounds, H5S_hyper_bound_t **hi_bounds, hssize_t *pos) +{ + H5S_hyper_region_t *ret_value=NULL; /* Pointer to array to return */ + size_t num_reg=0, /* Number of regions in array */ + curr_reg=0; /* The current region we are working with */ + intn next_dim, /* Next fastest dimension */ + temp_dim; /* Temporary dim. holder */ + size_t i; /* Counters */ + + FUNC_ENTER (H5S_hyper_get_regions, NULL); + + assert(num_regions); + assert(lo_bounds); + assert(hi_bounds); + assert(pos); + +#ifdef QAK +printf("%s: check 1.0, dim=%d\n",FUNC,dim); +#endif /* QAK */ + + /* Check if we need to generate a list of regions for the 0th dim. */ + if(dim<0) { +#ifdef QAK +printf("%s: check 1.1, bound_count=%d\n",FUNC,bound_count); +#endif /* QAK */ + for(i=0; i<bound_count; i++) { + /* Check if we've allocated the array yet */ + if(num_reg==0) { + /* Allocate array */ + ret_value=H5MM_malloc(sizeof(H5S_hyper_node_t)); + + /* Initialize with first region */ + ret_value[0].start=lo_bounds[0][i].bound; + ret_value[0].end=hi_bounds[0][i].bound; + + /* Increment the number of regions */ + num_reg++; + } else { + /* Check if we should merge this region into the current region */ + if(lo_bounds[0][i].bound<ret_value[curr_reg].end) + ret_value[curr_reg].end=MAX(hi_bounds[0][i].bound,ret_value[curr_reg].end); + else { /* no overlap with previous region, add new region */ + /* Enlarge array */ + ret_value=H5MM_realloc(ret_value,sizeof(H5S_hyper_node_t)*(num_reg+1)); + + /* Initialize with new region */ + ret_value[num_reg].start=lo_bounds[0][i].bound; + ret_value[num_reg].end=hi_bounds[0][i].bound; + + /* Increment the number of regions & the current region */ + num_reg++; + curr_reg++; + } /* end else */ + } /* end else */ + } /* end for */ + } else { /* Generate list of regions based on the current position */ +#ifdef QAK +printf("%s: check 2.0, bound_count=%d\n",FUNC,bound_count); +#endif /* QAK */ + next_dim=dim+1; + for(i=0; i<bound_count; i++) { + + /* Check if each boundary overlaps in the higher dimensions */ + temp_dim=dim; + while(temp_dim>=0 && pos[temp_dim]>=lo_bounds[temp_dim][i].bound && + pos[temp_dim]<=hi_bounds[temp_dim][i].bound) + temp_dim--; + + /* Yes, all previous positions match, this is a valid region */ + if(temp_dim<0) { + /* Check if we've allocated the array yet */ + if(num_reg==0) { + /* Allocate array */ + ret_value=H5MM_malloc(sizeof(H5S_hyper_node_t)); + + /* Initialize with first region */ + ret_value[0].start=lo_bounds[next_dim][i].bound; + ret_value[0].end=hi_bounds[next_dim][i].bound; + + /* Increment the number of regions */ + num_reg++; + } else { + /* Check if we should merge this region into the current region */ + if(lo_bounds[next_dim][i].bound<ret_value[curr_reg].end) + ret_value[curr_reg].end=MAX(hi_bounds[next_dim][i].bound,ret_value[curr_reg].end); + else { /* no overlap with previous region, add new region */ + /* Enlarge array */ + ret_value=H5MM_realloc(ret_value,sizeof(H5S_hyper_node_t)*(num_reg+1)); + + /* Initialize with new region */ + ret_value[num_reg].start=lo_bounds[next_dim][i].bound; + ret_value[num_reg].end=hi_bounds[next_dim][i].bound; + + /* Increment the number of regions & the current region */ + num_reg++; + curr_reg++; + } /* end else */ + } /* end else */ + } /* end if */ + } /* end for */ + } /* end else */ + + /* Save the number of regions we generated */ + *num_regions=num_reg; + +#ifdef QAK +printf("%s: check 10.0, ret_value=%p, num_reg=%d\n",FUNC,ret_value,num_reg); +#endif /* QAK */ + + FUNC_LEAVE (ret_value); +} /* end H5S_hyper_get_regions() */ + +/*------------------------------------------------------------------------- + * Function: H5S_hyper_fread + * + * Purpose: Recursively gathers data points from a file using the parameters + * passed to H5S_hyper_fgath. + * + * Return: Success: Number of elements copied. + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5S_hyper_fread (intn dim, H5S_hyper_fhyper_info_t *fhyper_info) +{ + hssize_t file_offset[H5O_LAYOUT_NDIMS]; /*offset of slab in file*/ + hsize_t hsize[H5O_LAYOUT_NDIMS]; /*size of hyperslab */ + hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero */ + H5S_hyper_region_t *regions; /* Pointer to array of hyperslab nodes overlapped */ + size_t num_regions; /* number of regions overlapped */ + size_t i; /* Counters */ + intn j; + size_t num_read=0; /* Number of elements read */ + + FUNC_ENTER (H5S_hyper_fread, 0); + + assert(fhyper_info); + +#ifdef QAK +printf("%s: check 1.0, dim=%d\n",FUNC,dim); +#endif /* QAK */ + + /* Get a sorted list (in the next dimension down) of the regions which */ + /* overlap the current index in this dim */ + if((regions=H5S_hyper_get_regions(&num_regions,dim, + fhyper_info->space->select.sel_info.hyper_lst->count, + fhyper_info->lo_bounds, fhyper_info->hi_bounds, + fhyper_info->iter->hyp.pos))!=NULL) { + + /* Check if this is the second to last dimension in dataset */ + /* (Which means that we've got a list of the regions in the fastest */ + /* changing dimension and should input those regions) */ +#ifdef QAK +printf("%s: check 2.0, rank=%d\n",FUNC,(int)fhyper_info->space->extent.u.simple.rank); +for(i=0; i<num_regions; i++) + printf("%s: check 2.1, region #%d: start=%d, end=%d\n",FUNC,i,(int)regions[i].start,(int)regions[i].end); +#endif /* QAK */ + if((dim+2)==fhyper_info->space->extent.u.simple.rank) { + + /* Set up hyperslab I/O parameters which apply to all regions */ + + /* Copy the location of the region in the file */ + HDmemcpy(file_offset,fhyper_info->iter->hyp.pos,fhyper_info->space->extent.u.simple.rank*sizeof(hssize_t)); + file_offset[fhyper_info->space->extent.u.simple.rank]=0; + + /* Set the hyperslab size to copy */ + hsize[0]=1; + H5V_array_fill(hsize,hsize,sizeof(hsize[0]),fhyper_info->space->extent.u.simple.rank); + hsize[fhyper_info->space->extent.u.simple.rank]=fhyper_info->elmt_size; + + /* Set the memory offset to the origin */ + HDmemset (zero, 0, fhyper_info->layout->ndims*sizeof(*zero)); + + /* perform I/O on data from regions */ + for(i=0; i<num_regions; i++) { +#ifdef QAK +printf("%s: check 2.1, i=%d\n",FUNC,(int)i); +#endif /* QAK */ + hsize[fhyper_info->space->extent.u.simple.rank-1]=(regions[i].end-regions[i].start)+1; + file_offset[fhyper_info->space->extent.u.simple.rank-1]=regions[i].start; + + /* + * Gather from file. + */ + if (H5F_arr_read (fhyper_info->f, fhyper_info->layout, + fhyper_info->comp, fhyper_info->efl, hsize, hsize, zero, + file_offset, fhyper_info->xfer_mode, + fhyper_info->_buf/*out*/)<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_READERROR, 0, "read error"); + } +#ifdef QAK +printf("%s: check 2.2\n",FUNC); +#endif /* QAK */ + + /* Advance the pointer in the buffer */ + fhyper_info->_buf=((uint8 *)fhyper_info->_buf)+((regions[i].end-regions[i].start)+1)*fhyper_info->elmt_size; + + /* Increment the number of elements read */ + num_read+=(regions[i].end-regions[i].start)+1; + + /* Decrement the iterator count */ + fhyper_info->iter->hyp.elmt_left-=(regions[i].end-regions[i].start)+1; + } /* end for */ + } else { /* recurse on each region to next dimension down */ +#ifdef QAK +printf("%s: check 3.0, num_regions=%d\n",FUNC,(int)num_regions); +#endif /* QAK */ + + /* Increment the dimension we are working with */ + dim++; + + /* Step through each region in this dimension */ + for(i=0; i<num_regions; i++) { + /* Step through each location in each region */ + for(j=regions[i].start; j<=regions[i].end; j++) { +#ifdef QAK +printf("%s: check 4.0, dim=%d, location=%d\n",FUNC,dim,j); +#endif /* QAK */ + + /* Set the correct position we are working on */ + fhyper_info->iter->hyp.pos[dim]=j; + + /* Go get the regions in the next lower dimension */ + num_read+=H5S_hyper_fread(dim, fhyper_info); + } /* end for */ + } /* end for */ + } /* end else */ + + /* Free the region space */ + H5MM_xfree(regions); + } /* end if */ + + FUNC_LEAVE (num_read); +} /* H5S_hyper_fread() */ + +/*------------------------------------------------------------------------- + * Function: H5S_hyper_fgath + * + * Purpose: Gathers data points from file F and accumulates them in the + * type conversion buffer BUF. The LAYOUT argument describes + * how the data is stored on disk and EFL describes how the data + * is organized in external files. ELMT_SIZE is the size in + * bytes of a datum which this function treats as opaque. + * FILE_SPACE describes the data space of the dataset on disk + * and the elements that have been selected for reading (via + * hyperslab, etc). This function will copy at most NELMTS elements. + * + * Return: Success: Number of elements copied. + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +size_t +H5S_hyper_fgath (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, + size_t elmt_size, const H5S_t *file_space, H5S_sel_iter_t *file_iter, + size_t nelmts, + const H5D_transfer_t xfer_mode, void *_buf/*out*/) +{ + H5S_hyper_bound_t **lo_bounds; /* Lower (closest to the origin) bound array for each dimension */ + H5S_hyper_bound_t **hi_bounds; /* Upper (farthest from the origin) bound array for each dimension */ + H5S_hyper_fhyper_info_t fhyper_info; /* Block of parameters to pass into recursive calls */ + intn i; /*counters */ + size_t num_read; /* number of elements read into buffer */ + + FUNC_ENTER (H5S_hyper_fgath, 0); + + /* Check args */ + assert (f); + assert (layout); + assert (elmt_size>0); + assert (file_space); + assert (file_iter); + assert (nelmts>0); + assert (_buf); + +#ifdef QAK +printf("%s: check 1.0\n", FUNC); +#endif /* QAK */ + /* Allocate space for the low & high bound arrays */ + lo_bounds = H5MM_malloc(file_space->extent.u.simple.rank * sizeof(H5S_hyper_bound_t *)); + hi_bounds = H5MM_malloc(file_space->extent.u.simple.rank * sizeof(H5S_hyper_bound_t *)); + + /* Initialize to correct order to walk through arrays. + (When another iteration order besides the default 'C' order is chosen, + this is the correct place to change the order of the array iterations) + */ + for(i=0; i<file_space->extent.u.simple.rank; i++) { + lo_bounds[i]=file_space->select.sel_info.hyper_lst->lo_bounds[i]; + hi_bounds[i]=file_space->select.sel_info.hyper_lst->hi_bounds[i]; + } /* end for */ + + /* Initialize parameter block for recursive calls */ + fhyper_info.f=f; + fhyper_info.layout=layout; + fhyper_info.comp=comp; + fhyper_info.efl=efl; + fhyper_info.elmt_size=elmt_size; + fhyper_info.space=file_space; + fhyper_info.iter=file_iter; + fhyper_info.nelmts=nelmts; + fhyper_info.xfer_mode=xfer_mode; + fhyper_info._buf=_buf; + fhyper_info.lo_bounds=lo_bounds; + fhyper_info.hi_bounds=hi_bounds; + + /* Recursively input the hyperslabs currently defined */ + /* starting with the slowest changing dimension */ +#ifdef QAK +printf("%s: check 4.0\n",FUNC); +#endif /* QAK */ + num_read=H5S_hyper_fread(-1,&fhyper_info); +#ifdef QAK +printf("%s: check 5.0, num_read=%d\n",FUNC,(int)num_read); +#endif /* QAK */ + + /* Release the memory we allocated */ + H5MM_xfree(lo_bounds); + H5MM_xfree(hi_bounds); + + FUNC_LEAVE (num_read); +} /* H5S_hyper_fgath() */ + +/*------------------------------------------------------------------------- + * Function: H5S_hyper_fwrite + * + * Purpose: Recursively scatters data points to a file using the parameters + * passed to H5S_hyper_fscat. + * + * Return: Success: Number of elements copied. + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5S_hyper_fwrite (intn dim, H5S_hyper_fhyper_info_t *fhyper_info) +{ + hssize_t file_offset[H5O_LAYOUT_NDIMS]; /*offset of slab in file*/ + hsize_t hsize[H5O_LAYOUT_NDIMS]; /*size of hyperslab */ + hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero */ + H5S_hyper_region_t *regions; /* Pointer to array of hyperslab nodes overlapped */ + size_t num_regions; /* number of regions overlapped */ + size_t i; /* Counters */ + intn j; + size_t num_written=0; /* Number of elements read */ + + FUNC_ENTER (H5S_hyper_fwrite, 0); + + assert(fhyper_info); + + /* Get a sorted list (in the next dimension down) of the regions which */ + /* overlap the current index in this dim */ + if((regions=H5S_hyper_get_regions(&num_regions,dim, + fhyper_info->space->select.sel_info.hyper_lst->count, + fhyper_info->lo_bounds, fhyper_info->hi_bounds, + fhyper_info->iter->hyp.pos))!=NULL) { + + /* Check if this is the second to last dimension in dataset */ + /* (Which means that we've got a list of the regions in the fastest */ + /* changing dimension and should input those regions) */ + if((dim+2)==fhyper_info->space->extent.u.simple.rank) { + + /* Set up hyperslab I/O parameters which apply to all regions */ + + /* Copy the location of the region in the file */ + HDmemcpy(file_offset,fhyper_info->iter->hyp.pos,fhyper_info->space->extent.u.simple.rank*sizeof(hssize_t)); + file_offset[fhyper_info->space->extent.u.simple.rank]=0; + + /* Set the hyperslab size to copy */ + hsize[0]=1; + H5V_array_fill(hsize,hsize,sizeof(hsize[0]),fhyper_info->space->extent.u.simple.rank); + hsize[fhyper_info->space->extent.u.simple.rank]=fhyper_info->elmt_size; + + /* Set the memory offset to the origin */ + HDmemset (zero, 0, fhyper_info->layout->ndims*sizeof(*zero)); + + /* perform I/O on data from regions */ + for(i=0; i<num_regions; i++) { + hsize[fhyper_info->space->extent.u.simple.rank-1]=(regions[i].end-regions[i].start)+1; + file_offset[fhyper_info->space->extent.u.simple.rank-1]=regions[i].start; + + /* + * Scatter from file. + */ + if (H5F_arr_write (fhyper_info->f, fhyper_info->layout, + fhyper_info->comp, fhyper_info->efl, hsize, hsize, zero, + file_offset, fhyper_info->xfer_mode, + fhyper_info->_buf)<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_WRITEERROR, 0, "write error"); + } + + /* Advance the pointer in the buffer */ + fhyper_info->_buf=((uint8 *)fhyper_info->_buf)+((regions[i].end-regions[i].start)+1)*fhyper_info->elmt_size; + + /* Increment the number of elements read */ + num_written+=(regions[i].end-regions[i].start)+1; + + /* Decrement the iterator count */ + fhyper_info->iter->hyp.elmt_left-=(regions[i].end-regions[i].start)+1; + } /* end for */ + } else { /* recurse on each region to next dimension down */ + + /* Increment the dimension we are working with */ + dim++; + + /* Step through each region in this dimension */ + for(i=0; i<num_regions; i++) { + /* Step through each location in each region */ + for(j=regions[i].start; j<=regions[i].end; j++) { + + /* Set the correct position we are working on */ + fhyper_info->iter->hyp.pos[dim]=j; + + /* Go get the regions in the next lower dimension */ + num_written+=H5S_hyper_fwrite(dim, fhyper_info); + } /* end for */ + } /* end for */ + } /* end else */ + + /* Free the region space */ + H5MM_xfree(regions); + } /* end if */ + + FUNC_LEAVE (num_written); +} /* H5S_hyper_fwrite() */ + +/*------------------------------------------------------------------------- + * Function: H5S_hyper_fscat + * + * Purpose: Scatters dataset elements from the type conversion buffer BUF + * to the file F where the data points are arranged according to + * the file data space FILE_SPACE and stored according to + * LAYOUT and EFL. Each element is ELMT_SIZE bytes. + * The caller is requesting that NELMTS elements are copied. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_hyper_fscat (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, + size_t elmt_size, const H5S_t *file_space, H5S_sel_iter_t *file_iter, + size_t nelmts, + const H5D_transfer_t xfer_mode, const void *_buf) +{ + H5S_hyper_bound_t **lo_bounds; /* Lower (closest to the origin) bound array for each dimension */ + H5S_hyper_bound_t **hi_bounds; /* Upper (farthest from the origin) bound array for each dimension */ + H5S_hyper_fhyper_info_t fhyper_info; /* Block of parameters to pass into recursive calls */ + intn i; /*counters */ + size_t num_written; /* number of elements read into buffer */ + + FUNC_ENTER (H5S_hyper_fscat, 0); + + /* Check args */ + assert (f); + assert (layout); + assert (elmt_size>0); + assert (file_space); + assert (file_iter); + assert (nelmts>0); + assert (_buf); + +#ifdef QAK +printf("%s: check 1.0\n", FUNC); +#endif /* QAK */ + /* Allocate space for the low & high bound arrays */ + lo_bounds = H5MM_malloc(file_space->extent.u.simple.rank * sizeof(H5S_hyper_bound_t *)); + hi_bounds = H5MM_malloc(file_space->extent.u.simple.rank * sizeof(H5S_hyper_bound_t *)); + + /* Initialize to correct order to walk through arrays. + (When another iteration order besides the default 'C' order is chosen, + this is the correct place to change the order of the array iterations) + */ + for(i=0; i<file_space->extent.u.simple.rank; i++) { + lo_bounds[i]=file_space->select.sel_info.hyper_lst->lo_bounds[i]; + hi_bounds[i]=file_space->select.sel_info.hyper_lst->hi_bounds[i]; + } /* end for */ + + /* Initialize parameter block for recursive calls */ + fhyper_info.f=f; + fhyper_info.layout=layout; + fhyper_info.comp=comp; + fhyper_info.efl=efl; + fhyper_info.elmt_size=elmt_size; + fhyper_info.space=file_space; + fhyper_info.iter=file_iter; + fhyper_info.nelmts=nelmts; + fhyper_info.xfer_mode=xfer_mode; + fhyper_info._buf=_buf; + fhyper_info.lo_bounds=lo_bounds; + fhyper_info.hi_bounds=hi_bounds; + + /* Recursively input the hyperslabs currently defined */ + /* starting with the slowest changing dimension */ + num_written=H5S_hyper_fwrite(-1,&fhyper_info); + + /* Release the memory we allocated */ + H5MM_xfree(lo_bounds); + H5MM_xfree(hi_bounds); + + FUNC_LEAVE (num_written); +} /* H5S_hyper_fscat() */ + +/*------------------------------------------------------------------------- + * Function: H5S_hyper_mread + * + * Purpose: Recursively gathers data points from memory using the parameters + * passed to H5S_hyper_mgath. + * + * Return: Success: Number of elements copied. + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5S_hyper_mread (intn dim, H5S_hyper_fhyper_info_t *fhyper_info) +{ + hssize_t mem_size[H5O_LAYOUT_NDIMS]; /*size of memory buffer*/ + hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /*offset of slab in memory*/ + hsize_t hsize[H5O_LAYOUT_NDIMS]; /*size of hyperslab */ + hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero */ + H5S_hyper_region_t *regions; /* Pointer to array of hyperslab nodes overlapped */ + size_t num_regions; /* number of regions overlapped */ + size_t i; /* Counters */ + intn j; + size_t num_read=0; /* Number of elements read */ + + FUNC_ENTER (H5S_hyper_mread, 0); + + assert(fhyper_info); + +#ifdef QAK +printf("%s: check 1.0, dim=%d\n",FUNC,dim); +#endif /* QAK */ + + /* Get a sorted list (in the next dimension down) of the regions which */ + /* overlap the current index in this dim */ + if((regions=H5S_hyper_get_regions(&num_regions,dim, + fhyper_info->space->select.sel_info.hyper_lst->count, + fhyper_info->lo_bounds, fhyper_info->hi_bounds, + fhyper_info->iter->hyp.pos))!=NULL) { + + /* Check if this is the second to last dimension in dataset */ + /* (Which means that we've got a list of the regions in the fastest */ + /* changing dimension and should input those regions) */ +#ifdef QAK +printf("%s: check 2.0, rank=%d\n",FUNC,(int)fhyper_info->space->extent.u.simple.rank); +for(i=0; i<num_regions; i++) + printf("%s: check 2.1, region #%d: start=%d, end=%d\n",FUNC,i,(int)regions[i].start,(int)regions[i].end); +#endif /* QAK */ + + if((dim+2)==fhyper_info->space->extent.u.simple.rank) { + + /* Set up hyperslab I/O parameters which apply to all regions */ + + /* Set up the size of the memory space */ + HDmemcpy(mem_size,fhyper_info->space->extent.u.simple.size,fhyper_info->space->extent.u.simple.rank*sizeof(hssize_t)); + mem_size[fhyper_info->space->extent.u.simple.rank]=fhyper_info->elmt_size; + + /* Copy the location of the region in the file */ + HDmemcpy(mem_offset,fhyper_info->iter->hyp.pos,fhyper_info->space->extent.u.simple.rank*sizeof(hssize_t)); + mem_offset[fhyper_info->space->extent.u.simple.rank]=0; + + /* Set the hyperslab size to copy */ + hsize[0]=1; + H5V_array_fill(hsize,hsize,sizeof(hsize[0]),fhyper_info->space->extent.u.simple.rank); + hsize[fhyper_info->space->extent.u.simple.rank]=fhyper_info->elmt_size; + + /* Set the memory offset to the origin */ + HDmemset (zero, 0, (fhyper_info->space->extent.u.simple.rank+1)*sizeof(*zero)); + + /* perform I/O on data from regions */ + for(i=0; i<num_regions; i++) { +#ifdef QAK +printf("%s: check 2.1, i=%d\n",FUNC,(int)i); +#endif /* QAK */ + hsize[fhyper_info->space->extent.u.simple.rank-1]=(regions[i].end-regions[i].start)+1; + mem_offset[fhyper_info->space->extent.u.simple.rank-1]=regions[i].start; + + /* + * Gather from memory. + */ + if (H5V_hyper_copy (fhyper_info->space->extent.u.simple.rank+1, + hsize, hsize, zero, fhyper_info->tconv_buf, + mem_size, mem_offset, fhyper_info->_buf)<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_READERROR, 0, "unable to gather data from memory"); + } + + /* Advance the pointer in the buffer */ + fhyper_info->tconv_buf=((uint8 *)fhyper_info->tconv_buf)+((regions[i].end-regions[i].start)+1)*fhyper_info->elmt_size; + + /* Increment the number of elements read */ + num_read+=(regions[i].end-regions[i].start)+1; + + /* Decrement the iterator count */ + fhyper_info->iter->hyp.elmt_left-=(regions[i].end-regions[i].start)+1; + } /* end for */ + } else { /* recurse on each region to next dimension down */ +#ifdef QAK +printf("%s: check 3.0, num_regions=%d\n",FUNC,(int)num_regions); +#endif /* QAK */ + + /* Increment the dimension we are working with */ + dim++; + + /* Step through each region in this dimension */ + for(i=0; i<num_regions; i++) { + /* Step through each location in each region */ + for(j=regions[i].start; j<=regions[i].end; j++) { +#ifdef QAK +printf("%s: check 4.0, dim=%d, location=%d\n",FUNC,dim,j); +#endif /* QAK */ + + /* Set the correct position we are working on */ + fhyper_info->iter->hyp.pos[dim]=j; + + /* Go get the regions in the next lower dimension */ + num_read+=H5S_hyper_mread(dim, fhyper_info); + } /* end for */ + } /* end for */ + } /* end else */ + + /* Free the region space */ + H5MM_xfree(regions); + } /* end if */ + + FUNC_LEAVE (num_read); +} /* H5S_hyper_mread() */ + +/*------------------------------------------------------------------------- + * Function: H5S_hyper_mgath + * + * Purpose: Gathers dataset elements from application memory BUF and + * copies them into the data type conversion buffer TCONV_BUF. + * Each element is ELMT_SIZE bytes and arranged in application + * memory according to MEM_SPACE. + * The caller is requesting that at most NELMTS be gathered. + * + * Return: Success: Number of elements copied. + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +size_t +H5S_hyper_mgath (const void *_buf, size_t elmt_size, + const H5S_t *mem_space, H5S_sel_iter_t *mem_iter, + size_t nelmts, void *_tconv_buf/*out*/) +{ + H5S_hyper_bound_t **lo_bounds; /* Lower (closest to the origin) bound array for each dimension */ + H5S_hyper_bound_t **hi_bounds; /* Upper (farthest from the origin) bound array for each dimension */ + H5S_hyper_fhyper_info_t fhyper_info; /* Block of parameters to pass into recursive calls */ + intn i,j; /* Counters */ + size_t num_read; /* number of elements read into buffer */ + + FUNC_ENTER (H5S_hyper_mgath, 0); + +#ifdef QAK +printf("%s: check 1.0, elmt_size=%d, mem_space=%p\n",FUNC,(int)elmt_size,mem_space); +printf("%s: check 1.0, mem_iter=%p, nelmts=%d\n",FUNC,mem_iter,nelmts); +printf("%s: check 1.0, _buf=%p, _tconv_buf=%p\n",FUNC,_buf,_tconv_buf); +#endif /* QAK */ + + /* Check args */ + assert (elmt_size>0); + assert (mem_space); + assert (mem_iter); + assert (nelmts>0); + assert (_buf); + assert (_tconv_buf); + +#ifdef QAK +printf("%s: check 2.0, mem_space->extent.u.simple.rank=%d\n",FUNC, (int)mem_space->extent.u.simple.rank); +#endif /* QAK */ + + /* Allocate space for the low & high bound arrays */ + lo_bounds = H5MM_malloc(mem_space->extent.u.simple.rank * sizeof(H5S_hyper_bound_t *)); + hi_bounds = H5MM_malloc(mem_space->extent.u.simple.rank * sizeof(H5S_hyper_bound_t *)); + + /* Initialize to correct order to walk through arrays. + (When another iteration order besides the default 'C' order is chosen, + this is the correct place to change the order of the array iterations) + */ +#ifdef QAK +printf("%s: check 3.0\n",FUNC); +#endif /* QAK */ + for(i=0; i<mem_space->extent.u.simple.rank; i++) { + lo_bounds[i]=mem_space->select.sel_info.hyper_lst->lo_bounds[i]; + hi_bounds[i]=mem_space->select.sel_info.hyper_lst->hi_bounds[i]; +#ifdef QAK +printf("%s: check 3.1, lo[%d]=%p, hi[%d]=%p\n",FUNC,i,lo_bounds[i],i,hi_bounds[i]); + for(j=0; j<mem_space->select.sel_info.hyper_lst->count; j++) +printf("%s: check 3.2, lo[%d][%d]=%d, hi[%d][%d]=%d\n",FUNC,i,j,(int)lo_bounds[i][j].bound,i,j,(int)hi_bounds[i][j].bound); +#endif /* QAK */ + } /* end for */ + + /* Initialize parameter block for recursive calls */ + fhyper_info.elmt_size=elmt_size; + fhyper_info.space=mem_space; + fhyper_info.iter=mem_iter; + fhyper_info.nelmts=nelmts; + fhyper_info._buf=_buf; + fhyper_info.tconv_buf=_tconv_buf; + fhyper_info.lo_bounds=lo_bounds; + fhyper_info.hi_bounds=hi_bounds; + + /* Recursively input the hyperslabs currently defined */ + /* starting with the slowest changing dimension */ +#ifdef QAK +printf("%s: check 4.0\n",FUNC); +#endif /* QAK */ + num_read=H5S_hyper_mread(-1,&fhyper_info); +#ifdef QAK +printf("%s: check 5.0\n",FUNC); +#endif /* QAK */ + + /* Release the memory we allocated */ + H5MM_xfree(lo_bounds); + H5MM_xfree(hi_bounds); + + FUNC_LEAVE (num_read); +} /* H5S_hyper_mgath() */ + +/*------------------------------------------------------------------------- + * Function: H5S_hyper_mwrite + * + * Purpose: Recursively scatters data points from memory using the parameters + * passed to H5S_hyper_mscat. + * + * Return: Success: Number of elements copied. + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5S_hyper_mwrite (intn dim, H5S_hyper_fhyper_info_t *fhyper_info) +{ + hssize_t mem_size[H5O_LAYOUT_NDIMS]; /*size of memory buffer*/ + hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /*offset of slab in file*/ + hsize_t hsize[H5O_LAYOUT_NDIMS]; /*size of hyperslab */ + hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero */ + H5S_hyper_region_t *regions; /* Pointer to array of hyperslab nodes overlapped */ + size_t num_regions; /* number of regions overlapped */ + size_t i; /* Counters */ + intn j; + size_t num_read=0; /* Number of elements read */ + + FUNC_ENTER (H5S_hyper_mwrite, 0); + + assert(fhyper_info); +#ifdef QAK +printf("%s: check 1.0\n",FUNC); +#endif /* QAK */ + + /* Get a sorted list (in the next dimension down) of the regions which */ + /* overlap the current index in this dim */ + if((regions=H5S_hyper_get_regions(&num_regions,dim, + fhyper_info->space->select.sel_info.hyper_lst->count, + fhyper_info->lo_bounds, fhyper_info->hi_bounds, + fhyper_info->iter->hyp.pos))!=NULL) { + +#ifdef QAK +printf("%s: check 2.0, rank=%d\n",FUNC,(int)fhyper_info->space->extent.u.simple.rank); +for(i=0; i<num_regions; i++) + printf("%s: check 2.1, region #%d: start=%d, end=%d\n",FUNC,i,(int)regions[i].start,(int)regions[i].end); +#endif /* QAK */ + /* Check if this is the second to last dimension in dataset */ + /* (Which means that we've got a list of the regions in the fastest */ + /* changing dimension and should input those regions) */ + if((dim+2)==fhyper_info->space->extent.u.simple.rank) { + + /* Set up hyperslab I/O parameters which apply to all regions */ + + /* Set up the size of the memory space */ + HDmemcpy(mem_size,fhyper_info->space->extent.u.simple.size,fhyper_info->space->extent.u.simple.rank*sizeof(hssize_t)); + mem_size[fhyper_info->space->extent.u.simple.rank]=fhyper_info->elmt_size; + + /* Copy the location of the region in the file */ + HDmemcpy(mem_offset,fhyper_info->iter->hyp.pos,fhyper_info->space->extent.u.simple.rank*sizeof(hssize_t)); + mem_offset[fhyper_info->space->extent.u.simple.rank]=0; + + /* Set the hyperslab size to copy */ + hsize[0]=1; + H5V_array_fill(hsize,hsize,sizeof(hsize[0]),fhyper_info->space->extent.u.simple.rank); + hsize[fhyper_info->space->extent.u.simple.rank]=fhyper_info->elmt_size; + + /* Set the memory offset to the origin */ + HDmemset (zero, 0, (fhyper_info->space->extent.u.simple.rank+1)*sizeof(*zero)); + +#ifdef QAK +printf("%s: check 3.0\n",FUNC); +#endif /* QAK */ + /* perform I/O on data from regions */ + for(i=0; i<num_regions; i++) { + hsize[fhyper_info->space->extent.u.simple.rank-1]=(regions[i].end-regions[i].start)+1; + mem_offset[fhyper_info->space->extent.u.simple.rank-1]=regions[i].start; + + /* + * Gather from memory. + */ + if (H5V_hyper_copy (fhyper_info->space->extent.u.simple.rank+1, + hsize, mem_size, mem_offset, fhyper_info->_buf, + hsize, zero, fhyper_info->tconv_buf)<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_READERROR, 0, "unable to gather data from memory"); + } + + /* Advance the pointer in the buffer */ + fhyper_info->tconv_buf=((uint8 *)fhyper_info->tconv_buf)+((regions[i].end-regions[i].start)+1)*fhyper_info->elmt_size; + + /* Increment the number of elements read */ + num_read+=(regions[i].end-regions[i].start)+1; + + /* Decrement the iterator count */ + fhyper_info->iter->hyp.elmt_left-=(regions[i].end-regions[i].start)+1; + } /* end for */ + } else { /* recurse on each region to next dimension down */ + + /* Increment the dimension we are working with */ + dim++; + + /* Step through each region in this dimension */ + for(i=0; i<num_regions; i++) { + /* Step through each location in each region */ + for(j=regions[i].start; j<=regions[i].end; j++) { + + /* Set the correct position we are working on */ + fhyper_info->iter->hyp.pos[dim]=j; + + /* Go get the regions in the next lower dimension */ + num_read+=H5S_hyper_mwrite(dim, fhyper_info); + } /* end for */ + } /* end for */ + } /* end else */ + + /* Free the region space */ + H5MM_xfree(regions); + } /* end if */ + + FUNC_LEAVE (num_read); +} /* H5S_hyper_mwrite() */ +/*------------------------------------------------------------------------- + * Function: H5S_hyper_mscat + * + * Purpose: Scatters NELMTS data points from the type conversion buffer + * TCONV_BUF to the application buffer BUF. Each element is + * ELMT_SIZE bytes and they are organized in application memory + * according to MEM_SPACE. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, June 17, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_hyper_mscat (const void *_tconv_buf, size_t elmt_size, + const H5S_t *mem_space, H5S_sel_iter_t *mem_iter, + size_t nelmts, void *_buf/*out*/) +{ + H5S_hyper_bound_t **lo_bounds; /* Lower (closest to the origin) bound array for each dimension */ + H5S_hyper_bound_t **hi_bounds; /* Upper (farthest from the origin) bound array for each dimension */ + H5S_hyper_fhyper_info_t fhyper_info; /* Block of parameters to pass into recursive calls */ + intn i; /*counters */ + size_t num_read; /* number of elements read into buffer */ + + FUNC_ENTER (H5S_hyper_mscat, 0); + + /* Check args */ + assert (elmt_size>0); + assert (mem_space); + assert (mem_iter); + assert (nelmts>0); + assert (_buf); + assert (_tconv_buf); + + /* Allocate space for the low & high bound arrays */ + lo_bounds = H5MM_malloc(mem_space->extent.u.simple.rank * sizeof(H5S_hyper_bound_t *)); + hi_bounds = H5MM_malloc(mem_space->extent.u.simple.rank * sizeof(H5S_hyper_bound_t *)); + + /* Initialize to correct order to walk through arrays. + (When another iteration order besides the default 'C' order is chosen, + this is the correct place to change the order of the array iterations) + */ + for(i=0; i<mem_space->extent.u.simple.rank; i++) { + lo_bounds[i]=mem_space->select.sel_info.hyper_lst->lo_bounds[i]; + hi_bounds[i]=mem_space->select.sel_info.hyper_lst->hi_bounds[i]; + } /* end for */ + + /* Initialize parameter block for recursive calls */ + fhyper_info.elmt_size=elmt_size; + fhyper_info.space=mem_space; + fhyper_info.iter=mem_iter; + fhyper_info.nelmts=nelmts; + fhyper_info._buf=_buf; + fhyper_info.tconv_buf=_tconv_buf; + fhyper_info.lo_bounds=lo_bounds; + fhyper_info.hi_bounds=hi_bounds; + + /* Recursively input the hyperslabs currently defined */ + /* starting with the slowest changing dimension */ +#ifdef QAK +printf("%s: check 1.0\n",FUNC); +#endif /* QAK */ + num_read=H5S_hyper_mwrite(-1,&fhyper_info); +#ifdef QAK +printf("%s: check 2.0\n",FUNC); +#endif /* QAK */ + + /* Release the memory we allocated */ + H5MM_xfree(lo_bounds); + H5MM_xfree(hi_bounds); + + FUNC_LEAVE (SUCCEED); +} /* H5S_hyper_mscat() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_bsearch + PURPOSE + Search for a boundary + USAGE + herr_t H5S_hyper_bsearch(key,barr,count) + hssize_t size; IN: Key we are searching for + H5S_hyper_bount_t *barr; IN: Pointer to the array of bounds + size_t count; IN: Number of elements in the bound array + RETURNS + The element number to insert in front of on success (the value in the 'count' + parameter if the new bound should be added to end) or negative on failure. + DESCRIPTION + Finds the proper place to insert a boundary in a sorted boundary array. + Uses a binary search algorithm for the actual searching. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static intn H5S_hyper_bsearch(hssize_t size, H5S_hyper_bound_t *barr, size_t count) +{ + intn lo, mid, hi; /* Indices for the search */ + intn ret_value=-1; /* Return value index */ + + FUNC_ENTER (H5S_hyper_bsearch, FAIL); + + assert(barr); + assert(count>0); + + /* Check bounds first */ + if(size<barr[0].bound) + ret_value=0; + else if(size>barr[count-1].bound) + ret_value=count; + else { /* must be in the middle somewhere, go get it */ + lo=0; + hi=count-1; + do { + /* Calc. the mid-point */ + mid=(hi+lo)/2; + + /* check for bounds only seperated by one element */ + if((hi-lo)<=1) { + ret_value=hi; + break; + } else { /* Divide and conquer! */ + if(size>barr[mid].bound) + lo=mid; + else + hi=mid; + } /* end else */ + } while(lo!=hi); + } /* end else */ + FUNC_LEAVE (ret_value); +} /* H5S_hyper_bsearch() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_add + PURPOSE + Add a block to hyperslab selection + USAGE + herr_t H5S_hyper_add(space, start, size) + H5S_t *space; IN: Pointer to dataspace + hssize_t *start; IN: Offset of block + hssize_t *size; IN: Size of block + RETURNS + SUCCEED/FAIL + DESCRIPTION + Adds a block to an existing hyperslab selection. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_hyper_add (H5S_t *space, hssize_t *start, hssize_t *size) +{ + H5S_hyper_node_t *slab; /* New hyperslab node to insert */ + H5S_hyper_bound_t *tmp; /* Temporary pointer to an hyperslab bound array */ + intn bound_loc; /* Boundary location to insert hyperslab */ + size_t elem_count; /* Number of elements in hyperslab selection */ + intn i; /* Counters */ + herr_t ret_value=FAIL; +extern int qak_debug; + + FUNC_ENTER (H5S_hyper_add, FAIL); + + /* Check args */ + assert (space); + assert (start); + assert (size); + +qak_debug=1; + +#ifdef QAK +printf("%s: check 1.0\n",FUNC); +#endif /* QAK */ + /* Create new hyperslab node to insert */ + if((slab = H5MM_malloc(sizeof(H5S_hyper_node_t)))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "can't allocate hyperslab node"); + if((slab->start = H5MM_malloc(sizeof(hsize_t)*space->extent.u.simple.rank))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "can't allocate hyperslab start boundary"); + if((slab->end = H5MM_malloc(sizeof(hsize_t)*space->extent.u.simple.rank))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "can't allocate hyperslab end boundary"); + +#ifdef QAK +printf("%s: check 2.0\n",FUNC); +#endif /* QAK */ + /* Set boundary on new node */ + for(i=0,elem_count=1; i<space->extent.u.simple.rank; i++) { + slab->start[i]=start[i]; + slab->end[i]=start[i]+size[i]-1; + elem_count*=size[i]; + } /* end for */ + +#ifdef QAK +printf("%s: check 3.0, lo_bounds=%p, hi_bounds=%p\n",FUNC, + space->select.sel_info.hyper_lst->lo_bounds, space->select.sel_info.hyper_lst->hi_bounds); +#endif /* QAK */ + /* Increase size of boundary arrays for dataspace's selection */ + for(i=0; i<space->extent.u.simple.rank; i++) { +#ifdef QAK +printf("%s: check 3.1, i=%d\n",FUNC,(int)i); +#endif /* QAK */ + tmp=space->select.sel_info.hyper_lst->lo_bounds[i]; + if((space->select.sel_info.hyper_lst->lo_bounds[i]=H5MM_realloc(tmp,sizeof(H5S_hyper_bound_t)*(space->select.sel_info.hyper_lst->count+1)))==NULL) { + space->select.sel_info.hyper_lst->lo_bounds[i]=tmp; + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "can't allocate hyperslab lo boundary array"); + } /* end if */ +#ifdef QAK +printf("%s: check 3.2, i=%d\n",FUNC,(int)i); +#endif /* QAK */ + tmp=space->select.sel_info.hyper_lst->hi_bounds[i]; + if((space->select.sel_info.hyper_lst->hi_bounds[i]=H5MM_realloc(tmp,sizeof(H5S_hyper_bound_t)*(space->select.sel_info.hyper_lst->count+1)))==NULL) { + space->select.sel_info.hyper_lst->hi_bounds[i]=tmp; + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "can't allocate hyperslab hi boundary array"); + } /* end if */ + } /* end for */ + +#ifdef QAK +printf("%s: check 4.0\n",FUNC); +#endif /* QAK */ + /* Insert each boundary of the hyperslab into the sorted lists of bounds */ + for(i=0; i<space->extent.u.simple.rank; i++) { + /* Check if this is the first hyperslab inserted */ + if(space->select.sel_info.hyper_lst->count==0) { + space->select.sel_info.hyper_lst->lo_bounds[i][0].bound=slab->start[i]; + space->select.sel_info.hyper_lst->lo_bounds[i][0].node=slab; + space->select.sel_info.hyper_lst->hi_bounds[i][0].bound=slab->end[i]; + space->select.sel_info.hyper_lst->hi_bounds[i][0].node=slab; + } /* end if */ + else { + /* Take care of the low boundary first */ + /* Find the location to insert in front of */ + if((bound_loc=H5S_hyper_bsearch(slab->start[i],space->select.sel_info.hyper_lst->lo_bounds[i], + space->select.sel_info.hyper_lst->count))<0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "can't find location to insert hyperslab boundary"); + + /* Check if we need to move boundary elements */ + if(bound_loc!=(intn)space->select.sel_info.hyper_lst->count) { + HDmemmove(space->select.sel_info.hyper_lst->lo_bounds[bound_loc+1], + space->select.sel_info.hyper_lst->lo_bounds[bound_loc], + sizeof(H5S_hyper_bound_t)*(space->select.sel_info.hyper_lst->count-bound_loc)); + } /* end if */ + space->select.sel_info.hyper_lst->lo_bounds[bound_loc][i].bound=slab->start[i]; + space->select.sel_info.hyper_lst->lo_bounds[bound_loc][i].node=slab; + + /* Take care of the high boundary next */ + /* Find the location to insert in front of */ + if((bound_loc=H5S_hyper_bsearch(slab->end[i],space->select.sel_info.hyper_lst->hi_bounds[i], + space->select.sel_info.hyper_lst->count))<0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "can't find location to insert hyperslab boundary"); + + /* Check if we need to move boundary elements */ + if(bound_loc!=(intn)space->select.sel_info.hyper_lst->count) { + HDmemmove(space->select.sel_info.hyper_lst->hi_bounds[bound_loc+1], + space->select.sel_info.hyper_lst->hi_bounds[bound_loc], + sizeof(H5S_hyper_bound_t)*(space->select.sel_info.hyper_lst->count-bound_loc)); + } /* end if */ + space->select.sel_info.hyper_lst->hi_bounds[bound_loc][i].bound=slab->end[i]; + space->select.sel_info.hyper_lst->hi_bounds[bound_loc][i].node=slab; + } /* end else */ + } /* end for */ +#ifdef QAK +printf("%s: check 5.0\n",FUNC); +#endif /* QAK */ + + /* Increment the number of bounds in the array */ + space->select.sel_info.hyper_lst->count++; + + /* Prepend on list of hyperslabs for this selection */ + slab->next=space->select.sel_info.hyper_lst->head; + space->select.sel_info.hyper_lst->head=slab; + + /* Increment the number of elements in the hyperslab selection */ + space->select.num_elem+=elem_count; +#ifdef QAK +printf("%s: check 6.0\n",FUNC); +#endif /* QAK */ + +done: + FUNC_LEAVE (SUCCEED); +} /* H5S_hyper_add() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_release + PURPOSE + Release hyperslab selection information for a dataspace + USAGE + herr_t H5S_hyper_release(space) + H5S_t *space; IN: Pointer to dataspace + RETURNS + SUCCEED/FAIL + DESCRIPTION + Releases all hyperslab selection information for a dataspace + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_hyper_release (H5S_t *space) +{ + H5S_hyper_node_t *curr,*next; /* Pointer to hyperslab nodes */ + intn i; /* Counters */ + + FUNC_ENTER (H5S_hyper_release, FAIL); + + /* Check args */ + assert (space && H5S_SEL_HYPERSLABS==space->select.type); +#ifdef QAK +printf("%s: check 1.0\n",FUNC); +#endif /* QAK */ + + /* Reset the number of points selected */ + space->select.num_elem=0; + + /* Release hi and lo boundary information */ + for(i=0; i<space->extent.u.simple.rank; i++) { + H5MM_xfree(space->select.sel_info.hyper_lst->lo_bounds[i]); + H5MM_xfree(space->select.sel_info.hyper_lst->hi_bounds[i]); + } /* end for */ + H5MM_xfree(space->select.sel_info.hyper_lst->lo_bounds); + H5MM_xfree(space->select.sel_info.hyper_lst->hi_bounds); + + /* Release list of selected regions */ + curr=space->select.sel_info.hyper_lst->head; + while(curr!=NULL) { + next=curr->next; + H5MM_xfree(curr->start); + H5MM_xfree(curr->end); + H5MM_xfree(curr); + curr=next; + } /* end while */ + + /* Release hyperslab selection node itself */ + H5MM_xfree(space->select.sel_info.hyper_lst); + space->select.sel_info.hyper_lst=NULL; + +#ifdef QAK +printf("%s: check 2.0\n",FUNC); +#endif /* QAK */ + +done: + FUNC_LEAVE (SUCCEED); +} /* H5S_hyper_release() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_npoints + PURPOSE + Compute number of elements in current selection + USAGE + hsize_t H5S_hyper_npoints(space) + H5S_t *space; IN: Pointer to dataspace + RETURNS + The number of elements in selection on success, 0 on failure + DESCRIPTION + Compute number of elements in current selection. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hsize_t +H5S_point_npoints (H5S_t *space) +{ + FUNC_ENTER (H5S_point_npoints, 0); + + /* Check args */ + assert (space); + + FUNC_LEAVE (space->select.num_elem); +} /* H5S_point_npoints() */ diff --git a/src/H5Spoint.c b/src/H5Spoint.c new file mode 100644 index 0000000..86b1bc9 --- /dev/null +++ b/src/H5Spoint.c @@ -0,0 +1,455 @@ +/* + * Copyright (C) 1998 NCSA + * All rights reserved. + * + * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Tuesday, June 16, 1998 + * + * Purpose: Point selection data space I/O functions. + */ +#include <H5private.h> +#include <H5Eprivate.h> +#include <H5Sprivate.h> +#include <H5Vprivate.h> + +/* Interface initialization */ +#define PABLO_MASK H5S_point_mask +#define INTERFACE_INIT NULL +static intn interface_initialize_g = FALSE; + +/*------------------------------------------------------------------------- + * Function: H5S_point_init + * + * Purpose: Initializes iteration information for point selection. + * + * Return: non-negative on success, negative on failure. + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_point_init (const struct H5O_layout_t __unused__ *layout, + const H5S_t *space, H5S_sel_iter_t *sel_iter) +{ + FUNC_ENTER (H5S_point_init, FAIL); + + /* Check args */ + assert (layout); + assert (space && H5S_SEL_POINTS==space->select.type); + assert (sel_iter); + + /* Initialize the number of points to iterate over */ + sel_iter->pnt.elmt_left=space->select.num_elem; + + /* Start at the head of the list of points */ + sel_iter->pnt.curr=space->select.sel_info.pnt_lst->head; + + FUNC_LEAVE (SUCCEED); +} + +/*------------------------------------------------------------------------- + * Function: H5S_point_favail + * + * Purpose: Figure out the optimal number of elements to transfer to/from the file + * + * Return: non-negative number of elements on success, negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +size_t +H5S_point_favail (const H5S_t __unused__ *space, const H5S_sel_iter_t *sel_iter, size_t max) +{ + FUNC_ENTER (H5S_point_favail, FAIL); + + /* Check args */ + assert (space && H5S_SEL_POINTS==space->select.type); + assert (sel_iter); + + FUNC_LEAVE (MIN(sel_iter->pnt.elmt_left,max)); +} /* H5S_point_favail() */ + +/*------------------------------------------------------------------------- + * Function: H5S_point_fgath + * + * Purpose: Gathers data points from file F and accumulates them in the + * type conversion buffer BUF. The LAYOUT argument describes + * how the data is stored on disk and EFL describes how the data + * is organized in external files. ELMT_SIZE is the size in + * bytes of a datum which this function treats as opaque. + * FILE_SPACE describes the data space of the dataset on disk + * and the elements that have been selected for reading (via + * hyperslab, etc). This function will copy at most NELMTS elements. + * + * Notes: This could be optimized by gathering selected elements near (how + * near?) each other into one I/O request and then moving the correct + * elements into the return buffer + * + * Return: Success: Number of elements copied. + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +size_t +H5S_point_fgath (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, + size_t elmt_size, const H5S_t *file_space, H5S_sel_iter_t *file_iter, + size_t nelmts, + const H5D_transfer_t xfer_mode, void *_buf/*out*/) +{ + hssize_t file_offset[H5O_LAYOUT_NDIMS]; /*offset of slab in file*/ + hsize_t hsize[H5O_LAYOUT_NDIMS]; /*size of hyperslab */ + hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero */ + uint8 *buf=(uint8 *)_buf; /* Alias for pointer arithmetic */ + intn i; /*counters */ + size_t num_read; /* number of elements read into buffer */ + + FUNC_ENTER (H5S_point_fgath, 0); + + /* Check args */ + assert (f); + assert (layout); + assert (elmt_size>0); + assert (file_space); + assert (file_iter); + assert (nelmts>0); + assert (buf); + + /* initialize hyperslab size and offset in memory buffer */ + for(i=0; i<layout->ndims; i++) { + hsize[i]=1; /* hyperslab size is 1, except for last element */ + zero[i]=0; /* memory offset is 0 */ + } /* end for */ + hsize[layout->ndims] = elmt_size; + + /* Walk though and request each element we need and put it into the buffer */ + num_read=0; + while(num_read<nelmts) { + if(file_iter->pnt.elmt_left>0) { + /* Copy the location of the point to get */ + HDmemcpy(file_offset,file_iter->pnt.curr->pnt,layout->ndims); + file_offset[layout->ndims] = 0; + + /* Go read the point */ + if (H5F_arr_read (f, layout, comp, efl, hsize, hsize, zero, file_offset, + xfer_mode, buf/*out*/)<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_READERROR, 0, "read error"); + } + + /* Increment the offset of the buffer */ + buf+=elmt_size; + + /* Increment the count read */ + num_read++; + + /* Advance the point iterator */ + file_iter->pnt.elmt_left--; + file_iter->pnt.curr=file_iter->pnt.curr->next; + } else { + break; /* out of elements in the selection */ + } /* end else */ + } /* end while */ + + FUNC_LEAVE (num_read); +} /* H5S_point_fgath() */ + +/*------------------------------------------------------------------------- + * Function: H5S_point_fscat + * + * Purpose: Scatters dataset elements from the type conversion buffer BUF + * to the file F where the data points are arranged according to + * the file data space FILE_SPACE and stored according to + * LAYOUT and EFL. Each element is ELMT_SIZE bytes. + * The caller is requesting that NELMTS elements are copied. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_point_fscat (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, + size_t elmt_size, const H5S_t *file_space, H5S_sel_iter_t *file_iter, + size_t nelmts, + const H5D_transfer_t xfer_mode, const void *_buf) +{ + hssize_t file_offset[H5O_LAYOUT_NDIMS]; /*offset of hyperslab */ + hsize_t hsize[H5O_LAYOUT_NDIMS]; /*size of hyperslab */ + hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero vector */ + const uint8 *buf=(const uint8 *)_buf; /* Alias for pointer arithmetic */ + intn i; /*counters */ + size_t num_written; /* number of elements written from buffer */ + + FUNC_ENTER (H5S_point_fscat, FAIL); + + /* Check args */ + assert (f); + assert (layout); + assert (elmt_size>0); + assert (file_space); + assert (file_iter); + assert (nelmts>0); + assert (buf); + + /* initialize hyperslab size and offset in memory buffer */ + for(i=0; i<layout->ndims; i++) { + hsize[i]=1; /* hyperslab size is 1, except for last element */ + zero[i]=0; /* memory offset is 0 */ + } /* end for */ + hsize[layout->ndims] = elmt_size; + + /* Walk though and request each element we need and put it into the buffer */ + num_written=0; + while(num_written<nelmts) { + if(file_iter->pnt.elmt_left>0) { + /* Copy the location of the point to get */ + HDmemcpy(file_offset,file_iter->pnt.curr->pnt,layout->ndims); + file_offset[layout->ndims] = 0; + + /* Go read the point */ + if (H5F_arr_write (f, layout, comp, efl, hsize, hsize, zero, file_offset, + xfer_mode, buf)<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_READERROR, 0, "read error"); + } + + /* Increment the offset of the buffer */ + buf+=elmt_size; + + /* Increment the count read */ + num_written++; + + /* Advance the point iterator */ + file_iter->pnt.elmt_left--; + file_iter->pnt.curr=file_iter->pnt.curr->next; + } else { + break; /* out of elements in the selection */ + } /* end else */ + } /* end while */ + + FUNC_LEAVE (num_written); +} /* H5S_point_fscat() */ + +/*------------------------------------------------------------------------- + * Function: H5S_point_mgath + * + * Purpose: Gathers dataset elements from application memory BUF and + * copies them into the data type conversion buffer TCONV_BUF. + * Each element is ELMT_SIZE bytes and arranged in application + * memory according to MEM_SPACE. + * The caller is requesting that at most NELMTS be gathered. + * + * Return: Success: Number of elements copied. + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Tuesday, June 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +size_t +H5S_point_mgath (const void *_buf, size_t elmt_size, + const H5S_t *mem_space, H5S_sel_iter_t *mem_iter, + size_t nelmts, void *_tconv_buf/*out*/) +{ + hsize_t mem_size[H5O_LAYOUT_NDIMS]; /*total size of app buf */ + const uint8 *buf=(const uint8 *)_buf; /* Get local copies for address arithmetic */ + uint8 *tconv_buf=(uint8 *)_tconv_buf; + hsize_t acc; /*accumulator */ + intn space_ndims; /*dimensionality of space*/ + intn i; /*counters */ + size_t num_gath; /* number of elements gathered */ + + FUNC_ENTER (H5S_point_mgath, 0); + + /* Check args */ + assert (buf); + assert (elmt_size>0); + assert (mem_space && H5S_SEL_POINTS==mem_space->select.type); + assert (nelmts>0); + assert (tconv_buf); + + if ((space_ndims=H5S_get_dims (mem_space, mem_size, NULL))<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, 0, + "unable to retrieve data space dimensions"); + } + + for(num_gath=0; num_gath<nelmts; num_gath++) { + if(mem_iter->pnt.elmt_left>0) { + /* Compute the location of the point to get */ + for(i=0,acc=0; i<space_ndims; i++) + acc+=mem_size[i]*mem_iter->pnt.curr->pnt[i]; + + /* Copy the elements into the type conversion buffer */ + *tconv_buf=*(buf+acc); + + /* Increment the offset of the buffers */ + tconv_buf+=elmt_size; + + /* Advance the point iterator */ + mem_iter->pnt.elmt_left--; + mem_iter->pnt.curr=mem_iter->pnt.curr->next; + } else { + break; /* out of elements in the selection */ + } /* end else */ + } /* end for */ + + FUNC_LEAVE (num_gath); +} /* H5S_point_mgath() */ + +/*------------------------------------------------------------------------- + * Function: H5S_point_mscat + * + * Purpose: Scatters NELMTS data points from the type conversion buffer + * TCONV_BUF to the application buffer BUF. Each element is + * ELMT_SIZE bytes and they are organized in application memory + * according to MEM_SPACE. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Wednesday, June 17, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_point_mscat (const void *_tconv_buf, size_t elmt_size, + const H5S_t *mem_space, H5S_sel_iter_t *mem_iter, + size_t nelmts, void *_buf/*out*/) +{ + hsize_t mem_size[H5O_LAYOUT_NDIMS]; /*total size of app buf */ + uint8 *buf=(uint8 *)_buf; /* Get local copies for address arithmetic */ + const uint8 *tconv_buf=(const uint8 *)_tconv_buf; + hsize_t acc; /*accumulator */ + intn space_ndims; /*dimensionality of space*/ + intn i; /*counters */ + size_t num_scat; /* Number of elements scattered */ + + FUNC_ENTER (H5S_point_mscat, FAIL); + + /* Check args */ + assert (tconv_buf); + assert (elmt_size>0); + assert (mem_space && H5S_SEL_POINTS==mem_space->select.type); + assert (nelmts>0); + assert (buf); + + /* + * Retrieve hyperslab information to determine what elements are being + * selected (there might be other selection methods in the future). We + * only handle hyperslabs with unit sample because there's currently no + * way to pass sample information to H5V_hyper_copy(). + */ + if ((space_ndims=H5S_get_dims (mem_space, mem_size, NULL))<0) { + HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, + "unable to retrieve data space dimensions"); + } + + for(num_scat=0; num_scat<nelmts; num_scat++) { + if(mem_iter->pnt.elmt_left>0) { + /* Compute the location of the point to get */ + for(i=0,acc=0; i<space_ndims; i++) + acc+=mem_size[i]*mem_iter->pnt.curr->pnt[i]; + + /* Copy the elements into the type conversion buffer */ + *(buf+acc)=*tconv_buf; + + /* Increment the offset of the buffers */ + tconv_buf+=elmt_size; + + /* Advance the point iterator */ + mem_iter->pnt.elmt_left--; + mem_iter->pnt.curr=mem_iter->pnt.curr->next; + } else { + break; /* out of elements in the selection */ + } /* end else */ + } /* end for */ + + FUNC_LEAVE (SUCCEED); +} /* H5S_point_mscat() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_point_release + PURPOSE + Release point selection information for a dataspace + USAGE + herr_t H5S_point_release(space) + H5S_t *space; IN: Pointer to dataspace + RETURNS + SUCCEED/FAIL + DESCRIPTION + Releases all point selection information for a dataspace + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_point_release (H5S_t *space) +{ + intn i; /* Counters */ + + FUNC_ENTER (H5S_point_release, FAIL); + + /* Check args */ + assert (space); + +done: + FUNC_LEAVE (SUCCEED); +} /* H5S_point_release() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_point_npoints + PURPOSE + Compute number of elements in current selection + USAGE + hsize_t H5S_point_npoints(space) + H5S_t *space; IN: Pointer to dataspace + RETURNS + The number of elements in selection on success, 0 on failure + DESCRIPTION + Compute number of elements in current selection. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hsize_t +H5S_hyper_npoints (H5S_t *space) +{ + FUNC_ENTER (H5S_hyper_npoints, 0); + + /* Check args */ + assert (space); + + FUNC_LEAVE (space->select.num_elem); +} /* H5S_hyper_npoints() */ diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 084c282..a523405 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -29,71 +29,162 @@ #define H5S_VALID_MAX 0x01 #define H5S_VALID_PERM 0x02 -typedef struct H5S_hyperslab_t { - hssize_t *start; /* Location of start of hyperslab */ - hsize_t *count; /* Number of elements in hyperslab */ - hsize_t *stride; /* Packing of values of hyperslab */ -} H5S_hyperslab_t; - +/* + * Dataspace extent information + */ +/* Simple extent container */ typedef struct H5S_simple_t { - intn rank; /*number of dimensions */ - hsize_t *size; /*dimension sizes */ - hsize_t *max; /*maximum dimension sizes or NULL */ - intn *perm; /*dimension permutations or NULL */ + intn rank; /* Number of dimensions */ + hsize_t *size; /* Current size of the dimensions */ + hsize_t *max; /* Maximum size of the dimensions */ } H5S_simple_t; -typedef struct H5S_t { - H5S_class_t type; /*type of dimensionality object */ +/* Extent container */ +typedef struct { + H5S_class_t type; /* Type of extent */ union { - H5S_simple_t simple; /*simple dimensionality information */ + H5S_simple_t simple; /* Simple dimensionality information */ } u; - uintn hslab_def; /* Whether the hyperslab is defined */ - H5S_hyperslab_t h; /* Hyperslab information */ -} H5S_t; +} H5S_extent_t; -/* - * This structure contains information about how the elements of a data space - * are numbered. +/* + * Dataspace selection information */ -typedef struct H5S_number_t { - int _place_holder; /*remove this field! */ -} H5S_number_t; +/* Enumerated type for the type of selection */ +typedef enum { + H5S_SEL_NONE, /* Nothing selected */ + H5S_SEL_POINTS, /* Sequence of points selected */ + H5S_SEL_HYPERSLABS, /* Hyperslab selection defined */ + H5S_SEL_ALL /* Entire extent selected */ +}H5S_sel_type; + +/* Node in point selection list */ +typedef struct H5S_pnt_node_tag { + hssize_t *pnt; /* Pointer to a selected point */ + struct H5S_pnt_node_tag *next; /* pointer to next point in list */ +} H5S_pnt_node_t; + +/* Information about point selection list */ +typedef struct { + H5S_pnt_node_t *head; /* Pointer to head of point list */ +} H5S_pnt_list_t; + +/* Region in dimension */ +typedef struct H5S_hyper_region_tag { + hssize_t start; /* The low bound of a region in a dimension */ + hssize_t end; /* The high bound of a region in a dimension */ +} H5S_hyper_region_t; + +/* Node in hyperslab selection list */ +typedef struct H5S_hyper_node_tag { + hssize_t *start; /* Pointer to a corner of a hyperslab closest to the origin */ + hssize_t *end; /* Pointer to a corner of a hyperslab furthest from the origin */ + struct H5S_hyper_node_tag *next; /* pointer to next hyperslab in list */ +} H5S_hyper_node_t; + +/* Information about hyperslab boundary and pointer to hyperslab node */ +typedef struct { + hssize_t bound; /* Location of boundary */ + H5S_hyper_node_t *node; /* Boundary's node */ +} H5S_hyper_bound_t; + +/* Information about hyperslab selection */ +typedef struct { + size_t count; /* Number of nodes in list */ + H5S_hyper_node_t *head; /* Pointer to head of hyperslab list */ + H5S_hyper_bound_t **lo_bounds; /* Lower (closest to the origin) bound array for each dimension */ + H5S_hyper_bound_t **hi_bounds; /* Upper (farthest from the origin) bound array for each dimension */ +} H5S_hyper_list_t; + +/* Selection information container */ +typedef struct { + H5S_sel_type type; /* Type of selection (list of points or hyperslabs) */ + hsize_t *offset; /* Offset within the extent (NULL means a 0 offset) */ + hsize_t *order; /* Selection order. (NULL means a specific ordering of points) */ + hsize_t num_elem; /* Number of elements in selection */ + union { + H5S_pnt_list_t *pnt_lst; /* List of selected points (order is important) */ + H5S_hyper_list_t *hyper_lst; /* List of selected hyperslabs (order is not important) */ + } sel_info; +} H5S_select_t; + +/* Point selection iteration container */ +typedef struct { + hsize_t elmt_left; /* Number of elements left to iterate over */ + H5S_pnt_node_t *curr; /* Pointer to next node to output */ +} H5S_point_iter_t; + +/* Hyperslab selection iteration container */ +typedef struct { + hsize_t elmt_left; /* Number of elements left to iterate over */ + hssize_t *pos; /* Position to start iterating at */ +} H5S_hyper_iter_t; + +/* "All" selection iteration container */ +typedef struct { + hsize_t elmt_left; /* Number of elements left to iterate over */ + hsize_t offset; /* Next element to output */ +} H5S_all_iter_t; + +/* Selection iteration container */ +typedef union { + H5S_point_iter_t pnt; /* Point selection iteration information */ + H5S_hyper_iter_t hyp; /* Hyperslab selection iteration information */ + H5S_all_iter_t all; /* "All" selection iteration information */ +} H5S_sel_iter_t; + +/* Main dataspace structure */ +typedef struct H5S_t { + H5S_extent_t extent; /* Dataspace extent */ + H5S_select_t select; /* Dataspace selection */ +} H5S_t; /* * Callbacks for data space conversion. */ typedef struct H5S_tconv_t { - /* Initialize element numbering information */ - size_t (*init)(const struct H5O_layout_t *layout, const H5S_t *mem_space, - const H5S_t *file_space, size_t desired_nelmts, - H5S_number_t *numbering/*out*/); + /* Initialize file element numbering information */ + herr_t (*finit)(const struct H5O_layout_t *layout, const H5S_t *space, + H5S_sel_iter_t *iter); + + /* Initialize memory element numbering information */ + herr_t (*minit)(const struct H5O_layout_t *layout, const H5S_t *space, + H5S_sel_iter_t *iter); + + /* Initialize background element numbering information */ + herr_t (*binit)(const struct H5O_layout_t *layout, const H5S_t *space, + H5S_sel_iter_t *iter); + + /* Figure out the optimal number of elements to transfer to/from the file */ + size_t (*favail)(const H5S_t *file_space, const H5S_sel_iter_t *file_iter, + size_t max); /* Gather elements from disk to type conversion buffer */ size_t (*fgath)(H5F_t *f, const struct H5O_layout_t *layout, const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, size_t elmt_size, - const H5S_t *file_space, const H5S_number_t *numbering, - size_t start, size_t nelmts, + const H5S_t *file_space, H5S_sel_iter_t *file_iter, + size_t nelmts, const H5D_transfer_t xfer_mode, void *tconv_buf/*out*/); - /* Scatter elements from type conversion buffer to application buffer */ - herr_t (*mscat)(const void *tconv_buf, size_t elmt_size, - const H5S_t *mem_space, const H5S_number_t *numbering, - size_t start, size_t nelmts, void *buf/*out*/); - - /* Gather elements from app buffer to type conversion buffer */ - size_t (*mgath)(const void *buf, size_t elmt_size, - const H5S_t *mem_space, const H5S_number_t *numbering, - size_t start, size_t nelmts, void *tconv_buf/*out*/); - /* Scatter elements from type conversion buffer to disk */ herr_t (*fscat)(H5F_t *f, const struct H5O_layout_t *layout, const struct H5O_compress_t *compress, const struct H5O_efl_t *efl, size_t elmt_size, - const H5S_t *file_space, const H5S_number_t *numbering, - size_t start, size_t nelmts, + const H5S_t *file_space, H5S_sel_iter_t *file_iter, + size_t nelmts, const H5D_transfer_t xfer_mode, const void *tconv_buf); + /* Gather elements from app buffer to type conversion buffer */ + size_t (*mgath)(const void *buf, size_t elmt_size, + const H5S_t *mem_space, H5S_sel_iter_t *mem_iter, + size_t nelmts, void *tconv_buf/*out*/); + + /* Scatter elements from type conversion buffer to application buffer */ + herr_t (*mscat)(const void *tconv_buf, size_t elmt_size, + const H5S_t *mem_space, H5S_sel_iter_t *mem_iter, + size_t nelmts, void *buf/*out*/); + /* Read from file to application w/o intermediate scratch buffer */ herr_t (*read)(H5F_t *f, const struct H5O_layout_t *layout, const struct H5O_compress_t *comp, @@ -109,6 +200,7 @@ typedef struct H5S_tconv_t { const H5D_transfer_t xfer_mode, const void *buf); } H5S_conv_t; +H5S_t *H5S_create (H5S_class_t type); H5S_t *H5S_copy (const H5S_t *src); herr_t H5S_close_simple (H5S_simple_t *simple); herr_t H5S_close (H5S_t *ds); @@ -122,31 +214,36 @@ H5S_t *H5S_read (H5G_entry_t *ent); intn H5S_cmp (const H5S_t *ds1, const H5S_t *ds2); hbool_t H5S_is_simple (const H5S_t *sdim); uintn H5S_nelem (const H5S_t *space); -const H5S_conv_t *H5S_find (const H5S_t *mem_space, const H5S_t *file_space); +herr_t H5S_find (H5S_conv_t *conv, const H5S_t *mem_space, const H5S_t *file_space); intn H5S_get_hyperslab (const H5S_t *ds, hssize_t offset[]/*out*/, hsize_t size[]/*out*/, hsize_t stride[]/*out*/); +herr_t H5S_release_simple(H5S_simple_t *simple); +herr_t H5S_extent_copy(H5S_extent_t *dst, const H5S_extent_t *src); +herr_t H5S_select_copy (H5S_t *dst, const H5S_t *src); +herr_t H5S_select_release (H5S_t *space); +hsize_t H5S_select_npoints (H5S_t *space); intn H5S_extend (H5S_t *space, const hsize_t *size); /* Conversion functions for simple data spaces */ size_t H5S_simp_init (const struct H5O_layout_t *layout, const H5S_t *mem_space, const H5S_t *file_space, - size_t desired_nelmts, H5S_number_t *numbering/*out*/); + size_t desired_nelmts); size_t H5S_simp_fgath (H5F_t *f, const struct H5O_layout_t *layout, const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, size_t elmt_size, - const H5S_t *file_space, const H5S_number_t *numbering, + const H5S_t *file_space, size_t start, size_t nelmts, const H5D_transfer_t xfer_mode, void *tconv_buf/*out*/); herr_t H5S_simp_mscat (const void *tconv_buf, size_t elmt_size, - const H5S_t *mem_space, const H5S_number_t *numbering, + const H5S_t *mem_space, size_t start, size_t nelmts, void *buf/*out*/); size_t H5S_simp_mgath (const void *buf, size_t elmt_size, - const H5S_t *mem_space, const H5S_number_t *numbering, + const H5S_t *mem_space, size_t start, size_t nelmts, void *tconv_buf/*out*/); herr_t H5S_simp_fscat (H5F_t *f, const struct H5O_layout_t *layout, const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, size_t elmt_size, - const H5S_t *file_space, const H5S_number_t *numbering, + const H5S_t *file_space, size_t start, size_t nelmts, const H5D_transfer_t xfer_mode, const void *tconv_buf); herr_t H5S_simp_read (H5F_t *f, const struct H5O_layout_t *layout, @@ -159,4 +256,78 @@ herr_t H5S_simp_write (H5F_t *f, const struct H5O_layout_t *layout, const struct H5O_efl_t *efl, size_t elmt_size, const H5S_t *file_space, const H5S_t *mem_space, const H5D_transfer_t xfer_mode, const void *buf); + +/* Point select functions */ +herr_t H5S_point_init (const struct H5O_layout_t *layout, + const H5S_t *space, H5S_sel_iter_t *iter); +size_t H5S_point_favail (const H5S_t *space, const H5S_sel_iter_t *iter, + size_t max); +size_t H5S_point_fgath (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, + size_t elmt_size, const H5S_t *file_space, H5S_sel_iter_t *file_iter, + size_t nelmts, + const H5D_transfer_t xfer_mode, void *buf/*out*/); +herr_t H5S_point_fscat (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, + size_t elmt_size, const H5S_t *file_space, H5S_sel_iter_t *file_iter, + size_t nelmts, + const H5D_transfer_t xfer_mode, const void *buf); +size_t H5S_point_mgath (const void *_buf, size_t elmt_size, + const H5S_t *mem_space, H5S_sel_iter_t *mem_iter, + size_t nelmts, void *_tconv_buf/*out*/); +herr_t H5S_point_mscat (const void *_tconv_buf, size_t elmt_size, + const H5S_t *mem_space, H5S_sel_iter_t *mem_iter, + size_t nelmts, void *_buf/*out*/); +herr_t H5S_point_release (H5S_t *space); +hsize_t H5S_point_npoints (H5S_t *space); + +/* "All" select functions */ +herr_t H5S_all_init (const struct H5O_layout_t *layout, + const H5S_t *space, H5S_sel_iter_t *iter); +size_t H5S_all_favail (const H5S_t *space, const H5S_sel_iter_t *iter, + size_t max); +size_t H5S_all_fgath (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, + size_t elmt_size, const H5S_t *file_space, H5S_sel_iter_t *file_iter, + size_t nelmts, + const H5D_transfer_t xfer_mode, void *buf/*out*/); +herr_t H5S_all_fscat (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, + size_t elmt_size, const H5S_t *file_space, H5S_sel_iter_t *file_iter, + size_t nelmts, + const H5D_transfer_t xfer_mode, const void *buf); +size_t H5S_all_mgath (const void *_buf, size_t elmt_size, + const H5S_t *mem_space, H5S_sel_iter_t *mem_iter, + size_t nelmts, void *_tconv_buf/*out*/); +herr_t H5S_all_mscat (const void *_tconv_buf, size_t elmt_size, + const H5S_t *mem_space, H5S_sel_iter_t *mem_iter, + size_t nelmts, void *_buf/*out*/); +herr_t H5S_all_release (H5S_t *space); +hsize_t H5S_all_npoints (H5S_t *space); + +/* Hyperslab selection functions */ +herr_t H5S_hyper_init (const struct H5O_layout_t *layout, + const H5S_t *space, H5S_sel_iter_t *iter); +size_t H5S_hyper_favail (const H5S_t *space, const H5S_sel_iter_t *iter, + size_t max); +size_t H5S_hyper_fgath (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, + size_t elmt_size, const H5S_t *file_space, H5S_sel_iter_t *file_iter, + size_t nelmts, + const H5D_transfer_t xfer_mode, void *buf/*out*/); +herr_t H5S_hyper_fscat (H5F_t *f, const struct H5O_layout_t *layout, + const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, + size_t elmt_size, const H5S_t *file_space, H5S_sel_iter_t *file_iter, + size_t nelmts, + const H5D_transfer_t xfer_mode, const void *buf); +size_t H5S_hyper_mgath (const void *_buf, size_t elmt_size, + const H5S_t *mem_space, H5S_sel_iter_t *mem_iter, + size_t nelmts, void *_tconv_buf/*out*/); +herr_t H5S_hyper_mscat (const void *_tconv_buf, size_t elmt_size, + const H5S_t *mem_space, H5S_sel_iter_t *mem_iter, + size_t nelmts, void *_buf/*out*/); +herr_t H5S_hyper_add (H5S_t *space, hssize_t *start, hssize_t *size); +herr_t H5S_hyper_release (H5S_t *space); +hsize_t H5S_hyper_npoints (H5S_t *space); + #endif diff --git a/src/H5Spublic.h b/src/H5Spublic.h index 39b6502..b7c0f01 100644 --- a/src/H5Spublic.h +++ b/src/H5Spublic.h @@ -13,8 +13,8 @@ /* * This file contains public declarations for the H5S module. */ -#ifndef _H5pproto_H -#define _H5Sproto_H +#ifndef _H5Spublic_H +#define _H5Spublic_H /* Public headers needed by this file */ #include <H5public.h> @@ -32,13 +32,20 @@ typedef enum H5S_class_t { H5S_COMPLEX = 2 /*complex data space */ } H5S_class_t; +/* Different ways of combining selections */ +typedef enum H5S_seloper_t { + H5S_NOOP = -1, /*error */ + H5S_SELECT_SET = 0 /* Select "set" operation */ +} H5S_seloper_t; + #ifdef __cplusplus extern "C" { #endif /* Functions in H5S.c */ -hid_t H5Screate_simple (int rank, const hsize_t dims[], - const hsize_t maxdims[]); +hid_t H5Screate(H5S_class_t type); +hid_t H5Screate_simple (int rank, const hsize_t dims[], const hsize_t maxdims[]); +herr_t H5Sset_extent_simple (hid_t sid, int rank, const hsize_t *dims, const hsize_t *max); hid_t H5Scopy (hid_t space_id); herr_t H5Sclose (hid_t space_id); hsize_t H5Sget_npoints (hid_t space_id); @@ -46,10 +53,9 @@ int H5Sget_ndims (hid_t space_id); int H5Sget_dims (hid_t space_id, hsize_t dims[], hsize_t maxdims[]); hbool_t H5Sis_simple (hid_t space_id); herr_t H5Sset_space (hid_t space_id, int rank, const hsize_t *dims); -herr_t H5Sset_hyperslab(hid_t sid, const hssize_t *start, const hsize_t *count, - const hsize_t *stride); -int H5Sget_hyperslab (hid_t sid, hssize_t offset[]/*out*/, - hsize_t size[]/*out*/, hsize_t stride[]/*out*/); +hsize_t H5Sselect_npoints (hid_t spaceid); +herr_t H5Sselect_hyperslab (hid_t spaceid, H5S_seloper_t op, hssize_t *start, + hssize_t *_stride, hssize_t *count, hssize_t *_block); #ifdef __cplusplus } diff --git a/src/H5Sselect.c b/src/H5Sselect.c new file mode 100644 index 0000000..e07b60b --- /dev/null +++ b/src/H5Sselect.c @@ -0,0 +1,386 @@ +/* + * Copyright (C) 1998 NCSA + * All rights reserved. + * + * Programmer: Quincey Koziol <koziol@ncsa.uiuc.ued> + * Friday, May 29, 1998 + * + * Purpose: Dataspace functions. + */ + +#include <H5private.h> +#include <H5Eprivate.h> +#include <H5Iprivate.h> +#include <H5MMprivate.h> +#include <H5Sprivate.h> +#include <H5Vprivate.h> + +/* Interface initialization */ +#define PABLO_MASK H5S_select_mask +#define INTERFACE_INIT H5S_select_init +static intn interface_initialize_g = FALSE; +static herr_t H5S_select_init(void); +static void H5S_select_term(void); + + +/*-------------------------------------------------------------------------- + NAME + H5S_select_init + PURPOSE + Initialize selection interface + USAGE + herr_t H5S_select_init(void) + RETURNS + SUCCEED/FAIL + DESCRIPTION + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t H5S_select_init (void) +{ + herr_t ret_value = SUCCEED; + FUNC_ENTER (H5S_select_init, FAIL); + + /* Register the atexit function for this (sub)interface */ + ret_value = H5_add_exit(&H5S_select_term); + FUNC_LEAVE(ret_value); +} + +/*-------------------------------------------------------------------------- + NAME + H5S_select_term + PURPOSE + Terminate various H5S selection objects and free lists + USAGE + void H5S_select_term() + RETURNS + SUCCEED/FAIL + DESCRIPTION + Release the selection resources allocated. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Can't report errors... + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static void +H5S_select_term(void) +{ +} + +/*-------------------------------------------------------------------------- + NAME + H5S_select_copy + PURPOSE + Copy a selection from one dataspace to another + USAGE + herr_t H5S_select_copy(dst, src) + H5S_t *dst; OUT: Pointer to the destination dataspace + H5S_t *src; IN: Pointer to the source dataspace + RETURNS + SUCCEED/FAIL + DESCRIPTION + Copies all the selection information (include offset) from the source + dataspace to the destination dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t H5S_select_copy (H5S_t *dst, const H5S_t *src) +{ + FUNC_ENTER (H5S_select_copy, FAIL); + + /* Check args */ + assert(dst); + assert(src); + + + /* Perform correct type of copy based on the type of selection */ + + FUNC_LEAVE (SUCCEED); +} /* H5S_select_copy() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_select_release + PURPOSE + Release selection information for a dataspace + USAGE + herr_t H5S_select_release(space) + H5S_t *space; IN: Pointer to dataspace + RETURNS + SUCCEED/FAIL + DESCRIPTION + Releases all selection information for a dataspace + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_select_release (H5S_t *space) +{ + herr_t ret_value; /* Counters */ + + FUNC_ENTER (H5S_select_release, FAIL); + + /* Check args */ + assert (space); + + switch(space->select.type) { + case H5S_SEL_POINTS: /* Sequence of points selected */ + ret_value=H5S_point_release(space); + break; + + case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */ + ret_value=H5S_hyper_release(space); + break; + + case H5S_SEL_ALL: /* Entire extent selected */ + ret_value=H5S_all_release(space); + break; + + case H5S_SEL_NONE: /* Nothing selected */ + break; + } /* end switch() */ + + FUNC_LEAVE (SUCCEED); +} /* H5S_select_release() */ + +/*-------------------------------------------------------------------------- + NAME + H5Sselect_hyperslab + PURPOSE + Specify a hyperslab to combine with the current hyperslab selection + USAGE + herr_t H5Sselect_hyperslab(dsid, op, start, stride, count, block) + hid_t dsid; IN: Dataspace ID of selection to modify + H5S_seloper_t op; IN: Operation to perform on current selection + hssize_t *start; IN: Offset of start of hyperslab + hssize_t *stride; IN: Hyperslab stride + hssize_t *count; IN: Number of blocks included in hyperslab + hssize_t *block; IN: Size of block in hyperslab + RETURNS + SUCCEED/FAIL + DESCRIPTION + Combines a hyperslab selection with the current selection for a dataspace. + If the current selection is not a hyperslab, it is freed and the hyperslab + parameters passed in are combined with the H5S_SEL_ALL hyperslab (ie. a + selection composing the entire current extent). Currently, only the + H5S_SELECT_SET operation is supported. If STRIDE or BLOCK is NULL, they + are assumed to be set to all '1'. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t H5Sselect_hyperslab (hid_t spaceid, H5S_seloper_t op, hssize_t *start, + hssize_t *_stride, hssize_t *count, hssize_t *_block) +{ + H5S_t *space = NULL; /* Dataspace to modify selection of */ + hssize_t *stride, /* Stride array */ + *block; /* Block size array */ + uintn contig; /* whether selection is contiguous or not */ + int i; /* Counters */ + herr_t ret_value=FAIL; /* return value */ + + FUNC_ENTER (H5Sselect_hyperslab, FAIL); + + /* Check args */ + if (H5_DATASPACE != H5I_group(spaceid) || + NULL == (space=H5I_object(spaceid))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); + } + if(start==NULL || count==NULL) { + HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "hyperslab not specified"); + } /* end if */ + if(op!=H5S_SELECT_SET) { + HRETURN_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, + "operations other than H5S_SELECT_SET not supported currently"); + } /* end if */ + + /* Fill in the correct stride values */ + if(_stride==NULL) { + hssize_t fill=1; + + if((stride = H5MM_malloc(sizeof(hssize_t)*space->extent.u.simple.rank))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "can't allocate stride vector"); + H5V_array_fill(stride,&fill,sizeof(hssize_t),space->extent.u.simple.rank); + } else { + stride=_stride; + } /* end else */ + + /* Fill in the correct block values */ + if(_block==NULL) { + hssize_t fill=1; + + if((block = H5MM_malloc(sizeof(hssize_t)*space->extent.u.simple.rank))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "can't allocate stride vector"); + H5V_array_fill(block,&fill,sizeof(hssize_t),space->extent.u.simple.rank); + } else { + block=_block; + } /* end else */ + +/* Check for overlapping blocks (remove when real block-merging algorithm is in place) */ +if(op==H5S_SELECT_SET && _block!=NULL) { + for(i=0; i<space->extent.u.simple.rank; i++) { + if(stride[i]<block[i]) { + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, + "hyperslab blocks overlap"); + } /* end if */ + } /* end for */ +} /* end if */ + + /* Determine if selection is contiguous */ + contig=1; /* assume hyperslab is contiguous, until proven otherwise */ + for(i=0; i<space->extent.u.simple.rank; i++) { + /* contiguous hyperslabs have the block size equal to the stride */ + if(stride[i]!=block[i]) { + contig=0; /* hyperslab isn't contiguous */ + break; /* no use looking further */ + } /* end if */ + } /* end for */ + +#ifdef QAK +printf("%s: check 1.0\n",FUNC); +#endif /* QAK */ + /* If we are setting a new selection, remove current selection first */ + if(op==H5S_SELECT_SET) { + if(H5S_select_release(space)<0) { + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, + "can't release hyperslab"); + } /* end if */ + } /* end if */ + +#ifdef QAK +printf("%s: check 2.0\n",FUNC); +#endif /* QAK */ + /* Allocate space for the hyperslab selection information if necessary */ + if(space->select.type!=H5S_SEL_HYPERSLABS || space->select.sel_info.hyper_lst==NULL) { + if((space->select.sel_info.hyper_lst = H5MM_calloc(sizeof(H5S_hyper_list_t)))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "can't allocate hyperslab information"); + if((space->select.sel_info.hyper_lst->lo_bounds = H5MM_calloc(space->extent.u.simple.rank*sizeof(H5S_hyper_bound_t *)))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "can't allocate hyperslab lo bound information"); + if((space->select.sel_info.hyper_lst->hi_bounds = H5MM_calloc(space->extent.u.simple.rank*sizeof(H5S_hyper_bound_t *)))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "can't allocate hyperslab lo bound information"); + } /* end if */ + +#ifdef QAK +printf("%s: check 3.0\n",FUNC); +#endif /* QAK */ + /* Add hyperslab to selection */ + if(contig) { /* Check for trivial case */ + if(H5S_hyper_add(space,start,count)<0) { + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, + "can't insert hyperslab"); + } + } else { +/* Generate list of blocks to add/remove based on selection operation */ +/* Add/Remove blocks to/from selection */ + assert("complex hyperslabs not supported yet" && 0); + } /* end if */ + + /* Set selection type */ + space->select.type=H5S_SEL_HYPERSLABS; + ret_value=SUCCEED; +#ifdef QAK +printf("%s: check 4.0\n",FUNC); +#endif /* QAK */ + +done: + if(_stride==NULL && stride!=NULL) + H5MM_xfree(stride); + if(_block==NULL && block!=NULL) + H5MM_xfree(block); + + FUNC_LEAVE (ret_value); +} /* H5Sselect_hyperslab() */ + +/*-------------------------------------------------------------------------- + NAME + H5Sselect_npoints + PURPOSE + Get the number of elements in current selection + USAGE + herr_t H5Sselect_hyperslab(dsid) + hid_t dsid; IN: Dataspace ID of selection to query + RETURNS + The number of elements in selection on success, 0 on failure + DESCRIPTION + Returns the number of elements in current selection for dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hsize_t H5Sselect_npoints (hid_t spaceid) +{ + H5S_t *space = NULL; /* Dataspace to modify selection of */ + hsize_t ret_value=0; /* return value */ + + FUNC_ENTER (H5Sselect_npoints, 0); + + /* Check args */ + if (H5_DATASPACE != H5I_group(spaceid) || + NULL == (space=H5I_object(spaceid))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a data space"); + } + + ret_value = H5S_select_npoints(space); + + FUNC_LEAVE (ret_value); +} /* H5Sselect_npoints() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_select_npoints + PURPOSE + Get the number of elements in current selection + USAGE + herr_t H5Sselect_hyperslab(ds) + H5S_t *ds; IN: Dataspace pointer + RETURNS + The number of elements in selection on success, 0 on failure + DESCRIPTION + Returns the number of elements in current selection for dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hsize_t H5S_select_npoints (H5S_t *space) +{ + herr_t ret_value=FAIL; /* return value */ + + FUNC_ENTER (H5Sselect_npoints, FAIL); + + assert(space); + + switch(space->select.type) { + case H5S_SEL_POINTS: /* Sequence of points selected */ + ret_value=H5S_point_npoints(space); + break; + + case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */ + ret_value=H5S_hyper_npoints(space); + break; + + case H5S_SEL_ALL: /* Entire extent selected */ + ret_value=H5S_all_npoints(space); + break; + + case H5S_SEL_NONE: /* Nothing selected */ + ret_value=0; + break; + } /* end switch */ + + FUNC_LEAVE (ret_value); +} /* H5Sselect_npoints() */ diff --git a/src/H5Ssimp.c b/src/H5Ssimp.c index 64be705..1f47b45 100644 --- a/src/H5Ssimp.c +++ b/src/H5Ssimp.c @@ -5,7 +5,7 @@ * Programmer: Robb Matzke <matzke@llnl.gov> * Wednesday, January 21, 1998 * - * Purpose: Simple data space functions. + * Purpose: Simple selection data space I/O functions. */ #include <H5private.h> #include <H5Eprivate.h> @@ -38,7 +38,7 @@ static intn interface_initialize_g = FALSE; size_t H5S_simp_init (const struct H5O_layout_t __unused__ *layout, const H5S_t *mem_space, const H5S_t *file_space, - size_t desired_nelmts, H5S_number_t *numbering/*out*/) + size_t desired_nelmts) { hsize_t nelmts; int m_ndims, f_ndims; /*mem, file dimensionality */ @@ -50,12 +50,8 @@ H5S_simp_init (const struct H5O_layout_t __unused__ *layout, /* Check args */ assert (layout); - assert (mem_space && H5S_SIMPLE==mem_space->type); - assert (file_space && H5S_SIMPLE==file_space->type); - assert (numbering); - - /* Numbering is implied by the hyperslab, C order, no data here */ - HDmemset (numbering, 0, sizeof(H5S_number_t)); + assert (mem_space && H5S_SIMPLE==mem_space->extent.type); + assert (file_space && H5S_SIMPLE==file_space->extent.type); /* * The stripmine size is such that only the slowest varying dimension can @@ -66,7 +62,7 @@ H5S_simp_init (const struct H5O_layout_t __unused__ *layout, for (i=m_ndims-1, acc=1; i>0; --i) acc *= size[i]; nelmts = (desired_nelmts/acc) * acc; if (nelmts<=0) { - HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, 0, + HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, 0, "strip mine buffer is too small"); } @@ -76,20 +72,19 @@ H5S_simp_init (const struct H5O_layout_t __unused__ *layout, */ f_ndims = H5S_get_hyperslab (file_space, NULL, size, NULL); if (m_ndims!=f_ndims) { - nelmts = H5S_get_npoints (file_space); - if (nelmts>desired_nelmts) { - HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, 0, - "strip mining not supported across " - "dimensionalities"); - } - assert (nelmts==H5S_get_npoints (mem_space)); + nelmts = H5S_get_npoints (file_space); + if (nelmts>desired_nelmts) { + HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, 0, + "strip mining not supported across dimensionalities"); + } + assert (nelmts==H5S_get_npoints (mem_space)); } else { - for (i=f_ndims-1, acc=1; i>0; --i) acc *= size[i]; - acc *= (desired_nelmts/acc); - if (nelmts!=acc) { - HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, 0, - "unsupported strip mine size for shape change"); - } + for (i=f_ndims-1, acc=1; i>0; --i) acc *= size[i]; + acc *= (desired_nelmts/acc); + if (nelmts!=acc) { + HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, 0, + "unsupported strip mine size for shape change"); + } } assert (nelmts < MAX_SIZET); @@ -128,7 +123,6 @@ size_t H5S_simp_fgath (H5F_t *f, const struct H5O_layout_t *layout, const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, size_t elmt_size, const H5S_t *file_space, - const H5S_number_t __unused__ *numbering, size_t start, size_t nelmts, const H5D_transfer_t xfer_mode, void *buf/*out*/) { @@ -147,7 +141,6 @@ H5S_simp_fgath (H5F_t *f, const struct H5O_layout_t *layout, assert (layout); assert (elmt_size>0); assert (file_space); - assert (numbering); assert (nelmts>0); assert (buf); @@ -219,7 +212,6 @@ H5S_simp_fgath (H5F_t *f, const struct H5O_layout_t *layout, herr_t H5S_simp_mscat (const void *tconv_buf, size_t elmt_size, const H5S_t *mem_space, - const H5S_number_t __unused__ *numbering, size_t start, size_t nelmts, void *buf/*out*/) { hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /*slab offset in app buf*/ @@ -236,8 +228,7 @@ H5S_simp_mscat (const void *tconv_buf, size_t elmt_size, /* Check args */ assert (tconv_buf); assert (elmt_size>0); - assert (mem_space && H5S_SIMPLE==mem_space->type); - assert (numbering); + assert (mem_space && H5S_SIMPLE==mem_space->extent.type); assert (nelmts>0); assert (buf); @@ -316,7 +307,6 @@ H5S_simp_mscat (const void *tconv_buf, size_t elmt_size, size_t H5S_simp_mgath (const void *buf, size_t elmt_size, const H5S_t *mem_space, - const H5S_number_t __unused__ *numbering, size_t start, size_t nelmts, void *tconv_buf/*out*/) { hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /*slab offset in app buf*/ @@ -333,8 +323,7 @@ H5S_simp_mgath (const void *buf, size_t elmt_size, /* Check args */ assert (buf); assert (elmt_size>0); - assert (mem_space && H5S_SIMPLE==mem_space->type); - assert (numbering); + assert (mem_space && H5S_SIMPLE==mem_space->extent.type); assert (nelmts>0); assert (tconv_buf); @@ -415,7 +404,6 @@ herr_t H5S_simp_fscat (H5F_t *f, const struct H5O_layout_t *layout, const struct H5O_compress_t *comp, const struct H5O_efl_t *efl, size_t elmt_size, const H5S_t *file_space, - const H5S_number_t __unused__ *numbering, size_t start, size_t nelmts, const H5D_transfer_t xfer_mode, const void *buf) { @@ -434,7 +422,6 @@ H5S_simp_fscat (H5F_t *f, const struct H5O_layout_t *layout, assert (layout); assert (elmt_size>0); assert (file_space); - assert (numbering); assert (nelmts>0); assert (buf); @@ -521,9 +508,10 @@ H5S_simp_read (H5F_t *f, const struct H5O_layout_t *layout, FUNC_ENTER (H5S_simp_read, FAIL); #ifndef NDEBUG - assert (file_space->type==mem_space->type); - assert (file_space->u.simple.rank==mem_space->u.simple.rank); - for (i=0; i<file_space->u.simple.rank; i++) { + assert (file_space->extent.type==mem_space->extent.type); + assert (file_space->extent.u.simple.rank==mem_space->extent.u.simple.rank); + for (i=0; i<file_space->extent.u.simple.rank; i++) { +#ifdef FIXME if (file_space->hslab_def && mem_space->hslab_def) { assert (1==file_space->h.stride[i]); assert (1==mem_space->h.stride[i]); @@ -538,6 +526,7 @@ H5S_simp_read (H5F_t *f, const struct H5O_layout_t *layout, assert (file_space->u.simple.size[i]== mem_space->u.simple.size[i]); } +#endif } #endif @@ -546,40 +535,74 @@ H5S_simp_read (H5F_t *f, const struct H5O_layout_t *layout, * Calculate size of hyperslab and offset of hyperslab into file and * memory. */ - if (file_space->hslab_def) { - for (i=0; i<file_space->u.simple.rank; i++) { - hslab_size[i] = file_space->h.count[i]; - } - } else { - for (i=0; i<file_space->u.simple.rank; i++) { - hslab_size[i] = file_space->u.simple.size[i]; - } - } - for (i=0; i<mem_space->u.simple.rank; i++) { - mem_size[i] = mem_space->u.simple.size[i]; - } - if (file_space->hslab_def) { - for (i=0; i<file_space->u.simple.rank; i++) { - file_offset[i] = file_space->h.start[i]; - } - } else { - for (i=0; i<file_space->u.simple.rank; i++) { - file_offset[i] = 0; - } - } - if (mem_space->hslab_def) { - for (i=0; i<mem_space->u.simple.rank; i++) { - mem_offset[i] = mem_space->h.start[i]; - } - } else { - for (i=0; i<mem_space->u.simple.rank; i++) { - mem_offset[i] = 0; - } - } - hslab_size[file_space->u.simple.rank] = elmt_size; - mem_size[file_space->u.simple.rank] = elmt_size; - file_offset[file_space->u.simple.rank] = 0; - mem_offset[file_space->u.simple.rank] = 0; + switch(file_space->select.type) { + case H5S_SEL_NONE: /* no selection defined */ + HRETURN_ERROR (H5E_DATASPACE, H5E_BADVALUE, FAIL, "selection not defined"); + + case H5S_SEL_POINTS: /* point sequence selection defined */ + case H5S_SEL_HYPERSLABS: /* hyperslab selection defined */ + HRETURN_ERROR (H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "selection type not supprted currently"); + + case H5S_SEL_ALL: /* entire dataspace selection */ + for (i=0; i<file_space->extent.u.simple.rank; i++) + hslab_size[i] = file_space->extent.u.simple.size[i]; + break; + } /* end switch */ + + switch(mem_space->select.type) { + case H5S_SEL_NONE: /* no selection defined */ + HRETURN_ERROR (H5E_DATASPACE, H5E_BADVALUE, FAIL, "selection not defined"); + + case H5S_SEL_POINTS: /* point sequence selection defined */ + case H5S_SEL_HYPERSLABS: /* hyperslab selection defined */ + HRETURN_ERROR (H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "selection type not supprted currently"); + + case H5S_SEL_ALL: /* entire dataspace selection */ + for (i=0; i<mem_space->extent.u.simple.rank; i++) + mem_size[i] = mem_space->extent.u.simple.size[i]; + break; + } /* end switch */ + + switch(file_space->select.type) { + case H5S_SEL_NONE: /* no selection defined */ + HRETURN_ERROR (H5E_DATASPACE, H5E_BADVALUE, FAIL, "selection not defined"); + + case H5S_SEL_POINTS: /* point sequence selection defined */ + case H5S_SEL_HYPERSLABS: /* hyperslab selection defined */ +#ifdef LATER + for (i=0; i<file_space->u.simple.rank; i++) + file_offset[i] = file_space->h.start[i]; +#endif + HRETURN_ERROR (H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "selection type not supprted currently"); + + case H5S_SEL_ALL: /* entire dataspace selection */ + for (i=0; i<file_space->extent.u.simple.rank; i++) + file_offset[i] = 0; + break; + } /* end switch */ + + switch(mem_space->select.type) { + case H5S_SEL_NONE: /* no selection defined */ + HRETURN_ERROR (H5E_DATASPACE, H5E_BADVALUE, FAIL, "selection not defined"); + + case H5S_SEL_POINTS: /* point sequence selection defined */ + case H5S_SEL_HYPERSLABS: /* hyperslab selection defined */ +#ifdef LATER + for (i=0; i<mem_space->u.simple.rank; i++) + mem_offset[i] = mem_space->h.start[i]; +#endif + HRETURN_ERROR (H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "selection type not supprted currently"); + + case H5S_SEL_ALL: /* entire dataspace selection */ + for (i=0; i<mem_space->extent.u.simple.rank; i++) + mem_offset[i] = 0; + break; + } /* end switch */ + + hslab_size[file_space->extent.u.simple.rank] = elmt_size; + mem_size[file_space->extent.u.simple.rank] = elmt_size; + file_offset[file_space->extent.u.simple.rank] = 0; + mem_offset[file_space->extent.u.simple.rank] = 0; /* Read the hyperslab */ if (H5F_arr_read (f, layout, comp, efl, hslab_size, @@ -629,8 +652,9 @@ H5S_simp_write (H5F_t *f, const struct H5O_layout_t *layout, FUNC_ENTER (H5S_simp_write, FAIL); #ifndef NDEBUG - assert (file_space->type==mem_space->type); - assert (file_space->u.simple.rank==mem_space->u.simple.rank); + assert (file_space->extent.type==mem_space->extent.type); + assert (file_space->extent.u.simple.rank==mem_space->extent.u.simple.rank); +#ifdef LATER for (i=0; i<file_space->u.simple.rank; i++) { if (file_space->hslab_def && mem_space->hslab_def) { assert (1==file_space->h.stride[i]); @@ -648,46 +672,81 @@ H5S_simp_write (H5F_t *f, const struct H5O_layout_t *layout, } } #endif +#endif /* * Calculate size of hyperslab and offset of hyperslab into file and * memory. */ - if (file_space->hslab_def) { - for (i=0; i<file_space->u.simple.rank; i++) { - hslab_size[i] = file_space->h.count[i]; - } - } else { - for (i=0; i<file_space->u.simple.rank; i++) { - hslab_size[i] = file_space->u.simple.size[i]; - } - } - for (i=0; i<mem_space->u.simple.rank; i++) { - mem_size[i] = mem_space->u.simple.size[i]; - } - if (file_space->hslab_def) { - for (i=0; i<file_space->u.simple.rank; i++) { - file_offset[i] = file_space->h.start[i]; - } - } else { - for (i=0; i<file_space->u.simple.rank; i++) { - file_offset[i] = 0; - } - } - if (mem_space->hslab_def) { - for (i=0; i<mem_space->u.simple.rank; i++) { - mem_offset[i] = mem_space->h.start[i]; - } - } else { - for (i=0; i<mem_space->u.simple.rank; i++) { - mem_offset[i] = 0; - } - } - hslab_size[file_space->u.simple.rank] = elmt_size; - mem_size[file_space->u.simple.rank] = elmt_size; - file_offset[file_space->u.simple.rank] = 0; - mem_offset[file_space->u.simple.rank] = 0; + switch(file_space->select.type) { + case H5S_SEL_NONE: /* no selection defined */ + HRETURN_ERROR (H5E_DATASPACE, H5E_BADVALUE, FAIL, "selection not defined"); + + case H5S_SEL_POINTS: /* point sequence selection defined */ + case H5S_SEL_HYPERSLABS: /* hyperslab selection defined */ + HRETURN_ERROR (H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "selection type not supprted currently"); + + case H5S_SEL_ALL: /* entire dataspace selection */ + for (i=0; i<file_space->extent.u.simple.rank; i++) + hslab_size[i] = file_space->extent.u.simple.size[i]; + break; + } /* end switch */ + + switch(mem_space->select.type) { + case H5S_SEL_NONE: /* no selection defined */ + HRETURN_ERROR (H5E_DATASPACE, H5E_BADVALUE, FAIL, "selection not defined"); + + case H5S_SEL_POINTS: /* point sequence selection defined */ + case H5S_SEL_HYPERSLABS: /* hyperslab selection defined */ + HRETURN_ERROR (H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "selection type not supprted currently"); + + case H5S_SEL_ALL: /* entire dataspace selection */ + for (i=0; i<mem_space->extent.u.simple.rank; i++) + mem_size[i] = mem_space->extent.u.simple.size[i]; + break; + } /* end switch */ + + switch(file_space->select.type) { + case H5S_SEL_NONE: /* no selection defined */ + HRETURN_ERROR (H5E_DATASPACE, H5E_BADVALUE, FAIL, "selection not defined"); + + case H5S_SEL_POINTS: /* point sequence selection defined */ + case H5S_SEL_HYPERSLABS: /* hyperslab selection defined */ +#ifdef LATER + for (i=0; i<file_space->u.simple.rank; i++) + file_offset[i] = file_space->h.start[i]; +#endif + HRETURN_ERROR (H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "selection type not supprted currently"); + + case H5S_SEL_ALL: /* entire dataspace selection */ + for (i=0; i<file_space->extent.u.simple.rank; i++) + file_offset[i] = 0; + break; + } /* end switch */ + + switch(mem_space->select.type) { + case H5S_SEL_NONE: /* no selection defined */ + HRETURN_ERROR (H5E_DATASPACE, H5E_BADVALUE, FAIL, "selection not defined"); + + case H5S_SEL_POINTS: /* point sequence selection defined */ + case H5S_SEL_HYPERSLABS: /* hyperslab selection defined */ +#ifdef LATER + for (i=0; i<mem_space->u.simple.rank; i++) + mem_offset[i] = mem_space->h.start[i]; +#endif + HRETURN_ERROR (H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "selection type not supprted currently"); + + case H5S_SEL_ALL: /* entire dataspace selection */ + for (i=0; i<mem_space->extent.u.simple.rank; i++) + mem_offset[i] = 0; + break; + } /* end switch */ + + hslab_size[file_space->extent.u.simple.rank] = elmt_size; + mem_size[file_space->extent.u.simple.rank] = elmt_size; + file_offset[file_space->extent.u.simple.rank] = 0; + mem_offset[file_space->extent.u.simple.rank] = 0; /* Write the hyperslab */ if (H5F_arr_write (f, layout, comp, efl, hslab_size, @@ -699,6 +758,3 @@ H5S_simp_write (H5F_t *f, const struct H5O_layout_t *layout, FUNC_LEAVE (SUCCEED); } - - - diff --git a/src/H5TB.c b/src/H5TB.c new file mode 100644 index 0000000..627f755 --- /dev/null +++ b/src/H5TB.c @@ -0,0 +1,506 @@ +/**************************************************************************** +* NCSA HDF * +* Software Development Group * +* National Center for Supercomputing Applications * +* University of Illinois at Urbana-Champaign * +* 605 E. Springfield, Champaign IL 61820 * +* * +* For conditions of distribution and use, see the accompanying * +* hdf/COPYING file. * +* * +****************************************************************************/ + +/* + * Created: H5TB.c + * Jun 11 1998 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Temporary buffer management functions + * + * Library Public API Functions: + * H5TBget_buf - Get an ID for a temporary buffer + * H5TBbuf_ptr - Get a pointer to the temporary buffer's memory + * H5TBresize_buf - Resize a temporary buffer + * H5TBgarbage_coll- Free all unused temporary buffers + * H5TBrelease_buf - Release temporary buffer + * + * Modifications: + * + */ + +#ifdef RCSID +static char RcsId[] = "@(#)$Revision$"; +#endif + +/* $Id$ */ + +#include <H5private.h> /* Generic Functions */ +#include <H5Iprivate.h> /* ID Functions */ +#include <H5Eprivate.h> /* Error handling */ +#include <H5MMprivate.h> /* Memory Management functions */ +#include <H5TBprivate.h> /* Temporary buffer info */ + +/* Interface init/term information */ +#define PABLO_MASK H5TB_mask +#define INTERFACE_INIT H5TB_init_interface +static intn interface_initialize_g = FALSE; +static herr_t H5TB_init_interface(void); +static void H5TB_term_interface(void); + +/* Local information for managing buffers */ +#define H5TB_RESERVED_ATOMS 0 + +typedef struct tag_H5TB_t { + hbool_t inuse; /* Flag to indicate whether the buffer is in use or not */ + hsize_t size; /* Current size of the buffer */ + struct tag_H5TB_t *next; /* Pointer to next buffer in list */ + struct tag_H5TB_t *prev; /* Pointer to previous buffer in list */ + void *buf; /* Pointer to actual temporary buffer */ +} H5TB_t; + +static H5TB_t * H5TB_list_head=NULL; /* pointer to beginning of temp. buffer list (list is in order of increasing size) */ +static H5TB_t * H5TB_list_tail=NULL; /* pointer to end of temp. buffer list */ + +/* Local functions */ +herr_t H5TB_close(H5TB_t *tb); + + +/*-------------------------------------------------------------------------- +NAME + H5TB_init_interface -- Initialize interface-specific information +USAGE + herr_t H5TB_init_interface() + +RETURNS + SUCCEED/FAIL +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t +H5TB_init_interface(void) +{ + herr_t ret_value = SUCCEED; + FUNC_ENTER(H5TB_init_interface, FAIL); + + /* Initialize the atom group for the file IDs */ + if ((ret_value = H5I_init_group(H5_TEMPBUF, H5I_TEMPBUFID_HASHSIZE, + H5TB_RESERVED_ATOMS, NULL)) != FAIL) { + ret_value = H5_add_exit(&H5TB_term_interface); + } + FUNC_LEAVE(ret_value); +} + + +/*-------------------------------------------------------------------------- + NAME + H5TB_term_interface + PURPOSE + Terminate various H5TB objects + USAGE + void H5TB_term_interface() + RETURNS + SUCCEED/FAIL + DESCRIPTION + Release the atom group and any other resources allocated. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Can't report errors... + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static void +H5TB_term_interface(void) +{ + /* Destroy the atom group */ + /* Step through the list and free the buffers */ +} + +/*------------------------------------------------------------------------- + * Function: H5TB_close + * + * Purpose: Releases all memory associated with a temporary buffer. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Thursday, June 11, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t H5TB_close(H5TB_t *tb) +{ + FUNC_ENTER(H5TB_close, FAIL); + + assert(tb); + + + /* Release the main structure */ + H5MM_xfree(tb); + + FUNC_LEAVE(SUCCEED); +} + +/*-------------------------------------------------------------------------- + NAME + H5TBget_buf + PURPOSE + Get an ID for a temporary buffer + USAGE + hid_t H5TBget_buf(size,resize) + hsize_t size; IN: Minimum size of buffer requested + hbool_t resize; IN: Whether to resize an existing buffer or get a + new buffer if one doesn't match the correct size + RETURNS + Valid buffer ID on success, negative on failure + DESCRIPTION + Checks for an available temporary buffer of at least the size requested and + returns an ID for an appropriate one. If a buffer of the minimum size + requested is not available and the resize flag is set, the smallest buffer + available is resized to be the correct size and returned, otherwise a new + buffer of the correct size is allocated and returned. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hid_t H5TBget_buf(hsize_t size, hbool_t resize) +{ + hid_t ret_value = FAIL; + H5TB_t *curr=H5TB_list_head, /* pointer to current temp. buffer */ + *new; /* pointer to a newly created temp. buffer */ + + FUNC_ENTER (H5TBget_buf, FAIL); + + while(curr!=NULL) { + if(!curr->inuse && size<curr->size) + break; + curr=curr->next; + } /* end while */ + + /* Check if we found a block or not */ + if(curr!=NULL) { + curr->inuse=TRUE; + } else { + if(resize) { + curr=H5TB_list_head; /* start at beginning again */ + + /* Search for first node which isn't in use */ + while(curr!=NULL) { + if(!curr->inuse) + break; + curr=curr->next; + } /* end while */ + + /* Mark the buffer in use and resize the buffer */ + if(curr!=NULL) { + void * old_ptr=curr->buf; + + if((curr->buf = H5MM_xrealloc(curr->buf, size))==NULL) { + curr->buf=old_ptr; /* restore pointer if no memory available */ + HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "unable to allocate space for temporary buffer"); + } + curr->inuse=TRUE; + } + } /* end if */ + } /* end else */ + + /* No blocks in the list are acceptable */ + /* (either too small or not able to be resized) */ + if(curr==NULL) { + if((new=H5MM_xcalloc(1,sizeof(H5TB_t)))==NULL) + HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "unable to allocate space for temporary buffer struct"); + new->inuse=TRUE; + new->size=size; + if((new->buf=H5MM_xmalloc(size))==NULL) { + H5MM_xfree(new); /* free structure */ + HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "unable to allocate space for temporary buffer"); + } + + /* Check if this is the first node in the list */ + if(H5TB_list_head==NULL) { + H5TB_list_head=H5TB_list_tail=curr=new; + } else { + /* Find correct place to insert in list */ + for(curr=H5TB_list_head; curr!=NULL; curr=curr->next) { + /* Found node to insert before */ + if(curr->size > new->size) { + H5TB_t *tmp=curr->prev; /* temporary pointer */ + + /* Inserting at head of list */ + if(tmp==NULL) { + H5TB_list_head=new; + new->next=curr; + curr->prev=new; + } else { + tmp->next=new; + new->prev=tmp; + curr->prev=new; + new->next=curr; + } /* end else */ + + /* set this so we can fall through to getting the ID */ + curr=new; + } /* end if */ + } /* end for */ + + /* Add to end of list */ + if(curr==NULL) { + curr=H5TB_list_tail; + H5TB_list_tail=curr->next=new; + new->prev=curr; + } /* end if */ + + /* set this so we can fall through to getting the ID */ + curr=new; + } /* end else */ + } /* end if */ + + /* Atomize */ + if ((ret_value=H5I_register (H5_TEMPBUF, curr))<0) { + HGOTO_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register temp. buffer atom"); + } + +done: + if (ret_value < 0) { + } + FUNC_LEAVE(ret_value); +} /* H5TBget_buf() */ + +/*-------------------------------------------------------------------------- + NAME + H5TBbuf_ptr + PURPOSE + Get the pointer to a temp. buffer memory + USAGE + void *H5TBbuf_ptr(tbid) + hid_t tbid; IN: Temp. buffer ID + RETURNS + Non-NULL pointer to buffer memory on success, NULL on failure + DESCRIPTION + Gets the pointer to a temp. buffer's memory. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +void *H5TBbuf_ptr(hid_t tbid) +{ + void *ret_value = NULL; + H5TB_t *tbuf; /* Pointer to temporary buffer */ + + FUNC_ENTER (H5TBbuf_ptr, NULL); + + if (H5_TEMPBUF != H5I_group(tbid) || + NULL == (tbuf = H5I_object(tbid))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a temp. buffer"); + } + + ret_value=tbuf->buf; + +#ifdef LATER +done: +#endif + if (ret_value == NULL) { + } + FUNC_LEAVE(ret_value); +} /* H5TBbuf_ptr() */ + +/*-------------------------------------------------------------------------- + NAME + H5TBresize_ptr + PURPOSE + Resize a temp. buffer to a new size + USAGE + herr_t H5TBresize_ptr(tbid, size) + hid_t tbid; IN: Temp. buffer ID to resize + hsize_t size; IN: New size of temp. buffer + RETURNS + non-negative on success, negative on failure + DESCRIPTION + Resizes a temporary buffer to a new size. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t H5TBresize_ptr(hid_t tbid, hsize_t size) +{ + herr_t ret_value = FAIL; + H5TB_t *tbuf, /* Pointer to temporary buffer */ + *curr; /* Pointer to temp. buffer node */ + void * old_ptr; /* Pointer to the previous buffer */ + + FUNC_ENTER (H5TBresize_ptr, FAIL); + + if (H5_TEMPBUF != H5I_group(tbid) || + NULL == (tbuf = H5I_object(tbid))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a temp. buffer"); + } + + /* Save old pointer for later */ + old_ptr=tbuf->buf; + + /* Try to resize buffer to new size */ + if((tbuf->buf = H5MM_xrealloc(tbuf->buf, size))==NULL) { + tbuf->buf=old_ptr; /* restore pointer if no memory available */ + HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, + "unable to allocate space for temporary buffer"); + } + + /* Change the size of the buffer */ + tbuf->size=size; + + /* + * Check if we need to move the buffer in the sorted list + */ + + /* Check if this is not the last node and it need's to move */ + if(tbuf->next!=NULL && tbuf->next->size < tbuf->size) { + /* Remove this node from the list */ + if(tbuf->prev==NULL) { /* remove from head of list */ + H5TB_list_head=tbuf->next; + tbuf->next->prev=NULL; + } else { /* remove from middle of list */ + tbuf->prev->next=tbuf->next; + tbuf->next->prev=tbuf->prev; + } /* end if */ + + /* Find correct position in list */ + curr=H5TB_list_head; + while(curr!=NULL) { + if(!curr->inuse && size<curr->size) + break; + curr=curr->next; + } /* end while */ + + /* Insert into correct position in list */ + if(curr!=NULL) { /* can't be adding to the beginning of list, so this is in the middle somewhere */ + curr->prev->next=tbuf; + tbuf->prev=curr->prev; + curr->prev=tbuf; + tbuf->next=curr; + } else { /* append to end of list */ + H5TB_list_tail->next=tbuf; + tbuf->prev=H5TB_list_tail; + tbuf->next=NULL; + H5TB_list_tail=tbuf; + } /* end else */ + } /* end if */ + +#ifdef LATER +done: +#endif + if (ret_value == FAIL) { + } + FUNC_LEAVE(ret_value); +} /* H5TBresize_ptr() */ + +/*-------------------------------------------------------------------------- + NAME + H5TBgarbage_coll + PURPOSE + Release all unused temporary buffers + USAGE + herr_t H5TBgarbase_coll() + RETURNS + non-negative on success, negative on failure + DESCRIPTION + Steps through the list of temporary buffers, removing unused nodes from the + list and freeing their memory + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t H5TBgarbage_coll(void) +{ + herr_t ret_value = FAIL; + H5TB_t *curr,*next; /* Current temp. buffer node */ + + FUNC_ENTER (H5TBgarbage_coll, FAIL); + + /* Step through the list, remove each unused node, repair the list and free the node */ + curr=H5TB_list_head; + while(curr!=NULL) { + next=curr->next; + if(!curr->inuse) { + /* maintain list head & tail */ + if(H5TB_list_head==curr) + H5TB_list_head=curr->next; + if(H5TB_list_tail==curr) + H5TB_list_tail=curr->prev; + + /* Delete node from list */ + if(curr->prev!=NULL) + curr->prev->next=curr->next; + if(curr->next!=NULL) + curr->next->prev=curr->prev; + + /* Free memory for node */ + if(curr->buf!=NULL) + H5MM_xfree(curr->buf); + H5MM_xfree(curr); + } /* end if */ + curr=next; + } /* end while */ + + ret_value=SUCCEED; + +#ifdef LATER +done: +#endif + if (ret_value == FAIL) { + } + FUNC_LEAVE(ret_value); +} /* H5TBgarbage_coll() */ + +/*-------------------------------------------------------------------------- + NAME + H5TBrelease_buf + PURPOSE + Release a temp. buffer back to the list of unused ones. + USAGE + herr_t H5TBrelease_buf(tbid) + hid_t tbid; IN: Temp. buffer ID to release + RETURNS + non-negative on success, negative on failure + DESCRIPTION + Releases a temporary buffer. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t H5TBrelease_buf(hid_t tbid) +{ + herr_t ret_value = FAIL; + H5TB_t *tbuf; /* Pointer to temporary buffer */ + + FUNC_ENTER (H5TBresize_ptr, FAIL); + + if (H5_TEMPBUF != H5I_group(tbid) || + NULL == (tbuf = H5I_object(tbid))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a temp. buffer"); + } + + /* Release the buffer */ + tbuf->inuse=FALSE; + + ret_value=SUCCEED; + +#ifdef LATER +done: +#endif + if (ret_value == FAIL) { + } + FUNC_LEAVE(ret_value); +} /* H5TBresize_ptr() */ + diff --git a/src/H5TBprivate.h b/src/H5TBprivate.h new file mode 100644 index 0000000..2d48b1c --- /dev/null +++ b/src/H5TBprivate.h @@ -0,0 +1,26 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* + * This file contains private information about the H5TB module + */ +#ifndef _H5TBprivate_H +#define _H5TBprivate_H + +/* Functions defined in H5TB.c */ +hid_t H5TBget_buf(hsize_t size, hbool_t resize); +void *H5TBbuf_ptr(hid_t tbid); +herr_t H5TBresize_ptr(hid_t tbid, hsize_t size); +herr_t H5TBgarbage_coll(void); +herr_t H5TBrelease_buf(hid_t tbid); + +#endif @@ -410,6 +410,16 @@ H5V_hyper_copy(intn n, const hsize_t *_size, assert(src_size[i] > 0); } #endif +#ifdef QAK +{ + intn i; + + printf("%s: n=%d, _dst=%p, _src=%p\n",FUNC,(int)n,_dst,_src); + for(i=0; i<n; i++) { + printf("%d: size=%d, dst_size=%d, dst_offset=%d, src_size=%d, src_offset=%d\n",i,(int)size[i],(int)dst_size[i],(int)dst_offset[i],(int)src_size[i],(int)src_offset[i]); + } /* end for */ +} +#endif /* QAK */ /* Copy the size vector so we can modify it */ H5V_vector_cpy(n, size, _size); @@ -610,3 +620,59 @@ H5V_stride_copy2(hsize_t nelmts, hsize_t elmt_size, FUNC_LEAVE(SUCCEED); } + +/*------------------------------------------------------------------------- + * Function: H5V_array_fill + * + * Purpose: Fills all bytes of an array with the same value using memset(). + * Increases amount copied by power of two until the halfway point is + * crossed, then copies the rest in one swoop. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Quincey Koziol + * Thursday, June 18, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5V_array_fill(void *_dst, const void *src, size_t size, size_t count) +{ + size_t copy_size; /* size of the buffer to copy */ + size_t copy_items; /* number of items currently copying */ + size_t items_left; /* number of items left to copy */ + uint8 *dst=(uint8 *)_dst; /* alias for pointer arithmetic */ + + FUNC_ENTER(H5V_array_fill, FAIL); + assert (dst); + assert (src); + assert (size < MAX_SIZET && size > 0); + assert (count < MAX_SIZET && count > 0); + + HDmemcpy(dst, src, size); /* copy first item */ + + /* Initialize counters, etc. while compensating for first element copied */ + copy_size = size; + copy_items = 1; + items_left = count - 1; + dst += size; + + /* copy until we've copied at least half of the items */ + while (items_left >= copy_items) + { + HDmemcpy(dst, _dst, copy_size); /* copy the current chunk */ + dst += copy_size; /* move the offset for the next chunk */ + items_left -= copy_items; /* decrement the number of items left */ + + copy_size *= 2; /* increase the size of the chunk to copy */ + copy_items *= 2; /* increase the count of items we are copying */ + } /* end while */ + if (items_left > 0) /* if there are any items left to copy */ + HDmemcpy(dst, _dst, items_left * size); + + FUNC_LEAVE(SUCCEED); +} /* H5V_array_fill() */ diff --git a/src/H5Vprivate.h b/src/H5Vprivate.h index 64f085a..895a240 100644 --- a/src/H5Vprivate.h +++ b/src/H5Vprivate.h @@ -62,6 +62,7 @@ herr_t H5V_stride_optimize1(intn *np, hsize_t *elmt_size, hsize_t *size, hssize_t *stride1); herr_t H5V_stride_optimize2(intn *np, hsize_t *elmt_size, hsize_t *size, hssize_t *stride1, hssize_t *stride2); +herr_t H5V_array_fill(void *_dst, const void *src, size_t size, size_t count); /*------------------------------------------------------------------------- diff --git a/src/H5public.h b/src/H5public.h index 0f2aebf..6f1eb0b 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -27,7 +27,7 @@ /* Version numbers */ #define H5_VERS_MAJOR 1 /* For major interface changes */ #define H5_VERS_MINOR 0 /* For minor interface changes */ -#define H5_VERS_RELEASE 2 /* For interface tweaks & bug-fixes */ +#define H5_VERS_RELEASE 8 /* For interface tweaks & bug-fixes */ #define H5_VERS_PATCH 0 /* For small groups of bug fixes */ #define H5check() H5vers_check(H5_VERS_MAJOR,H5_VERS_MINOR,\ diff --git a/src/Makefile.in b/src/Makefile.in index eb054b4..604e347 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -16,11 +16,12 @@ PROGS=debug h5ls h5repart # Source and object files for the library (lexicographically)... LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5D.c H5E.c H5F.c H5Farray.c H5Fcore.c \ - H5Ffamily.c H5Fistore.c H5Flow.c H5Fmpio.c H5Fsec2.c H5Fsplit.c \ - H5Fstdio.c H5G.c H5Gent.c H5Gnode.c H5Gstab.c H5HG.c H5HL.c H5I.c H5MF.c \ - H5MM.c H5O.c H5Oattr.c H5Ocomp.c H5Ocont.c H5Odtype.c H5Oefl.c \ - H5Olayout.c H5Oname.c H5Onull.c H5Osdspace.c H5Oshared.c H5Ostab.c H5P.c \ - H5S.c H5Ssimp.c H5T.c H5Tbit.c H5Tconv.c H5Tinit.c H5V.c H5Z.c + H5Ffamily.c H5Fistore.c H5Flow.c H5Fmpio.c H5Fsec2.c H5Fsplit.c H5Fstdio.c \ + H5G.c H5Gent.c H5Gnode.c H5Gstab.c H5HG.c H5HL.c H5I.c H5MF.c H5MM.c H5O.c \ + H5Oattr.c H5Ocomp.c H5Ocont.c H5Odtype.c H5Oefl.c H5Olayout.c H5Oname.c \ + H5Onull.c H5Osdspace.c H5Oshared.c H5Ostab.c H5P.c H5S.c H5Sall.c \ + H5Shyper.c H5Spoint.c H5Ssimp.c H5Sselect.c H5T.c H5Tbit.c H5Tconv.c \ + H5Tinit.c H5TB.c H5V.c H5Z.c LIB_OBJ=$(LIB_SRC:.c=.o) @@ -41,8 +42,8 @@ PUB_HDR=H5public.h H5Apublic.h H5ACpublic.h H5Bpublic.h H5Ppublic.h \ PRIVATE_HDR=H5private.h H5Aprivate.h H5Apkg.h H5ACprivate.h H5Bprivate.h \ H5Pprivate.h H5Dprivate.h H5Dpkg.h H5Eprivate.h H5Fprivate.h H5Gprivate.h \ H5Gpkg.h H5HGprivate.h H5HLprivate.h H5Iprivate.h H5MFprivate.h \ - H5MMprivate.h H5Oprivate.h H5Sprivate.h H5Tprivate.h H5Tpkg.h \ - H5Vprivate.h H5Zprivate.h + H5MMprivate.h H5Oprivate.h H5Sprivate.h H5Tprivate.h H5TBprivate.h \ + H5Tpkg.h H5Vprivate.h H5Zprivate.h # Number format detection H5Tinit.c: H5detect |