1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
 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);
 }