~ubuntu-branches/ubuntu/feisty/postgis/feisty

« back to all changes in this revision

Viewing changes to lwgeom/lwgparse.c

  • Committer: Bazaar Package Importer
  • Author(s): Alex Bodnaru
  • Date: 2005-05-05 10:02:45 UTC
  • Revision ID: james.westby@ubuntu.com-20050505100245-3005l6jn1jwvpsrw
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
11
#include "liblwgeom.h"
 
12
#include "wktparse.h"
 
13
 
 
14
/*
 
15
//To get byte order
 
16
#include <sys/types.h>
 
17
#include <netinet/in.h>
 
18
#include <netinet/in_systm.h>
 
19
#include <netinet/ip.h>
 
20
*/
 
21
 
 
22
void set_zm(char z, char m);
 
23
void close_parser(void);
 
24
 
 
25
typedef unsigned long int4;
 
26
 
 
27
typedef struct tag_tuple tuple;
 
28
 
 
29
struct tag_outputstate{
 
30
        uchar*  pos;
 
31
};
 
32
 
 
33
typedef struct tag_outputstate output_state;
 
34
typedef void (*output_func)(tuple* this,output_state* out);
 
35
typedef void (*read_col_func)(const uchar**f);
 
36
 
 
37
 
 
38
 
 
39
/* Globals */
 
40
 
 
41
int srid=-1;
 
42
 
 
43
static int ferror_occured;
 
44
static allocator local_malloc;
 
45
static report_error error_func;
 
46
 
 
47
struct tag_tuple{
 
48
        output_func   of;
 
49
        union union_tag {
 
50
                double points[4];
 
51
                int4   pointsi[4];
 
52
 
 
53
                struct struct_tag {
 
54
                        tuple*  stack_next;
 
55
                        int     type;
 
56
                        int     num;
 
57
                        int     size_here;
 
58
                } nn;
 
59
        } uu;
 
60
        struct tag_tuple *next;
 
61
};
 
62
 
 
63
struct {
 
64
        int     type;
 
65
        int     flags;
 
66
        int     srid;
 
67
        int     ndims;
 
68
        int     hasZ;
 
69
        int     hasM;
 
70
        /* create integer version */
 
71
        int lwgi;
 
72
        /* input is integer (wkb only)*/
 
73
        int from_lwgi;
 
74
 
 
75
        int4 alloc_size;
 
76
 
 
77
        /*
 
78
                linked list of all tuples
 
79
        */
 
80
        tuple*  first;
 
81
        tuple*  last;
 
82
 
 
83
        /*
 
84
                stack of open geometries
 
85
        */
 
86
        tuple*  stack;
 
87
 
 
88
} the_geom;
 
89
 
 
90
tuple* free_list=0;
 
91
int minpoints;
 
92
int checkclosed;
 
93
double *first_point=NULL;
 
94
double *last_point=NULL;
 
95
 
 
96
/* External functions */
 
97
extern void init_parser(const uchar *);
 
98
 
 
99
/* Prototypes */
 
100
tuple* alloc_tuple(output_func of,size_t size);
 
101
static void error(const char* err);
 
102
void free_tuple(tuple* to_free);
 
103
void inc_num(void);
 
104
void alloc_stack_tuple(int type,output_func of,size_t size);
 
105
void check_dims(int num);
 
106
void WRITE_DOUBLES(output_state* out,double* points, int cnt);
 
107
#ifdef SHRINK_INTS
 
108
void WRITE_INT4(output_state * out,int4 val);
 
109
#endif
 
110
void write_size(tuple* this,output_state* out);
 
111
void alloc_lwgeom(int srid);
 
112
void write_point_2(tuple* this,output_state* out);
 
113
void write_point_3(tuple* this,output_state* out);
 
114
void write_point_4(tuple* this,output_state* out);
 
115
void write_point_2i(tuple* this,output_state* out);
 
116
void write_point_3i(tuple* this,output_state* out);
 
117
void write_point_4i(tuple* this,output_state* out);
 
118
void alloc_point_2d(double x,double y);
 
