Compares two persistent objects

ss_pers_cmp is a function defined in sspers.c.

Synopsis:

int ss_pers_cmp(ss_pers_t *p1, ss_pers_t *p2, const ss_persobj_t *mask)

Formal Arguments:

  • p1: First of two objects to compare.
  • p2: Second of two objects to cmpare.
  • mask: Optional mask to use for deep comparisons. A null value implies a shallow comparison, which means that the comparison should only look at the object handles and not the objects themselves.

Description: Compares two objects, P1 and P2, and returns a value similar to memcmp or strcmp.

If mask is the null pointer then only the contents of the links P1 and P2 are consulted and the underlying objects are never referenced, a so called shallow comparison. The return value will be one of the following:

1
2
3
4
                         |  1 if A > B by some well defined global ordering
 ss_pers_cmp(A,B,NULL) = |  0 if A and B point to the same object
                         | -1 if A < B
                         | -2 on error

On the other hand, if mask is not null then a deep comparison is performed and mask should be a block of memory the same size as the objects to which P1 and P2 point (mask is not referenced if P1 and P2 point to objects of different types). The block of memory should be initialized to zero except where a comparison in the two underlying objects is desired. For instance, when comparing the roles and topological dimensions of two categories (SAF__Cat) you would do the following:

1
2
3
4
5
6
 SAF_Cat a=...; b=...;
 ss_catobj_t mask;
 memset(&mask, 0, sizeof mask);
 memset(&mask.role, SS_VAL_CMP_DFLT, 1); // default comparison mode for roles
 memset(&mask.tdim, SS_VAL_CMP_DFLT, 1); // default comparison mode for topological dimensions
 ss_pers_cmp((ss_pers_t*)&a, (ss_pers_t*)&b, (ss_persobj_t*)&mask);

Note two things: (1) only the first non-zero byte in the mask corresponding to any particular member is consulted to determine the kind of comparison, and (2) ss_pers_t and ss_persobj_t are the types from which all persistent object links and objects are derived and are binary compatible with all links and objects.

To compare all fields of two categories you could just set the whole mask to the desired comparison because ss_pers_cmp will skip over parts of the mask that don’t actually correspond to things that can be compared (e.g., padding bytes inserted by the compiler between members of the object and parts of the objects that are SSlib’s private bookkeeping records):

1
 memset(&mask, SS_VAL_CMP_DFLT, sizeof mask);

The various flags defining comparisons are defined by the ss_val_cmp_t type.

Return Value: Similar to memcmp except successful return value is one of: -1, 0, or 1 instead of arbitrary negative and positive values. This allows -2 (or less) to indicate failure, which is standard practice in SSlib for comparison functions.

Parallel Notes: Independent

Issues: Deep comparisons are not yet fully recursive. I.e., if P1 and P2 are being deeply compared and the objects to which P1 and P2 point contain object links which are being compared because they correspond to non-zero bits in mask, then only a shallow comparison is performed on those links. We plan to add a property list argument to this function that would allow finer-grained control of the deep comparison recursion.

See Also: