1 /* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22
23 #ifndef SPATIAL_INCLUDED
24 #define SPATIAL_INCLUDED
25
26 #include "my_global.h"
27 #include "mysql/mysql_lex_string.h" // LEX_STRING
28 #include "mysqld.h"
29 #include "sql_string.h" // String
30
31 #include <vector>
32 #include <algorithm>
33 #include <stdexcept>
34 #include <cstdlib>
35 #include <utility>
36 #include <memory>
37 #include "inplace_vector.h"
38
39
40 class Gis_read_stream;
41
42 const uint GEOM_DIM= 2;
43 const uint SRID_SIZE= 4;
44 const uint SIZEOF_STORED_DOUBLE= 8;
45 const uint POINT_DATA_SIZE= (SIZEOF_STORED_DOUBLE * 2);
46 const uint WKB_HEADER_SIZE= (1+4);
47 const uint GEOM_HEADER_SIZE= (SRID_SIZE + WKB_HEADER_SIZE);
48
49 const uint32 GET_SIZE_ERROR= 0xFFFFFFFFU;
50
51
is_little_endian()52 inline bool is_little_endian()
53 {
54 #ifdef WORDS_BIGENDIAN
55 return false;
56 #else
57 return true;
58 #endif
59 }
60
61
62 /**
63 Point with coordinates X and Y.
64 */
65 class point_xy
66 {
67 public:
68 double x;
69 double y;
point_xy()70 point_xy() { }
point_xy(double x_arg,double y_arg)71 point_xy(double x_arg, double y_arg): x(x_arg), y(y_arg) { }
72 double distance(const point_xy &p) const;
73 /**
74 Compare to another point.
75 Return true if equal, false if not equal.
76 */
eq(point_xy p)77 bool eq(point_xy p) const
78 {
79 return (x == p.x) && (y == p.y);
80 }
81 };
82
83 typedef struct wkb_header_st
84 {
85 uchar byte_order;
86 uint32 wkb_type;
87 } wkb_header;
88
89
90 /***************************** MBR *******************************/
91
92
93 struct MBR
94 {
95 double xmin, ymin, xmax, ymax;
96
MBRMBR97 MBR()
98 {
99 xmin= ymin= DBL_MAX;
100 xmax= ymax= -DBL_MAX;
101 }
102
MBRMBR103 MBR(const double xmin_arg, const double ymin_arg,
104 const double xmax_arg, const double ymax_arg)
105 :xmin(xmin_arg), ymin(ymin_arg), xmax(xmax_arg), ymax(ymax_arg)
106 {}
107
MBRMBR108 MBR(const point_xy &min, const point_xy &max)
109 :xmin(min.x), ymin(min.y), xmax(max.x), ymax(max.y)
110 {}
111
add_xyMBR112 void add_xy(double x, double y)
113 {
114 /* Not using "else" for proper one point MBR calculation */
115 if (x < xmin)
116 xmin= x;
117 if (x > xmax)
118 xmax= x;
119 if (y < ymin)
120 ymin= y;
121 if (y > ymax)
122 ymax= y;
123 }
add_xyMBR124 void add_xy(point_xy p)
125 {
126 add_xy(p.x, p.y);
127 }
add_xyMBR128 void add_xy(const char *px, const char *py)
129 {
130 double x, y;
131 float8get(&x, px);
132 float8get(&y, py);
133 add_xy(x,y);
134 }
add_mbrMBR135 void add_mbr(const MBR *mbr)
136 {
137 if (mbr->xmin < xmin)
138 xmin= mbr->xmin;
139 if (mbr->xmax > xmax)
140 xmax= mbr->xmax;
141 if (mbr->ymin < ymin)
142 ymin= mbr->ymin;
143 if (mbr->ymax > ymax)
144 ymax= mbr->ymax;
145 }
146
equalsMBR147 int equals(const MBR *mbr) const
148 {
149 /* The following should be safe, even if we compare doubles */
150 return ((mbr->xmin == xmin) && (mbr->ymin == ymin) &&
151 (mbr->xmax == xmax) && (mbr->ymax == ymax));
152 }
153
disjointMBR154 int disjoint(const MBR *mbr) const
155 {
156 /* The following should be safe, even if we compare doubles */
157 return ((mbr->xmin > xmax) || (mbr->ymin > ymax) ||
158 (mbr->xmax < xmin) || (mbr->ymax < ymin));
159 }
160
intersectsMBR161 int intersects(const MBR *mbr) const
162 {
163 return !disjoint(mbr);
164 }
165
166 int touches(const MBR *mbr) const;
167
168 int within(const MBR *mbr) const;
169
containsMBR170 int contains(const MBR *mbr) const
171 {
172 return mbr->within(this);
173 }
174
covered_byMBR175 int covered_by(const MBR *mbr) const
176 {
177 /* The following should be safe, even if we compare doubles */
178 return ((mbr->xmin <= xmin) && (mbr->ymin <= ymin) &&
179 (mbr->xmax >= xmax) && (mbr->ymax >= ymax));
180 }
181
coversMBR182 int covers(const MBR *mbr) const
183 {
184 return mbr->covered_by(this);
185 }
186
inner_pointMBR187 bool inner_point(double x, double y) const
188 {
189 /* The following should be safe, even if we compare doubles */
190 return (xmin<x) && (xmax>x) && (ymin<y) && (ymax>y);
191 }
192
193 /**
194 The dimension maps to an integer as:
195 - Polygon -> 2
196 - Horizontal or vertical line -> 1
197 - Point -> 0
198 - Invalid MBR -> -1
199 */
dimensionMBR200 int dimension() const
201 {
202 int d= 0;
203
204 if (xmin > xmax)
205 return -1;
206 else if (xmin < xmax)
207 d++;
208
209 if (ymin > ymax)
210 return -1;
211 else if (ymin < ymax)
212 d++;
213
214 return d;
215 }
216
overlapsMBR217 int overlaps(const MBR *mbr) const
218 {
219 /*
220 overlaps() requires that some point inside *this is also inside
221 *mbr, and that both geometries and their intersection are of the
222 same dimension.
223 */
224 int d= dimension();
225 DBUG_ASSERT(d >= 0 && d <= 2);
226
227 if (d != mbr->dimension() || d == 0 || contains(mbr) || within(mbr))
228 return 0;
229
230 MBR intersection(std::max(xmin, mbr->xmin), std::max(ymin, mbr->ymin),
231 std::min(xmax, mbr->xmax), std::min(ymax, mbr->ymax));
232
233 return (d == intersection.dimension());
234 }
235 };
236
237
238 /***************************** Geometry *******************************/
239
240 struct Geometry_buffer;
241
242 /*
243 Memory management functions for BG adapter code. Allocate extra space for
244 GEOMETRY header so that we can later prefix the header if needed.
245 */
gis_wkb_alloc(size_t sz)246 inline void *gis_wkb_alloc(size_t sz)
247 {
248 sz+= GEOM_HEADER_SIZE;
249 char *p= static_cast<char *>(my_malloc(key_memory_Geometry_objects_data,
250 sz, MYF(MY_FAE)));
251 p+= GEOM_HEADER_SIZE;
252 return p;
253 }
254
255
gis_wkb_fixed_alloc(size_t sz)256 inline void *gis_wkb_fixed_alloc(size_t sz)
257 {
258 return gis_wkb_alloc(sz);
259 }
260
261
gis_wkb_realloc(void * p,size_t sz)262 inline void *gis_wkb_realloc(void *p, size_t sz)
263 {
264 char *cp= static_cast<char *>(p);
265 if (cp)
266 cp-= GEOM_HEADER_SIZE;
267 sz+= GEOM_HEADER_SIZE;
268
269 p= my_realloc(key_memory_Geometry_objects_data, cp, sz, MYF(MY_FAE));
270 cp= static_cast<char *>(p);
271 return cp + GEOM_HEADER_SIZE;
272 }
273
274
gis_wkb_free(void * p)275 inline void gis_wkb_free(void *p)
276 {
277 if (p == NULL)
278 return;
279 char *cp= static_cast<char *>(p);
280 my_free(cp - GEOM_HEADER_SIZE);
281 }
282
283
gis_wkb_raw_free(void * p)284 inline void gis_wkb_raw_free(void *p)
285 {
286 my_free(p);
287 }
288
289
290 class Geometry
291 {
292 friend void parse_wkb_data(Geometry *g, const char *p, size_t num_geoms);
293 protected:
294 // Flag bits for m_flags.props.
295
296 /*
297 Whether the linestring is a polygon's outer ring, or inner ring.
298 */
299 const static int POLYGON_OUTER_RING= 0x1;
300 const static int POLYGON_INNER_RING= 0x2;
301
302 /*
303 Whether the Geometry object is created to be used by Boost Geometry or
304 only by MySQL. There are some operations that only work for one type and
305 can or must be skipped otherwise. This state is transient and mutable, we
306 set it even to a const geometry object.
307 */
308 const static int IS_BOOST_GEOMETRY_ADAPTER= 0x4;
309
310 /*
311 Whether the geometry length is verified, so that we can return the stored
312 length without having to parse the WKB again.
313 */
314 const static int GEOM_LENGTH_VERIFIED= 0x8;
315
316 /*
317 Whether the geometry has components stored out of line, see
318 Gis_wkb_vector<>::resize for details.
319 */
320 const static int HAS_OUT_OF_LINE_COMPONENTS= 0x10;
321
322 /*
323 Whether the polygon's data is in WKB form, as is so in MySQL, or it's in
324 BG form, where the m_ptr points to an outer ring object, and m_inn_rings
325 points to the inner rings. See Gis_polygon for more information.
326 */
327 const static int POLYGON_IN_WKB_FORM= 0x20;
328
329 /*
330 whether the geometry's data buffer has space for a GEOMETRY header.
331 BG adapter code use gis_wkb_alloc to allocate WKB buffer for Geometry
332 objects, they always has such space. Gis_geometry_collection created
333 from a single geometry and then appended with more geometries also have
334 such space. Those with such space we can simply prefix the GEOMETRY header
335 into its buffer without copying its WKB data.
336 */
337 const static int HAS_GEOM_HEADER_SPACE= 0x40;
338
339 /*
340 Whether the multi geometry has overlapped components, if false(the bit set)
341 this geometry will be skipped from merge-component operation.
342 Effective only for multipolygons, multilinestrings and geometry collections.
343 Such geometries returned by BG always has this bit set, i.e. their
344 components don't overlap.
345 */
346 const static int MULTIPOLYGON_NO_OVERLAPPED_COMPS= 0x80;
347 public:
348 // Check user's transmitted data against these limits.
349 const static uint32 MAX_GEOM_WKB_LENGTH= 0x3fffffff;
350
351 typedef uint32 srid_t;
352 const static srid_t default_srid= 0;
353
354 virtual ~Geometry();
355
356
357 /*
358 We have to define a wkb_first and wkb_invalid_type and set them to 0
359 because Geometry objects stored in m_geo_vect vector can be constructed
360 using the default constructur Geometry() which sets geotype to 0, and
361 there are asserts in BG adapter code which asserts geotype is in valid
362 range [wkb_first, wkb_last]. Neither items will be treated as valid
363 geometry types.
364
365 wkb_first and wkb_last are only intended to be used to express a valid
366 range of wkbType values, other items are to be used as real type values.
367 */
368 enum wkbType
369 {
370 wkb_invalid_type= 0,
371 wkb_first= 1,
372 wkb_point= 1,
373 wkb_linestring= 2,
374 wkb_polygon= 3,
375 wkb_multipoint= 4,
376 wkb_multilinestring= 5,
377 wkb_multipolygon= 6,
378 wkb_geometrycollection= 7,
379 /*
380 OGC defines 10 more basic geometry types for values 8 to 17, we don't
381 support them now so don't define them. And there may be more of
382 them defined in the future. Since we will need 5 bits anyway, we grow
383 from 31 down to 18 for our extra private types instead of from 18 to 31,
384 to avoid potential data file format binary compatibility issues, which
385 would occur if OGC defined more basic types and we would support them.
386 */
387 wkb_polygon_inner_rings= 31,
388 wkb_last=31
389 };
390 enum wkbByteOrder
391 {
392 wkb_xdr= 0, /* Big Endian */
393 wkb_ndr= 1, /* Little Endian */
394 wkb_invalid
395 };
396 enum enum_coordinate_reference_system
397 {
398 coord_first= 1,
399 cartesian= 1,
400 coord_last= 1
401 };
402
403
404 static String bad_geometry_data;
405
406 /**
407 Constant storage for WKB.
408 Encapsulation and the available methods make it impossible
409 to update the members of wkb_container once it is initialized.
410 The only allowed modification method is set(),
411 which fully replaces the previous buffer.
412 */
413 class wkb_container
414 {
415 protected:
416 const char *m_data;
417 const char *m_data_end;
418 public:
wkb_container()419 wkb_container() { }
wkb_container(const char * data,const char * data_end)420 wkb_container(const char *data, const char *data_end)
421 {
422 set(data, data_end);
423 }
set(const char * data,const char * data_end)424 void set(const char *data, const char *data_end)
425 {
426 m_data= data;
427 m_data_end= data_end;
428 }
data()429 const char *data() const
430 {
431 return m_data;
432 }
data_end()433 const char *data_end() const
434 {
435 return m_data_end;
436 }
length()437 uint32 length() const
438 {
439 return (uint32) (m_data_end - m_data);
440 }
441 /**
442 Check if there's enough data remaining as requested.
443
444 @arg data_amount data requested
445
446 @return true if not enough data
447 */
no_data(size_t data_amount)448 bool no_data(size_t data_amount) const
449 {
450 return (m_data + data_amount > m_data_end);
451 }
452
453 /**
454 Check if there're enough points remaining as requested.
455
456 Need to perform the calculation in logical units, since multiplication
457 can overflow the size data type.
458
459 @arg expected_points number of points expected
460 @arg extra_point_space extra space for each point element in the array
461
462 @return true if there are not enough points
463 */
464 bool not_enough_points(uint32 expected_points,
465 uint32 extra_point_space= 0) const
466 {
467 return (m_data_end < m_data ||
468 expected_points > ((m_data_end - m_data) /
469 (POINT_DATA_SIZE + extra_point_space)));
470 }
471 };
472
473 /**
474 WKB parser, designed to traverse through WKB data from
475 beginning of the buffer towards the end using a set
476 of scan_xxx(), get_xxx() and skip_xxx() routines,
477 with safety tests to avoid going beyond the buffer end.
478 */
479 class wkb_parser: public wkb_container
480 {
481 /* Low level routines to get data of various types */
get_uint4(uint32 * number)482 void get_uint4(uint32 *number)
483 {
484 *number= uint4korr(m_data); //GIS-TODO: byte order
485 }
get_float8(double * x)486 void get_float8(double *x)
487 {
488 float8get(x, m_data); //GIS-TODO: byte order
489 }
490 public:
wkb_parser(const char * data,const char * data_end)491 wkb_parser(const char *data, const char *data_end)
492 :wkb_container(data, data_end) { }
493
494 /* Routines to skip non-interesting data */
skip_unsafe(size_t nbytes)495 void skip_unsafe(size_t nbytes)
496 {
497 DBUG_ASSERT(!no_data(nbytes));
498 m_data+= nbytes;
499 }
skip(size_t nbytes)500 bool skip(size_t nbytes)
501 {
502 if (no_data(nbytes))
503 return true;
504 m_data+= nbytes;
505 return false;
506 }
skip_wkb_header()507 bool skip_wkb_header()
508 {
509 return skip(WKB_HEADER_SIZE);
510 }
skip_coord()511 bool skip_coord()
512 {
513 return skip(SIZEOF_STORED_DOUBLE);
514 }
515
516 /* Routines to scan wkb header information */
scan_wkb_header(wkb_header * header)517 bool scan_wkb_header(wkb_header *header)
518 {
519 if (no_data(WKB_HEADER_SIZE))
520 return true;
521 header->byte_order= (uchar) (*m_data);
522 m_data++;
523 get_uint4(&header->wkb_type);
524 m_data+= 4;
525 return false;
526 }
527
528 /* Routines to scan uint4 information */
scan_uint4(uint32 * number)529 bool scan_uint4(uint32 *number)
530 {
531 if (no_data(4))
532 return true;
533 get_uint4(number);
534 m_data+= 4;
535 return false;
536 }
scan_non_zero_uint4(uint32 * number)537 bool scan_non_zero_uint4(uint32 *number)
538 {
539 return (scan_uint4(number) || 0 == *number);
540 }
541 bool scan_n_points_and_check_data(uint32 *n_points,
542 uint32 extra_point_space= 0)
543 {
544 return scan_non_zero_uint4(n_points) ||
545 not_enough_points(*n_points, extra_point_space);
546 }
547
548 /* Routines to scan coordinate information */
scan_xy_unsafe(point_xy * p)549 void scan_xy_unsafe(point_xy *p)
550 {
551 DBUG_ASSERT(!no_data(POINT_DATA_SIZE));
552 get_float8(&p->x);
553 m_data+= SIZEOF_STORED_DOUBLE;
554 get_float8(&p->y);
555 m_data+= SIZEOF_STORED_DOUBLE;
556 }
scan_xy(point_xy * p)557 bool scan_xy(point_xy *p)
558 {
559 if (no_data(SIZEOF_STORED_DOUBLE * 2))
560 return true;
561 scan_xy_unsafe(p);
562 return false;
563 }
scan_coord(double * x)564 bool scan_coord(double *x)
565 {
566 if (no_data(SIZEOF_STORED_DOUBLE))
567 return true;
568 get_float8(x);
569 m_data+= SIZEOF_STORED_DOUBLE;
570 return false;
571 }
572 };
573
574 /** Callback which creates Geometry objects on top of a given placement. */
575 typedef Geometry *(*create_geom_t)(char *);
576
577 class Class_info
578 {
579 public:
580 LEX_STRING m_name;
581 int m_type_id;
582 create_geom_t m_create_func;
583 Class_info(const char *name, int type_id, create_geom_t create_func);
584 };
585
get_class_info()586 virtual const Class_info *get_class_info() const { return NULL; }
587
get_data_size()588 virtual uint32 get_data_size() const { return -1; }
589
590 /* read from trs the wkt string and write into wkb as wkb encoded data. */
init_from_wkt(Gis_read_stream * trs,String * wkb)591 virtual bool init_from_wkt(Gis_read_stream *trs, String *wkb) { return true;}
592
593 /* read from wkb the wkb data and write into res as wkb encoded data. */
594 /* returns the length of the wkb that was read */
init_from_wkb(const char * wkb,uint len,wkbByteOrder bo,String * res)595 virtual uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
596 String *res) { return 0; }
597
get_data_as_wkt(String * txt,wkb_parser * wkb)598 virtual bool get_data_as_wkt(String *txt, wkb_parser *wkb) const
599 { return true;}
get_mbr(MBR * mbr,wkb_parser * wkb)600 virtual bool get_mbr(MBR *mbr, wkb_parser *wkb) const
601 { return true;}
get_mbr(MBR * mbr)602 bool get_mbr(MBR *mbr)
603 {
604 wkb_parser wkb(get_cptr(), get_cptr() + get_nbytes());
605 return get_mbr(mbr, &wkb);
606 }
dimension(uint32 * dim,wkb_parser * wkb)607 virtual bool dimension(uint32 *dim, wkb_parser *wkb) const
608 {
609 *dim= feature_dimension();
610 uint32 length;
611 if ((length= get_data_size()) == GET_SIZE_ERROR)
612 return true;
613 wkb->skip(length);
614 return false;
615 }
dimension(uint32 * dim)616 bool dimension(uint32 *dim) const
617 {
618 wkb_parser wkb(get_cptr(), get_cptr() + get_nbytes());
619 return dimension(dim, &wkb);
620 }
get_type()621 wkbType get_type() const
622 {
623 return static_cast<Geometry::wkbType>(get_class_info()->m_type_id);
624 }
get_coordsys()625 enum_coordinate_reference_system get_coordsys() const
626 {
627 return cartesian;
628 }
feature_dimension()629 virtual uint32 feature_dimension() const
630 {
631 DBUG_ASSERT(false);
632 return 0;
633 }
634
get_x(double * x)635 virtual int get_x(double *x) const { return -1; }
get_y(double * y)636 virtual int get_y(double *y) const { return -1; }
geom_length(double * len)637 virtual int geom_length(double *len) const { return -1; }
is_closed(int * closed)638 virtual int is_closed(int *closed) const { return -1; }
num_interior_ring(uint32 * n_int_rings)639 virtual int num_interior_ring(uint32 *n_int_rings) const { return -1; }
num_points(uint32 * n_points)640 virtual int num_points(uint32 *n_points) const { return -1; }
num_geometries(uint32 * num)641 virtual int num_geometries(uint32 *num) const { return -1; }
copy_points(String * result)642 virtual int copy_points(String *result) const { return -1; }
643 /* The following 7 functions return geometries in wkb format. */
start_point(String * point)644 virtual int start_point(String *point) const { return -1; }
end_point(String * point)645 virtual int end_point(String *point) const { return -1; }
exterior_ring(String * ring)646 virtual int exterior_ring(String *ring) const { return -1; }
point_n(uint32 num,String * result)647 virtual int point_n(uint32 num, String *result) const { return -1; }
interior_ring_n(uint32 num,String * result)648 virtual int interior_ring_n(uint32 num, String *result) const { return -1; }
geometry_n(uint32 num,String * result)649 virtual int geometry_n(uint32 num, String *result) const { return -1; }
650
651 public:
652 static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id);
653
654 static Geometry *construct(Geometry_buffer *buffer,
655 const char *data, uint32 data_len,
656 bool has_srid= true);
657 static Geometry *construct(Geometry_buffer *buffer, const String *str,
658 bool has_srid= true)
659 {
660 return construct(buffer, str->ptr(),
661 static_cast<uint32>(str->length()), has_srid);
662 }
663 static Geometry *create_from_wkt(Geometry_buffer *buffer,
664 Gis_read_stream *trs, String *wkt,
665 bool init_stream= true,
666 bool check_trailing= true);
667 static Geometry *create_from_wkb(Geometry_buffer *buffer, const char *wkb,
668 uint32 len, String *res, bool init);
as_wkt(String * wkt,wkb_parser * wkb)669 bool as_wkt(String *wkt, wkb_parser *wkb) const
670 {
671 uint32 len= (uint) get_class_info()->m_name.length;
672 if (wkt->reserve(len + 2, 512))
673 return true;
674 wkt->qs_append(get_class_info()->m_name.str, len);
675 wkt->qs_append('(');
676 if (get_data_as_wkt(wkt, wkb))
677 return true;
678 wkt->qs_append(')');
679 return false;
680 }
as_wkt(String * wkt)681 bool as_wkt(String *wkt) const
682 {
683 wkb_parser wkb(get_cptr(), get_cptr() + get_nbytes());
684 return as_wkt(wkt, &wkb);
685 }
686
687 bool as_wkb(String *wkb, bool shallow_copy) const;
688 bool as_geometry(String *wkb, bool shallow_copy) const;
689
set_data_ptr(const void * data,size_t data_len)690 void set_data_ptr(const void *data, size_t data_len)
691 {
692 m_ptr= const_cast<void *>(data);
693 set_nbytes(data_len);
694 }
695
set_data_ptr(const wkb_container * c)696 void set_data_ptr(const wkb_container *c)
697 {
698 m_ptr= const_cast<void *>(static_cast<const void *>(c->data()));
699 set_nbytes(c->length());
700 }
get_data_ptr()701 void *get_data_ptr() const
702 {
703 return m_ptr;
704 }
705
706 bool envelope(String *result) const;
707 bool envelope(MBR *mbr) const;
708
709 static Class_info *ci_collection[wkb_last+1];
710
is_polygon_ring()711 bool is_polygon_ring() const
712 {
713 return m_flags.props & (POLYGON_OUTER_RING | POLYGON_INNER_RING);
714 }
715
is_polygon_outer_ring()716 bool is_polygon_outer_ring() const
717 {
718 return m_flags.props & POLYGON_OUTER_RING;
719 }
720
is_polygon_inner_ring()721 bool is_polygon_inner_ring() const
722 {
723 return m_flags.props & POLYGON_INNER_RING;
724 }
725
has_geom_header_space()726 bool has_geom_header_space() const
727 {
728 return (m_flags.props & HAS_GEOM_HEADER_SPACE) ||
729 (m_flags.props & IS_BOOST_GEOMETRY_ADAPTER);
730 }
731
has_geom_header_space(bool b)732 void has_geom_header_space(bool b)
733 {
734 if (b)
735 m_flags.props|= HAS_GEOM_HEADER_SPACE;
736 else
737 m_flags.props&= ~HAS_GEOM_HEADER_SPACE;
738 }
739
is_components_no_overlapped()740 bool is_components_no_overlapped() const
741 {
742 return (m_flags.props & MULTIPOLYGON_NO_OVERLAPPED_COMPS);
743 }
744
set_components_no_overlapped(bool b)745 void set_components_no_overlapped(bool b)
746 {
747 DBUG_ASSERT(get_type() == wkb_multilinestring ||
748 get_type() == wkb_multipolygon ||
749 get_type() == wkb_geometrycollection);
750 if (b)
751 m_flags.props|= MULTIPOLYGON_NO_OVERLAPPED_COMPS;
752 else
753 m_flags.props&= ~MULTIPOLYGON_NO_OVERLAPPED_COMPS;
754 }
755
set_props(uint16 flag)756 void set_props(uint16 flag)
757 {
758 DBUG_ASSERT(0xfff >= flag);
759 m_flags.props |= flag;
760 }
761
get_props()762 uint16 get_props() const { return (uint16)m_flags.props; }
763
set_srid(srid_t id)764 void set_srid(srid_t id)
765 {
766 m_srid= id;
767 }
768
get_srid()769 srid_t get_srid() const { return m_srid; }
770
771 const void *normalize_ring_order();
772 protected:
find_class(int type_id)773 static Class_info *find_class(int type_id)
774 {
775 return ((type_id < wkb_first) || (type_id > wkb_last)) ?
776 NULL : ci_collection[type_id];
777 }
778 static Class_info *find_class(const char *name, size_t len);
779 void append_points(String *txt, uint32 n_points,
780 wkb_parser *wkb, uint32 offset,
781 bool bracket_pt= false) const;
782 bool create_point(String *result, wkb_parser *wkb) const;
783 bool create_point(String *result, point_xy p) const;
784 bool get_mbr_for_points(MBR *mbr, wkb_parser *wkb, uint offset) const;
is_length_verified()785 bool is_length_verified() const {return m_flags.props & GEOM_LENGTH_VERIFIED;}
786
787 // Have to make this const because it's called in a const member function.
set_length_verified(bool b)788 void set_length_verified(bool b) const
789 {
790 if (b)
791 m_flags.props |= GEOM_LENGTH_VERIFIED;
792 else
793 m_flags.props &= ~GEOM_LENGTH_VERIFIED;
794 }
795
796 /***************************** Boost Geometry Adapter Interface ************/
797 public:
798 /**
799 Highest byte is stores byte order, dimension, nomem and geotype as follows:
800 bo: byte order, 1 for little endian(ndr), 0 for big endian(xdr); Currently
801 it must be always wkb_ndr since it is MySQL's portable geometry format.
802 dimension: 0~3 for 1~4 dimensions;
803 nomem: indicating whether this object has its own memory.
804 If so, the memory is released when the object is destroyed. Some
805 objects may refer to an existing WKB buffer and access it read only.
806 geotype: stores the wkbType enum numbers, at most 32 values, valid range
807 so far: [0, 7] and 31.
808
809 nybytes: takes the following 30 bits, stores number of effective and valid
810 data bytes of current object's wkb data.
811
812 props: bits OR'ed for various other runtime properties of the geometry
813 object. Bits are defined above. No properties are stored
814 permanently, all properties here are specified/used at runtime
815 while the Geometry object is alive.
816 zm: not used now, always be 0, i.e. always 2D geometries. In future,
817 they represent Z and/or M settings, 1: Z, 2: M, 3: ZM.
818 unused: reserved for future use, it's unused now.
819 */
820 class Flags_t
821 {
822 public:
Flags_t(const Flags_t & o)823 Flags_t(const Flags_t &o)
824 {
825 compile_time_assert(sizeof(*this) == sizeof(uint64));
826 memcpy(this, &o, sizeof(o));
827 }
828
Flags_t()829 Flags_t()
830 {
831 compile_time_assert(sizeof(*this) == sizeof(uint64));
832 memset(this, 0, sizeof(*this));
833 bo= wkb_ndr;
834 dim= GEOM_DIM - 1;
835 nomem= 1;
836 }
837
Flags_t(wkbType type,size_t len)838 Flags_t(wkbType type, size_t len)
839 {
840 compile_time_assert(sizeof(*this) == sizeof(uint64));
841 memset(this, 0, sizeof(*this));
842 geotype= type;
843 nbytes= len;
844 bo= wkb_ndr;
845 dim= GEOM_DIM - 1;
846 nomem= 1;
847 }
848
849 uint64 bo:1;
850 uint64 dim:2;
851 uint64 nomem:1;
852 uint64 geotype:5;
853 uint64 nbytes:30;
854 uint64 props:12;
855 uint64 zm:2;
856 uint64 unused:11;
857 };
858
Geometry()859 Geometry()
860 {
861 m_ptr= NULL;
862 m_owner= NULL;
863 set_ownmem(false);
864 set_byte_order(Geometry::wkb_ndr);
865 set_srid(default_srid);
866 }
867
868 /**
869 Constructor used as BG adapter or by default constructors of children
870 classes.
871 @param ptr WKB buffer address, or NULL for an empty object.
872 @param len WKB buffer length in bytes.
873 @param flags the flags to set, no field is used for now except geotype.
874 @param srid srid of the geometry.
875 */
Geometry(const void * ptr,size_t len,const Flags_t & flags,srid_t srid)876 Geometry(const void *ptr, size_t len, const Flags_t &flags, srid_t srid)
877 {
878 m_ptr= const_cast<void *>(ptr);
879 m_flags.nbytes= len;
880 set_srid(srid);
881 m_flags.geotype= flags.geotype;
882 m_owner= NULL;
883 set_ownmem(false);
884 }
885
886 Geometry(const Geometry &geo);
887
888 Geometry &operator=(const Geometry &rhs);
889
890 /* Getters and setters. */
get_ptr()891 void *get_ptr() const
892 {
893 return m_ptr;
894 }
895
get_cptr()896 char *get_cptr() const
897 {
898 return static_cast<char *>(m_ptr);
899 }
900
get_ucptr()901 uchar *get_ucptr() const
902 {
903 return static_cast<uchar *>(m_ptr);
904 }
905
get_owner()906 Geometry *get_owner() const { return m_owner;}
907
set_owner(Geometry * o)908 void set_owner(Geometry *o) { m_owner= o; }
909
set_byte_order(Geometry::wkbByteOrder bo)910 void set_byte_order(Geometry::wkbByteOrder bo)
911 {
912 DBUG_ASSERT(bo == Geometry::wkb_ndr);
913 m_flags.bo= static_cast<char>(bo);
914 }
915
set_dimension(char dim)916 void set_dimension(char dim)
917 {
918 // Valid dim is one of [1, 2, 3, 4].
919 DBUG_ASSERT(dim >0 && dim <5);
920 m_flags.dim= dim - 1;
921 }
922
is_valid_geotype(uint32 gtype)923 static bool is_valid_geotype(uint32 gtype)
924 {
925 wkbType gt= static_cast<wkbType>(gtype);
926
927 /*
928 Stricter check, outside only checks for [wkb_first, wkb_last],
929 they don't have to know about the details.
930 */
931 return ((gt >= wkb_first && gt <= wkb_geometrycollection) ||
932 gt == wkb_polygon_inner_rings);
933 }
934
is_valid_geotype(Geometry::wkbType gt)935 static bool is_valid_geotype(Geometry::wkbType gt)
936 {
937 /*
938 Stricter check, outside only checks for [wkb_first, wkb_last],
939 they don't have to know about the details.
940 */
941 return ((gt >= wkb_first && gt <= wkb_geometrycollection) ||
942 gt == wkb_polygon_inner_rings);
943 }
944
945 /**
946 Verify that a string is a well-formed GEOMETRY string.
947
948 This does not check if the geometry is geometrically valid.
949
950 @see Geometry_well_formed_checker
951
952 @param from String to check
953 @param length Length of string
954 @param type Expected type of geometry, or
955 Geoemtry::wkb_invalid_type if any type is allowed
956
957 @return True if the string is a well-formed GEOMETRY string,
958 false otherwise
959 */
960 static bool is_well_formed(const char *from, size_t length,
961 wkbType type, wkbByteOrder bo);
962
set_geotype(Geometry::wkbType gt)963 void set_geotype(Geometry::wkbType gt)
964 {
965 is_valid_geotype(gt);
966 m_flags.geotype= static_cast<char>(gt);
967 }
968
969 // Have to make this const because it's called in a const member function.
set_nbytes(size_t n)970 void set_nbytes(size_t n) const
971 {
972 if (get_nbytes() != n)
973 {
974 set_length_verified(false);
975 m_flags.nbytes= n;
976 }
977 }
978
979 /**
980 Set whether this object has its own memory. If so, the memory is released
981 when this object is destroyed.
982 @param b true if this object has its own memory, false otherwise.
983
984 */
set_ownmem(bool b)985 void set_ownmem(bool b)
986 {
987 m_flags.nomem= (b ? 0 : 1);
988 }
989
990 /**
991 Returns whether this object has its own memory. If so, the memory is
992 released when this object is destroyed.
993 */
get_ownmem()994 bool get_ownmem() const
995 {
996 return !m_flags.nomem;
997 }
998
get_byte_order()999 Geometry::wkbByteOrder get_byte_order() const
1000 {
1001 DBUG_ASSERT(m_flags.bo == 1);
1002 return Geometry::wkb_ndr;
1003 }
1004
get_dimension()1005 char get_dimension() const
1006 {
1007 return static_cast<char>(m_flags.dim) + 1;
1008 }
1009
get_geotype()1010 Geometry::wkbType get_geotype() const
1011 {
1012 char gt= static_cast<char>(m_flags.geotype);
1013 return static_cast<Geometry::wkbType>(gt);
1014 }
1015
1016 /**
1017 Build an OGC standard type value from m_flags.zm and m_flags.geotype. For
1018 now m_flags.zm is always 0 so simply call get_geotype(). We don't
1019 directly store the OGC defined values in order to save more bits
1020 of m_flags for other purposes; and also separating zm settings from basic
1021 geometry types is easier for coding and geometry type identification.
1022
1023 When we start to support Z/M settings we need to modify all code which call
1024 write_wkb_header and write_geometry_header to pass to them an OGC standard
1025 type value returned by this function or built similarly. And by doing so
1026 our internal runtime geometry type encoding will work consistently with
1027 OGC defined standard geometry type values in byte strings of WKB format.
1028
1029 @return OGC standard geometry type value.
1030 */
get_ogc_geotype()1031 uint32 get_ogc_geotype() const
1032 {
1033 return static_cast<uint32>(get_geotype());
1034 }
1035
1036
get_nbytes()1037 size_t get_nbytes() const
1038 {
1039 return static_cast<size_t>(m_flags.nbytes);
1040 }
1041
1042 /*
1043 Only sets m_ptr, different from the overloaded one in Gis_wkb_vector<>
1044 which also does WKB parsing.
1045 */
set_ptr(const void * ptr)1046 void set_ptr(const void *ptr)
1047 {
1048 m_ptr= const_cast<void *>(ptr);
1049 }
1050
1051 /**
1052 Whether the Geometry object is created to be used by Boost Geometry or
1053 only by MySQL. There are some operations that only work for one type and
1054 can or must be skipped otherwise.
1055 @return true if it's a BG adapter, false otherwise.
1056 */
is_bg_adapter()1057 bool is_bg_adapter() const
1058 {
1059 return m_flags.props & IS_BOOST_GEOMETRY_ADAPTER;
1060 }
1061
1062 /**
1063 Set whether this object is a BG adapter.
1064 @param b true if it's a BG adapter, false otherwise.
1065 Have to declare this as const because even when a Geometry object's const
1066 adapter member function is called, it's regarded as a BG adapter object.
1067 */
set_bg_adapter(bool b)1068 void set_bg_adapter(bool b) const
1069 {
1070 if (b)
1071 m_flags.props |= IS_BOOST_GEOMETRY_ADAPTER;
1072 else
1073 m_flags.props &= ~IS_BOOST_GEOMETRY_ADAPTER;
1074 }
1075
1076 /*
1077 Give up ownership of m_ptr, so as not to release them when
1078 this object is destroyed, to be called when the two member is shallow
1079 assigned to another geometry object.
1080 */
donate_data()1081 virtual void donate_data()
1082 {
1083 set_ownmem(false);
1084 set_nbytes(0);
1085 m_ptr= NULL;
1086 }
1087 protected:
1088 /**
1089 In a polygon usable by boost geometry, the m_ptr points to the outer ring
1090 object, and m_inn_rings points to the inner rings, thus the polygon's data
1091 isn't stored in a single WKB. Users should call
1092 Gis_polygon::to_wkb_unparsed() before getting the polygon's wkb data,
1093 Gis_polygon::to_wkb_unparsed() will form a single WKB for the polygon
1094 and refer to it with m_ptr, and release the outer ring object
1095 and the inner rings objects, and such an polygon isn't usable by BG any
1096 more, it's exactly what we got with
1097 Geometry::create_from_wkt/Geometry::create_from_wkt.
1098 */
polygon_is_wkb_form()1099 bool polygon_is_wkb_form() const
1100 {
1101 return m_flags.props & POLYGON_IN_WKB_FORM;
1102 }
1103
polygon_is_wkb_form(bool b)1104 void polygon_is_wkb_form(bool b)
1105 {
1106 if (b)
1107 m_flags.props|= POLYGON_IN_WKB_FORM;
1108 else
1109 m_flags.props&= ~POLYGON_IN_WKB_FORM;
1110 }
1111
1112 /**
1113 If call Gis_wkb_vector<T>::resize() to add a component to X, the
1114 geometry may have a geometry not stored inside the WKB buffer of X, hence
1115 X has out of line component. For such an X, user should call
1116 Gis_wkb_vector<T>::reassemble() before fetching its WKB data.
1117 */
has_out_of_line_components()1118 bool has_out_of_line_components() const
1119 {
1120 return m_flags.props & HAS_OUT_OF_LINE_COMPONENTS;
1121 }
1122
has_out_of_line_components(bool b)1123 void has_out_of_line_components(bool b)
1124 {
1125 if (b)
1126 m_flags.props|= HAS_OUT_OF_LINE_COMPONENTS;
1127 else
1128 m_flags.props&= ~HAS_OUT_OF_LINE_COMPONENTS;
1129 }
1130
1131 void clear_wkb_data();
shallow_push(const Geometry *)1132 virtual void shallow_push(const Geometry *)
1133 {
1134 DBUG_ASSERT(false);
1135 }
1136
1137 protected:
1138
1139 /**
1140 The topmost (root) geometry object, whose m_ptr is the 1st byte of a
1141 wkb memory buffer. other geometry objects hold m_ptr which points
1142 inside somewhere in the memory buffer. when updating a geometry object,
1143 need to ask m_owner to reallocate memory if needed for new data.
1144 */
1145 Geometry *m_owner;
1146
1147
1148 /**
1149 Pointer to the geometry's wkb data's 1st byte, right after its
1150 wkb header if any.
1151 If the geometry is wkb_polygon, this field is a
1152 Gis_polygon_ring* pointer, pointing to the outer ring. Outer ring's wkb data
1153 is in the same wkb buffer as the inner rings, so we can get the wkb header
1154 from the outer ring like ((Geometry*)m_ptr)->get_ptr().
1155 */
1156 void *m_ptr;
1157 private:
1158
1159 /// Flags and meta information about this object.
1160 /// Make it mutable to modify some flags in const member functions.
1161 mutable Flags_t m_flags;
1162
1163 /// Srid of this object.
1164 srid_t m_srid;
1165 public:
1166
get_flags()1167 Flags_t get_flags() const {return m_flags;}
1168
set_flags(const Flags_t & flags)1169 void set_flags(const Flags_t &flags)
1170 {
1171 m_flags= flags;
1172 }
1173 };
1174
1175
get_byte_order(const void * p0)1176 inline Geometry::wkbByteOrder get_byte_order(const void *p0)
1177 {
1178 const char *p= static_cast<const char *>(p0);
1179
1180 if (!(*p == 0 || *p == 1))
1181 return Geometry::wkb_invalid;
1182 return *p == 0 ? Geometry::wkb_xdr : Geometry::wkb_ndr;
1183 }
1184
set_byte_order(void * p0,Geometry::wkbByteOrder bo)1185 inline void set_byte_order(void *p0, Geometry::wkbByteOrder bo)
1186 {
1187 char *p= static_cast<char *>(p0);
1188 *p= (bo == Geometry::wkb_ndr ? 1 : 0);
1189 }
1190
1191 /**
1192 Get wkbType value from WKB, the WKB is always little endian, so need
1193 platform specific conversion.
1194 @param p0 WKB geometry type field address.
1195 @return geometry type.
1196 */
get_wkb_geotype(const void * p0)1197 inline Geometry::wkbType get_wkb_geotype(const void *p0)
1198 {
1199 const char *p= static_cast<const char *>(p0);
1200 uint32 gt= uint4korr(p);
1201 DBUG_ASSERT(Geometry::is_valid_geotype(gt));
1202 return static_cast<Geometry::wkbType>(gt);
1203 }
1204
1205 /*
1206 Functions to write a GEOMETRY or WKB header into a piece of allocated and
1207 big enough raw memory or into a String object with enough reserved memory,
1208 and optionally append the object count right after the header.
1209 */
write_wkb_header(void * p0,Geometry::wkbType geotype)1210 inline char *write_wkb_header(void *p0, Geometry::wkbType geotype)
1211 {
1212 char *p= static_cast<char *>(p0);
1213 *p= static_cast<char>(Geometry::wkb_ndr);
1214 p++;
1215 int4store(p, static_cast<uint32>(geotype));
1216 return p + 4;
1217 }
1218
1219
write_wkb_header(void * p0,Geometry::wkbType geotype,uint32 obj_count)1220 inline char *write_wkb_header(void *p0, Geometry::wkbType geotype,
1221 uint32 obj_count)
1222 {
1223 char *p= static_cast<char *>(p0);
1224 p= write_wkb_header(p, geotype);
1225 int4store(p, obj_count);
1226 return p + 4;
1227 }
1228
1229
write_geometry_header(void * p0,uint32 srid,Geometry::wkbType geotype)1230 inline char *write_geometry_header(void *p0, uint32 srid,
1231 Geometry::wkbType geotype)
1232 {
1233 char *p= static_cast<char *>(p0);
1234 int4store(p, srid);
1235 return write_wkb_header(p + 4, geotype);
1236 }
1237
1238
write_geometry_header(void * p0,uint32 srid,Geometry::wkbType geotype,uint32 obj_count)1239 inline char *write_geometry_header(void *p0, uint32 srid,
1240 Geometry::wkbType geotype, uint32 obj_count)
1241 {
1242 char *p= static_cast<char *>(p0);
1243 int4store(p, srid);
1244 return write_wkb_header(p + 4, geotype, obj_count);
1245 }
1246
1247
write_wkb_header(String * str,Geometry::wkbType geotype)1248 inline void write_wkb_header(String *str, Geometry::wkbType geotype)
1249 {
1250 str->q_append(static_cast<char>(Geometry::wkb_ndr));
1251 str->q_append(static_cast<uint32>(geotype));
1252 }
1253
1254
write_wkb_header(String * str,Geometry::wkbType geotype,uint32 obj_count)1255 inline void write_wkb_header(String *str, Geometry::wkbType geotype,
1256 uint32 obj_count)
1257 {
1258 write_wkb_header(str, geotype);
1259 str->q_append(obj_count);
1260 }
1261
1262
write_geometry_header(String * str,uint32 srid,Geometry::wkbType geotype)1263 inline void write_geometry_header(String *str, uint32 srid,
1264 Geometry::wkbType geotype)
1265 {
1266 str->q_append(srid);
1267 write_wkb_header(str, geotype);
1268 }
1269
1270
write_geometry_header(String * str,uint32 srid,Geometry::wkbType geotype,uint32 obj_count)1271 inline void write_geometry_header(String *str, uint32 srid,
1272 Geometry::wkbType geotype, uint32 obj_count)
1273 {
1274 write_geometry_header(str, srid, geotype);
1275 str->q_append(obj_count);
1276 }
1277
1278
1279 /***************************** Point *******************************/
1280
1281 class Gis_point: public Geometry
1282 {
1283 public:
1284 uint32 get_data_size() const;
1285 bool init_from_wkt(Gis_read_stream *trs, String *wkb);
1286 uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
1287 bool get_data_as_wkt(String *txt, wkb_parser *wkb) const;
1288 bool get_mbr(MBR *mbr, wkb_parser *wkb) const;
1289
get_xy(point_xy * p)1290 int get_xy(point_xy *p) const
1291 {
1292 wkb_parser wkb(get_cptr(), get_cptr() + get_nbytes());
1293 return wkb.scan_xy(p);
1294 }
get_x(double * x)1295 int get_x(double *x) const
1296 {
1297 wkb_parser wkb(get_cptr(), get_cptr() + get_nbytes());
1298 return wkb.scan_coord(x);
1299 }
get_y(double * y)1300 int get_y(double *y) const
1301 {
1302 wkb_parser wkb(get_cptr(), get_cptr() + get_nbytes());
1303 return wkb.skip_coord() || wkb.scan_coord(y);
1304 }
feature_dimension()1305 uint32 feature_dimension() const { return 0; }
1306 const Class_info *get_class_info() const;
1307
1308
1309 /************* Boost Geometry Adapter Interface *************/
1310
1311
1312 typedef Gis_point self;
1313 typedef Geometry base;
1314
1315 explicit Gis_point(bool is_bg_adapter= true)
1316 :Geometry(NULL, 0, Flags_t(wkb_point, 0), default_srid)
1317 {
1318 set_ownmem(false);
1319 set_bg_adapter(is_bg_adapter);
1320 }
1321
1322 /// @brief Default constructor, no initialization.
Gis_point(const void * ptr,size_t nbytes,const Flags_t & flags,srid_t srid)1323 Gis_point(const void *ptr, size_t nbytes, const Flags_t &flags, srid_t srid)
1324 :Geometry(ptr, nbytes, flags, srid)
1325 {
1326 set_geotype(wkb_point);
1327 DBUG_ASSERT((ptr != NULL &&
1328 get_nbytes() == SIZEOF_STORED_DOUBLE * GEOM_DIM) ||
1329 (ptr == NULL && get_nbytes() == 0));
1330 set_ownmem(false);
1331 set_bg_adapter(true);
1332 }
1333
1334 Gis_point(const self &pt);
1335
~Gis_point()1336 virtual ~Gis_point()
1337 {}
1338
1339
1340 Gis_point &operator=(const Gis_point &rhs);
1341
1342 void set_ptr(void *ptr, size_t len);
1343
1344
1345 /// @brief Get a coordinate
1346 /// @tparam K coordinate to get
1347 /// @return the coordinate
1348 template <std::size_t K>
get()1349 double get() const
1350 {
1351 DBUG_ASSERT(K < static_cast<size_t>(get_dimension()) &&
1352 ((m_ptr != NULL &&
1353 get_nbytes() == SIZEOF_STORED_DOUBLE * GEOM_DIM) ||
1354 (m_ptr == NULL && get_nbytes() == 0)));
1355
1356 set_bg_adapter(true);
1357 const char *p= static_cast<char *>(m_ptr) + K * SIZEOF_STORED_DOUBLE;
1358 double val;
1359
1360 /*
1361 Boost Geometry may use a point that is only default constructed that
1362 has not specified with any meaningful value, and in such a case the
1363 default value are expected to be all zeros.
1364 */
1365 if (m_ptr == NULL)
1366 return 0;
1367
1368 float8get(&val, p);
1369 return val;
1370 }
1371
1372
1373 /// @brief Set a coordinate
1374 /// @tparam K coordinate to set
1375 /// @param value value to set
1376 // Deep assignment, not only allow assigning to a point owning its memory,
1377 // but also a point not own memory, since points are of same size.
1378 template <std::size_t K>
set(double const & value)1379 void set(double const &value)
1380 {
1381 /* Allow assigning to others' memory. */
1382 DBUG_ASSERT((m_ptr != NULL && K < static_cast<size_t>(get_dimension()) &&
1383 get_nbytes() == SIZEOF_STORED_DOUBLE * GEOM_DIM) ||
1384 (!get_ownmem() && get_nbytes() == 0 && m_ptr == NULL));
1385 set_bg_adapter(true);
1386 if (m_ptr == NULL)
1387 {
1388 m_ptr= gis_wkb_fixed_alloc(SIZEOF_STORED_DOUBLE * GEOM_DIM);
1389 if (m_ptr == NULL)
1390 {
1391 set_ownmem(false);
1392 set_nbytes(0);
1393 return;
1394 }
1395 set_ownmem(true);
1396 set_nbytes(SIZEOF_STORED_DOUBLE * GEOM_DIM);
1397 }
1398
1399 char *p= get_cptr() + K * SIZEOF_STORED_DOUBLE;
1400 float8store(p, value);
1401 }
1402
1403
1404 bool operator<(const Gis_point &pt) const
1405 {
1406 bool x= get<0>(), px= pt.get<0>();
1407 return x == px ? get<1>() < pt.get<1>() : x < px;
1408 }
1409
1410 bool operator==(const Gis_point &pt) const
1411 {
1412 return (get<0>() == pt.get<0>() && get<1>() == pt.get<1>());
1413 }
1414
1415 bool operator!=(const Gis_point &pt) const
1416 {
1417 return !(operator==(pt));
1418 }
1419 };
1420
1421
1422 /******************************** Gis_wkb_vector **************************/
1423
1424
1425 template <typename T>
1426 class Gis_wkb_vector;
1427
1428 /// @ingroup iterators
1429 /// @{
1430 /// @defgroup Gis_wkb_vector_iterators Iterator classes for Gis_wkb_vector.
1431 /// Gis_wkb_vector has two iterator classes --- Gis_wkb_vector_const_iterator
1432 /// and Gis_wkb_vector_iterator. The differences
1433 /// between the two classes are that the Gis_wkb_vector_const_iterator
1434 /// can only be used to read its referenced value, so it is intended as
1435 /// Gis_wkb_vector's const iterator; While the other class allows both read and
1436 /// write access. If your access pattern is readonly, it is strongly
1437 /// recommended that you use the const iterator because it is faster
1438 /// and more efficient.
1439 /// The two classes have identical behaviors to std::vector::const_iterator and
1440 /// std::vector::iterator respectively.
1441 //@{
1442 ///////////////////////////////////////////////////////////////////////
1443 ///////////////////////////////////////////////////////////////////////
1444 //
1445 // Gis_wkb_vector_const_iterator class template definition
1446 //
1447 /// Gis_wkb_vector_const_iterator is const_iterator class for Gis_wkb_vector,
1448 /// and base class of Gis_wkb_vector_iterator -- iterator class for
1449 /// Gis_wkb_vector.
1450 /// @tparam T Vector element type
1451 template <typename T>
1452 class Gis_wkb_vector_const_iterator
1453 {
1454 protected:
1455 typedef Gis_wkb_vector_const_iterator<T> self;
1456 typedef Gis_wkb_vector<T> owner_t;
1457 typedef ptrdiff_t index_type;
1458 public:
1459 ////////////////////////////////////////////////////////////////////
1460 //
1461 // Begin public type definitions.
1462 //
1463 typedef T value_type;
1464 typedef ptrdiff_t difference_type;
1465 typedef difference_type distance_type;
1466 typedef typename owner_t::size_type size_type;
1467
1468 /// This is the return type for operator[].
1469 typedef value_type& reference;
1470 typedef value_type* pointer;
1471 // Use the STL tag, to ensure compatability with interal STL functions.
1472 //
1473 typedef std::random_access_iterator_tag iterator_category;
1474 ////////////////////////////////////////////////////////////////////
1475
1476 ////////////////////////////////////////////////////////////////////
1477 // Begin public constructors and destructor.
1478 /// @name Constructors and destroctor
1479 /// Do not construct iterators explictily using these constructors,
1480 /// but call Gis_wkb_vector::begin() const to get an valid iterator.
1481 /// @sa Gis_wkb_vector::begin() const
1482 //@{
Gis_wkb_vector_const_iterator(const self & vi)1483 Gis_wkb_vector_const_iterator(const self &vi)
1484 {
1485 m_curidx= vi.m_curidx;
1486 m_owner= vi.m_owner;
1487 }
1488
1489
Gis_wkb_vector_const_iterator()1490 Gis_wkb_vector_const_iterator()
1491 {
1492 m_curidx= -1;
1493 m_owner= NULL;
1494 }
1495
1496
Gis_wkb_vector_const_iterator(index_type idx,const owner_t * owner)1497 Gis_wkb_vector_const_iterator(index_type idx, const owner_t *owner)
1498 {
1499 m_curidx= idx;
1500 m_owner= const_cast<owner_t *>(owner);
1501 }
1502
1503
~Gis_wkb_vector_const_iterator()1504 ~Gis_wkb_vector_const_iterator()
1505 {
1506 }
1507 //@}
1508
1509 ////////////////////////////////////////////////////////////////////
1510
1511 ////////////////////////////////////////////////////////////////////
1512 //
1513 // Begin functions that compare iterator positions.
1514 //
1515 /// @name Iterator comparison operators
1516 /// The way to compare two iterators is to compare the index values
1517 /// of the two elements they point to. The iterator sitting on an
1518 /// element with less index is regarded to be smaller. And the invalid
1519 /// iterator sitting after last element is greater than any other
1520 /// iterators, because it is assumed to have an index equal to last
1521 /// element's index plus one; The invalid iterator sitting before first
1522 /// element is less than any other iterators because it is assumed to
1523 /// have an index -1.
1524 //@{
1525 /// @brief Equality comparison operator.
1526 ///
1527 /// Invalid iterators are equal; Valid iterators
1528 /// sitting on the same key/data pair equal; Otherwise not equal.
1529 /// @param itr The iterator to compare against.
1530 /// @return True if this iterator equals to itr; False otherwise.
1531 bool operator==(const self &itr) const
1532 {
1533 DBUG_ASSERT(m_owner == itr.m_owner);
1534 return m_curidx == itr.m_curidx;
1535 }
1536
1537
1538 /// @brief Unequal compare, identical to !operator(==itr)
1539 /// @param itr The iterator to compare against.
1540 /// @return False if this iterator equals to itr; True otherwise.
1541 bool operator!=(const self &itr) const
1542 {
1543 return !(*this == itr) ;
1544 }
1545
1546
1547 // The end() iterator is largest. If both are end() iterator return false.
1548 /// @brief Less than comparison operator.
1549 /// @param itr The iterator to compare against.
1550 /// @return True if this iterator is less than itr.
1551 bool operator < (const self &itr) const
1552 {
1553 DBUG_ASSERT(m_owner == itr.m_owner);
1554 return m_curidx < itr.m_curidx;
1555 }
1556
1557
1558 /// @brief Less equal comparison operator.
1559 /// @param itr The iterator to compare against.
1560 /// @return True if this iterator is less than or equal to itr.
1561 bool operator <= (const self &itr) const
1562 {
1563 return !(this->operator>(itr));
1564 }
1565
1566
1567 /// @brief Greater equal comparison operator.
1568 /// @param itr The iterator to compare against.
1569 /// @return True if this iterator is greater than or equal to itr.
1570 bool operator >= (const self &itr) const
1571 {
1572 return !(this->operator<(itr));
1573 }
1574
1575
1576 // The end() iterator is largest. If both are end() iterator return false.
1577 /// @brief Greater comparison operator.
1578 /// @param itr The iterator to compare against.
1579 /// @return True if this iterator is greater than itr.
1580 bool operator > (const self &itr) const
1581 {
1582 DBUG_ASSERT(m_owner == itr.m_owner);
1583 return m_curidx > itr.m_curidx;
1584 }
1585 //@} // vctitr_cmp
1586 ////////////////////////////////////////////////////////////////////
1587
1588
1589 ////////////////////////////////////////////////////////////////////
1590 //
1591 // Begin functions that shift the iterator position.
1592 //
1593 /// @name Iterator movement operators.
1594 /// When we talk about iterator movement, we think the
1595 /// container is a uni-directional range, represented by [begin, end),
1596 /// and this is true no matter we are using iterators or reverse
1597 /// iterators. When an iterator is moved closer to "begin", we say it
1598 /// is moved backward, otherwise we say it is moved forward.
1599 //@{
1600 /// @brief Pre-increment.
1601 ///
1602 /// Move the iterator one element forward, so that
1603 /// the element it sits on has a bigger index.
1604 /// Use ++iter rather than iter++ where possible to avoid two useless
1605 /// iterator copy constructions.
1606 /// @return This iterator after incremented.
1607 self &operator++()
1608 {
1609 move_by(*this, 1, false);
1610 return *this;
1611 }
1612
1613
1614 /// @brief Post-increment.
1615 /// Move the iterator one element forward, so that
1616 /// the element it sits on has a bigger index.
1617 /// Use ++iter rather than iter++ where possible to avoid two useless
1618 /// iterator copy constructions.
1619 /// @return A new iterator not incremented.
1620 self operator++(int)
1621 {
1622 self itr(*this);
1623 move_by(*this, 1, false);
1624
1625 return itr;
1626 }
1627
1628
1629 /// @brief Pre-decrement.
1630 /// Move the iterator one element backward, so
1631 /// that the element it sits on has a smaller index.
1632 /// Use --iter rather than iter-- where possible to avoid two useless
1633 /// iterator copy constructions.
1634 /// @return This iterator after decremented.
1635 self &operator--()
1636 {
1637 move_by(*this, 1, true);
1638 return *this;
1639 }
1640
1641
1642 /// @brief Post-decrement.
1643 ///
1644 /// Move the iterator one element backward, so
1645 /// that the element it sits on has a smaller index.
1646 /// Use --iter rather than iter-- where possible to avoid two useless
1647 /// iterator copy constructions.
1648 /// @return A new iterator not decremented.
1649 self operator--(int)
1650 {
1651 self itr= *this;
1652 move_by(*this, 1, true);
1653 return itr;
1654 }
1655
1656
1657 /// @brief Assignment operator.
1658 ///
1659 /// This iterator will point to the same key/data
1660 /// pair as itr, and have the same configurations as itr.
1661 /// @param itr The right value of the assignment.
1662 /// @return This iterator's reference.
1663 const self &operator=(const self &itr)
1664 {
1665 m_curidx= itr.m_curidx;
1666 m_owner= itr.m_owner;
1667 return itr;
1668 }
1669
1670
1671 /// Iterator movement operator.
1672 /// Return another iterator by moving this iterator forward by n
1673 /// elements.
1674 /// @param n The amount and direction of movement. If negative, will
1675 /// move backward by |n| element.
1676 /// @return The new iterator at new position.
1677 self operator+(difference_type n) const
1678 {
1679 self itr(*this);
1680 move_by(itr, n, false);
1681 return itr;
1682 }
1683
1684
1685 /// @brief Move this iterator forward by n elements.
1686 /// @param n The amount and direction of movement. If negative, will
1687 /// move backward by |n| element.
1688 /// @return Reference to this iterator at new position.
1689 const self &operator+=(difference_type n)
1690 {
1691 move_by(*this, n, false);
1692 return *this;
1693 }
1694
1695
1696 /// @brief Iterator movement operator.
1697 ///
1698 /// Return another iterator by moving this iterator backward by n
1699 /// elements.
1700 /// @param n The amount and direction of movement. If negative, will
1701 /// move forward by |n| element.
1702 /// @return The new iterator at new position.
1703 self operator-(difference_type n) const
1704 {
1705 self itr(*this);
1706 move_by(itr, n, true);
1707
1708 return itr;
1709 }
1710
1711
1712 /// @brief Move this iterator backward by n elements.
1713 /// @param n The amount and direction of movement. If negative, will
1714 /// move forward by |n| element.
1715 /// @return Reference to this iterator at new position.
1716 const self &operator-=(difference_type n)
1717 {
1718 move_by(*this, n, true);
1719 return *this;
1720 }
1721 //@} //itr_movement
1722
1723
1724 /// @brief Iterator distance operator.
1725 ///
1726 /// Return the index difference of this iterator and itr, so if this
1727 /// iterator sits on an element with a smaller index, this call will
1728 /// return a negative number.
1729 /// @param itr The other iterator to substract. itr can be the invalid
1730 /// iterator after last element or before first element, their index
1731 /// will be regarded as last element's index + 1 and -1 respectively.
1732 /// @return The index difference.
1733 difference_type operator-(const self &itr) const
1734 {
1735 DBUG_ASSERT(m_owner == itr.m_owner);
1736 return (m_curidx - itr.m_curidx);
1737 }
1738
1739
1740 ////////////////////////////////////////////////////////////////////
1741 //
1742 // Begin functions that retrieve values from the iterator.
1743 //
1744 /// @name Functions that retrieve values from the iterator.
1745 //@{
1746 /// @brief Dereference operator.
1747 ///
1748 /// Return the reference to the cached data element.
1749 /// The returned value can only be used to read its referenced
1750 /// element.
1751 /// @return The reference to the element this iterator points to.
1752 reference operator*() const
1753 {
1754 DBUG_ASSERT(this->m_owner != NULL && this->m_curidx >= 0 &&
1755 this->m_curidx <
1756 static_cast<index_type>(this->m_owner->size()));
1757 return (*m_owner)[m_curidx];
1758 }
1759
1760
1761 /// @brief Arrow operator.
1762 ///
1763 /// Return the pointer to the cached data element.
1764 /// The returned value can only be used to read its referenced
1765 /// element.
1766 /// @return The address of the referenced object.
1767 pointer operator->() const
1768 {
1769 DBUG_ASSERT(this->m_owner != NULL && this->m_curidx >= 0 &&
1770 this->m_curidx <
1771 static_cast<index_type>(this->m_owner->size()));
1772 return &(*m_owner)[m_curidx];
1773 }
1774
1775
1776 /// @brief Iterator index operator.
1777 ///
1778 /// @param offset The offset of target element relative to this iterator.
1779 /// @return Return the reference of the element which is at
1780 /// position *this + offset.
1781 /// The returned value can only be used to read its referenced
1782 /// element.
1783 reference operator[](difference_type offset) const
1784 {
1785 self itr= *this;
1786 move_by(itr, offset, false);
1787
1788 DBUG_ASSERT(itr.m_owner != NULL && itr.m_curidx >= 0 &&
1789 itr.m_curidx < static_cast<index_type>(itr.m_owner->size()));
1790 return (*m_owner)[itr.m_curidx];
1791 }
1792 //@}
1793 ////////////////////////////////////////////////////////////////////
1794
1795
1796 protected:
1797 // The 'back' parameter indicates whether to decrease or
1798 // increase the index when moving. The default is to decrease.
1799 //
move_by(self & itr,difference_type n,bool back)1800 void move_by(self &itr, difference_type n, bool back) const
1801 {
1802 if (back)
1803 n= -n;
1804
1805 index_type newidx= itr.m_curidx + n;
1806 size_t sz= 0;
1807
1808 if (newidx < 0)
1809 newidx= -1;
1810 else if (newidx >= static_cast<index_type>((sz= m_owner->size())))
1811 newidx= sz;
1812
1813 itr.m_curidx= newidx;
1814 }
1815
1816
1817 protected:
1818 /// Current element's index, starting from 0.
1819 index_type m_curidx;
1820 /// The owner container of this iteraotr.
1821 owner_t *m_owner;
1822 }; // Gis_wkb_vector_const_iterator<>
1823
1824
1825 ///////////////////////////////////////////////////////////////////////
1826 ///////////////////////////////////////////////////////////////////////
1827 //
1828 // Gis_wkb_vector_iterator class template definition
1829 /// This class is the iterator class for Gis_wkb_vector, its instances can
1830 /// be used to mutate their referenced data element.
1831 /// @tparam T Vector element type
1832 //
1833 template <class T>
1834 class Gis_wkb_vector_iterator :public Gis_wkb_vector_const_iterator<T>
1835 {
1836 protected:
1837 typedef Gis_wkb_vector_iterator<T> self;
1838 typedef Gis_wkb_vector_const_iterator<T> base;
1839 typedef Gis_wkb_vector<T> owner_t;
1840 public:
1841 typedef ptrdiff_t index_type;
1842 typedef T value_type;
1843 typedef ptrdiff_t difference_type;
1844 typedef difference_type distance_type;
1845 typedef value_type& reference;
1846 typedef value_type* pointer;
1847 // Use the STL tag, to ensure compatability with interal STL functions.
1848 typedef std::random_access_iterator_tag iterator_category;
1849
1850
1851 ////////////////////////////////////////////////////////////////////
1852 /// Begin public constructors and destructor.
1853 //
1854 /// @name Constructors and destructor
1855 /// Do not construct iterators explictily using these constructors,
1856 /// but call Gis_wkb_vector::begin to get an valid iterator.
1857 /// @sa Gis_wkb_vector::begin
1858 //@{
Gis_wkb_vector_iterator(const self & vi)1859 Gis_wkb_vector_iterator(const self &vi) :base(vi)
1860 {
1861 }
1862
1863
Gis_wkb_vector_iterator()1864 Gis_wkb_vector_iterator() :base()
1865 {
1866 }
1867
1868
Gis_wkb_vector_iterator(const base & obj)1869 Gis_wkb_vector_iterator(const base &obj) :base(obj)
1870 {
1871 }
1872
1873
Gis_wkb_vector_iterator(index_type idx,const owner_t * owner)1874 Gis_wkb_vector_iterator(index_type idx, const owner_t *owner)
1875 :base(idx, owner)
1876 {}
1877
1878
~Gis_wkb_vector_iterator()1879 ~Gis_wkb_vector_iterator()
1880 {
1881 }
1882 //@}
1883
1884
1885 ////////////////////////////////////////////////////////////////////
1886
1887
1888 ////////////////////////////////////////////////////////////////////
1889 //
1890 /// Begin functions that shift the iterator position.
1891 //
1892 /// These functions are identical to those defined in
1893 /// Gis_wkb_vector_const_iterator, but we have to redefine them here because
1894 /// the "self" have different definitions.
1895 //
1896 /// @name Iterator movement operators.
1897 /// These functions have identical behaviors and semantics as those of
1898 /// Gis_wkb_vector_const_iterator, so please refer to equivalent in that
1899 /// class.
1900 //@{
1901 /// @brief Pre-increment.
1902 /// @return This iterator after incremented.
1903 /// @sa Gis_wkb_vector_const_iterator::operator++()
1904 self &operator++()
1905 {
1906 this->move_by(*this, 1, false);
1907 return *this;
1908 }
1909
1910
1911 /// @brief Post-increment.
1912 /// @return A new iterator not incremented.
1913 /// @sa Gis_wkb_vector_const_iterator::operator++(int)
1914 self operator++(int)
1915 {
1916 self itr(*this);
1917 this->move_by(*this, 1, false);
1918
1919 return itr;
1920 }
1921
1922
1923 /// @brief Pre-decrement.
1924 /// @return This iterator after decremented.
1925 /// @sa Gis_wkb_vector_const_iterator::operator--()
1926 self &operator--()
1927 {
1928 this->move_by(*this, 1, true);
1929 return *this;
1930 }
1931
1932
1933 /// @brief Post-decrement.
1934 /// @return A new iterator not decremented.
1935 /// @sa Gis_wkb_vector_const_iterator::operator--(int)
1936 self operator--(int)
1937 {
1938 self itr= *this;
1939 this->move_by(*this, 1, true);
1940 return itr;
1941 }
1942
1943
1944 /// @brief Assignment operator.
1945 ///
1946 /// This iterator will point to the same key/data
1947 /// pair as itr, and have the same configurations as itr.
1948 /// @param itr The right value of the assignment.
1949 /// @return This iterator's reference.
1950 const self &operator=(const self &itr)
1951 {
1952 base::operator=(itr);
1953
1954 return itr;
1955 }
1956
1957
1958 /// @brief Iterator movement operator.
1959 ///
1960 /// Return another iterator by moving this iterator backward by n
1961 /// elements.
1962 /// @param n The amount and direction of movement. If negative, will
1963 /// move forward by |n| element.
1964 /// @return The new iterator at new position.
1965 /// @sa Gis_wkb_vector_const_iterator::operator+(difference_type n) const
1966 self operator+(difference_type n) const
1967 {
1968 self itr(*this);
1969 this->move_by(itr, n, false);
1970 return itr;
1971 }
1972
1973
1974 /// @brief Move this iterator backward by n elements.
1975 /// @param n The amount and direction of movement. If negative, will
1976 /// move forward by |n| element.
1977 /// @return Reference to this iterator at new position.
1978 /// @sa Gis_wkb_vector_const_iterator::operator+=(difference_type n)
1979 const self &operator+=(difference_type n)
1980 {
1981 this->move_by(*this, n, false);
1982 return *this;
1983 }
1984
1985
1986 /// @brief Iterator movement operator.
1987 ///
1988 /// Return another iterator by moving this iterator forward by n
1989 /// elements.
1990 /// @param n The amount and direction of movement. If negative, will
1991 /// move backward by |n| element.
1992 /// @return The new iterator at new position.
1993 /// @sa Gis_wkb_vector_const_iterator::operator-(difference_type n) const
1994 self operator-(difference_type n) const
1995 {
1996 self itr(*this);
1997 this->move_by(itr, n, true);
1998
1999 return itr;
2000 }
2001
2002
2003 /// @brief Move this iterator forward by n elements.
2004 /// @param n The amount and direction of movement. If negative, will
2005 /// move backward by |n| element.
2006 /// @return Reference to this iterator at new position.
2007 /// @sa Gis_wkb_vector_const_iterator::operator-=(difference_type n)
2008 const self &operator-=(difference_type n)
2009 {
2010 this->move_by(*this, n, true);
2011 return *this;
2012 }
2013 //@} // itr_movement
2014
2015 /// @brief Iterator distance operator.
2016 ///
2017 /// Return the index difference of this iterator and itr, so if this
2018 /// iterator sits on an element with a smaller index, this call will
2019 /// return a negative number.
2020 /// @param itr The other iterator to substract. itr can be the invalid
2021 /// iterator after last element or before first element, their index
2022 /// will be regarded as last element's index + 1 and -1 respectively.
2023 /// @return The index difference.
2024 /// @sa Gis_wkb_vector_const_iterator::operator-(const self &itr) const
2025 difference_type operator-(const self &itr) const
2026 {
2027 return base::operator-(itr);
2028 }
2029 ////////////////////////////////////////////////////////////////////
2030
2031
2032 ////////////////////////////////////////////////////////////////////
2033 //
2034 // Begin functions that retrieve values from the iterator.
2035 //
2036 /// @name Functions that retrieve values from the iterator.
2037 //@{
2038 /// @brief Dereference operator.
2039 ///
2040 /// Return the reference to the cached data element
2041 /// The returned value can be used to read or update its referenced
2042 /// element.
2043 /// @return The reference to the element this iterator points to.
2044 reference operator*() const
2045 {
2046 DBUG_ASSERT(this->m_owner != NULL && this->m_curidx >= 0 &&
2047 this->m_curidx <
2048 static_cast<index_type>(this->m_owner->size()));
2049 return (*this->m_owner)[this->m_curidx];
2050 }
2051
2052
2053 /// @brief Arrow operator.
2054 ///
2055 /// Return the pointer to the cached data element
2056 /// The returned value can be used to read or update its referenced
2057 /// element.
2058 /// @return The address of the referenced object.
2059 pointer operator->() const
2060 {
2061 DBUG_ASSERT(this->m_owner != NULL && this->m_curidx >= 0 &&
2062 this->m_curidx <
2063 static_cast<index_type>(this->m_owner->size()));
2064 return &(*this->m_owner)[this->m_curidx];
2065 }
2066
2067
2068 /// @brief Iterator index operator.
2069 ///
2070 /// @param offset The offset of target element relative to this iterator.
2071 /// @return Return the element which is at position *this + offset.
2072 /// The returned value can be used to read or update its referenced
2073 /// element.
2074 reference operator[](difference_type offset) const
2075 {
2076 self itr= *this;
2077 this->move_by(itr, offset, false);
2078 DBUG_ASSERT(itr.m_owner != NULL && itr.m_curidx >= 0 &&
2079 itr.m_curidx < static_cast<index_type>(this->m_owner->size()));
2080 return (*this->m_owner)[itr.m_curidx];
2081 }
2082 //@} // funcs_val
2083 ////////////////////////////////////////////////////////////////////
2084
2085 }; // Gis_wkb_vector_iterator
2086 //@} // Gis_wkb_vector_iterators
2087 //@} // iterators
2088
2089
2090 // These operators make "n + itr" expressions valid. Without it, you can only
2091 // use "itr + n"
2092 template <typename T>
2093 Gis_wkb_vector_const_iterator<T>
2094 operator+(typename Gis_wkb_vector_const_iterator<T>::difference_type n,
2095 const Gis_wkb_vector_const_iterator<T> &itr)
2096 {
2097 Gis_wkb_vector_const_iterator<T> itr2= itr;
2098
2099 itr2+= n;
2100 return itr2;
2101 }
2102
2103
2104 template <typename T>
2105 Gis_wkb_vector_iterator<T>
2106 operator+(typename Gis_wkb_vector_iterator<T>::difference_type n,
2107 const Gis_wkb_vector_iterator<T>& itr)
2108 {
2109 Gis_wkb_vector_iterator<T> itr2= itr;
2110
2111 itr2+= n;
2112 return itr2;
2113 }
2114
2115
2116 void *get_packed_ptr(const Geometry *geo, size_t *pnbytes);
2117 const char *get_packed_ptr(Geometry *geo);
2118 bool polygon_is_packed(Geometry *plgn, Geometry *mplgn);
2119 void own_rings(Geometry *geo);
2120 void parse_wkb_data(Geometry *g, const char *p, size_t num_geoms= 0);
2121
2122 /**
2123 Geometry vector class.
2124 @tparam T Vector element type.
2125 */
2126 template<typename T>
2127 class Geometry_vector : public Inplace_vector<T>
2128 {
2129 typedef Inplace_vector<T> base;
2130 public:
Geometry_vector()2131 Geometry_vector() :base(PSI_INSTRUMENT_ME)
2132 {}
2133 };
2134
2135
2136 /// @ingroup containers
2137 //@{
2138 ////////////////////////////////////////////////////////////////////////
2139 ////////////////////////////////////////////////////////////////////////
2140 //
2141 /// Gis_wkb_vector class template definition
2142 /// @tparam T Vector element type
2143 //
2144 template <typename T>
2145 class Gis_wkb_vector : public Geometry
2146 {
2147 private:
2148 typedef Gis_wkb_vector<T> self;
2149 typedef ptrdiff_t index_type;
2150 typedef Geometry base;
2151 public:
2152 typedef T value_type;
2153 typedef Gis_wkb_vector_const_iterator<T> const_iterator;
2154 typedef Gis_wkb_vector_iterator<T> iterator;
2155 typedef size_t size_type;
2156 typedef const T* const_pointer;
2157 typedef const T& const_reference;
2158 typedef T* pointer;
2159 typedef T& reference;
2160 typedef ptrdiff_t difference_type;
2161
2162 typedef Geometry_vector<T> Geo_vector;
2163
2164 private:
2165
2166 /**
2167 The geometry vector of this geometry object's components, each of which
2168 is an object of Geometry or its children classes where appropriate.
2169 */
2170 Geo_vector *m_geo_vect;
2171 public:
2172 /////////////////////////////////////////////////////////////////////
2173 // Begin functions that create iterators.
2174 /// @name Iterator functions.
2175 //@{
begin()2176 iterator begin()
2177 {
2178 set_bg_adapter(true);
2179 iterator itr(m_geo_vect ? 0 : -1, this);
2180 return itr;
2181 }
2182
2183
2184 /// @brief Create a const iterator.
2185 ///
2186 /// The created iterator can only be used to read its referenced
2187 /// data element. Can only be called when using a const reference to
2188 /// the contaienr object.
begin()2189 const_iterator begin()const
2190 {
2191 set_bg_adapter(true);
2192 const_iterator itr(m_geo_vect ? 0 : -1, this);
2193 return itr;
2194 }
2195
2196
2197 /// @brief Create an open boundary iterator.
2198 /// @return Returns an invalid iterator denoting the position after
2199 /// the last valid element of the container.
end()2200 iterator end()
2201 {
2202 iterator itr(m_geo_vect ? m_geo_vect->size() : -1, this);
2203 return itr;
2204 }
2205
2206
2207 /// @brief Create an open boundary iterator.
2208 /// @return Returns an invalid const iterator denoting the position
2209 /// after the last valid element of the container.
end()2210 const_iterator end() const
2211 {
2212 const_iterator itr(m_geo_vect ? m_geo_vect->size() : -1, this);
2213 return itr;
2214 }
2215
2216
2217 //@} // iterator_funcs
2218 /////////////////////////////////////////////////////////////////////
2219
2220 /// @brief Get container size.
2221 /// @return Return the number of elements in this container.
size()2222 size_type size() const
2223 {
2224 set_bg_adapter(true);
2225 return m_geo_vect ? m_geo_vect->size() : 0;
2226 }
2227
2228
empty()2229 bool empty() const
2230 {
2231 return size() == 0;
2232 }
2233
2234
back()2235 const_reference back() const
2236 {
2237 set_bg_adapter(true);
2238 /*
2239 Carefully crafted to avoid invoking any copy constructor using pointer
2240 cast. Also true for the two operator[] member functions below.
2241 */
2242 const Geometry *p= &(get_geo_vect()->back());
2243 return *((const T*)p);
2244 }
2245
2246
back()2247 reference back()
2248 {
2249 set_bg_adapter(true);
2250 /*
2251 Carefully crafted to avoid invoking any copy constructor using pointer
2252 cast. Also true for the two operator[] member functions below.
2253 */
2254 Geometry *p= &(get_geo_vect()->back());
2255 return *((T*)p);
2256 }
2257
2258
2259 const_reference operator[](index_type i) const
2260 {
2261 DBUG_ASSERT(!(i < 0 || i >= (index_type)size()));
2262 set_bg_adapter(true);
2263
2264 const Geometry *p= &((*m_geo_vect)[i]);
2265 return *((const T*)p);
2266 }
2267
2268
2269 reference operator[](index_type i)
2270 {
2271 DBUG_ASSERT(!(i < 0 || i >= (index_type)size()));
2272 set_bg_adapter(true);
2273
2274 Geometry *p= &((*m_geo_vect)[i]);
2275 return *((T*)p);
2276 }
2277
2278
2279 Gis_wkb_vector(const void *ptr, size_t nbytes, const Flags_t &flags,
2280 srid_t srid, bool is_bg_adapter= true);
2281 Gis_wkb_vector(const self &v);
2282
Gis_wkb_vector()2283 Gis_wkb_vector() :Geometry()
2284 {
2285 m_geo_vect= NULL;
2286 }
2287
2288
~Gis_wkb_vector()2289 ~Gis_wkb_vector()
2290 {
2291 /*
2292 See ~Geometry() for why we do try-catch like this.
2293
2294 Note that although ~Inplace_vector() calls std::vector member functions,
2295 all of them have no-throw guarantees, so this function won't throw any
2296 exception now. We do so nonetheless for potential mis-use of exceptions
2297 in futher code.
2298 */
2299 #if !defined(DBUG_OFF)
2300 try
2301 {
2302 #endif
2303 if (!is_bg_adapter())
2304 return;
2305 if (m_geo_vect != NULL)
2306 clear_wkb_data();
2307 #if !defined(DBUG_OFF)
2308 }
2309 catch (...)
2310 {
2311 // Should never throw exceptions in destructor.
2312 DBUG_ASSERT(false);
2313 }
2314 #endif
2315 }
2316
2317
clear_wkb_data()2318 void clear_wkb_data()
2319 {
2320 delete m_geo_vect;
2321 m_geo_vect= NULL;
2322 }
2323
2324
2325 self &operator=(const self &rhs);
2326 virtual void shallow_push(const Geometry *g);
2327
2328 Geo_vector *get_geo_vect(bool create_if_null= false)
2329 {
2330 if (m_geo_vect == NULL && create_if_null)
2331 m_geo_vect= new Geo_vector;
2332 return m_geo_vect;
2333 }
2334
2335
get_geo_vect()2336 Geo_vector *get_geo_vect() const
2337 {
2338 return m_geo_vect;
2339 }
2340
set_geo_vect(Geo_vector * ptr)2341 void set_geo_vect(Geo_vector *ptr)
2342 {
2343 m_geo_vect= ptr;
2344 }
2345
2346 /*
2347 Give up ownership of m_ptr and m_geo_vect, so as not to release them when
2348 this object is destroyed, to be called when the two member is shallow
2349 assigned to another geometry object.
2350 */
donate_data()2351 virtual void donate_data()
2352 {
2353 set_ownmem(false);
2354 set_nbytes(0);
2355 m_ptr= NULL;
2356 m_geo_vect= NULL;
2357 }
2358
2359 void set_ptr(void *ptr, size_t len);
2360 void clear();
2361 size_t get_nbytes_free() const;
2362 size_t current_size() const;
2363 void push_back(const T &val);
2364 void resize(size_t sz);
2365 void reassemble();
2366 private:
2367 typedef Gis_wkb_vector<Gis_point> Linestring;
2368 typedef Gis_wkb_vector<Linestring> Multi_linestrings;
2369
2370 }; // Gis_wkb_vector
2371
2372 //@} //
2373
2374 /***************************** LineString *******************************/
2375
2376 class Gis_line_string: public Gis_wkb_vector<Gis_point>
2377 {
2378 // Maximum number of points in LineString that can fit into String
2379 static const uint32 max_n_points=
2380 (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) /
2381 POINT_DATA_SIZE;
2382 public:
~Gis_line_string()2383 virtual ~Gis_line_string() {} /* Remove gcc warning */
2384 uint32 get_data_size() const;
2385 bool init_from_wkt(Gis_read_stream *trs, String *wkb);
2386 uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
2387 bool get_data_as_wkt(String *txt, wkb_parser *wkb) const;
2388 bool get_mbr(MBR *mbr, wkb_parser *wkb) const;
2389 int geom_length(double *len) const;
2390 int is_closed(int *closed) const;
2391 int num_points(uint32 *n_points) const;
2392 int start_point(String *point) const;
2393 int end_point(String *point) const;
2394 int point_n(uint32 n, String *result) const;
feature_dimension()2395 uint32 feature_dimension() const { return 1; }
2396 const Class_info *get_class_info() const;
2397
2398 /**** Boost Geometry Adapter Interface ******/
2399
2400 typedef Gis_wkb_vector<Gis_point> base_type;
2401 typedef Gis_line_string self;
2402
2403 explicit Gis_line_string(bool is_bg_adapter= true)
2404 :base_type(NULL, 0, Flags_t(wkb_linestring, 0), default_srid, is_bg_adapter)
2405 {}
2406
Gis_line_string(const void * wkb,size_t len,const Flags_t & flags,srid_t srid)2407 Gis_line_string(const void *wkb, size_t len,
2408 const Flags_t &flags, srid_t srid)
2409 :base_type(wkb, len, flags, srid, true)
2410 {
2411 set_geotype(wkb_linestring);
2412 }
2413
Gis_line_string(const self & ls)2414 Gis_line_string(const self &ls) :base_type(ls)
2415 {}
2416 };
2417
2418 /*
2419 We have to use such an independent class in order to meet Ring Concept of
2420 Boost Geometry --- there must be a specialization of traits::tag defining
2421 ring_tag as type.
2422 If directly use Gis_line_string, we would have defined that tag twice.
2423 */
2424 class Gis_polygon_ring : public Gis_wkb_vector<Gis_point>
2425 {
2426 public:
2427 typedef Gis_wkb_vector<Gis_point> base;
2428 typedef Gis_polygon_ring self;
2429
~Gis_polygon_ring()2430 virtual ~Gis_polygon_ring()
2431 {}
Gis_polygon_ring(const void * wkb,size_t nbytes,const Flags_t & flags,srid_t srid)2432 Gis_polygon_ring(const void *wkb, size_t nbytes,
2433 const Flags_t &flags, srid_t srid)
2434 :base(wkb, nbytes, flags, srid, true)
2435 {
2436 set_geotype(wkb_linestring);
2437 }
2438
2439 // Coordinate data type, closed-ness and direction will never change, thus no
2440 // need for the template version of copy constructor.
Gis_polygon_ring(const self & r)2441 Gis_polygon_ring(const self &r) :base(r)
2442 {}
2443
Gis_polygon_ring()2444 Gis_polygon_ring()
2445 :base(NULL, 0, Flags_t(Geometry::wkb_linestring, 0),
2446 default_srid, true)
2447 {}
2448
2449 bool set_ring_order(bool want_ccw);
2450 };
2451
2452 /***************************** Polygon *******************************/
2453
2454 // For internal use only, only convert types, don't create rings.
outer_ring(const Geometry * g)2455 inline Gis_polygon_ring *outer_ring(const Geometry *g)
2456 {
2457 DBUG_ASSERT(g->get_geotype() == Geometry::wkb_polygon);
2458 Gis_polygon_ring *out= static_cast<Gis_polygon_ring *>(g->get_ptr());
2459
2460 return out;
2461 }
2462
2463
2464 class Gis_polygon: public Geometry
2465 {
2466 public:
2467 uint32 get_data_size() const;
2468 bool init_from_wkt(Gis_read_stream *trs, String *wkb);
2469 uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
2470 bool get_data_as_wkt(String *txt, wkb_parser *wkb) const;
2471 bool get_mbr(MBR *mbr, wkb_parser *wkb) const;
2472 int exterior_ring(String *result) const;
2473 int num_interior_ring(uint32 *n_int_rings) const;
2474 int interior_ring_n(uint32 num, String *result) const;
feature_dimension()2475 uint32 feature_dimension() const { return 2; }
2476 const Class_info *get_class_info() const;
2477
2478
2479 /**** Boost Geometry Adapter Interface ******/
2480 typedef Gis_polygon self;
2481 typedef Gis_polygon_ring ring_type;
2482 typedef Gis_wkb_vector<ring_type> inner_container_type;
2483
outer()2484 ring_type &outer() const
2485 {
2486 DBUG_ASSERT(!polygon_is_wkb_form());
2487 set_bg_adapter(true);
2488 // Create outer ring if none, although read only, calller may just want
2489 // to traverse the outer ring if any.
2490 if (this->m_ptr == NULL)
2491 const_cast<self *>(this)->make_rings();
2492
2493 return *(outer_ring(this));
2494 }
2495
inners()2496 inner_container_type &inners() const
2497 {
2498 DBUG_ASSERT(!polygon_is_wkb_form());
2499 set_bg_adapter(true);
2500 // Create inner rings if none, although read only, calller may just want
2501 // to traverse the inner rings if any.
2502 if (m_inn_rings == NULL)
2503 const_cast<self *>(this)->make_rings();
2504
2505 return *m_inn_rings;
2506 }
2507
2508 /// Clears outer and inner rings.
clear()2509 void clear()
2510 {
2511 set_bg_adapter(true);
2512 outer_ring(this)->clear();
2513 if (m_inn_rings)
2514 m_inn_rings->clear();
2515 }
2516
2517 Gis_polygon(const void *wkb, size_t nbytes,
2518 const Flags_t &flags, srid_t srid);
2519
2520
2521 /*
2522 We can't require boost geometry use the 'polygon' in any particular way,
2523 so we have to default to true.
2524 */
2525 explicit Gis_polygon(bool isbgadapter= true)
2526 :Geometry(NULL, 0, Flags_t(Geometry::wkb_polygon, 0), default_srid)
2527 {
2528 m_inn_rings= NULL;
2529 set_bg_adapter(isbgadapter);
2530 }
2531
2532 Gis_polygon(const self &r);
2533 Gis_polygon &operator=(const Gis_polygon &rhs);
2534 ~Gis_polygon();
2535
2536 void to_wkb_unparsed();
2537 void set_ptr(void *ptr, size_t len);
2538
2539 /*
2540 Give up ownership of m_ptr and m_inn_rings, so as not to release them when
2541 this object is destroyed, to be called when the two member is shallow
2542 assigned to another geometry object.
2543 */
donate_data()2544 void donate_data()
2545 {
2546 set_ownmem(false);
2547 set_nbytes(0);
2548 m_ptr= NULL;
2549 m_inn_rings= NULL;
2550 }
2551
2552 bool set_polygon_ring_order();
2553
inner_rings()2554 inner_container_type *inner_rings() const
2555 {
2556 return m_inn_rings;
2557 }
2558
set_inner_rings(inner_container_type * inns)2559 void set_inner_rings(inner_container_type *inns)
2560 {
2561 m_inn_rings= inns;
2562 }
2563
2564 private:
2565 inner_container_type *m_inn_rings;
2566
2567 void make_rings();
2568 };
2569
2570
2571 /***************************** MultiPoint *******************************/
2572
2573 class Gis_multi_point: public Gis_wkb_vector<Gis_point>
2574 {
2575 // Maximum number of points in MultiPoint that can fit into String
2576 static const uint32 max_n_points=
2577 (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) /
2578 (WKB_HEADER_SIZE + POINT_DATA_SIZE);
2579 public:
~Gis_multi_point()2580 virtual ~Gis_multi_point() {} /* Remove gcc warning */
2581 uint32 get_data_size() const;
2582 bool init_from_wkt(Gis_read_stream *trs, String *wkb);
2583 uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
2584 bool get_data_as_wkt(String *txt, wkb_parser *wkb) const;
2585 bool get_mbr(MBR *mbr, wkb_parser *wkb) const;
2586 int num_geometries(uint32 *num) const;
2587 int geometry_n(uint32 num, String *result) const;
feature_dimension()2588 uint32 feature_dimension() const { return 0; }
2589 const Class_info *get_class_info() const;
2590
2591
2592 /**** Boost Geometry Adapter Interface ******/
2593
2594 typedef Gis_wkb_vector<Gis_point> base_type;
2595 typedef Gis_multi_point self;
2596
2597 explicit Gis_multi_point(bool is_bg_adapter= true)
2598 :base_type(NULL, 0, Flags_t(wkb_multipoint, 0),
2599 default_srid, is_bg_adapter)
2600 {}
2601
Gis_multi_point(const void * ptr,size_t nbytes,const Flags_t & flags,srid_t srid)2602 Gis_multi_point(const void *ptr, size_t nbytes,
2603 const Flags_t &flags, srid_t srid)
2604 :base_type(ptr, nbytes, flags, srid, true)
2605 {
2606 set_geotype(wkb_multipoint);
2607 }
2608
Gis_multi_point(const self & mpts)2609 Gis_multi_point(const self &mpts) :base_type(mpts)
2610 {}
2611 };
2612
2613
2614 /***************************** MultiLineString *******************************/
2615
2616 class Gis_multi_line_string : public Gis_wkb_vector<Gis_line_string>
2617 {
2618 public:
~Gis_multi_line_string()2619 virtual ~Gis_multi_line_string() {} /* Remove gcc warning */
2620 uint32 get_data_size() const;
2621 bool init_from_wkt(Gis_read_stream *trs, String *wkb);
2622 uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
2623 bool get_data_as_wkt(String *txt, wkb_parser *wkb) const;
2624 bool get_mbr(MBR *mbr, wkb_parser *wkb) const;
2625 int num_geometries(uint32 *num) const;
2626 int geometry_n(uint32 num, String *result) const;
2627 int geom_length(double *len) const;
2628 int is_closed(int *closed) const;
feature_dimension()2629 uint32 feature_dimension() const { return 1; }
2630 const Class_info *get_class_info() const;
2631
2632 /**** Boost Geometry Adapter Interface ******/
2633
2634 typedef Gis_wkb_vector<Gis_line_string> base;
2635 typedef Gis_multi_line_string self;
2636
2637 explicit Gis_multi_line_string(bool is_bg_adapter= true)
2638 :base(NULL, 0, Flags_t(wkb_multilinestring, 0),
2639 default_srid, is_bg_adapter)
2640 {}
2641
Gis_multi_line_string(const void * ptr,size_t nbytes,const Flags_t & flags,srid_t srid)2642 Gis_multi_line_string(const void *ptr, size_t nbytes,
2643 const Flags_t &flags, srid_t srid)
2644 :base(ptr, nbytes, Flags_t(wkb_multilinestring, nbytes), srid, true)
2645 {
2646 set_geotype(wkb_multilinestring);
2647 }
2648
Gis_multi_line_string(const self & mls)2649 Gis_multi_line_string(const self &mls) :base(mls)
2650 {}
2651 };
2652
2653
2654 /***************************** MultiPolygon *******************************/
2655
2656 class Gis_multi_polygon: public Gis_wkb_vector<Gis_polygon>
2657 {
2658 public:
~Gis_multi_polygon()2659 virtual ~Gis_multi_polygon() {} /* Remove gcc warning */
2660 uint32 get_data_size() const;
2661 bool init_from_wkt(Gis_read_stream *trs, String *wkb);
2662 uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
2663 bool get_data_as_wkt(String *txt, wkb_parser *wkb) const;
2664 bool get_mbr(MBR *mbr, wkb_parser *wkb) const;
2665 int num_geometries(uint32 *num) const;
2666 int geometry_n(uint32 num, String *result) const;
feature_dimension()2667 uint32 feature_dimension() const { return 2; }
2668 const Class_info *get_class_info() const;
2669
2670
2671 /**** Boost Geometry Adapter Interface ******/
2672 typedef Gis_multi_polygon self;
2673 typedef Gis_wkb_vector<Gis_polygon> base;
2674
2675 explicit Gis_multi_polygon(bool is_bg_adapter= true)
2676 :base(NULL, 0, Flags_t(wkb_multipolygon, 0), default_srid, is_bg_adapter)
2677 {}
2678
Gis_multi_polygon(const void * ptr,size_t nbytes,const Flags_t & flags,srid_t srid)2679 Gis_multi_polygon(const void *ptr, size_t nbytes,
2680 const Flags_t &flags, srid_t srid)
2681 :base(ptr, nbytes, flags, srid, true)
2682 {
2683 set_geotype(wkb_multipolygon);
2684 }
2685
Gis_multi_polygon(const self & mpl)2686 Gis_multi_polygon(const self &mpl) :base(mpl)
2687 {}
2688 };
2689
2690
2691 /*********************** GeometryCollection *******************************/
2692 class Gis_geometry_collection: public Geometry
2693 {
2694 private:
2695 static Geometry *scan_header_and_create(wkb_parser *wkb,
2696 Geometry_buffer *buffer);
2697 public:
Gis_geometry_collection()2698 Gis_geometry_collection()
2699 :Geometry(NULL, 0, Flags_t(wkb_geometrycollection, 0), default_srid)
2700 {
2701 set_bg_adapter(false);
2702 }
2703 Gis_geometry_collection(Geometry *geo, String *gcbuf);
2704 Gis_geometry_collection(srid_t srid, wkbType gtype, const String *gbuf,
2705 String *gcbuf);
~Gis_geometry_collection()2706 virtual ~Gis_geometry_collection() {} /* Remove gcc warning */
2707 bool append_geometry(const Geometry *geo, String *gcbuf);
2708 bool append_geometry(srid_t srid, wkbType gtype,
2709 const String *gbuf, String *gcbuf);
2710 uint32 get_data_size() const;
2711 bool init_from_wkt(Gis_read_stream *trs, String *wkb);
2712 uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
2713 bool get_data_as_wkt(String *txt, wkb_parser *wkb) const;
2714 bool get_mbr(MBR *mbr, wkb_parser *wkb) const;
2715 int num_geometries(uint32 *num) const;
2716 int geometry_n(uint32 num, String *result) const;
2717 bool dimension(uint32 *dim, wkb_parser *wkb) const;
feature_dimension()2718 uint32 feature_dimension() const
2719 {
2720 DBUG_ASSERT(0);
2721 return 0;
2722 }
2723 const Class_info *get_class_info() const;
2724 };
2725
2726
2727 /**
2728 Gis_polygon objects and Gis_wkb_vector<> objects are of same size, and
2729 Gis_point and Geometry objects are smaller. They are always allocated
2730 inside a Geometry_buffer object, unless used as boost geometry adapter,
2731 in which case the object may simply placed on stack or new'ed on heap.
2732 */
2733 struct Geometry_buffer : public
2734 my_aligned_storage<sizeof(Gis_polygon), MY_ALIGNOF(Gis_polygon)> {};
2735
2736
2737 class WKB_scanner_event_handler
2738 {
2739 public:
~WKB_scanner_event_handler()2740 virtual ~WKB_scanner_event_handler() {}
2741
2742 /**
2743 Notified when scanner sees the start of a geometry WKB.
2744 @param bo byte order of the WKB.
2745 @param geotype geometry type of the WKB;
2746 @param wkb WKB byte string, the first byte after the WKB header if any.
2747 @param len NO. of bytes of the WKB byte string starting from wkb.
2748 There can be many geometries in the [wkb, wkb+len) buffer.
2749 @param has_hdr whether there is a WKB header right before 'wkb' in the
2750 byte string.
2751 */
2752 virtual void on_wkb_start(Geometry::wkbByteOrder bo,
2753 Geometry::wkbType geotype,
2754 const void *wkb, uint32 len, bool has_hdr)= 0;
2755
2756 /**
2757 Notified when scanner sees the end of a geometry WKB.
2758 @param wkb the position of the first byte after the WKB byte string which
2759 the scanner just scanned.
2760 */
2761 virtual void on_wkb_end(const void *wkb)= 0;
2762
2763 /*
2764 Called after each on_wkb_start/end call, if returns false, wkb_scanner
2765 will stop scanning.
2766 */
continue_scan()2767 virtual bool continue_scan() const
2768 {
2769 return true;
2770 }
2771 };
2772
2773
2774 const char*
2775 wkb_scanner(const char *wkb, uint32 *len, uint32 geotype, bool has_hdr,
2776 WKB_scanner_event_handler *handler);
2777 #endif
2778