PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ gserialized_cmp()

int gserialized_cmp ( const GSERIALIZED g1,
const GSERIALIZED g2 
)

Return -1 if g1 is "less than" g2, 1 if g1 is "greater than" g2 and 0 if g1 and g2 are the "same".

Equality is evaluated with a memcmp and size check. So it is possible that two identical objects where one lacks a bounding box could be evaluated as non-equal initially. Greater and less than are evaluated by calculating a sortable key from the center point of the object bounds.

Definition at line 342 of file gserialized.c.

343 {
344  GBOX box1 = {0}, box2 = {0};
345  uint64_t hash1, hash2;
346  size_t sz1 = LWSIZE_GET(g1->size);
347  size_t sz2 = LWSIZE_GET(g2->size);
348  size_t hsz1 = gserialized_header_size(g1);
349  size_t hsz2 = gserialized_header_size(g2);
350  uint8_t *b1 = (uint8_t*)g1 + hsz1;
351  uint8_t *b2 = (uint8_t*)g2 + hsz2;
352  size_t bsz1 = sz1 - hsz1;
353  size_t bsz2 = sz2 - hsz2;
354  size_t bsz_min = bsz1 < bsz2 ? bsz1 : bsz2;
355 
356  /* Equality fast path */
357  /* Return equality for perfect equality only */
358  int cmp_srid = gserialized_cmp_srid(g1, g2);
359  int cmp = memcmp(b1, b2, bsz_min);
360  int g1hasz = gserialized_has_z(g1);
361  int g1hasm = gserialized_has_m(g1);
362  int g2hasz = gserialized_has_z(g2);
363  int g2hasm = gserialized_has_m(g2);
364 
365  if (bsz1 == bsz2 && cmp_srid == 0 && cmp == 0 && g1hasz == g2hasz && g1hasm == g2hasm)
366  return 0;
367  else
368  {
369  int g1_is_empty = (gserialized_get_gbox_p(g1, &box1) == LW_FAILURE);
370  int g2_is_empty = (gserialized_get_gbox_p(g2, &box2) == LW_FAILURE);
371  int32_t srid1 = gserialized_get_srid(g1);
372  int32_t srid2 = gserialized_get_srid(g2);
373 
374  /* Empty < Non-empty */
375  if (g1_is_empty && !g2_is_empty)
376  return -1;
377 
378  /* Non-empty > Empty */
379  if (!g1_is_empty && g2_is_empty)
380  return 1;
381 
382  if (!g1_is_empty && !g2_is_empty)
383  {
384  /* Using the boxes, calculate sortable hash key. */
385  hash1 = gbox_get_sortable_hash(&box1, srid1);
386  hash2 = gbox_get_sortable_hash(&box2, srid2);
387 
388  if (hash1 > hash2)
389  return 1;
390  if (hash1 < hash2)
391  return -1;
392  }
393 
394  /* Prefix comes before longer one. */
395  if (bsz1 != bsz2 && cmp == 0)
396  {
397  if (bsz1 < bsz2)
398  return -1;
399  return 1;
400  }
401 
402  /* If SRID is not equal, sort on it */
403  if (cmp_srid != 0)
404  return (srid1 > srid2) ? 1 : -1;
405 
406  /* ZM flag sort*/
407  if (g1hasz != g2hasz)
408  return (g1hasz > g2hasz) ? 1 : -1;
409 
410  if (g1hasm != g2hasm)
411  return (g1hasm > g2hasm) ? 1 : -1;
412 
413  assert(cmp != 0);
414  return cmp > 0 ? 1 : -1;
415  }
416 }
uint64_t gbox_get_sortable_hash(const GBOX *g, const int32_t srid)
Return a sortable key based on the center point of the GBOX.
Definition: gbox.c:808
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: gserialized.c:155
static size_t gserialized_header_size(const GSERIALIZED *g)
Definition: gserialized.c:307
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or calculate it if necessary.
Definition: gserialized.c:94
int gserialized_has_m(const GSERIALIZED *g)
Check if a GSERIALIZED has an M ordinate.
Definition: gserialized.c:214
static int gserialized_cmp_srid(const GSERIALIZED *g1, const GSERIALIZED *g2)
Definition: gserialized.c:332
int gserialized_has_z(const GSERIALIZED *g)
Check if a GSERIALIZED has a Z ordinate.
Definition: gserialized.c:203
#define LW_FAILURE
Definition: liblwgeom.h:96
#define LWSIZE_GET(varsize)
Macro for reading the size from the GSERIALIZED size attribute.
Definition: liblwgeom.h:324
uint32_t size
Definition: liblwgeom.h:444

References gbox_get_sortable_hash(), gserialized_cmp_srid(), gserialized_get_gbox_p(), gserialized_get_srid(), gserialized_has_m(), gserialized_has_z(), gserialized_header_size(), LW_FAILURE, LWSIZE_GET, and GSERIALIZED::size.

Referenced by geography_cmp(), geography_eq(), geography_ge(), geography_gt(), geography_le(), geography_lt(), lwgeom_cmp(), lwgeom_cmp_full(), lwgeom_eq(), lwgeom_ge(), lwgeom_gt(), lwgeom_le(), lwgeom_lt(), lwgeom_neq(), and LWGEOM_same().

Here is the call graph for this function:
Here is the caller graph for this function: