Find objects in a scope

ss_pers_find is a function defined in sspers.c.

Synopsis:

ss_pers_t * ss_pers_find(ss_scope_t *scope, ss_pers_t *key, ss_persobj_t *mask, size_t nskip, size_t *nfound, ss_pers_t *buffer, ss_prop_t *props)

Formal Arguments:

  • scope: Scope to be searched
  • key: Value for which to search. This is required even if mask is null because the key determines the type of objects for which to search.
  • mask: Which elements of key to consider when searching. It is an error if no bits of mask are set, but if mask is the null pointer then key is assumed to match every object. If non-null then mask and key must be of the same type. The reason mask is an object pointer rather than an object link is that the memory is really only used to store one-byte flags that control how the matching is performed. In other words, mask isn’t truly an object–it just has to be the same size as an object.
  • nskip: Number of initial matched results that should be skipped.
  • nfound [INOUT]: The input value limits the matching to the specified number of
  • buffer: Optional buffer to fill in with handles to items that were found. If this is the constant SS_PERS_TEST then this function behaves exactly as if the caller had supplied a buffer but does not attempt to return links to the matching objects.
  • props: Optional properties (See *Persistent Object Properties*)

Description: This function will find all objects in a particular scope that match certain fields of a specified key object. The key and mask must refer to persistent objects of the same type where key contains the values to compare against and mask specifies which part of key to consider and how to compare. However, the mask is not a true object in that it doesn’t need to be created in some table with ss_pers_new; it can just be allocated on the stack. Any atomic element of mask that has at least one bit set indicates that the corresponding element of key is to be considered during the comparison. If no bits of mask are set then an error is raised, but if mask is the null pointer then we treat the key as matching every object in the scope.

If nfound is non-null then its incoming value will be used to limit the search to the specified number of returned matches. If more items match than what was specified then the additional items are simply ignored as if they didn’t even exist (unless the “detect_overflow” property is true, in which case an error is raised). The caller can pass in SS_NOSIZE if no limit is desired. If nfound is the null pointer (it can only be so if buffer is also null) then it is treated as if it had pointed to SS_NOSIZE.

The caller can supply a buffer for the result or, by passing a null pointer, request that the library allocate the buffer. If buffer is supplied then it must contain at least nfound (as set on entry to this function) elements to hold the result. But if buffer is the special constant SS_PERS_TEST then the function behaves as if a valid buffer was supplied except that it does not attempt to initialize that buffer in any way. This can be used to count how many matches would be found and even limit the counting by supplying an initial value for nfound.

A positive value for an nskip argument causes this function to act as if the first nskip matched objects didn’t, in fact, match.

Return Value: On success this function returns an array of matching persistent object links into the specified scope (the caller supplied buffer or one allocated by the library) or the constant SS_PERS_TEST and nfound (if supplied) will point to the number of matches found limited by the incoming value of nfound (or SS_NOSIZE). If space permits, the last element of the return value will be followed by a null persistent link, which makes it possible to loop over the return value even if nfound was the null pointer.

In order to distinguish the case where no item is found from the case where an error occurs, the former results in a non-null return value (the library will allocate an array of size one if the caller didn’t supply a buffer and initialize it to SS_PERS_NULL). The nfound returned value is zero in either case.

If no objects match in the specified scope and the object type is not ss_scope_t or ss_file_t and the noregistries’ property is false or not set then each registry scope associated with the file containing ``scope` will be searched until matches are found in some scope or all registries are processed.

This function returns the null pointer for failure. It is not considered a failure when the key simply doesn’t match any of the available objects.

Parallel Notes: Independent

Example: Example 1: Find all fields with an association ratio of 1 in the main scope:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
 // Obtain key from a transient scope; allocate the mask on the stack
 ss_field_t *key = SS_PERS_NEW(transient, ss_field_t, SS_ALLSAME);
 ss_fieldobj_t mask;
 // Set key value for which to search and indicate such in the mask
 SS_FIELD(key)->assoc_ratio = 1;
 memset(&mask, 0, sizeof mask);
 mask.assoc_ratio = SS_VAL_CMP_DFLT; //default comparison
 // Search for matches
 size_t nfound = SS_NOSIZE;
 ss_field_t *found = ss_pers_find(main, key, mask, 0, &nfound, NULL, NULL);
 // Print names of all matches
 for (i=0; i<nfound; i++)
     printf("match %d name=\"%s\"\n",i,ss_string_ptr(SS_FIELD_P(found+i,name)));

Example 2: Find first 10 fields with a name consisting of the word “field” in any combination of upper and lower case letters, followed by one or more digits:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 // Obtain key from a transient scope; allocate the mask on the stack
 ss_field_t *key = SS_PERS_NEW(transient, ss_field_t, SS_ALLSAME);
 ss_fieldobj_t mask;
 // Set key value for which to search and indicate such in the mask
 ss_string_set(SS_FIELD_P(key,name), "^field[0-9]+$");
 memset(&mask, 0, sizeof mask);
 memset(&(mask.name), SS_VAL_CMP_RE_ICASE, 1);
 // Search for matches
 size_t nfound = 10;
 ss_field_t found[10];
 ss_pers_find(main, key, &mask, 0, &nfound, found, NULL);

Example 3: Count how many fields are in the scope proc1:

1
2
3
4
 ss_field_t *key = ....; // any field object
 size_t nfound = SS_NOSIZE; // do not limit the search
 ss_pers_find(proc1, key, NULL, 0, &nfound, SS_PERS_TEST, NULL);
 printf("found %lu item(s)\n", (unsigned long)nfound);

See Also: