geo_coder 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +12 -0
- data/Gemfile.lock +32 -0
- data/History.txt +6 -0
- data/Makefile +13 -0
- data/Manifest.txt +18 -0
- data/README.rdoc +197 -0
- data/Rakefile +53 -0
- data/TODO.txt +8 -0
- data/VERSION +1 -0
- data/bin/build_indexes +8 -0
- data/bin/rebuild_cluster +22 -0
- data/bin/rebuild_metaphones +23 -0
- data/bin/tiger_import +59 -0
- data/demos/demo/app/ext/geocodewrap.rb +84 -0
- data/demos/demo/app/views/index.builder +13 -0
- data/demos/demo/app/views/index.erb +71 -0
- data/demos/demo/config.ru +12 -0
- data/demos/demo/config/bootstraps.rb +130 -0
- data/demos/demo/config/geoenvironment.rb +25 -0
- data/demos/demo/geocoder_helper.rb +12 -0
- data/demos/demo/geocom_geocode.rb +10 -0
- data/demos/demo/main.rb +3 -0
- data/demos/demo/rakefile.rb +17 -0
- data/demos/demo/tmp/restart.txt +0 -0
- data/demos/simpledemo/views/index.builder +13 -0
- data/demos/simpledemo/views/index.erb +69 -0
- data/demos/simpledemo/ws.rb +83 -0
- data/doc/Makefile +7 -0
- data/doc/html4css1.css +279 -0
- data/doc/lookup.rst +193 -0
- data/doc/parsing.rst +125 -0
- data/doc/voidspace.css +147 -0
- data/geo_coder.gemspec +172 -0
- data/lib/geocoder/us.rb +21 -0
- data/lib/geocoder/us/address.rb +290 -0
- data/lib/geocoder/us/constants.rb +670 -0
- data/lib/geocoder/us/database.rb +745 -0
- data/lib/geocoder/us/import.rb +181 -0
- data/lib/geocoder/us/import/tiger.rb +13 -0
- data/lib/geocoder/us/numbers.rb +58 -0
- data/navteq/README +4 -0
- data/navteq/convert.sql +37 -0
- data/navteq/navteq_import +39 -0
- data/navteq/prepare.sql +92 -0
- data/sql/cluster.sql +16 -0
- data/sql/convert.sql +80 -0
- data/sql/create.sql +37 -0
- data/sql/index.sql +12 -0
- data/sql/place.csv +104944 -0
- data/sql/place.sql +104948 -0
- data/sql/setup.sql +78 -0
- data/src/Makefile +13 -0
- data/src/README +14 -0
- data/src/liblwgeom/Makefile +75 -0
- data/src/liblwgeom/box2d.c +54 -0
- data/src/liblwgeom/lex.yy.c +4799 -0
- data/src/liblwgeom/liblwgeom.h +1405 -0
- data/src/liblwgeom/lwalgorithm.c +946 -0
- data/src/liblwgeom/lwalgorithm.h +52 -0
- data/src/liblwgeom/lwcircstring.c +759 -0
- data/src/liblwgeom/lwcollection.c +541 -0
- data/src/liblwgeom/lwcompound.c +118 -0
- data/src/liblwgeom/lwcurvepoly.c +86 -0
- data/src/liblwgeom/lwgeom.c +886 -0
- data/src/liblwgeom/lwgeom_api.c +2201 -0
- data/src/liblwgeom/lwgparse.c +1219 -0
- data/src/liblwgeom/lwgunparse.c +1054 -0
- data/src/liblwgeom/lwline.c +525 -0
- data/src/liblwgeom/lwmcurve.c +125 -0
- data/src/liblwgeom/lwmline.c +137 -0
- data/src/liblwgeom/lwmpoint.c +138 -0
- data/src/liblwgeom/lwmpoly.c +141 -0
- data/src/liblwgeom/lwmsurface.c +129 -0
- data/src/liblwgeom/lwpoint.c +439 -0
- data/src/liblwgeom/lwpoly.c +579 -0
- data/src/liblwgeom/lwsegmentize.c +1047 -0
- data/src/liblwgeom/lwutil.c +369 -0
- data/src/liblwgeom/measures.c +861 -0
- data/src/liblwgeom/postgis_config.h +93 -0
- data/src/liblwgeom/ptarray.c +847 -0
- data/src/liblwgeom/vsprintf.c +179 -0
- data/src/liblwgeom/wktparse.h +126 -0
- data/src/liblwgeom/wktparse.lex +74 -0
- data/src/liblwgeom/wktparse.tab.c +2353 -0
- data/src/liblwgeom/wktparse.tab.h +145 -0
- data/src/liblwgeom/wktparse.y +385 -0
- data/src/libsqlite3_geocoder/Makefile +22 -0
- data/src/libsqlite3_geocoder/Makefile.nix +15 -0
- data/src/libsqlite3_geocoder/Makefile.redhat +15 -0
- data/src/libsqlite3_geocoder/extension.c +121 -0
- data/src/libsqlite3_geocoder/extension.h +13 -0
- data/src/libsqlite3_geocoder/levenshtein.c +42 -0
- data/src/libsqlite3_geocoder/metaphon.c +278 -0
- data/src/libsqlite3_geocoder/util.c +37 -0
- data/src/libsqlite3_geocoder/wkb_compress.c +54 -0
- data/src/metaphone/Makefile +7 -0
- data/src/metaphone/README +49 -0
- data/src/metaphone/extension.c +37 -0
- data/src/metaphone/metaphon.c +251 -0
- data/src/shp2sqlite/Makefile +37 -0
- data/src/shp2sqlite/Makefile.nix +36 -0
- data/src/shp2sqlite/Makefile.redhat +35 -0
- data/src/shp2sqlite/dbfopen.c +1595 -0
- data/src/shp2sqlite/getopt.c +695 -0
- data/src/shp2sqlite/getopt.h +127 -0
- data/src/shp2sqlite/shapefil.h +500 -0
- data/src/shp2sqlite/shp2sqlite.c +1974 -0
- data/src/shp2sqlite/shpopen.c +1894 -0
- data/tests/address.rb +236 -0
- data/tests/benchmark.rb +20 -0
- data/tests/constants.rb +57 -0
- data/tests/data/address-sample.csv +52 -0
- data/tests/data/db-test.csv +57 -0
- data/tests/data/locations.csv +4 -0
- data/tests/database.rb +137 -0
- data/tests/generate.rb +34 -0
- data/tests/numbers.rb +46 -0
- data/tests/run.rb +11 -0
- 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
|
+
|