119
void alloc_point_3d(double x,double y,double z);
 
120
void alloc_point_4d(double x,double y,double z,double m);
 
121
void write_type(tuple* this,output_state* out);
 
122
void write_count(tuple* this,output_state* out);
 
123
void write_type_count(tuple* this,output_state* out);
 
124
void alloc_point(void);
 
125
void alloc_linestring(void);
 
126
void alloc_polygon(void);
 
127
void alloc_multipoint(void);
 
128
void alloc_multilinestring(void);
 
129
void alloc_multipolygon(void);
 
130
void alloc_geomertycollection(void);
 
131
void alloc_counter(void);
 
132
void alloc_empty(void);
 
133
uchar* make_lwgeom(void);
 
134
uchar strhex_readbyte(const uchar* in);
 
135
uchar read_wkb_byte(const uchar** in);
 
136
void read_wkb_bytes(const uchar** in,uchar* out, int cnt);
 
137
int4 read_wkb_int(const uchar** in);
 
138
double read_wkb_double(const uchar** in,int convert_from_int);
 
139
void read_wkb_point(const uchar** b);
 
140
void read_collection(const uchar** b,read_col_func f);
 
141
void read_collection2(const uchar** b);
 
142
void parse_wkb(const uchar** b);
 
143
void alloc_wkb(const uchar* parser);
 
144
uchar* parse_it(const uchar* geometry,allocator allocfunc,report_error errfunc);
 
145
uchar* parse_lwg(const uchar* geometry,allocator allocfunc,report_error errfunc);
 
146
uchar* parse_lwgi(const uchar* geometry,allocator allocfunc,report_error errfunc);
 
147
 
 
148
void
 
149
set_srid(double d_srid)
 
150
{
 
151
        if ( d_srid >= 0 )
 
152
                d_srid+=0.1;
 
153
        else
 
154
                d_srid-=0.1;
 
155
 
 
156
 
 
157
        srid=(int)(d_srid+0.1);
 
158
}
 
159
 
 
160
tuple *
 
161
alloc_tuple(output_func of,size_t size)
 
162
{
 
163
        tuple* ret = free_list;
 
164
 
 
165
        if ( ! ret ){
 
166
                int toalloc = (ALLOC_CHUNKS /sizeof(tuple));
 
167
                ret = malloc( toalloc *sizeof(tuple) );
 
168
 
 
169
                free_list = ret;
 
170
 
 
171
                while(--toalloc){
 
172
                        ret->next = ret+1;
 
173
                        ret++;
 
174
                }
 
175
 
 
176
                ret->next = NULL;
 
177
 
 
178
                return alloc_tuple(of,size);
 
179
        }
 
180
 
 
181
        free_list = ret->next;
 
182
        ret->of = of;
 
183
        ret->next = NULL;
 
184
 
 
185
        if ( the_geom.last ) {
 
186
                the_geom.last->next = ret;
 
187
                the_geom.last = ret;
 
188
        }
 
189
        else {
 
190
                the_geom.first = the_geom.last = ret;
 
191
        }
 
192
 
 
193
        the_geom.alloc_size += size;
 
194
 
 
195
        return ret;
 
196
}
 
197
 
 
198
static void
 
199
error(const char* err)
 
200
{
 
201
        error_func(err);
 
202
        ferror_occured=1;
 
203
}
 
204
 
 
205
void
 
206
free_tuple(tuple* to_free)
 
207
{
 
208
 
 
209
        tuple* list_end = to_free;
 
210
 
 
211
        if( !to_free)
 
212
                return;
 
213
 
 
214
        while(list_end->next){
 
215
                list_end=list_end->next;
 
216
        }
 
217
 
 
218
        list_end->next = free_list;
 
219
        free_list = to_free;
 
220
}
 
221
 
 
222
void
 
223
inc_num(void)
 
224
{
 
225
        the_geom.stack->uu.nn.num++;
 
226
}
 
227
 
 
228
/*
 
229
        Allocate a 'counting' tuple
 
230
*/
 
231
void
 
