1 /*
2 
3     GeoPackage extensions for SpatiaLite / SQLite
4 
5 Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 
7 The contents of this file are subject to the Mozilla Public License Version
8 1.1 (the "License"); you may not use this file except in compliance with
9 the License. You may obtain a copy of the License at
10 http://www.mozilla.org/MPL/
11 
12 Software distributed under the License is distributed on an "AS IS" basis,
13 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 for the specific language governing rights and limitations under the
15 License.
16 
17 The Original Code is GeoPackage Extensions
18 
19 The Initial Developer of the Original Code is Brad Hards (bradh@frogmouth.net)
20 
21 Portions created by the Initial Developer are Copyright (C) 2012-2015
22 the Initial Developer. All Rights Reserved.
23 
24 Contributor(s):
25 
26 Alternatively, the contents of this file may be used under the terms of
27 either the GNU General Public License Version 2 or later (the "GPL"), or
28 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 in which case the provisions of the GPL or the LGPL are applicable instead
30 of those above. If you wish to allow use of your version of this file only
31 under the terms of either the GPL or the LGPL, and not to allow others to
32 use your version of this file under the terms of the MPL, indicate your
33 decision by deleting the provisions above and replace them with the notice
34 and other provisions required by the GPL or the LGPL. If you do not delete
35 the provisions above, a recipient may use your version of this file under
36 the terms of any one of the MPL, the GPL or the LGPL.
37 
38 */
39 
40 #include "spatialite/geopackage.h"
41 #include "geopackage_internal.h"
42 
43 #if defined(_WIN32) && !defined(__MINGW32__)
44 #include "config-msvc.h"
45 #else
46 #include "config.h"
47 #endif
48 
49 #ifdef ENABLE_GEOPACKAGE
50 
51 #define GEOPACKAGE_UNUSED() if (argc || argv) argc = argc;
52 
53 static void
gpkgMakePoint(double x,double y,int srid,unsigned char ** result,unsigned int * size)54 gpkgMakePoint (double x, double y, int srid, unsigned char **result,
55 	       unsigned int *size)
56 {
57     /* build a Blob encoded Geometry representing a POINT */
58     unsigned char *ptr;
59     int endian_arch = gaiaEndianArch ();
60 
61     /* computing the Blob size and then allocating it */
62     *size = GEOPACKAGE_HEADER_LEN + GEOPACKAGE_2D_ENVELOPE_LEN;
63     *size += GEOPACKAGE_WKB_HEADER_LEN;
64     *size += (sizeof (double) * 2);	/* [x,y] coords */
65     *result = malloc (*size);
66     if (*result == NULL)
67       {
68 	  return;
69       }
70     memset (*result, 0xD9, *size);
71     ptr = *result;
72 
73     /* setting the Blob value */
74     gpkgSetHeader2DLittleEndian (ptr, srid, endian_arch);
75 
76     gpkgSetHeader2DMbr (ptr + GEOPACKAGE_HEADER_LEN, x, y, x, y, endian_arch);
77 
78     *(ptr + GEOPACKAGE_HEADER_LEN +
79       GEOPACKAGE_2D_ENVELOPE_LEN) = GEOPACKAGE_WKB_LITTLEENDIAN;
80     gaiaExport32 (ptr +
81 		  GEOPACKAGE_HEADER_LEN +
82 		  GEOPACKAGE_2D_ENVELOPE_LEN
83 		  + 1, GEOPACKAGE_WKB_POINT, 1, endian_arch);
84     gaiaExport64 (ptr +
85 		  GEOPACKAGE_HEADER_LEN +
86 		  GEOPACKAGE_2D_ENVELOPE_LEN
87 		  + GEOPACKAGE_WKB_HEADER_LEN, x, 1, endian_arch);
88     gaiaExport64 (ptr +
89 		  GEOPACKAGE_HEADER_LEN +
90 		  GEOPACKAGE_2D_ENVELOPE_LEN
91 		  +
92 		  GEOPACKAGE_WKB_HEADER_LEN
93 		  + sizeof (double), y, 1, endian_arch);
94 }
95 
96 static void
gpkgMakePointZ(double x,double y,double z,int srid,unsigned char ** result,unsigned int * size)97 gpkgMakePointZ (double x, double y, double z, int srid, unsigned char **result,
98 		unsigned int *size)
99 {
100 /* build a Blob encoded Geometry representing a POINT */
101     unsigned char *ptr;
102     int endian_arch = gaiaEndianArch ();
103 /* computing the Blob size and then allocating it */
104     *size = GEOPACKAGE_HEADER_LEN + GEOPACKAGE_3D_ENVELOPE_LEN;
105     *size += GEOPACKAGE_WKB_HEADER_LEN;
106     *size += (sizeof (double) * 3);	/* [x,y,z] coords */
107     *result = malloc (*size);
108     if (*result == NULL)
109       {
110 	  return;
111       }
112     memset (*result, 0xD9, *size);	/* just a flag value */
113     ptr = *result;
114 /* setting the Blob value */
115     *ptr = GEOPACKAGE_MAGIC1;
116     *(ptr + 1) = GEOPACKAGE_MAGIC2;
117     *(ptr + 2) = GEOPACKAGE_VERSION;
118     *(ptr + 3) = GEOPACKAGE_FLAGS_3D_LITTLEENDIAN;
119     gaiaExport32 (ptr + 4, srid, 1, endian_arch);	/* the SRID */
120     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN, x, 1, endian_arch);	/* MBR - minimum X */
121     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + sizeof (double), x, 1, endian_arch);	/* MBR - maximum x */
122     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 2 * sizeof (double), y, 1, endian_arch);	/* MBR - minimum Y */
123     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 3 * sizeof (double), y, 1, endian_arch);	/* MBR - maximum Y */
124     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 4 * sizeof (double), z, 1, endian_arch);	/* MBR - maximum Z */
125     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 5 * sizeof (double), z, 1, endian_arch);	/* MBR - maximum Z */
126     *(ptr + GEOPACKAGE_HEADER_LEN +
127       GEOPACKAGE_3D_ENVELOPE_LEN) = GEOPACKAGE_WKB_LITTLEENDIAN;
128     gaiaExport32 (ptr +
129 		  GEOPACKAGE_HEADER_LEN +
130 		  GEOPACKAGE_3D_ENVELOPE_LEN
131 		  + 1, GEOPACKAGE_WKB_POINTZ, 1, endian_arch);
132     gaiaExport64 (ptr +
133 		  GEOPACKAGE_HEADER_LEN +
134 		  GEOPACKAGE_3D_ENVELOPE_LEN
135 		  + GEOPACKAGE_WKB_HEADER_LEN, x, 1, endian_arch);
136     gaiaExport64 (ptr +
137 		  GEOPACKAGE_HEADER_LEN +
138 		  GEOPACKAGE_3D_ENVELOPE_LEN
139 		  +
140 		  GEOPACKAGE_WKB_HEADER_LEN
141 		  + sizeof (double), y, 1, endian_arch);
142     gaiaExport64 (ptr +
143 		  GEOPACKAGE_HEADER_LEN +
144 		  GEOPACKAGE_3D_ENVELOPE_LEN
145 		  +
146 		  GEOPACKAGE_WKB_HEADER_LEN
147 		  + (2 * sizeof (double)), z, 1, endian_arch);
148 }
149 
150 static void
gpkgMakePointM(double x,double y,double m,int srid,unsigned char ** result,unsigned int * size)151 gpkgMakePointM (double x, double y, double m, int srid, unsigned char **result,
152 		unsigned int *size)
153 {
154 /* build a Blob encoded Geometry representing a POINT */
155     unsigned char *ptr;
156     int endian_arch = gaiaEndianArch ();
157 /* computing the Blob size and then allocating it */
158     *size = GEOPACKAGE_HEADER_LEN + GEOPACKAGE_3D_ENVELOPE_LEN;
159     *size += GEOPACKAGE_WKB_HEADER_LEN;
160     *size += (sizeof (double) * 3);	/* [x,y,m] coords */
161     *result = malloc (*size);
162     if (*result == NULL)
163       {
164 	  return;
165       }
166     memset (*result, 0xD9, *size);	/* just a flag value */
167     ptr = *result;
168 /* setting the Blob value */
169     *ptr = GEOPACKAGE_MAGIC1;
170     *(ptr + 1) = GEOPACKAGE_MAGIC2;
171     *(ptr + 2) = GEOPACKAGE_VERSION;
172     *(ptr + 3) = GEOPACKAGE_FLAGS_2DM_LITTLEENDIAN;
173     gaiaExport32 (ptr + 4, srid, 1, endian_arch);	/* the SRID */
174     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN, x, 1, endian_arch);	/* MBR - minimum X */
175     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + sizeof (double), x, 1, endian_arch);	/* MBR - maximum X */
176     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 2 * sizeof (double), y, 1, endian_arch);	/* MBR - minimum Y */
177     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 3 * sizeof (double), y, 1, endian_arch);	/* MBR - maximum Y */
178     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 4 * sizeof (double), m, 1, endian_arch);	/* MBR - maximum M */
179     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 5 * sizeof (double), m, 1, endian_arch);	/* MBR - maximum M */
180     *(ptr + GEOPACKAGE_HEADER_LEN +
181       GEOPACKAGE_3D_ENVELOPE_LEN) = GEOPACKAGE_WKB_LITTLEENDIAN;
182     gaiaExport32 (ptr +
183 		  GEOPACKAGE_HEADER_LEN +
184 		  GEOPACKAGE_3D_ENVELOPE_LEN
185 		  + 1, GEOPACKAGE_WKB_POINTM, 1, endian_arch);
186     gaiaExport64 (ptr +
187 		  GEOPACKAGE_HEADER_LEN +
188 		  GEOPACKAGE_3D_ENVELOPE_LEN
189 		  + GEOPACKAGE_WKB_HEADER_LEN, x, 1, endian_arch);
190     gaiaExport64 (ptr +
191 		  GEOPACKAGE_HEADER_LEN +
192 		  GEOPACKAGE_3D_ENVELOPE_LEN
193 		  +
194 		  GEOPACKAGE_WKB_HEADER_LEN
195 		  + sizeof (double), y, 1, endian_arch);
196     gaiaExport64 (ptr +
197 		  GEOPACKAGE_HEADER_LEN +
198 		  GEOPACKAGE_3D_ENVELOPE_LEN
199 		  +
200 		  GEOPACKAGE_WKB_HEADER_LEN
201 		  + (2 * sizeof (double)), m, 1, endian_arch);
202 }
203 
204 static void
gpkgMakePointZM(double x,double y,double z,double m,int srid,unsigned char ** result,unsigned int * size)205 gpkgMakePointZM (double x, double y, double z, double m, int srid,
206 		 unsigned char **result, unsigned int *size)
207 {
208 /* build a Blob encoded Geometry representing a POINT */
209     unsigned char *ptr;
210     int endian_arch = gaiaEndianArch ();
211 /* computing the Blob size and then allocating it */
212     *size = GEOPACKAGE_HEADER_LEN + GEOPACKAGE_4D_ENVELOPE_LEN;
213     *size += GEOPACKAGE_WKB_HEADER_LEN;
214     *size += (sizeof (double) * 4);	/* [x,y,z,m] coords */
215     *result = malloc (*size);
216     if (*result == NULL)
217       {
218 	  return;
219       }
220     memset (*result, 0xD9, *size);	/* just a flag value */
221     ptr = *result;
222 /* setting the Blob value */
223     *ptr = GEOPACKAGE_MAGIC1;
224     *(ptr + 1) = GEOPACKAGE_MAGIC2;
225     *(ptr + 2) = GEOPACKAGE_VERSION;
226     *(ptr + 3) = GEOPACKAGE_FLAGS_3DM_LITTLEENDIAN;
227     gaiaExport32 (ptr + 4, srid, 1, endian_arch);	/* the SRID */
228     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN, x, 1, endian_arch);	/* MBR - minimum X */
229     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 1 * sizeof (double), x, 1, endian_arch);	/* MBR - maximum X */
230     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 2 * sizeof (double), y, 1, endian_arch);	/* MBR - minimum Y */
231     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 3 * sizeof (double), y, 1, endian_arch);	/* MBR - maximum Y */
232     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 4 * sizeof (double), z, 1, endian_arch);	/* MBR - minimum Z */
233     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 5 * sizeof (double), z, 1, endian_arch);	/* MBR - maximum Z */
234     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 6 * sizeof (double), m, 1, endian_arch);	/* MBR - minimum M */
235     gaiaExport64 (ptr + GEOPACKAGE_HEADER_LEN + 7 * sizeof (double), m, 1, endian_arch);	/* MBR - maximum M */
236     *(ptr + GEOPACKAGE_HEADER_LEN +
237       GEOPACKAGE_4D_ENVELOPE_LEN) = GEOPACKAGE_WKB_LITTLEENDIAN;
238     gaiaExport32 (ptr +
239 		  GEOPACKAGE_HEADER_LEN +
240 		  GEOPACKAGE_4D_ENVELOPE_LEN
241 		  + 1, GEOPACKAGE_WKB_POINTZM, 1, endian_arch);
242     gaiaExport64 (ptr +
243 		  GEOPACKAGE_HEADER_LEN +
244 		  GEOPACKAGE_4D_ENVELOPE_LEN
245 		  + GEOPACKAGE_WKB_HEADER_LEN, x, 1, endian_arch);
246     gaiaExport64 (ptr +
247 		  GEOPACKAGE_HEADER_LEN +
248 		  GEOPACKAGE_4D_ENVELOPE_LEN
249 		  +
250 		  GEOPACKAGE_WKB_HEADER_LEN
251 		  + sizeof (double), y, 1, endian_arch);
252     gaiaExport64 (ptr +
253 		  GEOPACKAGE_HEADER_LEN +
254 		  GEOPACKAGE_4D_ENVELOPE_LEN
255 		  +
256 		  GEOPACKAGE_WKB_HEADER_LEN
257 		  + (2 * sizeof (double)), z, 1, endian_arch);
258     gaiaExport64 (ptr +
259 		  GEOPACKAGE_HEADER_LEN +
260 		  GEOPACKAGE_4D_ENVELOPE_LEN
261 		  +
262 		  GEOPACKAGE_WKB_HEADER_LEN
263 		  + (3 * sizeof (double)), m, 1, endian_arch);
264 }
265 
266 GEOPACKAGE_PRIVATE void
fnct_gpkgMakePoint(sqlite3_context * context,int argc UNUSED,sqlite3_value ** argv)267 fnct_gpkgMakePoint (sqlite3_context * context, int argc UNUSED,
268 		    sqlite3_value ** argv)
269 {
270 /* SQL function:
271 / gpkgMakePoint(x, y)
272 /
273 / Creates a GeoPackage geometry POINT
274 /
275 / returns nothing on success, raises exception on error
276 */
277     unsigned int len;
278     int int_value;
279     unsigned char *p_result = NULL;
280     double x;
281     double y;
282     GEOPACKAGE_UNUSED ();	/* LCOV_EXCL_LINE */
283     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
284       {
285 	  x = sqlite3_value_double (argv[0]);
286       }
287     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
288       {
289 	  int_value = sqlite3_value_int (argv[0]);
290 	  x = int_value;
291       }
292     else
293       {
294 	  sqlite3_result_null (context);
295 	  return;
296       }
297     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
298       {
299 	  y = sqlite3_value_double (argv[1]);
300       }
301     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
302       {
303 	  int_value = sqlite3_value_int (argv[1]);
304 	  y = int_value;
305       }
306     else
307       {
308 	  sqlite3_result_null (context);
309 	  return;
310       }
311     gpkgMakePoint (x, y, GEOPACKAGE_DEFAULT_UNDEFINED_SRID, &p_result, &len);
312     if (!p_result)
313       {
314 	  sqlite3_result_null (context);
315       }
316     else
317       {
318 	  sqlite3_result_blob (context, p_result, len, free);
319       }
320 }
321 
322 GEOPACKAGE_PRIVATE void
fnct_gpkgMakePointWithSRID(sqlite3_context * context,int argc UNUSED,sqlite3_value ** argv)323 fnct_gpkgMakePointWithSRID (sqlite3_context * context, int argc UNUSED,
324 			    sqlite3_value ** argv)
325 {
326 /* SQL function:
327 / gpkgMakePoint(x, y, srid)
328 /
329 / Creates a GeoPackage geometry POINT
330 /
331 / returns nothing on success, raises exception on error
332 */
333     unsigned int len;
334     int int_value;
335     unsigned char *p_result = NULL;
336     double x;
337     double y;
338     int srid;
339     GEOPACKAGE_UNUSED ();	/* LCOV_EXCL_LINE */
340     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
341       {
342 	  x = sqlite3_value_double (argv[0]);
343       }
344     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
345       {
346 	  int_value = sqlite3_value_int (argv[0]);
347 	  x = int_value;
348       }
349     else
350       {
351 	  sqlite3_result_null (context);
352 	  return;
353       }
354     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
355       {
356 	  y = sqlite3_value_double (argv[1]);
357       }
358     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
359       {
360 	  int_value = sqlite3_value_int (argv[1]);
361 	  y = int_value;
362       }
363     else
364       {
365 	  sqlite3_result_null (context);
366 	  return;
367       }
368     if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
369       {
370 	  sqlite3_result_null (context);
371 	  return;
372       }
373     srid = sqlite3_value_int (argv[2]);
374 
375     gpkgMakePoint (x, y, srid, &p_result, &len);
376     if (!p_result)
377       {
378 	  sqlite3_result_null (context);
379       }
380     else
381       {
382 	  sqlite3_result_blob (context, p_result, len, free);
383       }
384 }
385 
386 GEOPACKAGE_PRIVATE void
fnct_gpkgMakePointZ(sqlite3_context * context,int argc UNUSED,sqlite3_value ** argv)387 fnct_gpkgMakePointZ (sqlite3_context * context, int argc UNUSED,
388 		     sqlite3_value ** argv)
389 {
390 /* SQL function:
391 / gpkgMakePointZ(x, y, z)
392 /
393 / Creates a GeoPackage geometry POINT Z
394 /
395 / returns nothing on success, raises exception on error
396 */
397     unsigned int len;
398     int int_value;
399     unsigned char *p_result = NULL;
400     double x;
401     double y;
402     double z;
403     GEOPACKAGE_UNUSED ();	/* LCOV_EXCL_LINE */
404     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
405       {
406 	  x = sqlite3_value_double (argv[0]);
407       }
408     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
409       {
410 	  int_value = sqlite3_value_int (argv[0]);
411 	  x = int_value;
412       }
413     else
414       {
415 	  sqlite3_result_null (context);
416 	  return;
417       }
418     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
419       {
420 	  y = sqlite3_value_double (argv[1]);
421       }
422     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
423       {
424 	  int_value = sqlite3_value_int (argv[1]);
425 	  y = int_value;
426       }
427     else
428       {
429 	  sqlite3_result_null (context);
430 	  return;
431       }
432     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
433       {
434 	  z = sqlite3_value_double (argv[2]);
435       }
436     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
437       {
438 	  int_value = sqlite3_value_int (argv[2]);
439 	  z = int_value;
440       }
441     else
442       {
443 	  sqlite3_result_null (context);
444 	  return;
445       }
446 
447     gpkgMakePointZ (x, y, z,
448 		    GEOPACKAGE_DEFAULT_UNDEFINED_SRID, &p_result, &len);
449     if (!p_result)
450       {
451 	  sqlite3_result_null (context);
452       }
453     else
454       {
455 	  sqlite3_result_blob (context, p_result, len, free);
456       }
457 }
458 
459 GEOPACKAGE_PRIVATE void
fnct_gpkgMakePointZWithSRID(sqlite3_context * context,int argc UNUSED,sqlite3_value ** argv)460 fnct_gpkgMakePointZWithSRID (sqlite3_context * context, int argc UNUSED,
461 			     sqlite3_value ** argv)
462 {
463 /* SQL function:
464 / gpkgMakePointZ(x, y, z, srid)
465 /
466 / Creates a GeoPackage geometry POINT Z
467 /
468 / returns nothing on success, raises exception on error
469 */
470     unsigned int len;
471     int int_value;
472     unsigned char *p_result = NULL;
473     double x;
474     double y;
475     double z;
476     int srid;
477     GEOPACKAGE_UNUSED ();	/* LCOV_EXCL_LINE */
478     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
479       {
480 	  x = sqlite3_value_double (argv[0]);
481       }
482     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
483       {
484 	  int_value = sqlite3_value_int (argv[0]);
485 	  x = int_value;
486       }
487     else
488       {
489 	  sqlite3_result_null (context);
490 	  return;
491       }
492     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
493       {
494 	  y = sqlite3_value_double (argv[1]);
495       }
496     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
497       {
498 	  int_value = sqlite3_value_int (argv[1]);
499 	  y = int_value;
500       }
501     else
502       {
503 	  sqlite3_result_null (context);
504 	  return;
505       }
506     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
507       {
508 	  z = sqlite3_value_double (argv[2]);
509       }
510     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
511       {
512 	  int_value = sqlite3_value_int (argv[2]);
513 	  z = int_value;
514       }
515     else
516       {
517 	  sqlite3_result_null (context);
518 	  return;
519       }
520     if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
521       {
522 	  sqlite3_result_null (context);
523 	  return;
524       }
525     srid = sqlite3_value_int (argv[3]);
526 
527     gpkgMakePointZ (x, y, z, srid, &p_result, &len);
528     if (!p_result)
529       {
530 	  sqlite3_result_null (context);
531       }
532     else
533       {
534 	  sqlite3_result_blob (context, p_result, len, free);
535       }
536 }
537 
538 GEOPACKAGE_PRIVATE void
fnct_gpkgMakePointM(sqlite3_context * context,int argc UNUSED,sqlite3_value ** argv)539 fnct_gpkgMakePointM (sqlite3_context * context, int argc UNUSED,
540 		     sqlite3_value ** argv)
541 {
542 /* SQL function:
543 / gpkgMakePointM(x, y, m)
544 /
545 / Creates a GeoPackage geometry POINT M
546 /
547 / returns nothing on success, raises exception on error
548 */
549     unsigned int len;
550     int int_value;
551     unsigned char *p_result = NULL;
552     double x;
553     double y;
554     double m;
555     GEOPACKAGE_UNUSED ();	/* LCOV_EXCL_LINE */
556     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
557       {
558 	  x = sqlite3_value_double (argv[0]);
559       }
560     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
561       {
562 	  int_value = sqlite3_value_int (argv[0]);
563 	  x = int_value;
564       }
565     else
566       {
567 	  sqlite3_result_null (context);
568 	  return;
569       }
570     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
571       {
572 	  y = sqlite3_value_double (argv[1]);
573       }
574     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
575       {
576 	  int_value = sqlite3_value_int (argv[1]);
577 	  y = int_value;
578       }
579     else
580       {
581 	  sqlite3_result_null (context);
582 	  return;
583       }
584     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
585       {
586 	  m = sqlite3_value_double (argv[2]);
587       }
588     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
589       {
590 	  int_value = sqlite3_value_int (argv[2]);
591 	  m = int_value;
592       }
593     else
594       {
595 	  sqlite3_result_null (context);
596 	  return;
597       }
598 
599     gpkgMakePointM (x, y, m,
600 		    GEOPACKAGE_DEFAULT_UNDEFINED_SRID, &p_result, &len);
601     if (!p_result)
602       {
603 	  sqlite3_result_null (context);
604       }
605     else
606       {
607 	  sqlite3_result_blob (context, p_result, len, free);
608       }
609 }
610 
611 GEOPACKAGE_PRIVATE void
fnct_gpkgMakePointMWithSRID(sqlite3_context * context,int argc UNUSED,sqlite3_value ** argv)612 fnct_gpkgMakePointMWithSRID (sqlite3_context * context, int argc UNUSED,
613 			     sqlite3_value ** argv)
614 {
615 /* SQL function:
616 / gpkgMakePointM(x, y, m, srid)
617 /
618 / Creates a GeoPackage geometry POINT M
619 /
620 / returns nothing on success, raises exception on error
621 */
622     unsigned int len;
623     int int_value;
624     unsigned char *p_result = NULL;
625     double x;
626     double y;
627     double m;
628     int srid;
629     GEOPACKAGE_UNUSED ();	/* LCOV_EXCL_LINE */
630     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
631       {
632 	  x = sqlite3_value_double (argv[0]);
633       }
634     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
635       {
636 	  int_value = sqlite3_value_int (argv[0]);
637 	  x = int_value;
638       }
639     else
640       {
641 	  sqlite3_result_null (context);
642 	  return;
643       }
644     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
645       {
646 	  y = sqlite3_value_double (argv[1]);
647       }
648     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
649       {
650 	  int_value = sqlite3_value_int (argv[1]);
651 	  y = int_value;
652       }
653     else
654       {
655 	  sqlite3_result_null (context);
656 	  return;
657       }
658     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
659       {
660 	  m = sqlite3_value_double (argv[2]);
661       }
662     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
663       {
664 	  int_value = sqlite3_value_int (argv[2]);
665 	  m = int_value;
666       }
667     else
668       {
669 	  sqlite3_result_null (context);
670 	  return;
671       }
672     if (sqlite3_value_type (argv[3]) != SQLITE_INTEGER)
673       {
674 	  sqlite3_result_null (context);
675 	  return;
676       }
677     srid = sqlite3_value_int (argv[3]);
678 
679     gpkgMakePointM (x, y, m, srid, &p_result, &len);
680     if (!p_result)
681       {
682 	  sqlite3_result_null (context);
683       }
684     else
685       {
686 	  sqlite3_result_blob (context, p_result, len, free);
687       }
688 }
689 
690 GEOPACKAGE_PRIVATE void
fnct_gpkgMakePointZM(sqlite3_context * context,int argc UNUSED,sqlite3_value ** argv)691 fnct_gpkgMakePointZM (sqlite3_context * context, int argc UNUSED,
692 		      sqlite3_value ** argv)
693 {
694 /* SQL function:
695 / gpkgMakePointM(x, y, z, m)
696 /
697 / Creates a GeoPackage geometry POINT ZM
698 /
699 / returns nothing on success, raises exception on error
700 */
701     unsigned int len;
702     int int_value;
703     unsigned char *p_result = NULL;
704     double x;
705     double y;
706     double z;
707     double m;
708     GEOPACKAGE_UNUSED ();	/* LCOV_EXCL_LINE */
709     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
710       {
711 	  x = sqlite3_value_double (argv[0]);
712       }
713     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
714       {
715 	  int_value = sqlite3_value_int (argv[0]);
716 	  x = int_value;
717       }
718     else
719       {
720 	  sqlite3_result_null (context);
721 	  return;
722       }
723     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
724       {
725 	  y = sqlite3_value_double (argv[1]);
726       }
727     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
728       {
729 	  int_value = sqlite3_value_int (argv[1]);
730 	  y = int_value;
731       }
732     else
733       {
734 	  sqlite3_result_null (context);
735 	  return;
736       }
737     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
738       {
739 	  z = sqlite3_value_double (argv[2]);
740       }
741     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
742       {
743 	  int_value = sqlite3_value_int (argv[2]);
744 	  z = int_value;
745       }
746     else
747       {
748 	  sqlite3_result_null (context);
749 	  return;
750       }
751     if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
752       {
753 	  m = sqlite3_value_double (argv[3]);
754       }
755     else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
756       {
757 	  int_value = sqlite3_value_int (argv[3]);
758 	  m = int_value;
759       }
760     else
761       {
762 	  sqlite3_result_null (context);
763 	  return;
764       }
765 
766     gpkgMakePointZM (x, y, z, m,
767 		     GEOPACKAGE_DEFAULT_UNDEFINED_SRID, &p_result, &len);
768     if (!p_result)
769       {
770 	  sqlite3_result_null (context);
771       }
772     else
773       {
774 	  sqlite3_result_blob (context, p_result, len, free);
775       }
776 }
777 
778 GEOPACKAGE_PRIVATE void
fnct_gpkgMakePointZMWithSRID(sqlite3_context * context,int argc UNUSED,sqlite3_value ** argv)779 fnct_gpkgMakePointZMWithSRID (sqlite3_context * context, int argc UNUSED,
780 			      sqlite3_value ** argv)
781 {
782 /* SQL function:
783 / gpkgMakePointZM(x, y, z, m, srid)
784 /
785 / Creates a GeoPackage geometry POINT ZM
786 /
787 / returns nothing on success, raises exception on error
788 */
789     unsigned int len;
790     int int_value;
791     unsigned char *p_result = NULL;
792     double x;
793     double y;
794     double z;
795     double m;
796     int srid;
797     GEOPACKAGE_UNUSED ();	/* LCOV_EXCL_LINE */
798     if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
799       {
800 	  x = sqlite3_value_double (argv[0]);
801       }
802     else if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
803       {
804 	  int_value = sqlite3_value_int (argv[0]);
805 	  x = int_value;
806       }
807     else
808       {
809 	  sqlite3_result_null (context);
810 	  return;
811       }
812     if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
813       {
814 	  y = sqlite3_value_double (argv[1]);
815       }
816     else if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
817       {
818 	  int_value = sqlite3_value_int (argv[1]);
819 	  y = int_value;
820       }
821     else
822       {
823 	  sqlite3_result_null (context);
824 	  return;
825       }
826     if (sqlite3_value_type (argv[2]) == SQLITE_FLOAT)
827       {
828 	  z = sqlite3_value_double (argv[2]);
829       }
830     else if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER)
831       {
832 	  int_value = sqlite3_value_int (argv[2]);
833 	  z = int_value;
834       }
835     else
836       {
837 	  sqlite3_result_null (context);
838 	  return;
839       }
840     if (sqlite3_value_type (argv[3]) == SQLITE_FLOAT)
841       {
842 	  m = sqlite3_value_double (argv[3]);
843       }
844     else if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER)
845       {
846 	  int_value = sqlite3_value_int (argv[3]);
847 	  m = int_value;
848       }
849     else
850       {
851 	  sqlite3_result_null (context);
852 	  return;
853       }
854     if (sqlite3_value_type (argv[4]) != SQLITE_INTEGER)
855       {
856 	  sqlite3_result_null (context);
857 	  return;
858       }
859     srid = sqlite3_value_int (argv[4]);
860 
861     gpkgMakePointZM (x, y, z, m, srid, &p_result, &len);
862     if (!p_result)
863       {
864 	  sqlite3_result_null (context);
865       }
866     else
867       {
868 	  sqlite3_result_blob (context, p_result, len, free);
869       }
870 }
871 #endif
872