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