232
alloc_stack_tuple(int type,output_func of,size_t size)
 
233
{
 
234
        tuple*  p;
 
235
        inc_num();
 
236
 
 
237
        p = alloc_tuple(of,size);
 
238
        p->uu.nn.stack_next = the_geom.stack;
 
239
        p->uu.nn.type = type;
 
240
        p->uu.nn.size_here = the_geom.alloc_size;
 
241
        p->uu.nn.num = 0;
 
242
        the_geom.stack = p;
 
243
}
 
244
 
 
245
void
 
246
pop(void)
 
247
{
 
248
        the_geom.stack = the_geom.stack->uu.nn.stack_next;
 
249
}
 
250
 
 
251
void
 
252
popc(void)
 
253
{
 
254
        if ( the_geom.stack->uu.nn.num < minpoints){
 
255
                error("geometry requires more points");
 
256
        }
 
257
        if ( checkclosed && first_point && last_point) {
 
258
                if ( memcmp(first_point, last_point,
 
259
                        sizeof(double)*the_geom.ndims) )
 
260
                {
 
261
                        error("geometry contains non-closed rings");
 
262
                }
 
263
        }
 
264
        the_geom.stack = the_geom.stack->uu.nn.stack_next;
 
265
}
 
266
 
 
267
 
 
268
void
 
269
check_dims(int num)
 
270
{
 
271
        if( the_geom.ndims != num){
 
272
                if (the_geom.ndims) {
 
273
                        error("Can not mix dimentionality in a geometry");
 
274
                } else {
 
275
                        the_geom.ndims = num;
 
276
                        if ( num > 2 ) the_geom.hasZ = 1;
 
277
                        if ( num > 3 ) the_geom.hasM = 1;
 
278
                }
 
279
        }
 
280
}
 
281
 
 
282
#define WRITE_INT4_REAL(x,y) { memcpy(x->pos,&y,4); x->pos+=4;}
 
283
#define WRITE_INT4_REAL_MULTIPLE(x,y,z) { memcpy(x->pos,&y,z*4); x->pos+=(z*4);}
 
284
 
 
285
/*
 
286
        we can shrink ints to one byte if they are less than 127
 
287
        by setting the extra bit.  Because if the different byte
 
288
        ordering possibilities we need to set the lsb on little
 
289
        endian to show a packed one and the msb on a big endian
 
290
        machine
 
291
*/
 
292
#ifdef SHRINK_INTS
 
293
void
 
294
WRITE_INT4(output_state * out,int4 val)
 
295
{
 
296
        if ( val <= 0x7f ){
 
297
                if ( getMachineEndian() == NDR ){
 
298
                        val = (val<<1) | 1;
 
299
                }
 
300
                else{
 
301
                        val |=0x80;
 
302
                }
 
303
 
 
304
                *out->pos++ = (uchar)val;
 
305
                the_geom.alloc_size-=3;
 
306
        }
 
307
        else{
 
308
                if ( getMachineEndian() == NDR ){
 
309
                        val <<=1;
 
310
                }
 
311
                WRITE_INT4_REAL(out,val);
 
312
        }
 
313
}
 
314
#else
 
315
#define WRITE_INT4 WRITE_INT4_REAL
 
316
#endif
 
317
 
 
318
 
 
319
void
 
320
WRITE_DOUBLES(output_state* out,double* points, int cnt)
 
321
{
 
322
        if ( the_geom.lwgi){
 
323
                int4 vals[4];
 
324
                int i;
 
325
 
 
326
                for(i=0; i<cnt;i++){
 
327
                        vals[i] = (int4)(((points[i]+180.0)*0xB60B60)+.5);
 
328
                }
 
329
                memcpy(out->pos,vals,sizeof(int4)*cnt);
 
330
                out->pos+=sizeof(int4)*cnt;
 
331
        }
 
332
        else{
 
333
                memcpy(out->pos,points,sizeof(double)*cnt);
 
334
                out->pos+=sizeof(double)*cnt;
 
335
        }
 
336
 
 
337
}
 
338
 
 
339
void
 
