geo_coder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. data/Gemfile +12 -0
  2. data/Gemfile.lock +32 -0
  3. data/History.txt +6 -0
  4. data/Makefile +13 -0
  5. data/Manifest.txt +18 -0
  6. data/README.rdoc +197 -0
  7. data/Rakefile +53 -0
  8. data/TODO.txt +8 -0
  9. data/VERSION +1 -0
  10. data/bin/build_indexes +8 -0
  11. data/bin/rebuild_cluster +22 -0
  12. data/bin/rebuild_metaphones +23 -0
  13. data/bin/tiger_import +59 -0
  14. data/demos/demo/app/ext/geocodewrap.rb +84 -0
  15. data/demos/demo/app/views/index.builder +13 -0
  16. data/demos/demo/app/views/index.erb +71 -0
  17. data/demos/demo/config.ru +12 -0
  18. data/demos/demo/config/bootstraps.rb +130 -0
  19. data/demos/demo/config/geoenvironment.rb +25 -0
  20. data/demos/demo/geocoder_helper.rb +12 -0
  21. data/demos/demo/geocom_geocode.rb +10 -0
  22. data/demos/demo/main.rb +3 -0
  23. data/demos/demo/rakefile.rb +17 -0
  24. data/demos/demo/tmp/restart.txt +0 -0
  25. data/demos/simpledemo/views/index.builder +13 -0
  26. data/demos/simpledemo/views/index.erb +69 -0
  27. data/demos/simpledemo/ws.rb +83 -0
  28. data/doc/Makefile +7 -0
  29. data/doc/html4css1.css +279 -0
  30. data/doc/lookup.rst +193 -0
  31. data/doc/parsing.rst +125 -0
  32. data/doc/voidspace.css +147 -0
  33. data/geo_coder.gemspec +172 -0
  34. data/lib/geocoder/us.rb +21 -0
  35. data/lib/geocoder/us/address.rb +290 -0
  36. data/lib/geocoder/us/constants.rb +670 -0
  37. data/lib/geocoder/us/database.rb +745 -0
  38. data/lib/geocoder/us/import.rb +181 -0
  39. data/lib/geocoder/us/import/tiger.rb +13 -0
  40. data/lib/geocoder/us/numbers.rb +58 -0
  41. data/navteq/README +4 -0
  42. data/navteq/convert.sql +37 -0
  43. data/navteq/navteq_import +39 -0
  44. data/navteq/prepare.sql +92 -0
  45. data/sql/cluster.sql +16 -0
  46. data/sql/convert.sql +80 -0
  47. data/sql/create.sql +37 -0
  48. data/sql/index.sql +12 -0
  49. data/sql/place.csv +104944 -0
  50. data/sql/place.sql +104948 -0
  51. data/sql/setup.sql +78 -0
  52. data/src/Makefile +13 -0
  53. data/src/README +14 -0
  54. data/src/liblwgeom/Makefile +75 -0
  55. data/src/liblwgeom/box2d.c +54 -0
  56. data/src/liblwgeom/lex.yy.c +4799 -0
  57. data/src/liblwgeom/liblwgeom.h +1405 -0
  58. data/src/liblwgeom/lwalgorithm.c +946 -0
  59. data/src/liblwgeom/lwalgorithm.h +52 -0
  60. data/src/liblwgeom/lwcircstring.c +759 -0
  61. data/src/liblwgeom/lwcollection.c +541 -0
  62. data/src/liblwgeom/lwcompound.c +118 -0
  63. data/src/liblwgeom/lwcurvepoly.c +86 -0
  64. data/src/liblwgeom/lwgeom.c +886 -0
  65. data/src/liblwgeom/lwgeom_api.c +2201 -0
  66. data/src/liblwgeom/lwgparse.c +1219 -0
  67. data/src/liblwgeom/lwgunparse.c +1054 -0
  68. data/src/liblwgeom/lwline.c +525 -0
  69. data/src/liblwgeom/lwmcurve.c +125 -0
  70. data/src/liblwgeom/lwmline.c +137 -0
  71. data/src/liblwgeom/lwmpoint.c +138 -0
  72. data/src/liblwgeom/lwmpoly.c +141 -0
  73. data/src/liblwgeom/lwmsurface.c +129 -0
  74. data/src/liblwgeom/lwpoint.c +439 -0
  75. data/src/liblwgeom/lwpoly.c +579 -0
  76. data/src/liblwgeom/lwsegmentize.c +1047 -0
  77. data/src/liblwgeom/lwutil.c +369 -0
  78. data/src/liblwgeom/measures.c +861 -0
  79. data/src/liblwgeom/postgis_config.h +93 -0
  80. data/src/liblwgeom/ptarray.c +847 -0
  81. data/src/liblwgeom/vsprintf.c +179 -0
  82. data/src/liblwgeom/wktparse.h +126 -0
  83. data/src/liblwgeom/wktparse.lex +74 -0
  84. data/src/liblwgeom/wktparse.tab.c +2353 -0
  85. data/src/liblwgeom/wktparse.tab.h +145 -0
  86. data/src/liblwgeom/wktparse.y +385 -0
  87. data/src/libsqlite3_geocoder/Makefile +22 -0
  88. data/src/libsqlite3_geocoder/Makefile.nix +15 -0
  89. data/src/libsqlite3_geocoder/Makefile.redhat +15 -0
  90. data/src/libsqlite3_geocoder/extension.c +121 -0
  91. data/src/libsqlite3_geocoder/extension.h +13 -0
  92. data/src/libsqlite3_geocoder/levenshtein.c +42 -0
  93. data/src/libsqlite3_geocoder/metaphon.c +278 -0
  94. data/src/libsqlite3_geocoder/util.c +37 -0
  95. data/src/libsqlite3_geocoder/wkb_compress.c +54 -0
  96. data/src/metaphone/Makefile +7 -0
  97. data/src/metaphone/README +49 -0
  98. data/src/metaphone/extension.c +37 -0
  99. data/src/metaphone/metaphon.c +251 -0
  100. data/src/shp2sqlite/Makefile +37 -0
  101. data/src/shp2sqlite/Makefile.nix +36 -0
  102. data/src/shp2sqlite/Makefile.redhat +35 -0
  103. data/src/shp2sqlite/dbfopen.c +1595 -0
  104. data/src/shp2sqlite/getopt.c +695 -0
  105. data/src/shp2sqlite/getopt.h +127 -0
  106. data/src/shp2sqlite/shapefil.h +500 -0
  107. data/src/shp2sqlite/shp2sqlite.c +1974 -0
  108. data/src/shp2sqlite/shpopen.c +1894 -0
  109. data/tests/address.rb +236 -0
  110. data/tests/benchmark.rb +20 -0
  111. data/tests/constants.rb +57 -0
  112. data/tests/data/address-sample.csv +52 -0
  113. data/tests/data/db-test.csv +57 -0
  114. data/tests/data/locations.csv +4 -0
  115. data/tests/database.rb +137 -0
  116. data/tests/generate.rb +34 -0
  117. data/tests/numbers.rb +46 -0
  118. data/tests/run.rb +11 -0
  119. metadata +237 -0
