1 /*
2  geojson.h -- Gaia common support for the GeoJSON parser
3 
4  version 5.0, 2020 August 1
5 
6  Author: Sandro Furieri a.furieri@lqt.it
7 
8  ------------------------------------------------------------------------------
9 
10  Version: MPL 1.1/GPL 2.0/LGPL 2.1
11 
12  The contents of this file are subject to the Mozilla Public License Version
13  1.1 (the "License"); you may not use this file except in compliance with
14  the License. You may obtain a copy of the License at
15  http://www.mozilla.org/MPL/
16 
17 Software distributed under the License is distributed on an "AS IS" basis,
18 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
19 for the specific language governing rights and limitations under the
20 License.
21 
22 The Original Code is the SpatiaLite library
23 
24 The Initial Developer of the Original Code is Alessandro Furieri
25 
26 Portions created by the Initial Developer are Copyright (C) 2018-2021
27 the Initial Developer. All Rights Reserved.
28 
29 Contributor(s):
30 
31 
32 Alternatively, the contents of this file may be used under the terms of
33 either the GNU General Public License Version 2 or later (the "GPL"), or
34 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
35 in which case the provisions of the GPL or the LGPL are applicable instead
36 of those above. If you wish to allow use of your version of this file only
37 under the terms of either the GPL or the LGPL, and not to allow others to
38 use your version of this file under the terms of the MPL, indicate your
39 decision by deleting the provisions above and replace them with the notice
40 and other provisions required by the GPL or the LGPL. If you do not delete
41 the provisions above, a recipient may use your version of this file under
42 the terms of any one of the MPL, the GPL or the LGPL.
43 
44 */
45 
46 
47 /**
48  \file geojson.h
49 
50  GeoJSON structures
51  */
52 
53 #ifndef _GEOJSON_H
54 #ifndef DOXYGEN_SHOULD_SKIP_THIS
55 #define _GEOJSON_H
56 #endif
57 
58 #ifdef __cplusplus
59 extern "C"
60 {
61 #endif
62 
63 /* constant values for GeoJSON objects */
64 
65 /** UNKNOWN */
66 #define GEOJSON_UNKNOWN	0
67 
68 /** FeatureCollection object */
69 #define GEOJSON_FCOLLECTION	101
70 
71 /** Feature object */
72 #define GEOJSON_FEATURE		102
73 
74 /** Properties object */
75 #define GEOJSON_PROPERTIES	103
76 
77 
78 /* constant values for GeoJSON geometries */
79 
80 /** POINT */
81 #define GEOJSON_POINT			201
82 
83 /** LINESTRING */
84 #define GEOJSON_LINESTRING		202
85 
86 /** POLYGON */
87 #define GEOJSON_POLYGON			203
88 
89 /** MULTIPOINT */
90 #define GEOJSON_MULTIPOINT		204
91 
92 /** MULTILINESTRING */
93 #define GEOJSON_MULTILINESTRING	205
94 
95 /** MULTIPOLYGON */
96 #define GEOJSON_MULTIPOLYGON	206
97 
98 /** GEOMETRYCOLLECTION */
99 #define GEOJSON_GEOMCOLLECTION	207
100 
101 
102 /* constant values for GeoJSON datatypes */
103 
104 /** Text */
105 #define GEOJSON_TEXT	301
106 
107 /** Integer (namely Int64) */
108 #define GEOJSON_INTEGER	302
109 
110 /** Floating Point Double precision */
111 #define GEOJSON_DOUBLE	303
112 
113 /** Boolean - TRUE */
114 #define GEOJSON_TRUE	304
115 
116 /** Boolean - FALSE */
117 #define GEOJSON_FALSE	305
118 
119 /** NULL */
120 #define GEOJSON_NULL	306
121 
122 
123 /* constant values for GeoJSON sizes */
124 
125 /** number of objects per each block */
126 #define GEOJSON_BLOCK	4096
127 
128 /** max fixed length for Text Strings */
129 #define GEOJSON_MAX		1024
130 
131 /** number of stack levels */
132 #define GEOJSON_STACK	16
133 
134 
135 /* GeoJSON objects and data structures */
136 
137 /**
138  an object wrapping a GeoJSON Property (aka data attribute)
139 */
140     typedef struct geojson_property_str
141     {
142 /** Property name */
143 	char *name;
144 /** datatype */
145 	int type;
146 /** pointer to Text value */
147 	char *txt_value;
148 /** Integer value */
149 	sqlite3_int64 int_value;
150 /** Double value */
151 	double dbl_value;
152 /** pointer to next item [linked list] */
153 	struct geojson_property_str *next;
154     } geojson_property;
155 
156 /**
157  pointer to Property
158 */
159     typedef geojson_property *geojson_property_ptr;
160 
161 /**
162  an object wrapping a GeoJSON Feature
163 */
164     typedef struct geojson_feature_str
165     {
166 /** unique Feature ID */
167 	int fid;
168 /** start offset; Geometry object */
169 	long geom_offset_start;
170 /** end offset: Geometry object */
171 	long geom_offset_end;
172 /** start offset: Properties object */
173 	long prop_offset_start;
174 /** end offset: Properties object */
175 	long prop_offset_end;
176 /** pointer to the Geometry string */
177 	char *geometry;
178 /** linked list of Properties - pointer to first item */
179 	geojson_property_ptr first;
180 /** linked list of Properties - pointer to last item */
181 	geojson_property_ptr last;
182     } geojson_feature;
183 
184 /**
185  pointer to Feature
186 */
187     typedef geojson_feature *geojson_feature_ptr;
188 
189 /**
190  an object wrapping an entry (aka Object) in the GeoJSON file
191 */
192     typedef struct geojson_entry_str
193     {
194 /** name of the parent object [key] */
195 	char *parent_key;
196 /** object type */
197 	int type;
198 /** count of Properties children */
199 	int properties;
200 /** count of Geometry children */
201 	int geometry;
202 /** object's start offset */
203 	long offset_start;
204 /** object's end offset */
205 	long offset_end;
206     } geojson_entry;
207 
208 /**
209  pointer to Entry
210 */
211     typedef geojson_entry *geojson_entry_ptr;
212 
213 /**
214  an object wrapping a block of entries in the GeoJSON file */
215     typedef struct geojson_block_str
216     {
217 /** index of the next free entry in the block */
218 	int next_free_entry;
219 /** array of entries */
220 	geojson_entry entries[GEOJSON_BLOCK];
221 /** pointer to next item [linked list] */
222 	struct geojson_block_str *next;
223     } geojson_block;
224 
225 /**
226  pointer to Block
227 */
228     typedef geojson_block *geojson_block_ptr;
229 
230 /**
231  an object wrapping a data Column
232 */
233     typedef struct geojson_column_str
234     {
235 /** column name */
236 	char *name;
237 /** number of Text values */
238 	int n_text;
239 /** number of Int values */
240 	int n_int;
241 /** number of Double values */
242 	int n_double;
243 /** number of Boolean values */
244 	int n_bool;
245 /** number of NULL values */
246 	int n_null;
247 /** pointer to next item [linked list] */
248 	struct geojson_column_str *next;
249     } geojson_column;
250 
251 /**
252  pointer to Column
253 */
254     typedef geojson_column *geojson_column_ptr;
255 
256 /**
257  an object wrapping a GeoJSON parser
258 */
259     typedef struct geojson_parser_str
260     {
261 /** file handle */
262 	FILE *in;
263 /** linked list of Blocks - pointer to first item */
264 	geojson_block_ptr first;
265 /** linked list of Blocks - pointer to last item */
266 	geojson_block_ptr last;
267 /** total number of Features */
268 	int count;
269 /** array of Features */
270 	geojson_feature_ptr features;
271 /** linked list of Columns - pointer to first item */
272 	geojson_column_ptr first_col;
273 /** linked list of Columns - pointer to last item */
274 	geojson_column_ptr last_col;
275 /** total number of Point Geometries */
276 	int n_points;
277 /** total number of Linestring Geometries */
278 	int n_linestrings;
279 /** total number of Polygon Geometries */
280 	int n_polygons;
281 /** total number of MultiPoint Geometries */
282 	int n_mpoints;
283 /** total number of MultiLinestring Geometries */
284 	int n_mlinestrings;
285 /** total number of MultiPolygon Geometries */
286 	int n_mpolygons;
287 /** total number of GeometryCollection Geometries */
288 	int n_geomcolls;
289 /** total number of NULL Geometries */
290 	int n_geom_null;
291 /** total number of 2D Geometries */
292 	int n_geom_2d;
293 /** total number of 3D Geometries */
294 	int n_geom_3d;
295 /** total number of 4D Geometries */
296 	int n_geom_4d;
297 /** Geometry Type cast function */
298 	char cast_type[64];
299 /** Geometry Dims cast function */
300 	char cast_dims[64];
301     } geojson_parser;
302 
303 /**
304  pointer to Parser
305 */
306     typedef geojson_parser *geojson_parser_ptr;
307 
308 /**
309  an object wrapping a Key-Value pair
310 */
311     typedef struct geojson_keyval_str
312     {
313 /** pointer to the Key string */
314 	char *key;
315 /** pointer to the Value string */
316 	char *value;
317 /** FALSE for quoted Text strings */
318 	int numvalue;
319 /** pointer to next item [linked list] */
320 	struct geojson_keyval_str *next;
321     } geojson_keyval;
322 
323 /**
324  pointer to KeyValue
325 */
326     typedef geojson_keyval *geojson_keyval_ptr;
327 
328 /**
329  an object wrapping a stack entry
330 */
331     typedef struct geojson_stack_entry_str
332     {
333 /** pointer to an Entry object */
334 	geojson_entry_ptr obj;
335 /** linked list of KeyValues - pointer to first item */
336 	geojson_keyval_ptr first;
337 /** linked list of KeyValues - pointer to last item */
338 	geojson_keyval_ptr last;
339     } geojson_stack_entry;
340 
341 /**
342  pointer to Stakc Entry
343 */
344     typedef geojson_stack_entry *geojson_stack_entry_ptr;
345 
346 /**
347  an object wrapping a GeoJSON stack
348 */
349     typedef struct geojson_stack
350     {
351 	/* a stack for parsing nested GeoJSON objects */
352 /** current stack level */
353 	int level;
354 /** the stack levels array */
355 	geojson_stack_entry entries[GEOJSON_STACK];
356 /** the Key parsing buffer */
357 	char key[GEOJSON_MAX];
358 /** current Key index - last inserted byte */
359 	int key_idx;
360 /** the Value parsing buffer - quote delimited strings */
361 	char value[GEOJSON_MAX];
362 /** current Value index - last inserted byte */
363 	int value_idx;
364 /** the Values parsing buffer - numeric values */
365 	char numvalue[GEOJSON_MAX];
366 /** current numeric Value index - last inserted byte */
367 	int numvalue_idx;
368     } geojson_stack;
369 
370 /**
371  pointer to Stack
372 */
373     typedef geojson_stack *geojson_stack_ptr;
374 
375 
376 /* function prototypes */
377 
378 /**
379  Creates a new GeoJSON parser object
380 
381  \param in an open FILE supposed to contain the GeoJSON text to be parsed
382 
383  \return the pointer to newly created object
384 
385  \sa geojson_destroy_parser, geojson_parser_init
386 
387  \note you are responsible to destroy (before or after) any allocated
388  GeoJSON parser object.
389  */
390     SPATIALITE_DECLARE geojson_parser_ptr geojson_create_parser (FILE * in);
391 
392 /**
393  Destroys a GeoJSON parser object
394 
395  \param p pointer to object to be destroyed
396 
397  \sa geojson_create_parser
398  */
399     SPATIALITE_DECLARE void geojson_destroy_parser (geojson_parser_ptr p);
400 
401 /**
402  Fully initializes a GeoJSON parser object
403 
404  \param parser pointer to a GeoJSON parser object
405  \param error_message: will point to a diagnostic error message
406   in case of failure, otherwise NULL
407 
408  \return 1 on success. 0 on failure (invalid GeoJSON text).
409 
410  \sa geojson_create_parser, geojson_check_features
411 
412  \note you are expected to free before or later an eventual error
413  message by calling sqlite3_free()
414  */
415     SPATIALITE_DECLARE int geojson_parser_init (geojson_parser_ptr parser,
416 						char **error_message);
417 
418 /**
419  Checks a fully initialized GeoJSON parser object for containing valid Features
420 
421  \param parser pointer to a GeoJSON parser object
422  \param error_message: will point to a diagnostic error message
423   in case of failure, otherwise NULL
424 
425  \return 1 on success. 0 on failure (invalid GeoJSON text).
426 
427  \sa geojson_parser_init, geojson_create_features_index
428 
429  \note you are expected to free before or later an eventual error
430  message by calling sqlite3_free()
431  */
432     SPATIALITE_DECLARE int geojson_check_features (geojson_parser_ptr parser,
433 						   char **error_message);
434 
435 /**
436  Creates the Features Index on a GeoJSON parser object
437 
438  \param parser pointer to a GeoJSON parser object
439  \param error_message: will point to a diagnostic error message
440   in case of failure, otherwise NULL
441 
442  \return 1 on success. 0 on failure (invalid GeoJSON text).
443 
444  \sa geojson_check_features
445 
446  \note you are expected to free before or later an eventual error
447  message by calling sqlite3_free()
448  */
449     SPATIALITE_DECLARE int geojson_create_features_index (geojson_parser_ptr
450 							  parser,
451 							  char **error_message);
452 
453 /**
454  Will return the SQL CREATE TABLE statement
455 
456  \param parser pointer to a GeoJSON parser object
457  \param table name of the SQL table to be created
458  \param colname_case one between GAIA_DBF_COLNAME_LOWERCASE,
459 	GAIA_DBF_COLNAME_UPPERCASE or GAIA_DBF_COLNAME_CASE_IGNORE.
460 
461  \return the SQL CREATE TABLE statement as a text string; NULL on failure
462 
463  \sa geojson_check_features, geojson_sql_add_geometry, geojson_sql_create_rtree
464  geojson_insert_into
465 
466  \note you are expected to free the SQL string returned by this
467  function by calling sqlite3_free() when it's no longer useful.
468  */
469     SPATIALITE_DECLARE char *geojson_sql_create_table (geojson_parser_ptr
470 						       parser,
471 						       const char *table,
472 						       int colname_case);
473 
474 /**
475  Will return the SQL AddGeometryColumn() statement
476 
477  \param parser pointer to a GeoJSON parser object
478  \param table name of the SQL table being created
479  \param geom_col name of the Geometry column
480  \param colname_case one between GAIA_DBF_COLNAME_LOWERCASE,
481 	GAIA_DBF_COLNAME_UPPERCASE or GAIA_DBF_COLNAME_CASE_IGNORE.
482  \param srid the corresponding SRID value
483 
484  \return the AddGeometryColumn() SQL string; NULL on failure
485 
486  \sa geojson_check_features, geojson_sql_create_table, geojson_sql_create_rtree
487  geojson_insert_into
488 
489  \note you are expected to free the SQL string returned by this
490  function by calling sqlite3_free() when it's no longer useful.
491  */
492     SPATIALITE_DECLARE char *geojson_sql_add_geometry (geojson_parser_ptr
493 						       parser,
494 						       const char *table,
495 						       const char *geom_col,
496 						       int colname_case,
497 						       int srid);
498 
499 /**
500  Will return the SQL CreateSpatialIndex() statement
501 
502  \param table name of the SQL table being created
503  \param geom_col name of the Geometry column
504  \param colname_case one between GAIA_DBF_COLNAME_LOWERCASE,
505 	GAIA_DBF_COLNAME_UPPERCASE or GAIA_DBF_COLNAME_CASE_IGNORE.
506 
507  \return the CreateSpatialIndex() SQL string; NULL on failure
508 
509  \sa geojson_check_features, geojson_sql_create_table, geojson_sql_add_geometry,
510  geojson_insert_into
511 
512  \note you are expected to free the SQL string returned by this
513  function by calling sqlite3_free() when it's no longer useful.
514  */
515     SPATIALITE_DECLARE char *geojson_sql_create_rtree (const char *table,
516 						       const char *geom_col,
517 						       int colname_case);
518 
519 /**
520  Will return the SQL INSERT INTO statement
521 
522  \param parser pointer to a GeoJSON parser object
523  \param table name of the SQL table being created
524  \param geom_col name of the Geometry column
525 
526  \return the INSERT INTO SQL string; NULL on failure
527 
528  \sa geojson_check_features, geojson_sql_create_table, geojson_add_geometry,
529  geojson_sql_create_rtree
530 
531  \note you are expected to free the SQL string returned by this
532  function by calling sqlite3_free() when it's no longer useful.
533  */
534     SPATIALITE_DECLARE char *geojson_sql_insert_into (geojson_parser_ptr
535 						      parser,
536 						      const char *table);
537 
538 /**
539  Will fully initialize a Feature with all Property and Geometry values
540 
541  \param parser pointer to a GeoJSON parser object
542  \param ft pointer the some GeoJson Feature object into the Parser
543  \param error_message: will point to a diagnostic error message
544   in case of failure, otherwise NULL
545 
546  \return 1 on success. 0 on failure (invalid GeoJSON Feature).
547 
548  \sa geojson_create_features_index, geojson_reset_feature,
549  geojson_get_property_by_name
550 
551  \note you are expected to free all Values returned by this function by
552  calling geojson_reset_feature() when they are no longer useful.
553  And you are expected also to free before or later an eventual error
554  message by calling sqlite3_free()
555  */
556     SPATIALITE_DECLARE int geojson_init_feature (geojson_parser_ptr parser,
557 						 geojson_feature_ptr ft,
558 						 char **error_message);
559 
560 /**
561  Will reset a Feature by freeing all Property and Geometry Values
562 
563  \param ft pointer the some GeoJson Feature object into the Parser
564 
565  \sa geojson_create_features_index, geojson_init_feature,
566  geojson_get_property_by_name
567  */
568     SPATIALITE_DECLARE void geojson_reset_feature (geojson_feature_ptr ft);
569 
570 /**
571  Will return the pointer to a given Property within a Feature
572 
573  \param ft pointer the some GeoJson Feature object
574  \param name the name of some specific Property
575 
576  \sa geojson_create_features_index, geojson_init_feature,
577  geojson_reset_feature
578  */
579     SPATIALITE_DECLARE geojson_property_ptr
580 	geojson_get_property_by_name (geojson_feature_ptr ft, const char *name);
581 
582 #ifdef __cplusplus
583 }
584 #endif
585 
586 #endif				/* _GEOJSON_H */
587