PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
gserialized.c
Go to the documentation of this file.
2#include "gserialized1.h"
3#include "gserialized2.h"
4
5/* First four bits don't change between v0 and v1 */
6#define GFLAG_Z 0x01
7#define GFLAG_M 0x02
8#define GFLAG_BBOX 0x04
9#define GFLAG_GEODETIC 0x08
10/* v1 and v2 MUST share the same version bits */
11#define GFLAG_VER_0 0x40
12#define GFLAGS_GET_VERSION(gflags) (((gflags) & GFLAG_VER_0)>>6)
13
25
32{
34 return gserialized2_set_gbox(g, gbox);
35 else
36 return gserialized1_set_gbox(g, gbox);
37}
38
43{
44 return GFLAGS_GET_VERSION(g->gflags);
45}
46
47
59
66{
68 return gserialized2_get_gbox_p(g, gbox);
69 else
70 return gserialized1_get_gbox_p(g, gbox);
71}
72
78{
80 return gserialized2_fast_gbox_p(g, gbox);
81 else
82 return gserialized1_fast_gbox_p(g, gbox);
83}
84
90{
92 return gserialized2_get_type(g);
93 else
94 return gserialized1_get_type(g);
95}
96
102{
103 size_t sz1 = gserialized1_max_header_size();
104 size_t sz2 = gserialized2_max_header_size();
105 return sz1 > sz2 ? sz1 : sz2;
106}
107
113int32_t
115{
117 return gserialized2_hash(g);
118 else
119 return gserialized1_hash(g);
120}
121
127{
129 return gserialized2_get_srid(g);
130 else
131 return gserialized1_get_srid(g);
132}
133
138void gserialized_set_srid(GSERIALIZED *g, int32_t srid)
139{
141 return gserialized2_set_srid(g, srid);
142 else
143 return gserialized1_set_srid(g, srid);
144}
145
153{
155 return gserialized2_is_empty(g);
156 else
157 return gserialized1_is_empty(g);
158}
159
164{
166 return gserialized2_has_bbox(g);
167 else
168 return gserialized1_has_bbox(g);
169}
170
175{
177 return gserialized2_has_z(g);
178 else
179 return gserialized1_has_z(g);
180}
181
186{
188 return gserialized2_has_m(g);
189 else
190 return gserialized1_has_m(g);
191}
192
197{
199 return gserialized2_is_geodetic(g);
200 else
201 return gserialized1_is_geodetic(g);
202}
203
208{
210 return gserialized2_ndims(g);
211 else
212 return gserialized1_ndims(g);
213}
214
223{
224 return gserialized2_from_lwgeom(geom, size);
225}
226
231{
233}
234
240{
242 return lwgeom_from_gserialized2(g);
243 else
244 return lwgeom_from_gserialized1(g);
245}
246
247
248const float * gserialized_get_float_box_p(const GSERIALIZED *g, size_t *ndims)
249{
251 return gserialized2_get_float_box_p(g, ndims);
252 else
253 return gserialized1_get_float_box_p(g, ndims);
254}
255
256int
258{
260 return gserialized2_peek_first_point(g, out_point);
261 else
262 return gserialized1_peek_first_point(g, out_point);
263}
264
277#define G2FLAG_EXTENDED 0x10
278inline static size_t gserialized_header_size(const GSERIALIZED *g)
279{
280 size_t sz = 8; /* varsize (4) + srid(3) + flags (1) */
281
282 if ((GFLAGS_GET_VERSION(g->gflags)) &&
283 (G2FLAG_EXTENDED & g->gflags))
284 sz += 8;
285
286 if (GFLAG_BBOX & g->gflags)
287 {
288 if (GFLAG_GEODETIC & g->gflags)
289 {
290 sz += 6 * sizeof(float);
291 }
292 else
293 {
294 sz += 4 * sizeof(float) +
295 ((GFLAG_Z & g->gflags) ? 2*sizeof(float) : 0) +
296 ((GFLAG_M & g->gflags) ? 2*sizeof(float) : 0);
297 }
298 }
299
300 return sz;
301}
302
303inline static int gserialized_cmp_srid(const GSERIALIZED *g1, const GSERIALIZED *g2)
304{
305 return (
306 g1->srid[0] == g2->srid[0] &&
307 g1->srid[1] == g2->srid[1] &&
308 g1->srid[2] == g2->srid[2]
309 ) ? 0 : 1;
310}
311
312/* ORDER BY hash(g), g::bytea, ST_SRID(g), hasz(g), hasm(g) */
313int gserialized_cmp(const GSERIALIZED *g1, const GSERIALIZED *g2)
314{
315 GBOX box1, box2;
316 uint64_t hash1, hash2;
317 size_t sz1 = SIZE_GET(g1->size);
318 size_t sz2 = SIZE_GET(g2->size);
319 size_t hsz1 = gserialized_header_size(g1);
320 size_t hsz2 = gserialized_header_size(g2);
321 uint8_t *b1 = (uint8_t*)g1 + hsz1;
322 uint8_t *b2 = (uint8_t*)g2 + hsz2;
323 size_t bsz1 = sz1 - hsz1;
324 size_t bsz2 = sz2 - hsz2;
325 size_t bsz_min = bsz1 < bsz2 ? bsz1 : bsz2;
326
327 /* Equality fast path */
328 /* Return equality for perfect equality only */
329 int cmp_srid = gserialized_cmp_srid(g1, g2);
330 int cmp = memcmp(b1, b2, bsz_min);
331 int g1hasz = gserialized_has_z(g1);
332 int g1hasm = gserialized_has_m(g1);
333 int g2hasz = gserialized_has_z(g2);
334 int g2hasm = gserialized_has_m(g2);
335
336 if (bsz1 == bsz2 && cmp_srid == 0 && cmp == 0 && g1hasz == g2hasz && g1hasm == g2hasm)
337 return 0;
338 else
339 {
340 int g1_is_empty = (gserialized_get_gbox_p(g1, &box1) == LW_FAILURE);
341 int g2_is_empty = (gserialized_get_gbox_p(g2, &box2) == LW_FAILURE);
342 int32_t srid1 = gserialized_get_srid(g1);
343 int32_t srid2 = gserialized_get_srid(g2);
344
345 /* Empty < Non-empty */
346 if (g1_is_empty && !g2_is_empty)
347 return -1;
348
349 /* Non-empty > Empty */
350 if (!g1_is_empty && g2_is_empty)
351 return 1;
352
353 if (!g1_is_empty && !g2_is_empty)
354 {
355 /* Using the boxes, calculate sortable hash key. */
356 hash1 = gbox_get_sortable_hash(&box1, srid1);
357 hash2 = gbox_get_sortable_hash(&box2, srid2);
358
359 if (hash1 > hash2)
360 return 1;
361 if (hash1 < hash2)
362 return -1;
363 }
364
365 /* Prefix comes before longer one. */
366 if (bsz1 != bsz2 && cmp == 0)
367 {
368 if (bsz1 < bsz2)
369 return -1;
370 else if (bsz1 > bsz2)
371 return 1;
372 }
373
374 /* If SRID is not equal, sort on it */
375 if (cmp_srid != 0)
376 return (srid1 > srid2) ? 1 : -1;
377
378 /* ZM flag sort*/
379 if (g1hasz != g2hasz)
380 return (g1hasz > g2hasz) ? 1 : -1;
381
382 if (g1hasm != g2hasm)
383 return (g1hasm > g2hasm) ? 1 : -1;
384
385 assert(cmp != 0);
386 return cmp > 0 ? 1 : -1;
387 }
388}
389
390uint64_t
392{
393 GBOX box;
394 int is_empty = (gserialized_get_gbox_p(g, &box) == LW_FAILURE);
395
396 if (is_empty)
397 return 0;
398 else
400}
401
402void gserialized_error_if_srid_mismatch(const GSERIALIZED *g1, const GSERIALIZED *g2, const char *funcname);
403void
404gserialized_error_if_srid_mismatch(const GSERIALIZED *g1, const GSERIALIZED *g2, const char *funcname)
405{
406 int32_t srid1 = gserialized_get_srid(g1);
407 int32_t srid2 = gserialized_get_srid(g2);
408 if (srid1 != srid2)
409 lwerror("%s: Operation on mixed SRID geometries (%s, %d) != (%s, %d)",
410 funcname,
412 srid1,
414 srid2);
415}
416
417void gserialized_error_if_srid_mismatch_reference(const GSERIALIZED *g1, const int32_t srid2, const char *funcname);
418void
419gserialized_error_if_srid_mismatch_reference(const GSERIALIZED *g1, const int32_t srid2, const char *funcname)
420{
421 int32_t srid1 = gserialized_get_srid(g1);
422 if (srid1 != srid2)
423 lwerror("%s: Operation on mixed SRID geometries %s %d != %d",
424 funcname,
426 srid1,
427 srid2);
428}
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:893
LWGEOM * lwgeom_from_gserialized1(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
const float * gserialized1_get_float_box_p(const GSERIALIZED *g, size_t *ndims)
Point into the float box area of the serialization.
int gserialized1_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
int gserialized1_has_z(const GSERIALIZED *gser)
Check if a GSERIALIZED has a Z ordinate.
int32_t gserialized1_hash(const GSERIALIZED *g1)
Returns a hash code for the srid/type/geometry information in the GSERIALIZED.
int gserialized1_ndims(const GSERIALIZED *gser)
Return the number of dimensions (2, 3, 4) in a geometry.
GSERIALIZED * gserialized1_set_gbox(GSERIALIZED *g, GBOX *gbox)
Update the bounding box of a GSERIALIZED, allocating a fresh one if there is not enough space to just...
lwflags_t gserialized1_get_lwflags(const GSERIALIZED *g)
Read the flags from a GSERIALIZED and return a standard lwflag integer.
int32_t gserialized1_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
int gserialized1_get_gbox_p(const GSERIALIZED *g, GBOX *box)
Read the bounding box off a serialization and calculate one if it is not already there.
uint32_t gserialized1_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
GSERIALIZED * gserialized1_drop_gbox(GSERIALIZED *g)
Remove the bounding box from a GSERIALIZED.
int gserialized1_has_bbox(const GSERIALIZED *gser)
Check if a GSERIALIZED has a bounding box without deserializing first.
uint32_t gserialized1_max_header_size(void)
Returns the size in bytes to read from toast to get the basic information from a geometry: GSERIALIZE...
int gserialized1_has_m(const GSERIALIZED *gser)
Check if a GSERIALIZED has an M ordinate.
int gserialized1_peek_first_point(const GSERIALIZED *g, POINT4D *out_point)
int gserialized1_is_geodetic(const GSERIALIZED *gser)
Check if a GSERIALIZED is a geography.
void gserialized1_set_srid(GSERIALIZED *s, int32_t srid)
Write the SRID into the serialized form (it is packed into three bytes so this is a handy function).
int gserialized1_fast_gbox_p(const GSERIALIZED *g, GBOX *box)
Read the bounding box off a serialization and fail if it is not already there.
LWGEOM * lwgeom_from_gserialized2(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int gserialized2_fast_gbox_p(const GSERIALIZED *g, GBOX *box)
Read the bounding box off a serialization and fail if it is not already there.
int32_t gserialized2_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
int gserialized2_is_geodetic(const GSERIALIZED *g)
Check if a GSERIALIZED is a geography.
void gserialized2_set_srid(GSERIALIZED *g, int32_t srid)
Write the SRID into the serialized form (it is packed into three bytes so this is a handy function).
int gserialized2_has_z(const GSERIALIZED *g)
Check if a GSERIALIZED has a Z ordinate.
int32_t gserialized2_hash(const GSERIALIZED *g1)
Returns a hash code for the srid/type/geometry information in the GSERIALIZED.
GSERIALIZED * gserialized2_drop_gbox(GSERIALIZED *g)
Remove the bounding box from a GSERIALIZED.
uint32_t gserialized2_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
int gserialized2_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
int gserialized2_peek_first_point(const GSERIALIZED *g, POINT4D *out_point)
GSERIALIZED * gserialized2_from_lwgeom(LWGEOM *geom, size_t *size)
Allocate a new GSERIALIZED from an LWGEOM.
int gserialized2_ndims(const GSERIALIZED *g)
Return the number of dimensions (2, 3, 4) in a geometry.
int gserialized2_get_gbox_p(const GSERIALIZED *g, GBOX *box)
Read the bounding box off a serialization and calculate one if it is not already there.
size_t gserialized2_from_lwgeom_size(const LWGEOM *geom)
Return the memory size a GSERIALIZED will occupy for a given LWGEOM.
const float * gserialized2_get_float_box_p(const GSERIALIZED *g, size_t *ndims)
Point into the float box area of the serialization.
GSERIALIZED * gserialized2_set_gbox(GSERIALIZED *g, GBOX *gbox)
Update the bounding box of a GSERIALIZED, allocating a fresh one if there is not enough space to just...
int gserialized2_has_m(const GSERIALIZED *g)
Check if a GSERIALIZED has an M ordinate.
uint32_t gserialized2_max_header_size(void)
Returns the size in bytes to read from toast to get the basic information from a geometry: GSERIALIZE...
lwflags_t gserialized2_get_lwflags(const GSERIALIZED *g)
Read the flags from a GSERIALIZED and return a standard lwflag integer.
int gserialized2_has_bbox(const GSERIALIZED *g)
Check if a GSERIALIZED has a bounding box without deserializing first.
size_t gserialized_from_lwgeom_size(const LWGEOM *geom)
Return the memory size a GSERIALIZED will occupy for a given LWGEOM.
const float * gserialized_get_float_box_p(const GSERIALIZED *g, size_t *ndims)
Access to the float bounding box, if there is one.
GSERIALIZED * gserialized_set_gbox(GSERIALIZED *g, GBOX *gbox)
Copy a new bounding box into an existing gserialized.
Definition gserialized.c:31
void gserialized_error_if_srid_mismatch(const GSERIALIZED *g1, const GSERIALIZED *g2, const char *funcname)
void gserialized_error_if_srid_mismatch_reference(const GSERIALIZED *g1, const int32_t srid2, const char *funcname)
#define GFLAG_GEODETIC
Definition gserialized.c:9
int gserialized_has_bbox(const GSERIALIZED *g)
Check if a GSERIALIZED has a bounding box without deserializing first.
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)...
GSERIALIZED * gserialized_from_lwgeom(LWGEOM *geom, size_t *size)
Allocate a new GSERIALIZED from an LWGEOM.
GSERIALIZED * gserialized_drop_gbox(GSERIALIZED *g)
Remove the bounding box from a GSERIALIZED.
Definition gserialized.c:52
static size_t gserialized_header_size(const GSERIALIZED *g)
int gserialized_is_geodetic(const GSERIALIZED *g)
Check if a GSERIALIZED is a geography.
int gserialized_ndims(const GSERIALIZED *g)
Return the number of dimensions (2, 3, 4) in a geometry.
uint32_t gserialized_get_version(const GSERIALIZED *g)
Return the serialization version.
Definition gserialized.c:42
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or calculate it if necessary.
Definition gserialized.c:65
int gserialized_has_m(const GSERIALIZED *g)
Check if a GSERIALIZED has an M ordinate.
int gserialized_peek_first_point(const GSERIALIZED *g, POINT4D *out_point)
Pull the first point values of a GSERIALIZED.
static int gserialized_cmp_srid(const GSERIALIZED *g1, const GSERIALIZED *g2)
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
void gserialized_set_srid(GSERIALIZED *g, int32_t srid)
Write the SRID into the serialized form (it is packed into three bytes so this is a handy function).
#define GFLAGS_GET_VERSION(gflags)
Definition gserialized.c:12
#define GFLAG_Z
Definition gserialized.c:6
#define G2FLAG_EXTENDED
Return -1 if g1 is "less than" g2, 1 if g1 is "greater than" g2 and 0 if g1 and g2 are the "same".
#define GFLAG_BBOX
Definition gserialized.c:8
int gserialized_has_z(const GSERIALIZED *g)
Check if a GSERIALIZED has a Z ordinate.
uint64_t gserialized_get_sortable_hash(const GSERIALIZED *g)
Return a sortable key based on gserialized.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
Definition gserialized.c:89
uint32_t gserialized_max_header_size(void)
Returns the size in bytes to read from toast to get the basic information from a geometry: GSERIALIZE...
#define GFLAG_M
Definition gserialized.c:7
int gserialized_fast_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or return #LWFAILURE if box is unavailable.
Definition gserialized.c:77
lwflags_t gserialized_get_lwflags(const GSERIALIZED *g)
Read the flags from a GSERIALIZED and return a standard lwflag integer.
Definition gserialized.c:18
int32_t gserialized_hash(const GSERIALIZED *g)
Returns a hash code for the srid/type/geometry information in the GSERIALIZED.
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".
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
#define LW_FAILURE
Definition liblwgeom.h:110
uint16_t lwflags_t
Definition liblwgeom.h:313
#define SIZE_GET(varsize)
Macro for reading the size from the GSERIALIZED size attribute.
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition lwutil.c:190
uint8_t srid[3]
Definition liblwgeom.h:431
uint32_t size
Definition liblwgeom.h:430
uint8_t gflags
Definition liblwgeom.h:432