340
write_size(tuple* this,output_state* out)
 
341
{
 
342
        WRITE_INT4_REAL(out,the_geom.alloc_size);
 
343
}
 
344
 
 
345
void
 
346
alloc_lwgeom(int srid)
 
347
{
 
348
        the_geom.srid=srid;
 
349
        the_geom.alloc_size=0;
 
350
        the_geom.stack=NULL;
 
351
        the_geom.ndims=0;
 
352
        the_geom.hasZ=0;
 
353
        the_geom.hasM=0;
 
354
 
 
355
        //Free if used already
 
356
        if ( the_geom.first ){
 
357
                free_tuple(the_geom.first);
 
358
                the_geom.first=the_geom.last=NULL;
 
359
        }
 
360
 
 
361
        if ( srid != -1 ){
 
362
                the_geom.alloc_size+=4;
 
363
        }
 
364
 
 
365
        the_geom.stack = alloc_tuple(write_size,4);
 
366
}
 
367
 
 
368
void
 
369
write_point_2(tuple* this,output_state* out)
 
370
{
 
371
        WRITE_DOUBLES(out,this->uu.points,2);
 
372
}
 
373
 
 
374
void
 
375
write_point_3(tuple* this,output_state* out)
 
376
{
 
377
        WRITE_DOUBLES(out,this->uu.points,3);
 
378
}
 
379
 
 
380
void
 
381
write_point_4(tuple* this,output_state* out)
 
382
{
 
383
        WRITE_DOUBLES(out,this->uu.points,4);
 
384
}
 
385
 
 
386
void
 
387
write_point_2i(tuple* this,output_state* out)
 
388
{
 
389
        WRITE_INT4_REAL_MULTIPLE(out,this->uu.points,2);
 
390
}
 
391
 
 
392
void
 
393
write_point_3i(tuple* this,output_state* out)
 
394
{
 
395
        WRITE_INT4_REAL_MULTIPLE(out,this->uu.points,3);
 
396
}
 
397
 
 
398
void
 
399
write_point_4i(tuple* this,output_state* out)
 
400
{
 
401
        WRITE_INT4_REAL_MULTIPLE(out,this->uu.points,4);
 
402
}
 
403
 
 
404
void
 
405
alloc_point_2d(double x,double y)
 
406
{
 
407
        tuple* p = alloc_tuple(write_point_2,the_geom.lwgi?8:16);
 
408
        p->uu.points[0] = x;
 
409
        p->uu.points[1] = y;
 
410
 
 
411
        /* keep track of point */
 
412
        if ( checkclosed ) {
 
413
                if ( ! the_geom.stack->uu.nn.num )
 
414
                        first_point = p->uu.points;
 
415
                last_point = p->uu.points;
 
416
        }
 
417
 
 
418
        inc_num();
 
419
        check_dims(2);
 
420
}
 
421
 
 
422
void
 
423
alloc_point_3d(double x,double y,double z)
 
424
{
 
425
        tuple* p = alloc_tuple(write_point_3,the_geom.lwgi?12:24);
 
426
        p->uu.points[0] = x;
 
427
        p->uu.points[1] = y;
 
428
        p->uu.points[2] = z;
 
429
 
 
430
        /* keep track of point */
 
431
        if ( checkclosed ) {
 
432
                if ( ! the_geom.stack->uu.nn.num )
 
433
                        first_point = p->uu.points;
 
434
                last_point = p->uu.points;
 
435
        }
 
436
 
 
437
        inc_num();
 
438
        check_dims(3);
 
439
}
 
440
 
 
441
void
 
442
alloc_point_4d(double x,double y,double z,double m)
 
443
{
 
444
        tuple* p = alloc_tuple(write_point_4,the_geom.lwgi?16:32);
 
445
        p->uu.points[0] = x;
 
446
        p->uu.points[1] = y;
 
447
        p->uu.points[2] = z;
 
448
        p->uu.points[3] = m;
 
449
 
 
450
        /* keep track of point */
 
451
        if ( checkclosed ) {
 
452
                if ( ! the_geom.stack->uu.nn.num )
 
453
                        first_point = p->uu.points;
 
454
                last_point = p->uu.points;
 
455
        }
 
456
 
 
457
        inc_num();
 
458
        check_dims(4);
 
459
}
 
460
 
 
461
void
 
462
write_type(tuple* this,output_state* out)
 
463
{
 
464
        uchar type=0;
 
465
 
 
466
        //Empty handler - switch back
 
467
        if ( this->uu.nn.type == 0xff )
 
468
                this->uu.nn.type = COLLECTIONTYPE;
 
469
 
 
470
        type |= this->uu.nn.type;
 
471
 
 
472
        if (the_geom.ndims) //Support empty
 
473
        {
 
474
                TYPE_SETZM(type, the_geom.hasZ, the_geom.hasM);
 
475
        }
 
476
 
 
477
        if ( the_geom.srid != -1 ){
 
478
                type |= 0x40;
 
479
        }
 
480
 
 
481
        *(out->pos)=type;
 
482
        out->pos++;
 
483
 
 
484
        if ( the_geom.srid != -1 ){
 
485
                //Only the first geometry will have a srid attached
 
486
                WRITE_INT4(out,the_geom.srid);
 
487
                the_geom.srid = -1;
 
488
        }
 
489
}
 
490
 
 
491
void
 
492
write_count(tuple* this,output_state* out)
 
493
{
 
494
        int num = this->uu.nn.num;
 
495
        WRITE_INT4(out,num);
 
496
}
 
497
 
 
498
void
 
499
write_type_count(tuple* this,output_state* out)
 
500
{
 
501
        write_type(this,out);
 
502
        write_count(this,out);
 
503
}
 
504
 
 
505
void
 
506
alloc_point(void)
 
507
{
 
508
        if( the_geom.lwgi)
 
509
                alloc_stack_tuple(POINTTYPEI,write_type,1);
 
510
        else
 
511
                alloc_stack_tuple(POINTTYPE,write_type,1);
 
512
 
 
513
        minpoints=1;
 
514
        checkclosed=0;
 
515
}
 
516
 
 
517
void
 
518
alloc_linestring(void)
 
519
{
 
520
        if( the_geom.lwgi)
 
521
                alloc_stack_tuple(LINETYPEI,write_type,1);
 
522
        else
 
523
                alloc_stack_tuple(LINETYPE,write_type,1);
 
524
 
 
525
        minpoints=2;
 
526
        checkclosed=0;
 
527
}
 
528
 
 
529
void
 
530
alloc_polygon(void)
 
531
{
 
532
        if( the_geom.lwgi)
 
533
                alloc_stack_tuple(POLYGONTYPEI, write_type,1);
 
534
        else
 
535
                alloc_stack_tuple(POLYGONTYPE, write_type,1);
 
536
 
 
537
        minpoints=3;
 
538
        checkclosed=1;
 
539
}
 
540
 
 
541
void
 
542
alloc_multipoint(void)
 
543
{
 
544
        alloc_stack_tuple(MULTIPOINTTYPE,write_type,1);
 
545
}
 
546
 
 
547
void
 
548
alloc_multilinestring(void)
 
549
{
 
550
        alloc_stack_tuple(MULTILINETYPE,write_type,1);
 
551
}
 
552
 
 
553
void
 
554
alloc_multipolygon(void)
 
555
{
 
556
        alloc_stack_tuple(MULTIPOLYGONTYPE,write_type,1);
 
557
}
 
558
 
 
559
void
 
560
alloc_geomertycollection(void)
 
561
{
 
562
        alloc_stack_tuple(COLLECTIONTYPE,write_type,1);
 
563
}
 
564
 
 
565
void
 
566
alloc_counter(void)
 
567
{
 
568
        alloc_stack_tuple(0,write_count,4);
 
569
}
 
570
 
 
571
void
 
572
alloc_empty(void)
 
