int
saf_get_attribute(SAF_ParMode pmode, /* One of the parallel modes. */
ss_pers_t *obj, /* The handle to the object from which the attribute will be read. */
const char *name, /* The name of the attribute. See SAF_ATT_NAMES and other reserved attribute names
* for special kinds of attribute queries. */
hid_t *type, /* IN[OUT] If TYPE is NULL, this argument will be ignored. If TYPE points
* to a valid datatype, then the attribute will be converted to the specified type as
* it is read. If it does not, there will be *no*data*conversion* and the output value
* will be the datatype of the data returned (the caller should invoke H5Tclose()). */
int *count, /* [OUT] The number of items in the attribute. If COUNT is NULL, then the value of
* COUNT will not be returned. */
void **value /* IN[OUT] Points to an array of COUNT values each having datatype
* TYPE. If VALUE is NULL, then no attribute values will be returned. If
* VALUE points to NULL, then the library will allocate the array of values which is
* returned. Otherwise the library assumes that VALUE
* points to an array whose size is sufficient for storing COUNT values of datatype
* TYPE. That is, if VALUE is pointing to non-NULL, then so must COUNT point to non-NULL
* *and* the value pointed to by COUNT will be used by SAF as the size, in items of type
* TYPE, of the block of memory pointed to by VALUE. For a SAF_ATT_NAMES query if the
* caller supplies a buffer for this argument then it should be a buffer of !char
* pointers, the values of which will be allocated by this function. */
)
{
SAF_ENTER(saf_get_attribute, SAF_PRECONDITION_ERROR);
ss_attr_t attr, *attrs=NULL;
size_t nfound, my_count=SS_NOSIZE, i, maxfind;
hid_t stored_type=-1;
SAF_REQUIRE(_saf_valid_pmode(pmode), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("PMODE must be valid"));
if (!_saf_is_participating_proc(pmode)) SAF_RETURN(-1);
SAF_REQUIRE(name != NULL, SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR, _saf_errmsg("NAME must not be null"));
SAF_REQUIRE(_saf_valid_memhints(count, (void**)value), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("COUNT and VALUE must be compatible for return value allocation"));
SAF_REQUIRE(obj != NULL, SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR, _saf_errmsg("OBJ must not be null"));
if (!strcmp(name, SAF_ATT_COUNT)) {
/* Only count the matching attributes */
ss_attr_find(obj, NULL, 0, SS_NOSIZE, &nfound, SS_PERS_TEST);
if (count) *count = nfound;
} else if (!strcmp(name, SAF_ATT_NAMES)) {
/* Return the matching attribute names */
maxfind = value && *value && count ? (size_t)*count : SS_NOSIZE;
if (NULL==(attrs=ss_attr_find(obj, NULL, 0, maxfind, &nfound, NULL)))
SAF_ERROR(SAF_SSLIB_ERROR, _saf_errmsg("ss_attr_find failed"));
/* allocate string pointers */
if (!*value) {
if (NULL==(*value=calloc(nfound, sizeof(char *))))
SAF_ERROR(SAF_MEMORY_ERROR, _saf_errmsg("unable to allocate string pointers for names"));
} else {
memset(*value, 0, nfound*sizeof(char*));
}
/* Copy attribute names into string pointers */
/* ISSUE: If the pool allocation is being used then we'll have a problem if there are more attributes than what the
* string pool can store. */
for (i=0; i<nfound; i++)
_saf_setupReturned_string((char**)*value+i, ss_string_ptr(SS_ATTR_P(attrs+i,name)));
/* Output arguments */
if (count) *count = nfound;
if (type) *type = -1;
} else {
/* Find the attribute with the specified name */
if (NULL==ss_attr_find(obj, name, 0, 1, &nfound, &attr))
SAF_ERROR(SAF_SSLIB_ERROR, _saf_errmsg("ss_attr_find failed for \"%s\"", name));
/* As per defect HYPer03337, it is not an error to request an attribute that is not defined. */
if (0==nfound) {
if (count) *count = 0;
goto done;
}
/* Obtain the datatype and count. */
ss_attr_describe(&attr, NULL, &stored_type, &my_count);
if (!type) {
type = &stored_type;
} else if (*type<=0) {
*type = stored_type;
}
if (count) *count = my_count;
/* Read the attribute data */
*value = ss_attr_get(&attr, *type, 0, my_count, *value);
if (NULL==*value) SAF_ERROR(SAF_SSLIB_ERROR, _saf_errmsg("ss_attr_read failed for \"%s\"", name));
}
done:
SS_FREE(attrs);
SAF_LEAVE(SAF_SUCCESS);
}