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
 int
 saf_find_quantities(SAF_ParMode pmode,
                     SAF_Db *db,                 /* Database in which to limit the search. */
                     const char *desc,           /* Optional quantity description for which to search. */
                     const char *abbr,           /* Optional abbreviation for which to search. */
                     const char *url,            /* Optional URL for which to search. */
                     unsigned flags,             /* Optional flags for which to search, or SAF_ANY_INT. */
                     int *power,                 /* Optional base quantity powers for which to search. If the pointer is
                                                  * non-null then the elements can be SAF_ANY_INT for the ones in which the
                                                  * caller is not interested. */
                     int *num,                   /* For this and the succeeding argument [see Returned Handles]. */
                     SAF_Quantity **found        /* For this and the preceding argument [see Returned Handles]. */
                     )
 {
     SAF_ENTER(saf_find_quantities, SAF_PRECONDITION_ERROR);
     SAF_KEYMASK(SAF_Quantity, key, mask);
     size_t      nfound;
     ss_scope_t  scope;
     int         i;

     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(ss_file_isopen(db, NULL)>0, SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                 _saf_errmsg("DB must be a valid database"));
     SAF_REQUIRE(_saf_valid_memhints(num, (void**)found), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
                _saf_errmsg("NUM and FOUND must be compatible for return value allocation"));

     ss_file_topscope(db, &scope);
     if (desc) SAF_SEARCH_S(SAF_Quantity, key, mask, name, desc);
     if (abbr) SAF_SEARCH_S(SAF_Quantity, key, mask, abbr, abbr);
     if (url)  SAF_SEARCH_S(SAF_Quantity, key, mask, url, url);
     if (SAF_ANY_INT!=flags) SAF_SEARCH(SAF_Quantity, key, mask, flags, flags);
     if (power) {
         for (i=0; i<SS_MAX_BASEQS; i++) {
             if (SAF_ANY_INT!=power[i]) SAF_SEARCH(SAF_Quantity, key, mask, power[i], power[i]);
         }
     }

     if (!found) {
         /* Count the matches */
         assert(num);
         nfound = SS_NOSIZE;
         ss_pers_find(&scope, (ss_pers_t*)key, mask_count?(ss_persobj_t*)&mask:NULL, 0, &nfound, SS_PERS_TEST, NULL);
         *num = nfound;
     } else if (!*found) {
         /* Find all matches; library allocates results */
         nfound = SS_NOSIZE;
         *found = (ss_quantity_t*)ss_pers_find(&scope, (ss_pers_t*)key, mask_count?(ss_persobj_t*)&mask:NULL, 0, &nfound,
                                               NULL, NULL);
         if (num) *num = nfound;
     } else {
         /* Find limited matches; client allocates result buffer */
         assert(num);
         nfound = *num;
         if (NULL==ss_pers_find(&scope, (ss_pers_t*)key, mask_count?(ss_persobj_t*)&mask:NULL, 0, &nfound, (ss_pers_t*)*found,
                                _SAF_GLOBALS.find_detect_overflow)) {
             SAF_ERROR(SAF_CONSTRAINT_ERROR, _saf_errmsg("found too many matching objects"));
         }
         *num = nfound;
     }

     SAF_LEAVE(SAF_SUCCESS);
 }