573
{
 
574
        tuple* st = the_geom.stack;
 
575
        //Find the last geometry
 
576
        while(st->uu.nn.type == 0){
 
577
                st =st->uu.nn.stack_next;
 
578
        }
 
579
 
 
580
        //Reclaim memory
 
581
        free_tuple(st->next);
 
582
 
 
583
        //Put an empty geometry collection on the top of the stack
 
584
        st->next=NULL;
 
585
        the_geom.stack=st;
 
586
        the_geom.alloc_size=st->uu.nn.size_here;
 
587
 
 
588
        //Mark as a empty stop
 
589
        if (st->uu.nn.type != 0xFF){
 
590
                st->uu.nn.type=0xFF;
 
591
                st->of = write_type_count;
 
592
                the_geom.alloc_size+=4;
 
593
                st->uu.nn.size_here=the_geom.alloc_size;
 
594
        }
 
595
 
 
596
        st->uu.nn.num=0;
 
597
 
 
598
}
 
599
 
 
600
uchar *
 
601
make_lwgeom(void)
 
602
{
 
603
        uchar* out_c;
 
604
        output_state out;
 
605
        tuple* cur;
 
606
        out_c = (uchar*)local_malloc(the_geom.alloc_size);
 
607
        out.pos = out_c;
 
608
        cur = the_geom.first ;
 
609
 
 
610
        while(cur){
 
611
                cur->of(cur,&out);
 
612
                cur=cur->next;
 
613
        }
 
614
 
 
615
        //if ints shrink then we need to rewrite the size smaller
 
616
        out.pos = out_c;
 
617
        write_size(NULL,&out);
 
618
 
 
619
        return out_c;
 
620
}
 
621
 
 
622
int
 
623
lwg_parse_yyerror(char* s)
 
624
{
 
625
        error("parse error - invalid geometry");
 
626
        //error_func("parse error - invalid geometry");
 
627
        return 1;
 
628
}
 
629
 
 
630
/*
 
631
 Table below generated using this ruby.
 
632
 
 
633
 a=(0..0xff).to_a.collect{|x|0xff};('0'..'9').each{|x|a[x[0]]=x[0]-'0'[0]}
 
634
 ('a'..'f').each{|x|v=x[0]-'a'[0]+10;a[x[0]]=a[x.upcase[0]]=v}
 
635
 puts '{'+a.join(",")+'}'
 
636
 
 
637
 */
 
638
static const uchar to_hex[]  = {
 
639
        255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 
640
        255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 
641
        255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 
642
        0,1,2,3,4,5,6,7,8,9,255,255,255,255,255,255,255,10,11,12,13,14,
 
643
        15,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 
644
        255,255,255,255,255,255,255,255,255,255,255,10,11,12,13,14,15,255,
 
645
        255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 
646
        255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 
647
        255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 
648
        255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 
649
        255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 
650
        255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 
651
        255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 
652
        255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 
653
        255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 
654
        255,255,255,255,255,255,255,255};
 
655
 
 
656
uchar
 
657
strhex_readbyte(const uchar* in)
 
658
{
 
659
        if ( *in == 0 ){
 
660
                if ( ! ferror_occured){
 
661
                        error("invalid wkb");
 
662
                }
 
663
                return 0;
 
664
        }
 
665
        return to_hex[(int)*in]<<4 | to_hex[(int)*(in+1)];
 
666
}
 
667
 
 
668
uchar
 
669
read_wkb_byte(const uchar** in)
 
670
{
 
671
        uchar ret = strhex_readbyte(*in);
 
672
        (*in)+=2;
 
673
        return ret;
 
674
}
 
675
 
 
676
int swap_order;
 
677
 
 
678
void
 
679
read_wkb_bytes(const uchar** in,uchar* out, int cnt)
 
680
{
 
681
        if ( ! swap_order ){
 
682
                while(cnt--) *out++ = read_wkb_byte(in);
 
683
        }
 
684
        else{
 
685
                out += (cnt-1);
 
686
                while(cnt--) *out-- = read_wkb_byte(in);
 
687
        }
 
688
}
 
689
 
 
690
int4
 
691
read_wkb_int(const uchar** in)
 
692
{
 
693
        int4 ret=0;
 
694
        read_wkb_bytes(in,(uchar*)&ret,4);
 
695
        return ret;
 
696
}
 
697
 
 
698
double
 
699
read_wkb_double(const uchar** in,int convert_from_int)
 
700
{
 
701
        double ret=0;
 
702
 
 
703
        if ( ! convert_from_int){
 
704
                read_wkb_bytes(in,(uchar*)&ret,8);
 
705
                return ret;
 
706
        }else{
 
707
                ret  = read_wkb_int(in);
 
708
                ret /= 0xb60b60;
 
709
                return ret-180.0;
 
710
        }
 
711
}
 
712
 
 
713
void
 
714
read_wkb_point(const uchar** b)
 
715
{
 
716
        int i;
 
717
        tuple* p = NULL;
 
718
 
 
719
 
 
720
        if(the_geom.lwgi && the_geom.from_lwgi ){
 
721
                //Special case - reading from lwgi to lwgi
 
722
                //we don't want to go via doubles in the middle.
 
723
                switch(the_geom.ndims){
 
724
                        case 2: p=alloc_tuple(write_point_2i,8); break;
 
725
                        case 3: p=alloc_tuple(write_point_3i,12); break;
 
726
                        case 4: p=alloc_tuple(write_point_4i,16); break;
 
727
                }
 
728
 
 
729
                for(i=0;i<the_geom.ndims;i++){
 
730
                        p->uu.pointsi[i]=read_wkb_int(b);
 
731
                }
 
732
        }
 
733
        else{
 
734
                int mul = the_geom.lwgi ? 1 : 2;
 
735
 
 
736
                switch(the_geom.ndims){
 
737
                        case 2: p=alloc_tuple(write_point_2,8*mul); break;
 
738
                        case 3: p=alloc_tuple(write_point_3,12*mul); break;
 
739
                        case 4: p=alloc_tuple(write_point_4,16*mul); break;
 
740
                }
 
741
 
 
742
                for(i=0;i<the_geom.ndims;i++){
 
743
                        p->uu.points[i]=read_wkb_double(b,the_geom.from_lwgi);
 
744
                }
 
745
        }
 
746
 
 
747
        inc_num();
 
748
        check_dims(the_geom.ndims);
 
749
}
 
750
 
 
751
void
 
752
read_collection(const uchar** b,read_col_func f)
 
753
{
 
754
        int4 cnt=read_wkb_int(b);
 
755
        alloc_counter();
 
756
 
 
757
        while(cnt--){
 
758
                if ( ferror_occured )   return;
 
759
                f(b);
 
760
        }
 
761
 
 
762
        pop();
 
763
}
 
764
 
 
765
void
 
766
read_collection2(const uchar** b)
 
767
{
 
768
        return read_collection(b,read_wkb_point);
 
769
}
 
770
 
 
771
void
 
772
parse_wkb(const uchar** b)
 
