summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNeil Fortner <nfortne2@hdfgroup.org>2015-04-21 22:42:33 (GMT)
committerNeil Fortner <nfortne2@hdfgroup.org>2015-04-21 22:42:33 (GMT)
commit0a3151792fed6457cbd8092018b891f7f2b9653e (patch)
tree669b2259efc2ce8c79e0563db08265e3904b48b9 /src
parentb31103b33225c39fe0ddaa0c3fa1cdaae64f7cbc (diff)
downloadhdf5-0a3151792fed6457cbd8092018b891f7f2b9653e.zip
hdf5-0a3151792fed6457cbd8092018b891f7f2b9653e.tar.gz
hdf5-0a3151792fed6457cbd8092018b891f7f2b9653e.tar.bz2
[svn-r26878] Fix errors in unlimited selection serialize/deserialize
Other minor fixes Tested: jam
Diffstat (limited to 'src')
-rw-r--r--src/H5Olayout.c4
-rw-r--r--src/H5R.c2
-rw-r--r--src/H5S.c18
-rw-r--r--src/H5Sall.c4
-rw-r--r--src/H5Shyper.c83
-rw-r--r--src/H5Snone.c4
-rw-r--r--src/H5Spkg.h4
-rw-r--r--src/H5Spoint.c4
-rw-r--r--src/H5Sprivate.h6
-rw-r--r--src/H5Sselect.c13
10 files changed, 75 insertions, 67 deletions
diff --git a/src/H5Olayout.c b/src/H5Olayout.c
index b3987e8..a20b6d4 100644
--- a/src/H5Olayout.c
+++ b/src/H5Olayout.c
@@ -473,12 +473,12 @@ H5O_layout_encode(H5F_t *f, hbool_t UNUSED disable_shared, uint8_t *p, const voi
block_size += str_size[(2 * i) + 1];
/* Source selection */
- if((select_serial_size = H5S_SELECT_SERIAL_SIZE(mesg->storage.u.virt.list[i].source_select)) < 0)
+ if((select_serial_size = H5S_SELECT_SERIAL_SIZE(f, mesg->storage.u.virt.list[i].source_select)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to check dataspace selection size")
block_size += (size_t)select_serial_size;
/* Virtual dataset selection */
- if((select_serial_size = H5S_SELECT_SERIAL_SIZE(mesg->storage.u.virt.list[i].virtual_select)) < 0)
+ if((select_serial_size = H5S_SELECT_SERIAL_SIZE(f, mesg->storage.u.virt.list[i].virtual_select)) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to check dataspace selection size")
block_size += (size_t)select_serial_size;
} /* end for */
diff --git a/src/H5R.c b/src/H5R.c
index aa819f2..c9474c7 100644
--- a/src/H5R.c
+++ b/src/H5R.c
@@ -275,7 +275,7 @@ H5R_create(void *_ref, H5G_loc_t *loc, const char *name, H5R_type_t ref_type, H5
HDmemset(ref, 0, H5R_DSET_REG_REF_BUF_SIZE);
/* Get the amount of space required to serialize the selection */
- if((buf_size = H5S_SELECT_SERIAL_SIZE(space)) < 0)
+ if((buf_size = H5S_SELECT_SERIAL_SIZE(loc->oloc->file, space)) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTINIT, FAIL, "Invalid amount of space for serializing selection")
/* Increase buffer size to allow for the dataset OID */
diff --git a/src/H5S.c b/src/H5S.c
index 57e3b86..e24879c 100644
--- a/src/H5S.c
+++ b/src/H5S.c
@@ -52,8 +52,6 @@
/********************/
/* Local Prototypes */
/********************/
-static herr_t H5S_set_extent_simple (H5S_t *space, unsigned rank,
- const hsize_t *dims, const hsize_t *max);
static htri_t H5S_is_simple(const H5S_t *sdim);
static herr_t H5S_encode(H5S_t *obj, unsigned char *buf, size_t *nalloc);
static H5S_t *H5S_decode(const unsigned char *buf);
@@ -1278,7 +1276,7 @@ H5Sset_extent_simple(hid_t space_id, int rank, const hsize_t dims[/*rank*/],
}
/* Do it */
- if (H5S_set_extent_simple(space, (unsigned)rank, dims, max)<0)
+ if (H5S__set_extent_simple(space, (unsigned)rank, dims, max)<0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set simple extent")
done:
@@ -1287,7 +1285,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5S_set_extent_simple
+ * Function: H5S__set_extent_simple
*
* Purpose: This is where the real work happens for
* H5Sset_extent_simple().
@@ -1301,14 +1299,14 @@ done:
*
*-------------------------------------------------------------------------
*/
-static herr_t
-H5S_set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims,
+herr_t
+H5S__set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims,
const hsize_t *max)
{
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT
+ FUNC_ENTER_PACKAGE
/* Check args */
HDassert(rank <= H5S_MAX_RANK);
@@ -1370,7 +1368,7 @@ H5S_set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims,
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5S_set_extent_simple() */
+} /* H5S__set_extent_simple() */
/*-------------------------------------------------------------------------
@@ -1481,7 +1479,7 @@ H5S_create_simple(unsigned rank, const hsize_t dims[/*rank*/],
/* Create the space and set the extent */
if(NULL==(ret_value=H5S_create(H5S_SIMPLE)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "can't create simple dataspace")
- if(H5S_set_extent_simple(ret_value,rank,dims,maxdims)<0)
+ if(H5S__set_extent_simple(ret_value,rank,dims,maxdims)<0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "can't set dimensions")
done:
@@ -1564,7 +1562,7 @@ H5S_encode(H5S_t *obj, unsigned char *buf, size_t *nalloc)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADSIZE, FAIL, "can't find dataspace size")
/* Find out the size of buffer needed for selection */
- if((sselect_size = H5S_SELECT_SERIAL_SIZE(obj)) < 0)
+ if((sselect_size = H5S_SELECT_SERIAL_SIZE(f, obj)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADSIZE, FAIL, "can't find dataspace selection size")
H5_ASSIGN_OVERFLOW(select_size, sselect_size, hssize_t, size_t);
diff --git a/src/H5Sall.c b/src/H5Sall.c
index 505e4cf..cb7e6f2 100644
--- a/src/H5Sall.c
+++ b/src/H5Sall.c
@@ -38,7 +38,7 @@ static herr_t H5S_all_get_seq_list(const H5S_t *space, unsigned flags,
size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
static herr_t H5S_all_release(H5S_t *space);
static htri_t H5S_all_is_valid(const H5S_t *space);
-static hssize_t H5S_all_serial_size(const H5S_t *space);
+static hssize_t H5S_all_serial_size(const H5F_t *f, const H5S_t *space);
static herr_t H5S_all_serialize(const H5F_t *f, const H5S_t *space,
uint8_t **p);
static herr_t H5S_all_deserialize(const H5F_t *f, H5S_t *space,
@@ -478,7 +478,7 @@ H5S_all_is_valid (const H5S_t UNUSED *space)
REVISION LOG
--------------------------------------------------------------------------*/
static hssize_t
-H5S_all_serial_size (const H5S_t UNUSED *space)
+H5S_all_serial_size(const H5F_t UNUSED *f, const H5S_t UNUSED *space)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index 32b6fe9..0886b23 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -53,7 +53,7 @@ static herr_t H5S_hyper_get_seq_list(const H5S_t *space, unsigned flags,
size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
static herr_t H5S_hyper_release(H5S_t *space);
static htri_t H5S_hyper_is_valid(const H5S_t *space);
-static hssize_t H5S_hyper_serial_size(const H5S_t *space);
+static hssize_t H5S_hyper_serial_size(const H5F_t *f, const H5S_t *space);
static herr_t H5S_hyper_serialize(const H5F_t *f, const H5S_t *space,
uint8_t **p);
static herr_t H5S_hyper_deserialize(const H5F_t *f, H5S_t *space,
@@ -1976,7 +1976,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static hssize_t
-H5S_hyper_serial_size(const H5S_t *space)
+H5S_hyper_serial_size(const H5F_t *f, const H5S_t *space)
{
unsigned u; /* Counter */
hsize_t block_count; /* block counter for regular hyperslabs */
@@ -1986,24 +1986,41 @@ H5S_hyper_serial_size(const H5S_t *space)
HDassert(space);
- /* Basic number of bytes required to serialize hyperslab selection:
- * <type (4 bytes)> + <version (4 bytes)> + <padding (4 bytes)> +
- * <length (4 bytes)> + <rank (4 bytes)> + <# of blocks (4 bytes)> = 24 bytes
- */
- ret_value = 24;
+ /* Check for version (right now, an unlimited dimension is the only thing
+ * that would bump the version) */
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ /* Version 2 */
+ /* Size required is always:
+ * <type (4 bytes)> + <version (4 bytes)> + <flags (1 byte)> +
+ * <length (4 bytes)> + <rank (4 bytes)> +
+ * (4 * <rank> * <start/stride/count/block (sizeof_size bytes)>) =
+ * 17 + (4 * sizeof_size) bytes
+ */
+ ret_value = (hssize_t)17 + ((hssize_t)4 * (hssize_t)space->extent.rank
+ * (hssize_t)H5F_SIZEOF_SIZE(f));
+ else {
+ /* Version 1 */
+ /* Basic number of bytes required to serialize hyperslab selection:
+ * <type (4 bytes)> + <version (4 bytes)> + <padding (4 bytes)> +
+ * <length (4 bytes)> + <rank (4 bytes)> + <# of blocks (4 bytes)>
+ * = 24 bytes
+ */
+ ret_value = 24;
- /* Check for a "regular" hyperslab selection */
- if(space->select.sel_info.hslab->diminfo_valid) {
- /* Check each dimension */
- for(block_count = 1, u = 0; u < space->extent.rank; u++)
- block_count *= space->select.sel_info.hslab->opt_diminfo[u].count;
- } /* end if */
- else
- /* Spin through hyperslab spans, adding 8 * rank bytes for each block */
- block_count = H5S_hyper_span_nblocks(space->select.sel_info.hslab->span_lst);
+ /* Check for a "regular" hyperslab selection */
+ if(space->select.sel_info.hslab->diminfo_valid) {
+ /* Check each dimension */
+ for(block_count = 1, u = 0; u < space->extent.rank; u++)
+ block_count *= space->select.sel_info.hslab->opt_diminfo[u].count;
+ } /* end if */
+ else
+ /* Spin through hyperslab spans, adding 8 * rank bytes for each
+ * block */
+ block_count = H5S_hyper_span_nblocks(space->select.sel_info.hslab->span_lst);
- H5_CHECK_OVERFLOW((8 * space->extent.rank * block_count), hsize_t, hssize_t);
- ret_value += (hssize_t)(8 * block_count * space->extent.rank);
+ H5_CHECK_OVERFLOW((8 * space->extent.rank * block_count), hsize_t, hssize_t);
+ ret_value += (hssize_t)(8 * block_count * space->extent.rank);
+ } /* end else */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_hyper_serial_size() */
@@ -2339,29 +2356,15 @@ H5S_hyper_deserialize(const H5F_t *f, H5S_t *space, uint32_t UNUSED version,
/* Iterate over dimensions */
for(i = 0; i < space->extent.rank; i++) {
/* Decode start/stride/block/count */
- H5F_size_decode(f, p, &space->select.sel_info.hslab->opt_unlim_diminfo[i].start);
- H5F_size_decode(f, p, &space->select.sel_info.hslab->opt_unlim_diminfo[i].stride);
- H5F_size_decode(f, p, &space->select.sel_info.hslab->opt_unlim_diminfo[i].count);
- if(space->select.sel_info.hslab->opt_unlim_diminfo[i].count == H5S_UNLIMITED) {
- if(space->select.sel_info.hslab->unlim_dim >= 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot have more than one unlimited dimension in selection")
- space->select.sel_info.hslab->unlim_dim = (int)i;
- } /* end if */
- H5F_size_decode(f, p, &space->select.sel_info.hslab->opt_unlim_diminfo[i].block);
- if(space->select.sel_info.hslab->opt_unlim_diminfo[i].block == H5S_UNLIMITED) {
- if(space->select.sel_info.hslab->unlim_dim >= 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot have more than one unlimited dimension in selection")
- space->select.sel_info.hslab->unlim_dim = (int)i;
- } /* end if */
+ H5F_size_decode(f, p, &start[i]);
+ H5F_size_decode(f, p, &stride[i]);
+ H5F_size_decode(f, p, &count[i]);
+ H5F_size_decode(f, p, &block[i]);
} /* end for */
- /* Copy opt_unlim_diminfo to app_diminfo */
- HDassert(sizeof(space->select.sel_info.hslab->app_diminfo) == sizeof(space->select.sel_info.hslab->opt_unlim_diminfo));
- HDmemcpy(space->select.sel_info.hslab->app_diminfo, space->select.sel_info.hslab->opt_unlim_diminfo, sizeof(space->select.sel_info.hslab->app_diminfo));
-
- /* Update selection due to match current extent */
- if(H5S__hyper_update_extent_offset(space) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't update hyperslab")
+ /* Select the hyperslab to the current selection */
+ if((ret_value = H5S_select_hyperslab(space, H5S_SELECT_SET, start, stride, count, block)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
} /* end if */
else {
/* decode the number of points */
@@ -9546,7 +9549,7 @@ H5S__hyper_update_extent_offset(H5S_t *space)
/* Check for single block in unlimited dimension */
if(hslab->opt_diminfo[hslab->unlim_dim].count == (hsize_t)1) {
- HDassert(hslab->opt_diminfo[hslab->unlim_dim].block = H5S_UNLIMITED);
+ HDassert(hslab->opt_diminfo[hslab->unlim_dim].block == H5S_UNLIMITED);
/* Calculate actual block size for this extent */
hslab->opt_diminfo[hslab->unlim_dim].block =
diff --git a/src/H5Snone.c b/src/H5Snone.c
index 28c1ffb..11c4912 100644
--- a/src/H5Snone.c
+++ b/src/H5Snone.c
@@ -39,7 +39,7 @@ static herr_t H5S_none_get_seq_list(const H5S_t *space, unsigned flags,
size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
static herr_t H5S_none_release(H5S_t *space);
static htri_t H5S_none_is_valid(const H5S_t *space);
-static hssize_t H5S_none_serial_size(const H5S_t *space);
+static hssize_t H5S_none_serial_size(const H5F_t *f, const H5S_t *space);
static herr_t H5S_none_serialize(const H5F_t *f, const H5S_t *space,
uint8_t **p);
static herr_t H5S_none_deserialize(const H5F_t *f, H5S_t *space,
@@ -446,7 +446,7 @@ H5S_none_is_valid(const H5S_t UNUSED *space)
REVISION LOG
--------------------------------------------------------------------------*/
static hssize_t
-H5S_none_serial_size(const H5S_t UNUSED *space)
+H5S_none_serial_size(const H5F_t UNUSED *f, const H5S_t UNUSED *space)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
diff --git a/src/H5Spkg.h b/src/H5Spkg.h
index c8993dc..e28c118 100644
--- a/src/H5Spkg.h
+++ b/src/H5Spkg.h
@@ -140,7 +140,7 @@ typedef herr_t (*H5S_sel_release_func_t)(H5S_t *space);
/* Method to determine if current selection is valid for dataspace */
typedef htri_t (*H5S_sel_is_valid_func_t)(const H5S_t *space);
/* Method to determine number of bytes required to store current selection */
-typedef hssize_t (*H5S_sel_serial_size_func_t)(const H5S_t *space);
+typedef hssize_t (*H5S_sel_serial_size_func_t)(const H5F_t *f, const H5S_t *space);
/* Method to store current selection in "serialized" form (a byte sequence suitable for storing on disk) */
typedef herr_t (*H5S_sel_serialize_func_t)(const H5F_t *f, const H5S_t *space,
uint8_t **p);
@@ -258,6 +258,8 @@ H5_DLLVAR const H5S_select_class_t H5S_sel_none[1];
H5_DLLVAR const H5S_select_class_t H5S_sel_point[1];
/* Extent functions */
+H5_DLL herr_t H5S__set_extent_simple(H5S_t *space, unsigned rank,
+ const hsize_t *dims, const hsize_t *max);
H5_DLL herr_t H5S_extent_release(H5S_extent_t *extent);
H5_DLL herr_t H5S_extent_copy_real(H5S_extent_t *dst, const H5S_extent_t *src,
hbool_t copy_max);
diff --git a/src/H5Spoint.c b/src/H5Spoint.c
index 66fbb03..a7421de 100644
--- a/src/H5Spoint.c
+++ b/src/H5Spoint.c
@@ -40,7 +40,7 @@ static herr_t H5S_point_get_seq_list(const H5S_t *space, unsigned flags,
size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
static herr_t H5S_point_release(H5S_t *space);
static htri_t H5S_point_is_valid(const H5S_t *space);
-static hssize_t H5S_point_serial_size(const H5S_t *space);
+static hssize_t H5S_point_serial_size(const H5F_t *f, const H5S_t *space);
static herr_t H5S_point_serialize(const H5F_t *f, const H5S_t *space,
uint8_t **p);
static herr_t H5S_point_deserialize(const H5F_t *f, H5S_t *space,
@@ -773,7 +773,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static hssize_t
-H5S_point_serial_size (const H5S_t *space)
+H5S_point_serial_size(const H5F_t UNUSED *f, const H5S_t *space)
{
H5S_pnt_node_t *curr; /* Point information nodes */
hssize_t ret_value; /* return value */
diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h
index d037b03..8f9b530 100644
--- a/src/H5Sprivate.h
+++ b/src/H5Sprivate.h
@@ -125,7 +125,7 @@ typedef struct H5S_sel_iter_t {
#define H5S_SELECT_GET_SEQ_LIST(S,FLAGS,ITER,MAXSEQ,MAXBYTES,NSEQ,NBYTES,OFF,LEN) ((*(S)->select.type->get_seq_list)(S,FLAGS,ITER,MAXSEQ,MAXBYTES,NSEQ,NBYTES,OFF,LEN))
#define H5S_SELECT_VALID(S) ((*(S)->select.type->is_valid)(S))
#define H5S_SELECT_RELEASE(S) ((*(S)->select.type->release)(S))
-#define H5S_SELECT_SERIAL_SIZE(S) ((*(S)->select.type->serial_size)(S))
+#define H5S_SELECT_SERIAL_SIZE(F,S) ((*(S)->select.type->serial_size)(F,S))
#define H5S_SELECT_SERIALIZE(F,S,BUF) ((*(S)->select.type->serialize)(F,S,BUF))
#define H5S_SELECT_BOUNDS(S,START,END) ((*(S)->select.type->bounds)(S,START,END))
#define H5S_SELECT_OFFSET(S, OFFSET) ((*(S)->select.type->offset)(S, OFFSET))
@@ -151,7 +151,7 @@ typedef struct H5S_sel_iter_t {
#define H5S_SELECT_GET_SEQ_LIST(S,FLAGS,ITER,MAXSEQ,MAXBYTES,NSEQ,NBYTES,OFF,LEN) (H5S_select_get_seq_list(S,FLAGS,ITER,MAXSEQ,MAXBYTES,NSEQ,NBYTES,OFF,LEN))
#define H5S_SELECT_VALID(S) (H5S_select_valid(S))
#define H5S_SELECT_RELEASE(S) (H5S_select_release(S))
-#define H5S_SELECT_SERIAL_SIZE(S) (H5S_select_serial_size(S))
+#define H5S_SELECT_SERIAL_SIZE(F,S) (H5S_select_serial_size(F,S))
#define H5S_SELECT_SERIALIZE(F,S,BUF) (H5S_select_serialize(F,S,BUF))
#define H5S_SELECT_BOUNDS(S,START,END) (H5S_get_select_bounds(S,START,END))
#define H5S_SELECT_OFFSET(S, OFFSET) (H5S_get_select_offset(S, OFFSET))
@@ -228,7 +228,7 @@ H5_DLL herr_t H5S_select_release(H5S_t *ds);
H5_DLL herr_t H5S_select_get_seq_list(const H5S_t *space, unsigned flags,
H5S_sel_iter_t *iter, size_t maxseq, size_t maxbytes,
size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
-H5_DLL hssize_t H5S_select_serial_size(const H5S_t *space);
+H5_DLL hssize_t H5S_select_serial_size(const H5F_t *f, const H5S_t *space);
H5_DLL herr_t H5S_select_serialize(const H5F_t *f, const H5S_t *space,
uint8_t **p);
H5_DLL htri_t H5S_select_is_contiguous(const H5S_t *space);
diff --git a/src/H5Sselect.c b/src/H5Sselect.c
index a703cc3..52273c7 100644
--- a/src/H5Sselect.c
+++ b/src/H5Sselect.c
@@ -227,7 +227,7 @@ H5S_select_get_seq_list(const H5S_t *space, unsigned flags,
*-------------------------------------------------------------------------
*/
hssize_t
-H5S_select_serial_size(const H5S_t *space)
+H5S_select_serial_size(const H5F_t *f, const H5S_t *space)
{
hssize_t ret_value; /* Return value */
@@ -236,7 +236,7 @@ H5S_select_serial_size(const H5S_t *space)
HDassert(space);
/* Call the selection type's serial_size function */
- ret_value=(*space->select.type->serial_size)(space);
+ ret_value=(*space->select.type->serial_size)(f, space);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_select_serial_size() */
@@ -508,9 +508,14 @@ H5S_select_deserialize(const H5F_t *f, H5S_t **space, const uint8_t **p)
/* Decode the rank of the point selection */
UINT32DECODE(*p,rank);
- if(!*space)
+ if(!*space) {
+ hsize_t dims[H5S_MAX_RANK];
+
/* Patch the rank of the allocated dataspace */
- tmp_space->extent.rank = rank;
+ (void)HDmemset(dims, 0, (size_t)rank * sizeof(dims[0]));
+ if(H5S__set_extent_simple(tmp_space, rank, dims, NULL) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set dimensions")
+ } /* end if */
else
/* Verify the rank of the provided dataspace */
if(rank != tmp_space->extent.rank)