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
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
 int
 saf_find_fields(SAF_ParMode pmode,              /* The parallel mode. */
                 SAF_Db *db,                     /* Database in which to limit the search. */
                 SAF_Set *base,                  /* The base space to limit the search to. Pass SAF_UNIVERSE() or NULL if you
                                                  * do not want to limit the search to any particular base space. */
                 const char *name,               /* Limit search to fields with this name. Pass SAF_ANY_NAME if you do not want
                                                  * to limit the search. */
                 SAF_Quantity *quantity,         /* Limit search to fields of specified quantity. Pass NULL to not limit search. */
                 SAF_Algebraic *atype,           /* Limit the search to this algebraic type. Pass SAF_ALGTYPE_ANY if you do
                                                  * not want to limit the search. */
                 SAF_Basis *basis,               /* Limit the search to this basis. Pass SAF_ANY_BASIS if you do not want to
                                                  * limit the search. */
                 SAF_Unit *unit,                 /* Limit search to fields with these units. Pass SAF_ANY_UNIT to not limit
                                                  * search. */
                 SAF_Cat *coeff_assoc,           /* Limit search. Pass SAF_ANY_CAT to not limit the search. */
                 int assoc_ratio,                /* Limit search. Pass SAF_ANY_RATIO to not limit the search. */
                 SAF_Cat *eval_decomp,           /* Limit search. Pass SAF_ANY_CAT to not limit the search. */
                 SAF_Eval *eval_func,            /* Limit search. Pass SAF_ANY_EFUNC to not limit the search. */
                 int *nfound,                    /* For this and the succeeding argument, (see Returned Handles). */
                 SAF_Field **found               /* For this and the preceding argument, (see Returned Handles). */
                 )
 {
     SAF_ENTER(saf_find_fields, SAF_PRECONDITION_ERROR);
     SAF_KEYMASK(SAF_Field, key, mask);
     int                 nftmpls=0, n;
     SAF_FieldTmpl       *ftmpls=NULL;
     size_t              thisListN, nret=0, i;
     SAF_Field           *thisList=NULL, *retval=found?*found:NULL;
     ss_scope_t          scope;

     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(!base || SS_SET(base), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("BASE must either be a valid set handle or the universe set if supplied"));
     SAF_REQUIRE(!quantity || SS_QUANTITY(quantity), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("QUANTITY must either be a valid quantity handle or SAF_ANY_QUANTITY"));
     SAF_REQUIRE(!atype || SS_ALGEBRAIC(atype), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("ATYPE must be a valid algebraic type handle or SAF_ANY_ALGEBRAIC"));
     SAF_REQUIRE(!basis || SS_BASIS(basis), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("BASIS must be a valid basis handle or SAF_ANY_BASIS"));
     SAF_REQUIRE(!unit || SS_UNIT(unit), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("UNIT must either be a valid unit handle or SAF_ANY_UNIT"));
     SAF_REQUIRE(!eval_func || SS_EVALUATION(eval_func), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("EVAL_FUNC must be a valid evaluation function handle or SAF_ANY_EVALUATION"));
     SAF_REQUIRE(!coeff_assoc || SS_CAT(coeff_assoc), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("COEFF_ASSOC must either be a valid cat handle or SAF_ANY_CAT"));
     SAF_REQUIRE(!eval_decomp || SS_CAT(eval_decomp), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("EVAL_DECOMP must either be a valid cat handle or SAF_ANY_CAT"));
     SAF_REQUIRE(_saf_valid_memhints(nfound, (void**)found), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("NFOUND and FOUND must be compatible for return value allocation"));

     /* Where do we search? */
     ss_file_topscope(db, &scope);

     /* First find all the templates that match the search criteria, then loop over those templates to find the matching
      * fields. */
     if (atype || basis || quantity) {
         saf_find_field_tmpls(pmode, db, NULL, atype, basis, quantity, &nftmpls, &ftmpls);
         /* We're done early if the search criteria yielded no matching field template. */
         if (0==nftmpls) {
             if (found) *nfound = 0;
             SAF_RETURN(SAF_SUCCESS);
         }
     }

     /* Initialize the key/mask for the field search */
     if (name) SAF_SEARCH_S(SAF_Field, key, mask, name, name);
     if (coeff_assoc) SAF_SEARCH(SAF_Field, key, mask, dof_assoc_cat, *coeff_assoc);
     if (SAF_ANY_INT!=assoc_ratio) SAF_SEARCH(SAF_Field, key, mask, assoc_ratio, assoc_ratio);
     if (eval_decomp) SAF_SEARCH(SAF_Field, key, mask, eval_decomp_cat, *eval_decomp);
     if (base && !_saf_is_universe(base)) SAF_SEARCH(SAF_Field, key, mask, base_space, *base);
     if (unit) SAF_SEARCH(SAF_Field, key, mask, units, *unit);
     if (eval_func) SAF_SEARCH(SAF_Field, key, mask, evaluation, *eval_func);

     /*  Now, loop over the number of field templates doing finds on the fields */
     for (n=0; n<MAX(1, nftmpls); n++) {
         /* Fill in the field template id for this pass if we have any */
         if (ftmpls) SAF_SEARCH(SAF_Field, key, mask, ftmpl, ftmpls[n]);

         /* Find fields matching key/mask */
         thisList = SS_PERS_FIND(&scope, key, mask_count?&mask:NULL, SS_NOSIZE, thisListN);

         /* Append these fields to the return value */
         if (!found) {
             /* Count the matches */
             assert(nfound);
             nret += thisListN;
         } else if (!*found) {
             /* Find all matches; library allocates results */
             if (NULL==(retval=realloc(retval, MAX(nret+thisListN,1)*sizeof(*retval))))
                 SAF_ERROR(SAF_MEMORY_ERROR, _saf_errmsg("unable to allocate space for fields"));
             for (i=0; i<thisListN; i++)
                 retval[nret++] = thisList[i];
         } else {
             /* Find limited matches; client allocates result buffer */
             assert(nfound);
             if ((int)(nret+thisListN)>*nfound)
                 SAF_ERROR(SAF_CONSTRAINT_ERROR, _saf_errmsg("found too many matching objects"));
             for (i=0; i<thisListN; i++)
                 retval[nret++] = thisList[i];
         }

         thisList = SS_FREE(thisList);
     }

     /* Return values */
     if (nfound) *nfound = nret;
     if (found) *found = retval;
     SAF_LEAVE(SAF_SUCCESS);
 }