773
{
 
774
        int4 type;
 
775
        uchar xdr = read_wkb_byte(b);
 
776
        int4 localsrid;
 
777
 
 
778
        swap_order=0;
 
779
 
 
780
        if ( xdr != getMachineEndian() )
 
781
        {
 
782
                swap_order=1;
 
783
        }
 
784
 
 
785
        type = read_wkb_int(b);
 
786
 
 
787
        //quick exit on error
 
788
        if ( ferror_occured ) return;
 
789
 
 
790
        the_geom.ndims=2;
 
791
        if (type & WKBZOFFSET)
 
792
        {
 
793
                the_geom.hasZ = 1;
 
794
                the_geom.ndims++;
 
795
        }
 
796
        else the_geom.hasZ = 0;
 
797
        if (type & WKBMOFFSET)
 
798
        {
 
799
                the_geom.hasM = 1;
 
800
                the_geom.ndims++;
 
801
        }
 
802
        else the_geom.hasM = 0;
 
803
 
 
804
        if (type & WKBSRIDFLAG )
 
805
        {
 
806
                // local (in-EWKB) srid spec overrides SRID=#; 
 
807
                localsrid = read_wkb_int(b);
 
808
                if ( localsrid != -1 )
 
809
                {
 
810
                        if ( the_geom.srid == -1 ) the_geom.alloc_size += 4;
 
811
                        the_geom.srid = localsrid;
 
812
                }
 
813
        }
 
814
 
 
815
        type &=0x0f;
 
816
 
 
817
        if ( the_geom.lwgi  ){
 
818
 
 
819
                if ( type<= POLYGONTYPE )
 
820
                        alloc_stack_tuple(type +9,write_type,1);
 
821
                else
 
822
                        alloc_stack_tuple(type,write_type,1);
 
823
        }
 
824
        else{
 
825
                //If we are writing lwg and are reading wbki
 
826
                int4 towrite=type;
 
827
                if (towrite > COLLECTIONTYPE ){
 
828
                        towrite-=9;
 
829
                }
 
830
                alloc_stack_tuple(towrite,write_type,1);
 
831
        }
 
832
 
 
833
        switch(type ){
 
834
                case    POINTTYPE:
 
835
                        read_wkb_point(b);
 
836
                        break;
 
837
 
 
838
                case    LINETYPE:
 
839
                        read_collection(b,read_wkb_point);
 
840
                        break;
 
841
 
 
842
                case    POLYGONTYPE:
 
843
                        read_collection(b,read_collection2);
 
844
                        break;
 
845
 
 
846
                case    MULTIPOINTTYPE:
 
847
                case    MULTILINETYPE:
 
848
                case    MULTIPOLYGONTYPE:
 
849
                case    COLLECTIONTYPE:
 
850
                        read_collection(b,parse_wkb);
 
851
                        break;
 
852
 
 
853
                case    POINTTYPEI:
 
854
                        the_geom.from_lwgi=1;
 
855
                        read_wkb_point(b);
 
856
                        break;
 
857
 
 
858
                case    LINETYPEI:
 
859
                        the_geom.from_lwgi=1;
 
860
                        read_collection(b,read_wkb_point);
 
861
                        break;
 
862
 
 
863
                case    POLYGONTYPEI:
 
864
                        the_geom.from_lwgi=1;
 
865
                        read_collection(b,read_collection2);
 
866
                        break;
 
867
 
 
868
                default:
 
869
                        error("Invalid type in wbk");
 
870
        }
 
871
 
 
872
        the_geom.from_lwgi=0;
 
873
 
 
874
        pop();
 
875
}
 
876
 
 
877
 
 
878
void
 
879
alloc_wkb(const uchar* parser)
 
880
{
 
881
        parse_wkb(&parser);
 
882
}
 
883
 
 
884
/*
 
885
        Parse a string and return a LW_GEOM
 
886
*/
 
887
uchar *
 
888
parse_it(const uchar* geometry,allocator allocfunc,report_error errfunc)
 
889
{
 
890
 
 
891
        local_malloc = allocfunc;
 
892
        error_func=errfunc;
 
893
 
 
894
        ferror_occured = 0;
 
895
 
 
896
        init_parser(geometry);
 
897
        lwg_parse_yyparse();
 
898
        close_parser();
 
899
 
 
900
        if (ferror_occured)
 
901
                return NULL;
 
902
 
 
903
        return make_lwgeom();
 
904
}
 
905
 
 
906
uchar *
 
907
parse_lwg(const uchar* geometry,allocator allocfunc,report_error errfunc)
 
908
{
 
909
        the_geom.lwgi=0;
 
910
        return parse_it(geometry,allocfunc,errfunc);
 
911
}
 
912
 
 
913
uchar *
 
914
parse_lwgi(const uchar* geometry,allocator allocfunc,report_error errfunc)
 
915
{
 
916
        the_geom.lwgi=1;
 
917
        return parse_it(geometry,allocfunc,errfunc);
 
918
}
 
919
 
 
920
void
 
921
set_zm(char z, char m)
 
922
{
 
923
        the_geom.hasZ = z;
 
924
        the_geom.hasM = m;
 
925
        the_geom.ndims = 2+z+m;
 
926
}