text: /*-------------------------------------------------------------------------
   *
   * rangetypes.h
   *	  Declarations for Postgres range types.
   *
   *
   * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   * src/include/utils/rangetypes.h
   *
   *-------------------------------------------------------------------------
   */
  #ifndef RANGETYPES_H
  #define RANGETYPES_H
  
  #include "utils/typcache.h"
  
  
  /*
   * Ranges are varlena objects, so must meet the varlena convention that
   * the first int32 of the object contains the total object size in bytes.
   * Be sure to use VARSIZE() and SET_VARSIZE() to access it, though!
   */
  typedef struct
  {
  	int32		vl_len_;		/* varlena header (do not touch directly!) */
  	Oid			rangetypid;		/* range type's own OID */
  	/* Following the OID are zero to two bound values, then a flags byte */
  } RangeType;
  
  /* Use this macro in preference to fetching rangetypid field directly */
  #define RangeTypeGetOid(r)	((r)->rangetypid)
  
  /* A range's flags byte contains these bits: */
  #define RANGE_EMPTY			0x01	/* range is empty */
  #define RANGE_LB_INC		0x02	/* lower bound is inclusive */
  #define RANGE_UB_INC		0x04	/* upper bound is inclusive */
  #define RANGE_LB_INF		0x08	/* lower bound is -infinity */
  #define RANGE_UB_INF		0x10	/* upper bound is +infinity */
  #define RANGE_LB_NULL		0x20	/* lower bound is null (NOT USED) */
  #define RANGE_UB_NULL		0x40	/* upper bound is null (NOT USED) */
  #define RANGE_CONTAIN_EMPTY 0x80	/* marks a GiST internal-page entry whose
  									 * subtree contains some empty ranges */
  
  #define RANGE_HAS_LBOUND(flags) (!((flags) & (RANGE_EMPTY | \
  											  RANGE_LB_NULL | \
  											  RANGE_LB_INF)))
  
  #define RANGE_HAS_UBOUND(flags) (!((flags) & (RANGE_EMPTY | \
  											  RANGE_UB_NULL | \
  											  RANGE_UB_INF)))
  
  #define RangeIsEmpty(r)  ((range_get_flags(r) & RANGE_EMPTY) != 0)
  #define RangeIsOrContainsEmpty(r)  \
  	((range_get_flags(r) & (RANGE_EMPTY | RANGE_CONTAIN_EMPTY)) != 0)
  
  
  /* Internal representation of either bound of a range (not what's on disk) */
  typedef struct
  {
  	Datum		val;			/* the bound value, if any */
  	bool		infinite;		/* bound is +/- infinity */
  	bool		inclusive;		/* bound is inclusive (vs exclusive) */
  	bool		lower;			/* this is the lower (vs upper) bound */
  } RangeBound;
  
  /*
   * fmgr macros for range type objects
   */
  #define DatumGetRangeTypeP(X)		((RangeType *) PG_DETOAST_DATUM(X))
  #define DatumGetRangeTypePCopy(X)	((RangeType *) PG_DETOAST_DATUM_COPY(X))
  #define RangeTypePGetDatum(X)		PointerGetDatum(X)
  #define PG_GETARG_RANGE_P(n)		DatumGetRangeTypeP(PG_GETARG_DATUM(n))
  #define PG_GETARG_RANGE_P_COPY(n)	DatumGetRangeTypePCopy(PG_GETARG_DATUM(n))
  #define PG_RETURN_RANGE_P(x)		return RangeTypePGetDatum(x)
  
  /* Operator strategy numbers used in the GiST and SP-GiST range opclasses */
  /* Numbers are chosen to match up operator names with existing usages */
  #define RANGESTRAT_BEFORE				RTLeftStrategyNumber
  #define RANGESTRAT_OVERLEFT				RTOverLeftStrategyNumber
  #define RANGESTRAT_OVERLAPS				RTOverlapStrategyNumber
  #define RANGESTRAT_OVERRIGHT			RTOverRightStrategyNumber
  #define RANGESTRAT_AFTER				RTRightStrategyNumber
  #define RANGESTRAT_ADJACENT				RTSameStrategyNumber
  #define RANGESTRAT_CONTAINS				RTContainsStrategyNumber
  #define RANGESTRAT_CONTAINED_BY			RTContainedByStrategyNumber
  #define RANGESTRAT_CONTAINS_ELEM		RTContainsElemStrategyNumber
  #define RANGESTRAT_EQ					RTEqualStrategyNumber
  
  /*
   * prototypes for functions defined in rangetypes.c
   */
  
  extern bool range_contains_elem_internal(TypeCacheEntry *typcache, const RangeType *r, Datum val);
  
  /* internal versions of the above */
  extern bool range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1,
  							  const RangeType *r2);
  extern bool range_ne_internal(TypeCacheEntry *typcache, const RangeType *r1,
  							  const RangeType *r2);
  extern bool range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1,
  									const RangeType *r2);
  extern bool range_contained_by_internal(TypeCacheEntry *typcache, const RangeType *r1,
  										const RangeType *r2);
  extern bool range_before_internal(TypeCacheEntry *typcache, const RangeType *r1,
  								  const RangeType *r2);
  extern bool range_after_internal(TypeCacheEntry *typcache, const RangeType *r1,
  								 const RangeType *r2);
  extern bool range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1,
  									const RangeType *r2);
  extern bool range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1,
  									const RangeType *r2);
  extern bool range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1,
  									const RangeType *r2);
  extern bool range_overright_internal(TypeCacheEntry *typcache, const RangeType *r1,
  									 const RangeType *r2);
  
  /* assorted support functions */
  extern TypeCacheEntry *range_get_typcache(FunctionCallInfo fcinfo,
  										  Oid rngtypid);
  extern RangeType *range_serialize(TypeCacheEntry *typcache, RangeBound *lower,
  								  RangeBound *upper, bool empty);
  extern void range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
  							  RangeBound *lower, RangeBound *upper,
  							  bool *empty);
  extern char range_get_flags(const RangeType *range);
  extern void range_set_contain_empty(RangeType *range);
  extern RangeType *make_range(TypeCacheEntry *typcache, RangeBound *lower,
  							 RangeBound *upper, bool empty);
  extern int	range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1,
  							 const RangeBound *b2);
  extern int	range_cmp_bound_values(TypeCacheEntry *typcache, const RangeBound *b1,
  								   const RangeBound *b2);
  extern bool bounds_adjacent(TypeCacheEntry *typcache, RangeBound bound1,
  							RangeBound bound2);
  extern RangeType *make_empty_range(TypeCacheEntry *typcache);
  
  #endif							/* RANGETYPES_H */
  