@@ -0,0 +1,1219 @@
1
+ /*
2
+ * Written by Ralph Mason ralph.mason<at>telogis.com
3
+ *
4
+ * Copyright Telogis 2004
5
+ * www.telogis.com
6
+ *
7
+ */
8
+ #include <string.h>
9
+ #include <stdio.h>
10
+ /* Solaris9 does not provide stdint.h */
11
+ /* #include <stdint.h> */
12
+ #include <inttypes.h>
13
+
14
+ #include "liblwgeom.h"
15
+ #include "wktparse.h"
16
+ #include "wktparse.tab.h"
17
+
18
+ /*
19
+ * To get byte order
20
+ #include <sys/types.h>
21
+ #include <netinet/in.h>
22
+ #include <netinet/in_systm.h>
23
+ #include <netinet/ip.h>
24
+ */
25
+
26
+ void set_zm(char z, char m);
27
+ void close_parser(void);
28
+
29
+ typedef uint32_t int4;
30
+
31
+ typedef struct tag_tuple tuple;
32
+
33
+ struct tag_outputstate{
34
+ uchar* pos;
35
+ };
36
+
37
+ typedef struct tag_outputstate output_state;
38
+ typedef void (*output_func)(tuple* this, output_state* out);
39
+ typedef void (*read_col_func)(const char **f);
40
+
41
+
42
+
43
+ /* Globals */
44
+
45
+ int srid=-1;
46
+
47
+ static int parser_ferror_occured;
48
+ static allocator local_malloc;
49
+ static report_error error_func;
50
+
51
+ struct tag_tuple{
52
+ output_func of;
53
+ union union_tag {
54
+ double points[4];
55
+ int4 pointsi[4];
56
+
57
+ struct struct_tag {
58
+ tuple* stack_next;
59
+ int type;
60
+ int num;
61
+ int size_here;
62
+ } nn;
63
+ } uu;
64
+ struct tag_tuple *next;
65
+ };
66
+
67
+ struct {
68
+ int type;
69
+ int flags;
70
+ int srid;
71
+ int ndims;
72
+ int hasZ;
73
+ int hasM;
74
+ /* create integer version */
75
+ int lwgi;
76
+ /* input is integer (wkb only)*/
77
+ int from_lwgi;
78
+
79
+ int4 alloc_size;
80
+
81
+ /*
82
+ linked list of all tuples
83
+ */
84
+ tuple* first;
85
+ tuple* last;
86
+
87
+ /*
88
+ stack of open geometries
89
+ */
90
+ tuple* stack;
91
+
92
+ } the_geom;
93
+
94
+ tuple* free_list=0;
95
+
96
+
97
+ /*
98
+ * Parser current instance check flags - a bitmap of flags that determine which checks are enabled during the current parse
99
+ * (see liblwgeom.h for the related PARSER_CHECK constants)
100
+ */
101
+ int current_parser_check_flags;
102
+
103
+ /*
104
+ * Parser current instance result structure - the result structure being used for the current parse
105
+ */
106
+ LWGEOM_PARSER_RESULT *current_lwg_parser_result;
107
+
108
+
109
+ /* Parser state flags - these are set automatically by the parser */
110
+ int minpoints;
111
+ int checkclosed;
112
+
113
+ /*
114
+ * This indicates if the number of points in the geometry is required to
115
+ * be odd (one) or even (zero, currently not enforced) or whatever (-one)
116
+ */
117
+ int isodd;
118
+ double *first_point=NULL;
119
+ double *last_point=NULL;
120
+
121
+
122
+ /*
123
+ * Parser error messages
124
+ *
125
+ * IMPORTANT: Make sure the order of these messages matches the PARSER_ERROR constants in liblwgeom.h!
126
+ * The 0th element should always be empty since it is unused (error constants start from -1)
127
+ */
128
+
129
+ const char *parser_error_messages[] = {
130
+ "",
131
+ "geometry requires more points",
132
+ "geometry must have an odd number of points",
133
+ "geometry contains non-closed rings",
134
+ "can not mix dimensionality in a geometry",
135
+ "parse error - invalid geometry",
136
+ "invalid WKB type"
137
+ };
138
+
139
+ /* Macro to return the error message and the current position within WKT */
140
+ #define LWGEOM_WKT_PARSER_ERROR(errcode) \
141
+ do { \
142
+ if (!parser_ferror_occured) { \
143
+ parser_ferror_occured = -1 * errcode; \
144
+ current_lwg_parser_result->message = parser_error_messages[errcode]; \
145
+ current_lwg_parser_result->errlocation = lwg_parse_yylloc.last_column; \
146
+ } \
147
+ } while (0);
148
+
149
+
150
+ /* Macro to return the error message and the current position within WKB
151
+ NOTE: the position is handled automatically by strhex_readbyte */
152
+ #define LWGEOM_WKB_PARSER_ERROR(errcode) \
153
+ do { \
154
+ if (!parser_ferror_occured) { \
155
+ parser_ferror_occured = -1 * errcode; \
156
+ current_lwg_parser_result->message = parser_error_messages[errcode]; \
157
+ } \
158
+ } while (0);
159
+
160
+
161
+ /* External functions */
162
+ extern void init_parser(const char *);
163
+
164
+ /* Prototypes */
165
+ tuple* alloc_tuple(output_func of,size_t size);
166
+ void free_tuple(tuple* to_free);
167
+ void inc_num(void);
168
+ void alloc_stack_tuple(int type,output_func of,size_t size);
169
+ void check_dims(int num);
170
+ void WRITE_DOUBLES(output_state* out,double* points, int cnt);
171
+ #ifdef SHRINK_INTS
172
+ void WRITE_INT4(output_state * out,int4 val);
173
+ #endif
174
+ void empty_stack(tuple* this,output_state* out);
175
+ void alloc_lwgeom(int srid);
176
+ void write_point_2(tuple* this,output_state* out);
177
+ void write_point_3(tuple* this,output_state* out);
178
+ void write_point_4(tuple* this,output_state* out);
179
+ void write_point_2i(tuple* this,output_state* out);
180
+ void write_point_3i(tuple* this,output_state* out);
181
+ void write_point_4i(tuple* this,output_state* out);
182
+ void alloc_point_2d(double x,double y);
183
+ void alloc_point_3d(double x,double y,double z);
184
+ void alloc_point_4d(double x,double y,double z,double m);
185
+ void write_type(tuple* this,output_state* out);
186
+ void write_count(tuple* this,output_state* out);
187
+ void write_type_count(tuple* this,output_state* out);
188
+ void alloc_point(void);
189
+ void alloc_linestring(void);
190
+ void alloc_linestring_closed(void);
191
+ void alloc_circularstring(void);
192
+ void alloc_circularstring_closed(void);
193
+ void alloc_polygon(void);
194
+ void alloc_multipoint(void);
195
+ void alloc_multilinestring(void);
196
+ void alloc_multicurve(void);
197
+ void alloc_multipolygon(void);
198
+ void alloc_multisurface(void);
199
+ void alloc_geomertycollection(void);
200
+ void alloc_counter(void);
201
+ void alloc_empty(void);
202
+ void make_serialized_lwgeom(LWGEOM_PARSER_RESULT *lwg_parser_result);
203
+ uchar strhex_readbyte(const char *in);
204
+ uchar read_wkb_byte(const char **in);
205
+ void read_wkb_bytes(const char **in, uchar* out, int cnt);
206
+ int4 read_wkb_int(const char **in);
207
+ double read_wkb_double(const char **in, int convert_from_int);
208
+ void read_wkb_point(const char **b);
209
+ void read_wkb_polygon(const char **b);
210
+ void read_wkb_linestring(const char **b);
211
+ void read_wkb_circstring(const char **b);
212
+ void read_wkb_ordinate_array(const char **b);
213
+ void read_collection(const char **b, read_col_func f);
214
+ void parse_wkb(const char **b);
215
+ void alloc_wkb(const char *parser);
216
+ int parse_it(LWGEOM_PARSER_RESULT *lwg_parser_result, const char* geometry, int flags, allocator allocfunc, report_error errfunc);
217
+ int parse_lwg(LWGEOM_PARSER_RESULT *lwg_parser_result, const char* geometry, int flags, allocator allocfunc, report_error errfunc);
218
+ int parse_lwgi(LWGEOM_PARSER_RESULT *lwg_parser_result, const char* geometry, int flags, allocator allocfunc, report_error errfunc);
219
+
220
+ void
221
+ set_srid(double d_srid)
222
+ {
223
+ if ( d_srid >= 0 )
224
+ d_srid+=0.1;
225
+ else
226
+ d_srid-=0.1;
227
+
228
+
229
+ srid=(int)(d_srid+0.1);
230
+ }
231
+
232
+ tuple *
233
+ alloc_tuple(output_func of,size_t size)
234
+ {
235
+ tuple* ret = free_list;
236
+
237
+ if ( ! ret ){
238
+ int toalloc = (ALLOC_CHUNKS /sizeof(tuple));
239
+ ret = malloc( toalloc *sizeof(tuple) );
240
+
241
+ free_list = ret;
242
+
243
+ while(--toalloc){
244
+ ret->next = ret+1;
245
+ ret++;
246
+ }
247
+
248
+ ret->next = NULL;
249
+
250
+ return alloc_tuple(of,size);
251
+ }
252
+
253
+ free_list = ret->next;
254
+ ret->of = of;
255
+ ret->next = NULL;
256
+
257
+ if ( the_geom.last ) {
258
+ the_geom.last->next = ret;
259
+ the_geom.last = ret;
260
+ }
261
+ else {
262
+ the_geom.first = the_geom.last = ret;
263
+ }
264
+
265
+ the_geom.alloc_size += size;
266
+ return ret;
267
+ }
268
+
269
+ void
270
+ free_tuple(tuple* to_free)
271
+ {
272
+
273
+ tuple* list_end = to_free;
274
+
275
+ if( !to_free)
276
+ return;
277
+
278
+ while(list_end->next){
279
+ list_end=list_end->next;
280
+ }
281
+
282
+ list_end->next = free_list;
283
+ free_list = to_free;
284
+ }
285
+
286
+ void
287
+ inc_num(void)
288
+ {
289
+ the_geom.stack->uu.nn.num++;
290
+ }
291
+
292
+ /*
293
+ Allocate a 'counting' tuple
294
+ */
295
+ void
296
+ alloc_stack_tuple(int type,output_func of,size_t size)
297
+ {
298
+ tuple* p;
299
+ inc_num();
300
+
301
+ LWDEBUGF(2, "alloc_stack_tuple %d, %d", type, size);
302
+
303
+ p = alloc_tuple(of,size);
304
+ p->uu.nn.stack_next = the_geom.stack;
305
+ p->uu.nn.type = type;
306
+ p->uu.nn.size_here = the_geom.alloc_size;
307
+ p->uu.nn.num = 0;
308
+ the_geom.stack = p;
309
+ }
310
+
311
+ void
312
+ pop(void)
313
+ {
314
+ the_geom.stack = the_geom.stack->uu.nn.stack_next;
315
+ }
316
+
317
+ void
318
+ popc(void)
319
+ {
320
+ /* If the minimum point check has been enabled, perform it */
321
+ if (current_parser_check_flags & PARSER_CHECK_MINPOINTS) {
322
+ if ( the_geom.stack->uu.nn.num < minpoints){
323
+ LWGEOM_WKT_PARSER_ERROR(PARSER_ERROR_MOREPOINTS);
324
+ }
325
+ }
326
+
327
+ /* If the odd number point check has been enabled, perform it */
328
+ if (current_parser_check_flags & PARSER_CHECK_ODD) {
329
+ if(isodd != -1 && the_geom.stack->uu.nn.num % 2 != isodd) {
330
+ LWGEOM_WKT_PARSER_ERROR(PARSER_ERROR_ODDPOINTS);
331
+ }
332
+ }
333
+
334
+ /* If the polygon closure check has been enabled, perform it */
335
+ if (current_parser_check_flags & PARSER_CHECK_CLOSURE) {
336
+ if ( checkclosed && first_point && last_point) {
337
+ if ( memcmp(first_point, last_point,
338
+ sizeof(double)*the_geom.ndims) )
339
+ {
340
+ LWGEOM_WKT_PARSER_ERROR(PARSER_ERROR_UNCLOSED);
341
+ }
342
+ }
343
+ }
344
+
345
+ the_geom.stack = the_geom.stack->uu.nn.stack_next;
346
+ }
347
+
348
+
349
+ void
350
+ check_dims(int num)
351
+ {
352
+ LWDEBUGF(2, "check_dims the_geom.ndims = %d, num = %d", the_geom.ndims, num);
353
+
354
+ if( the_geom.ndims != num){
355
+ if (the_geom.ndims) {
356
+ LWGEOM_WKT_PARSER_ERROR(PARSER_ERROR_MIXDIMS);
357
+ } else {
358
+
359
+ LWDEBUGF(3, "check_dims: setting dim %d", num);
360
+
361
+ the_geom.ndims = num;
362
+ if ( num > 2 ) the_geom.hasZ = 1;
363
+ if ( num > 3 ) the_geom.hasM = 1;
364
+ }
365
+ }
366
+ }
367
+
368
+ #define WRITE_INT4_REAL(x,y) { memcpy(x->pos,&y,4); x->pos+=4;}
369
+ #define WRITE_INT4_REAL_MULTIPLE(x,y,z) { memcpy(x->pos,&y,z*4); x->pos+=(z*4);}
370
+
371
+ /*
372
+ we can shrink ints to one byte if they are less than 127
373
+ by setting the extra bit. Because if the different byte
374
+ ordering possibilities we need to set the lsb on little
375
+ endian to show a packed one and the msb on a big endian
376
+ machine
377
+ */
378
+ #ifdef SHRINK_INTS
379
+ void
380
+ WRITE_INT4(output_state * out,int4 val)
381
+ {
382
+ if ( val <= 0x7f ){
383
+ if ( getMachineEndian() == NDR ){
384
+ val = (val<<1) | 1;
385
+ }
386
+ else{
387
+ val |=0x80;
388
+ }
389
+
390
+ *out->pos++ = (uchar)val;
391
+ the_geom.alloc_size-=3;
392
+ }
393
+ else{
394
+ if ( getMachineEndian() == NDR ){
395
+ val <<=1;
396
+ }
397
+ WRITE_INT4_REAL(out,val);
398
+ }
399
+ }
400
+ #else
401
+ #define WRITE_INT4 WRITE_INT4_REAL
402
+ #endif
403
+
404
+
405
+ void
406
+ WRITE_DOUBLES(output_state* out,double* points, int cnt)
407
+ {
408
+ if ( the_geom.lwgi){
409
+ int4 vals[4];
410
+ int i;
411
+
412
+ for(i=0; i<cnt;i++){
413
+ vals[i] = (int4)(((points[i]+180.0)*0xB60B60)+.5);
414
+ }
415
+ memcpy(out->pos,vals,sizeof(int4)*cnt);
416
+ out->pos+=sizeof(int4)*cnt;
417
+ }
418
+ else{
419
+ memcpy(out->pos,points,sizeof(double)*cnt);
420
+ out->pos+=sizeof(double)*cnt;
421
+ }
422
+
423
+ }
424
+
425
+ void
426
+ empty_stack(tuple *this,output_state* out)
427
+ {
428
+ /* Do nothing but provide an empty base for the geometry stack */
429
+ }
430
+
431
+ void
432
+ alloc_lwgeom(int srid)
433
+ {
434
+ LWDEBUGF(2, "alloc_lwgeom %d", srid);
435
+
436
+ the_geom.srid=srid;
437
+ the_geom.alloc_size=0;
438
+ the_geom.stack=NULL;
439
+ the_geom.ndims=0;
440
+ the_geom.hasZ=0;
441
+ the_geom.hasM=0;
442
+
443
+ /* Free if used already */
444
+ if ( the_geom.first ){
445
+ free_tuple(the_geom.first);
446
+ the_geom.first=the_geom.last=NULL;
447
+ }
448
+
449
+ if ( srid != -1 ){
450
+ the_geom.alloc_size+=4;
451
+ }
452
+
453
+ /* Setup up an empty tuple as the stack base */
454
+ the_geom.stack = alloc_tuple(empty_stack, 0);
455
+ }
456
+
457
+ void
458
+ write_point_2(tuple* this,output_state* out)
459
+ {
460
+ WRITE_DOUBLES(out,this->uu.points,2);
461
+ }
462
+
463
+ void
464
+ write_point_3(tuple* this,output_state* out)
465
+ {
466
+ WRITE_DOUBLES(out,this->uu.points,3);
467
+ }
468
+
469
+ void
470
+ write_point_4(tuple* this,output_state* out)
471
+ {
472
+ WRITE_DOUBLES(out,this->uu.points,4);
473
+ }
474
+
475
+ void
476
+ write_point_2i(tuple* this,output_state* out)
477
+ {
478
+ WRITE_INT4_REAL_MULTIPLE(out,this->uu.points,2);
479
+ }
480
+
481
+ void
482
+ write_point_3i(tuple* this,output_state* out)
483
+ {
484
+ WRITE_INT4_REAL_MULTIPLE(out,this->uu.points,3);
485
+ }
486
+
487
+ void
488
+ write_point_4i(tuple* this,output_state* out)
489
+ {
490
+ WRITE_INT4_REAL_MULTIPLE(out,this->uu.points,4);
491
+ }
492
+
493
+ void
494
+ alloc_point_2d(double x,double y)
495
+ {
496
+ tuple* p = alloc_tuple(write_point_2,the_geom.lwgi?8:16);
497
+ p->uu.points[0] = x;
498
+ p->uu.points[1] = y;
499
+
500
+ LWDEBUGF(2, "alloc_point_2d %f,%f", x, y);
501
+
502
+ /* keep track of point */
503
+ if ( checkclosed ) {
504
+ if ( ! the_geom.stack->uu.nn.num )
505
+ first_point = p->uu.points;
506
+ last_point = p->uu.points;
507
+ }
508
+
509
+ inc_num();
510
+ check_dims(2);
511
+ }
512
+
513
+ void
514
+ alloc_point_3d(double x,double y,double z)
515
+ {
516
+ tuple* p = alloc_tuple(write_point_3,the_geom.lwgi?12:24);
517
+ p->uu.points[0] = x;
518
+ p->uu.points[1] = y;
519
+ p->uu.points[2] = z;
520
+
521
+ LWDEBUGF(2, "alloc_point_3d %f, %f, %f", x, y, z);
522
+
523
+ /* keep track of point */
524
+ if ( checkclosed ) {
525
+ if ( ! the_geom.stack->uu.nn.num )
526
+ first_point = p->uu.points;
527
+ last_point = p->uu.points;
528
+ }
529
+
530
+ inc_num();
531
+ check_dims(3);
532
+ }
533
+
534
+ void
535
+ alloc_point_4d(double x,double y,double z,double m)
536
+ {
537
+ tuple* p = alloc_tuple(write_point_4,the_geom.lwgi?16:32);
538
+ p->uu.points[0] = x;
539
+ p->uu.points[1] = y;
540
+ p->uu.points[2] = z;
541
+ p->uu.points[3] = m;
542
+
543
+ LWDEBUGF(2, "alloc_point_4d %f, %f, %f, %f", x, y, z, m);
544
+
545
+ /* keep track of point */
546
+ if ( checkclosed ) {
547
+ if ( ! the_geom.stack->uu.nn.num )
548
+ first_point = p->uu.points;
549
+ last_point = p->uu.points;
550
+ }
551
+
552
+ inc_num();
553
+ check_dims(4);
554
+ }
555
+
556
+ void
557
+ write_type(tuple* this,output_state* out)
558
+ {
559
+ uchar type=0;
560
+
561
+ /* Empty handler - switch back */
562
+ if ( this->uu.nn.type == 0xff )
563
+ this->uu.nn.type = COLLECTIONTYPE;
564
+
565
+ type |= this->uu.nn.type;
566
+
567
+ if (the_geom.ndims) /* Support empty */
568
+ {
569
+ TYPE_SETZM(type, the_geom.hasZ, the_geom.hasM);
570
+ }
571
+
572
+ if ( the_geom.srid != -1 ){
573
+ type |= 0x40;
574
+ }
575
+
576
+ *(out->pos)=type;
577
+ out->pos++;
578
+
579
+ if ( the_geom.srid != -1 ){
580
+ /* Only the first geometry will have a srid attached */
581
+ WRITE_INT4(out,the_geom.srid);
582
+ the_geom.srid = -1;
583
+ }
584
+ }
585
+
586
+ void
587
+ write_count(tuple* this,output_state* out)
588
+ {
589
+ int num = this->uu.nn.num;
590
+ WRITE_INT4(out,num);
591
+ }
592
+
593
+ void
594
+ write_type_count(tuple* this,output_state* out)
595
+ {
596
+ write_type(this,out);
597
+ write_count(this,out);
598
+ }
599
+
600
+ void
601
+ alloc_point(void)
602
+ {
603
+ LWDEBUG(2, "alloc_point");
604
+
605
+ if( the_geom.lwgi)
606
+ alloc_stack_tuple(POINTTYPEI,write_type,1);
607
+ else
608
+ alloc_stack_tuple(POINTTYPE,write_type,1);
609
+
610
+ minpoints=1;
611
+ checkclosed=0;
612
+ isodd=-1;
613
+ }
614
+
615
+ void
616
+ alloc_linestring(void)
617
+ {
618
+ LWDEBUG(2, "alloc_linestring");
619
+
620
+ if( the_geom.lwgi)
621
+ alloc_stack_tuple(LINETYPEI,write_type,1);
622
+ else
623
+ alloc_stack_tuple(LINETYPE,write_type,1);
624
+
625
+ minpoints=2;
626
+ checkclosed=0;
627
+ isodd=-1;
628
+ }
629
+
630
+ void alloc_linestring_closed(void)
631
+ {
632
+ LWDEBUG(2, "alloc_linestring_closed called.");
633
+
634
+ alloc_linestring();
635
+ checkclosed=1;
636
+ }
637
+
638
+ void
639
+ alloc_circularstring(void)
640
+ {
641
+ LWDEBUG(2, "alloc_circularstring");
642
+
643
+ alloc_stack_tuple(CIRCSTRINGTYPE,write_type,1);
644
+ minpoints=3;
645
+ checkclosed=0;
646
+ isodd=1;
647
+ }
648
+
649
+ void alloc_circularstring_closed(void)
650
+ {
651
+ LWDEBUG(2, "alloc_circularstring_closed");
652
+
653
+ alloc_circularstring();
654
+ checkclosed=1;
655
+ }
656
+
657
+ void
658
+ alloc_polygon(void)
659
+ {
660
+ LWDEBUG(2, "alloc_polygon");
661
+
662
+ if( the_geom.lwgi)
663
+ alloc_stack_tuple(POLYGONTYPEI, write_type,1);
664
+ else
665
+ alloc_stack_tuple(POLYGONTYPE, write_type,1);
666
+
667
+ minpoints=4;
668
+ checkclosed=1;
669
+ isodd=-1;
670
+
671
+ }
672
+
673
+ void
674
+ alloc_curvepolygon(void)
675
+ {
676
+ LWDEBUG(2, "alloc_curvepolygon called.");
677
+
678
+ alloc_stack_tuple(CURVEPOLYTYPE, write_type, 1);
679
+ minpoints=4;
680
+ checkclosed=1;
681
+ isodd=-1;
682
+ }
683
+
684
+ void
685
+ alloc_compoundcurve(void)
686
+ {
687
+ LWDEBUG(2, "alloc_compoundcurve called.");
688
+
689
+ alloc_stack_tuple(COMPOUNDTYPE, write_type, 1);
690
+ }
691
+
692
+ void
693
+ alloc_multipoint(void)
694
+ {
695
+ LWDEBUG(2, "alloc_multipoint");
696
+
697
+ alloc_stack_tuple(MULTIPOINTTYPE,write_type,1);
698
+ }
699
+
700
+ void
701
+ alloc_multilinestring(void)
702
+ {
703
+ LWDEBUG(2, "alloc_multilinestring");
704
+
705
+ alloc_stack_tuple(MULTILINETYPE,write_type,1);
706
+ }
707
+
708
+ void
709
+ alloc_multicurve(void)
710
+ {
711
+ LWDEBUG(2, "alloc_multicurve");
712
+
713
+ alloc_stack_tuple(MULTICURVETYPE,write_type,1);
714
+ }
715
+
716
+ void
717
+ alloc_multipolygon(void)
718
+ {
719
+ LWDEBUG(2, "alloc_multipolygon");
720
+
721
+ alloc_stack_tuple(MULTIPOLYGONTYPE,write_type,1);
722
+ }
723
+
724
+ void
725
+ alloc_multisurface(void)
726
+ {
727
+ LWDEBUG(2, "alloc_multisurface called");
728
+
729
+ alloc_stack_tuple(MULTISURFACETYPE,write_type,1);
730
+ }
731
+
732
+ void
733
+ alloc_geomertycollection(void)
734
+ {
735
+ LWDEBUG(2, "alloc_geometrycollection");
736
+
737
+ alloc_stack_tuple(COLLECTIONTYPE,write_type,1);
738
+ }
739
+
740
+ void
741
+ alloc_counter(void)
742
+ {
743
+ LWDEBUG(2, "alloc_counter");
744
+
745
+ alloc_stack_tuple(0,write_count,4);
746
+ }
747
+
748
+ void
749
+ alloc_empty(void)
750
+ {
751
+ tuple* st = the_geom.stack;
752
+
753
+ LWDEBUG(2, "alloc_empty");
754
+
755
+ /* Find the last geometry */
756
+ while(st->uu.nn.type == 0){
757
+ st =st->uu.nn.stack_next;
758
+ }
759
+
760
+ /* Reclaim memory */
761
+ free_tuple(st->next);
762
+
763
+ /* Put an empty geometry collection on the top of the stack */
764
+ st->next=NULL;
765
+ the_geom.stack=st;
766
+ the_geom.alloc_size=st->uu.nn.size_here;
767
+
768
+ /* Mark as a empty stop */
769
+ if (st->uu.nn.type != 0xFF){
770
+ st->uu.nn.type=0xFF;
771
+ st->of = write_type_count;
772
+ the_geom.alloc_size+=4;
773
+ st->uu.nn.size_here=the_geom.alloc_size;
774
+ }
775
+
776
+ st->uu.nn.num=0;
777
+ }
778
+
779
+ void
780
+ make_serialized_lwgeom(LWGEOM_PARSER_RESULT *lwg_parser_result)
781
+ {
782
+ uchar* out_c;
783
+ output_state out;
784
+ tuple* cur;
785
+
786
+ LWDEBUG(2, "make_serialized_lwgeom");
787
+
788
+ /* Allocate the LWGEOM itself */
789
+ out_c = (uchar*)local_malloc(the_geom.alloc_size);
790
+ out.pos = out_c;
791
+ cur = the_geom.first ;
792
+
793
+ while(cur){
794
+ cur->of(cur,&out);
795
+ cur=cur->next;
796
+ }
797
+
798
+ /* Setup the LWGEOM_PARSER_RESULT structure */
799
+ lwg_parser_result->serialized_lwgeom = out_c;
800
+ lwg_parser_result->size = the_geom.alloc_size;
801
+
802
+ return;
803
+ }
804
+
805
+ void
806
+ lwg_parse_yynotice(char* s)
807
+ {
808
+ lwnotice(s);
809
+ }
810
+
811
+ int
812
+ lwg_parse_yyerror(char* s)
813
+ {
814
+ LWGEOM_WKT_PARSER_ERROR(PARSER_ERROR_INVALIDGEOM);
815
+ return 1;
816
+ }
817
+
818
+ /*
819
+ Table below generated using this ruby.
820
+
821
+ a=(0..0xff).to_a.collect{|x|0xff};('0'..'9').each{|x|a[x[0]]=x[0]-'0'[0]}
822
+ ('a'..'f').each{|x|v=x[0]-'a'[0]+10;a[x[0]]=a[x.upcase[0]]=v}
823
+ puts '{'+a.join(",")+'}'
824
+
825
+ */
826
+ static const uchar to_hex[] = {
827
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
828
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
829
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
830
+ 0,1,2,3,4,5,6,7,8,9,255,255,255,255,255,255,255,10,11,12,13,14,
831
+ 15,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
832
+ 255,255,255,255,255,255,255,255,255,255,255,10,11,12,13,14,15,255,
833
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
834
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
835
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
836
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
837
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
838
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
839
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
840
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
841
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
842
+ 255,255,255,255,255,255,255,255};
843
+
844
+ uchar
845
+ strhex_readbyte(const char* in)
846
+ {
847
+ if ( *in == 0 ){
848
+ if ( ! parser_ferror_occured){
849
+ LWGEOM_WKB_PARSER_ERROR(PARSER_ERROR_INVALIDGEOM);
850
+ }
851
+ return 0;
852
+ }
853
+
854
+ if (!parser_ferror_occured) {
855
+ lwg_parse_yylloc.last_column++;
856
+ return to_hex[(int)*in]<<4 | to_hex[(int)*(in+1)];
857
+ } else {
858
+ return 0;
859
+ }
860
+ }
861
+
862
+ uchar
863
+ read_wkb_byte(const char** in)
864
+ {
865
+ uchar ret = strhex_readbyte(*in);
866
+ (*in)+=2;
867
+ return ret;
868
+ }
869
+
870
+ int swap_order;
871
+
872
+ void
873
+ read_wkb_bytes(const char** in, uchar* out, int cnt)
874
+ {
875
+ if ( ! swap_order ){
876
+ while(cnt--) *out++ = read_wkb_byte(in);
877
+ }
878
+ else{
879
+ out += (cnt-1);
880
+ while(cnt--) *out-- = read_wkb_byte(in);
881
+ }
882
+ }
883
+
884
+ int4
885
+ read_wkb_int(const char** in)
886
+ {
887
+ int4 ret=0;
888
+ read_wkb_bytes(in,(uchar*)&ret,4);
889
+ return ret;
890
+ }
891
+
892
+ double
893
+ read_wkb_double(const char** in, int convert_from_int)
894
+ {
895
+ double ret=0;
896
+
897
+ if ( ! convert_from_int){
898
+ read_wkb_bytes(in,(uchar*)&ret,8);
899
+ return ret;
900
+ }else{
901
+ ret = read_wkb_int(in);
902
+ ret /= 0xb60b60;
903
+ return ret-180.0;
904
+ }
905
+ }
906
+
907
+ void
908
+ read_wkb_point(const char **b)
909
+ {
910
+ int i;
911
+ tuple* p = NULL;
912
+
913
+
914
+ if(the_geom.lwgi && the_geom.from_lwgi ){
915
+ /*
916
+ * Special case - reading from lwgi to lwgi
917
+ * we don't want to go via doubles in the middle.
918
+ */
919
+ switch(the_geom.ndims){
920
+ case 2: p=alloc_tuple(write_point_2i,8); break;
921
+ case 3: p=alloc_tuple(write_point_3i,12); break;
922
+ case 4: p=alloc_tuple(write_point_4i,16); break;
923
+ }
924
+
925
+ for(i=0;i<the_geom.ndims;i++){
926
+ p->uu.pointsi[i]=read_wkb_int(b);
927
+ }
928
+ }
929
+ else{
930
+ int mul = the_geom.lwgi ? 1 : 2;
931
+
932
+ switch(the_geom.ndims){
933
+ case 2: p=alloc_tuple(write_point_2,8*mul); break;
934
+ case 3: p=alloc_tuple(write_point_3,12*mul); break;
935
+ case 4: p=alloc_tuple(write_point_4,16*mul); break;
936
+ }
937
+
938
+ for(i=0;i<the_geom.ndims;i++){
939
+ p->uu.points[i]=read_wkb_double(b,the_geom.from_lwgi);
940
+ }
941
+ }
942
+
943
+
944
+ /* keep track of point */
945
+ if ( checkclosed ) {
946
+ if ( ! the_geom.stack->uu.nn.num )
947
+ first_point = p->uu.points;
948
+ last_point = p->uu.points;
949
+ }
950
+
951
+ inc_num();
952
+ check_dims(the_geom.ndims);
953
+ }
954
+
955
+ void
956
+ read_wkb_polygon(const char **b)
957
+ {
958
+ /* Stack the number of ORDINATE_ARRAYs (rings) */
959
+ int4 cnt=read_wkb_int(b);
960
+ alloc_counter();
961
+
962
+ /* Read through each ORDINATE_ARRAY in turn */
963
+ while(cnt--){
964
+ if ( parser_ferror_occured ) return;
965
+
966
+ /* Things to check for POLYGON ORDINATE_ARRAYs */
967
+ minpoints=4;
968
+ checkclosed=1;
969
+ isodd=-1;
970
+
971
+ read_wkb_ordinate_array(b);
972
+ }
973
+
974
+ pop();
975
+ }
976
+
977
+ void
978
+ read_wkb_linestring(const char **b)
979
+ {
980
+
981
+ /* Things to check for LINESTRING ORDINATE_ARRAYs */
982
+ minpoints=2;
983
+ checkclosed=0;
984
+ isodd=-1;
985
+
986
+ read_wkb_ordinate_array(b);
987
+ }
988
+
989
+
990
+ void
991
+ read_wkb_circstring(const char **b)
992
+ {
993
+
994
+ /* Things to check for CIRCULARSTRING ORDINATE_ARRAYs */
995
+ minpoints=3;
996
+ checkclosed=0;
997
+ isodd=-1;
998
+
999
+ read_wkb_ordinate_array(b);
1000
+ }
1001
+
1002
+ void
1003
+ read_wkb_ordinate_array(const char **b)
1004
+ {
1005
+ /* Read through a WKB ordinate array */
1006
+ int4 cnt=read_wkb_int(b);
1007
+ alloc_counter();
1008
+
1009
+ while(cnt--){
1010
+ if ( parser_ferror_occured ) return;
1011
+ read_wkb_point(b);
1012
+ }
1013
+
1014
+ /* Perform a check of the ordinate array */
1015
+ popc();
1016
+ }
1017
+
1018
+ void
1019
+ read_collection(const char **b, read_col_func f)
1020
+ {
1021
+ /* Read through a COLLECTION or an EWKB */
1022
+ int4 cnt=read_wkb_int(b);
1023
+ alloc_counter();
1024
+
1025
+ while(cnt--){
1026
+ if ( parser_ferror_occured ) return;
1027
+ f(b);
1028
+ }
1029
+
1030
+ pop();
1031
+ }
1032
+
1033
+ void
1034
+ parse_wkb(const char **b)
1035
+ {
1036
+ int4 type;
1037
+ uchar xdr = read_wkb_byte(b);
1038
+ int4 localsrid;
1039
+
1040
+ LWDEBUG(2, "parse_wkb");
1041
+
1042
+ swap_order=0;
1043
+
1044
+ if ( xdr != getMachineEndian() )
1045
+ {
1046
+ swap_order=1;
1047
+ }
1048
+
1049
+ type = read_wkb_int(b);
1050
+
1051
+ /* quick exit on error */
1052
+ if ( parser_ferror_occured ) return;
1053
+
1054
+ the_geom.ndims=2;
1055
+ if (type & WKBZOFFSET)
1056
+ {
1057
+ the_geom.hasZ = 1;
1058
+ the_geom.ndims++;
1059
+ }
1060
+ else the_geom.hasZ = 0;
1061
+ if (type & WKBMOFFSET)
1062
+ {
1063
+ the_geom.hasM = 1;
1064
+ the_geom.ndims++;
1065
+ }
1066
+ else the_geom.hasM = 0;
1067
+
1068
+ if (type & WKBSRIDFLAG )
1069
+ {
1070
+ /* local (in-EWKB) srid spec overrides SRID=#; */
1071
+ localsrid = read_wkb_int(b);
1072
+ if ( localsrid != -1 )
1073
+ {
1074
+ if ( the_geom.srid == -1 ) the_geom.alloc_size += 4;
1075
+ the_geom.srid = localsrid;
1076
+ }
1077
+ }
1078
+
1079
+ type &=0x0f;
1080
+
1081
+ if ( the_geom.lwgi ){
1082
+
1083
+ if ( type<= POLYGONTYPE )
1084
+ alloc_stack_tuple(type +9,write_type,1);
1085
+ else
1086
+ alloc_stack_tuple(type,write_type,1);
1087
+ }
1088
+ else{
1089
+ /* If we are writing lwg and are reading wbki */
1090
+ int4 towrite=type;
1091
+ if (towrite >= POINTTYPEI && towrite <= POLYGONTYPEI){
1092
+ towrite-=9;
1093
+ }
1094
+ alloc_stack_tuple(towrite,write_type,1);
1095
+ }
1096
+
1097
+ switch(type ){
1098
+ case POINTTYPE:
1099
+ read_wkb_point(b);
1100
+ break;
1101
+
1102
+ case LINETYPE:
1103
+ read_wkb_linestring(b);
1104
+ break;
1105
+
1106
+ case CIRCSTRINGTYPE:
1107
+ read_wkb_circstring(b);
1108
+ break;
1109
+
1110
+ case POLYGONTYPE:
1111
+ read_wkb_polygon(b);
1112
+ break;
1113
+
1114
+ case COMPOUNDTYPE:
1115
+ read_collection(b,parse_wkb);
1116
+ break;
1117
+
1118
+ case CURVEPOLYTYPE:
1119
+ read_collection(b,parse_wkb);
1120
+ break;
1121
+
1122
+ case MULTIPOINTTYPE:
1123
+ case MULTILINETYPE:
1124
+ case MULTICURVETYPE:
1125
+ case MULTIPOLYGONTYPE:
1126
+ case MULTISURFACETYPE:
1127
+ case COLLECTIONTYPE:
1128
+ read_collection(b,parse_wkb);
1129
+ break;
1130
+
1131
+ case POINTTYPEI:
1132
+ the_geom.from_lwgi=1;
1133
+ read_wkb_point(b);
1134
+ break;
1135
+
1136
+ case LINETYPEI:
1137
+ the_geom.from_lwgi=1;
1138
+ read_wkb_linestring(b);
1139
+ break;
1140
+
1141
+ case POLYGONTYPEI:
1142
+ the_geom.from_lwgi=1;
1143
+ read_wkb_polygon(b);
1144
+ break;
1145
+
1146
+ default:
1147
+ LWGEOM_WKB_PARSER_ERROR(PARSER_ERROR_INVALIDWKBTYPE);
1148
+ }
1149
+
1150
+ the_geom.from_lwgi=0;
1151
+
1152
+ pop();
1153
+ }
1154
+
1155
+
1156
+ void
1157
+ alloc_wkb(const char *parser)
1158
+ {
1159
+ LWDEBUG(2, "alloc_wkb");
1160
+
1161
+ parse_wkb(&parser);
1162
+ }
1163
+
1164
+ /*
1165
+ Parse a string and return a LW_GEOM
1166
+ */
1167
+ int
1168
+ parse_it(LWGEOM_PARSER_RESULT *lwg_parser_result, const char *geometry, int flags, allocator allocfunc, report_error errfunc)
1169
+ {
1170
+ LWDEBUGF(2, "parse_it: %s with parser flags %d", geometry, flags);
1171
+
1172
+ local_malloc = allocfunc;
1173
+ error_func=errfunc;
1174
+
1175
+ parser_ferror_occured = 0;
1176
+
1177
+ /* Setup the inital parser flags and empty the return struct */
1178
+ current_lwg_parser_result = lwg_parser_result;
1179
+ current_parser_check_flags = flags;
1180
+ lwg_parser_result->serialized_lwgeom = NULL;
1181
+ lwg_parser_result->size = 0;
1182
+ lwg_parser_result->wkinput = geometry;
1183
+
1184
+ init_parser(geometry);
1185
+
1186
+ lwg_parse_yyparse();
1187
+
1188
+ close_parser();
1189
+
1190
+ /* Return the parsed geometry */
1191
+ make_serialized_lwgeom(lwg_parser_result);
1192
+
1193
+ return parser_ferror_occured;
1194
+ }
1195
+
1196
+ int
1197
+ parse_lwg(LWGEOM_PARSER_RESULT *lwg_parser_result, const char* geometry, int flags, allocator allocfunc, report_error errfunc)
1198
+ {
1199
+ the_geom.lwgi=0;
1200
+ return parse_it(lwg_parser_result, geometry, flags, allocfunc, errfunc);
1201
+ }
1202
+
1203
+ int
1204
+ parse_lwgi(LWGEOM_PARSER_RESULT *lwg_parser_result, const char* geometry, int flags, allocator allocfunc, report_error errfunc)
1205
+ {
1206
+ the_geom.lwgi=1;
1207
+ return parse_it(lwg_parser_result, geometry, flags, allocfunc, errfunc);
1208
+ }
1209
+
1210
+ void
1211
+ set_zm(char z, char m)
1212
+ {
1213
+ LWDEBUGF(2, "set_zm %d, %d", z, m);
1214
+
1215
+ the_geom.hasZ = z;
1216
+ the_geom.hasM = m;
1217
+ the_geom.ndims = 2+z+m;
1218
+ }
1219
+