Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /branches/libroutino/src/osmo5mparse.c
Parent Directory
|
Revision Log
Revision 1727 -
(show annotations)
(download)
(as text)
Wed Jul 1 18:20:13 2015 UTC (9 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 18842 byte(s)
Wed Jul 1 18:20:13 2015 UTC (9 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 18842 byte(s)
Merge changes from MS-Windows branch.
1 | /*************************************** |
2 | A simple o5m/o5c parser. |
3 | |
4 | Part of the Routino routing software. |
5 | ******************/ /****************** |
6 | This file Copyright 2012-2015 Andrew M. Bishop |
7 | |
8 | This program is free software: you can redistribute it and/or modify |
9 | it under the terms of the GNU Affero General Public License as published by |
10 | the Free Software Foundation, either version 3 of the License, or |
11 | (at your option) any later version. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU Affero General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU Affero General Public License |
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | ***************************************/ |
21 | |
22 | |
23 | #include <stdio.h> |
24 | |
25 | #if defined(_MSC_VER) |
26 | #include <io.h> |
27 | #include <basetsd.h> |
28 | #define read(fd,address,length) _read(fd,address,(unsigned int)(length)) |
29 | #define ssize_t SSIZE_T |
30 | #else |
31 | #include <unistd.h> |
32 | #endif |
33 | |
34 | #include <stdlib.h> |
35 | #include <string.h> |
36 | #include <inttypes.h> |
37 | #include <stdint.h> |
38 | |
39 | #include "osmparser.h" |
40 | #include "tagging.h" |
41 | #include "logging.h" |
42 | |
43 | |
44 | /* At the top level */ |
45 | |
46 | #define O5M_FILE_NODE 0x10 |
47 | #define O5M_FILE_WAY 0x11 |
48 | #define O5M_FILE_RELATION 0x12 |
49 | #define O5M_FILE_BOUNDING_BOX 0xdb |
50 | #define O5M_FILE_TIMESTAMP 0xdc |
51 | #define O5M_FILE_HEADER 0xe0 |
52 | #define O5M_FILE_SYNC 0xee |
53 | #define O5M_FILE_JUMP 0xef |
54 | #define O5M_FILE_END 0xfe |
55 | #define O5M_FILE_RESET 0xff |
56 | |
57 | /* Errors */ |
58 | |
59 | #define O5M_EOF 0 |
60 | |
61 | #define O5M_ERROR_UNEXP_EOF 100 |
62 | #define O5M_ERROR_RESET_NOT_FIRST 101 |
63 | #define O5M_ERROR_HEADER_NOT_FIRST 102 |
64 | #define O5M_ERROR_EXPECTED_O5M 103 |
65 | #define O5M_ERROR_EXPECTED_O5C 104 |
66 | #define O5M_ERROR_FILE_LEVEL 105 |
67 | |
68 | /* Local parsing variables (re-initialised for each file) */ |
69 | |
70 | static uint64_t byteno=0; |
71 | static uint64_t nnodes=0,nways=0,nrelations=0; |
72 | |
73 | static int64_t id=0; |
74 | static int32_t lat=0; |
75 | static int32_t lon=0; |
76 | static int64_t timestamp=0; |
77 | static int64_t node_refid=0,way_refid=0,relation_refid=0; |
78 | |
79 | static int mode_change=MODE_NORMAL; |
80 | |
81 | static uint32_t buffer_allocated; |
82 | static unsigned char *buffer=NULL; |
83 | static unsigned char *buffer_ptr,*buffer_end; |
84 | |
85 | static int string_table_start=0; |
86 | static unsigned char **string_table=NULL; |
87 | |
88 | #define STRING_TABLE_ALLOCATED 15000 |
89 | |
90 | |
91 | /*++++++++++++++++++++++++++++++++++++++ |
92 | Refill the data buffer and set the pointers. |
93 | |
94 | int buffer_refill Return 0 if everything is OK or 1 for EOF. |
95 | |
96 | int fd The file descriptor to read from. |
97 | |
98 | uint32_t bytes The number of bytes to read. |
99 | ++++++++++++++++++++++++++++++++++++++*/ |
100 | |
101 | static inline int buffer_refill(int fd,uint32_t bytes) |
102 | { |
103 | ssize_t n,m; |
104 | uint32_t totalbytes; |
105 | |
106 | m=buffer_end-buffer_ptr; |
107 | |
108 | if(m) |
109 | memmove(buffer,buffer_ptr,m); |
110 | |
111 | totalbytes=bytes+m; |
112 | |
113 | if(totalbytes>buffer_allocated) |
114 | buffer=(unsigned char *)realloc(buffer,buffer_allocated=totalbytes); |
115 | |
116 | byteno+=bytes; |
117 | |
118 | buffer_ptr=buffer; |
119 | buffer_end=buffer+m; |
120 | |
121 | do |
122 | { |
123 | n=read(fd,buffer_end,bytes); |
124 | |
125 | if(n<=0) |
126 | return(1); |
127 | |
128 | buffer_end+=n; |
129 | bytes-=n; |
130 | } |
131 | while(bytes>0); |
132 | |
133 | return(0); |
134 | } |
135 | |
136 | static void process_node(void); |
137 | static void process_way(void); |
138 | static void process_relation(void); |
139 | static void process_info(void); |
140 | static unsigned char *process_string(int pair,unsigned char **buf_ptr,unsigned char **string1,unsigned char **string2); |
141 | |
142 | |
143 | /* Macros to simplify the parser (and make it look more like the XML parser) */ |
144 | |
145 | #define BEGIN(xx) do{ state=(xx); goto finish_parsing; } while(0) |
146 | |
147 | #define BUFFER_CHARS(xx) do{ if(buffer_refill(fd,(xx))) BEGIN(O5M_ERROR_UNEXP_EOF); } while(0) |
148 | |
149 | |
150 | /* O5M decoding */ |
151 | |
152 | #define O5M_LATITUDE(xx) (double)(1E-7*(xx)) |
153 | #define O5M_LONGITUDE(xx) (double)(1E-7*(xx)) |
154 | |
155 | |
156 | /*++++++++++++++++++++++++++++++++++++++ |
157 | Parse an O5M int32 data value. |
158 | |
159 | uint32_t o5m_int32 Returns the integer value. |
160 | |
161 | unsigned char **ptr The pointer to read the data from. |
162 | ++++++++++++++++++++++++++++++++++++++*/ |
163 | |
164 | static inline uint32_t o5m_int32(unsigned char **ptr) |
165 | { |
166 | uint32_t result=(**ptr)&0x7F; |
167 | |
168 | if((**ptr)&0x80) result+=((*++(*ptr))&0x7F)<<7; |
169 | if((**ptr)&0x80) result+=((*++(*ptr))&0x7F)<<14; |
170 | if((**ptr)&0x80) result+=((*++(*ptr))&0x7F)<<21; |
171 | if((**ptr)&0x80) result+=((*++(*ptr))&0x7F)<<28; |
172 | |
173 | (*ptr)++; |
174 | |
175 | return(result); |
176 | } |
177 | |
178 | |
179 | /*++++++++++++++++++++++++++++++++++++++ |
180 | Parse an O5M int32 data value. |
181 | |
182 | int32_t o5m_sint32 Returns the integer value. |
183 | |
184 | unsigned char **ptr The pointer to read the data from. |
185 | ++++++++++++++++++++++++++++++++++++++*/ |
186 | |
187 | static inline int32_t o5m_sint32(unsigned char **ptr) |
188 | { |
189 | int64_t result=((**ptr)&0x7E)>>1; |
190 | int sign=(**ptr)&0x01; |
191 | |
192 | if((**ptr)&0x80) result+=(int64_t)((*++(*ptr))&0x7F)<<6; |
193 | if((**ptr)&0x80) result+=(int64_t)((*++(*ptr))&0x7F)<<13; |
194 | if((**ptr)&0x80) result+=(int64_t)((*++(*ptr))&0x7F)<<20; |
195 | if((**ptr)&0x80) result+=(int64_t)((*++(*ptr))&0x7F)<<27; |
196 | |
197 | (*ptr)++; |
198 | |
199 | if(sign) |
200 | result=-result-1; |
201 | |
202 | return(result); |
203 | } |
204 | |
205 | |
206 | /*++++++++++++++++++++++++++++++++++++++ |
207 | Parse an O5M int64 data value. |
208 | |
209 | int64_t o5m_int64 Returns the integer value. |
210 | |
211 | unsigned char **ptr The pointer to read the data from. |
212 | ++++++++++++++++++++++++++++++++++++++*/ |
213 | |
214 | static inline int64_t o5m_int64(unsigned char **ptr) |
215 | { |
216 | uint64_t result=(**ptr)&0x7F; |
217 | |
218 | if((**ptr)&0x80) result+=(uint64_t)((*++(*ptr))&0x7F)<<7; |
219 | if((**ptr)&0x80) result+=(uint64_t)((*++(*ptr))&0x7F)<<14; |
220 | if((**ptr)&0x80) result+=(uint64_t)((*++(*ptr))&0x7F)<<21; |
221 | if((**ptr)&0x80) result+=(uint64_t)((*++(*ptr))&0x7F)<<28; |
222 | if((**ptr)&0x80) result+=(uint64_t)((*++(*ptr))&0x7F)<<35; |
223 | if((**ptr)&0x80) result+=(uint64_t)((*++(*ptr))&0x7F)<<42; |
224 | if((**ptr)&0x80) result+=(uint64_t)((*++(*ptr))&0x7F)<<49; |
225 | if((**ptr)&0x80) result+=(uint64_t)((*++(*ptr))&0x7F)<<56; |
226 | if((**ptr)&0x80) result+=(uint64_t)((*++(*ptr))&0x7F)<<63; |
227 | |
228 | (*ptr)++; |
229 | |
230 | return(result); |
231 | } |
232 | |
233 | |
234 | /*++++++++++++++++++++++++++++++++++++++ |
235 | Parse an O5M sint64 data value. |
236 | |
237 | int64_t o5m_sint64 Returns the integer value. |
238 | |
239 | unsigned char **ptr The pointer to read the data from. |
240 | ++++++++++++++++++++++++++++++++++++++*/ |
241 | |
242 | static inline int64_t o5m_sint64(unsigned char **ptr) |
243 | { |
244 | int64_t result=((**ptr)&0x7E)>>1; |
245 | int sign=(**ptr)&0x01; |
246 | |
247 | if((**ptr)&0x80) result+=(int64_t)((*++(*ptr))&0x7F)<<6; |
248 | if((**ptr)&0x80) result+=(int64_t)((*++(*ptr))&0x7F)<<13; |
249 | if((**ptr)&0x80) result+=(int64_t)((*++(*ptr))&0x7F)<<20; |
250 | if((**ptr)&0x80) result+=(int64_t)((*++(*ptr))&0x7F)<<27; |
251 | if((**ptr)&0x80) result+=(int64_t)((*++(*ptr))&0x7F)<<34; |
252 | if((**ptr)&0x80) result+=(int64_t)((*++(*ptr))&0x7F)<<41; |
253 | if((**ptr)&0x80) result+=(int64_t)((*++(*ptr))&0x7F)<<48; |
254 | if((**ptr)&0x80) result+=(int64_t)((*++(*ptr))&0x7F)<<55; |
255 | if((**ptr)&0x80) result+=(int64_t)((*++(*ptr))&0x7F)<<62; |
256 | |
257 | (*ptr)++; |
258 | |
259 | if(sign) |
260 | result=-result-1; |
261 | |
262 | return(result); |
263 | } |
264 | |
265 | |
266 | /*++++++++++++++++++++++++++++++++++++++ |
267 | Parse the O5M and call the functions for each OSM item as seen. |
268 | |
269 | int ParseO5M Returns 0 if OK or something else in case of an error. |
270 | |
271 | int fd The file descriptor of the file to parse. |
272 | |
273 | int changes Set to 1 if this is expected to be a changes file, otherwise zero. |
274 | ++++++++++++++++++++++++++++++++++++++*/ |
275 | |
276 | static int ParseO5M(int fd,int changes) |
277 | { |
278 | int i; |
279 | int state; |
280 | int number_reset=0; |
281 | int error; |
282 | |
283 | /* Print the initial message */ |
284 | |
285 | printf_first("Reading: Bytes=0 Nodes=0 Ways=0 Relations=0"); |
286 | |
287 | /* The actual parser. */ |
288 | |
289 | nnodes=0,nways=0,nrelations=0; |
290 | |
291 | if(changes) |
292 | mode_change=MODE_MODIFY; |
293 | |
294 | string_table_start=0; |
295 | string_table=(unsigned char **)malloc(STRING_TABLE_ALLOCATED*sizeof(unsigned char *)); |
296 | for(i=0;i<STRING_TABLE_ALLOCATED;i++) |
297 | string_table[i]=(unsigned char*)malloc(252); |
298 | |
299 | buffer_allocated=4096; |
300 | buffer=(unsigned char*)malloc(buffer_allocated); |
301 | |
302 | buffer_ptr=buffer_end=buffer; |
303 | |
304 | while(1) |
305 | { |
306 | uint32_t dataset_length=0; |
307 | |
308 | /* ================ Parsing states ================ */ |
309 | |
310 | BUFFER_CHARS(1); |
311 | |
312 | state=*buffer_ptr++; |
313 | |
314 | if(state!=O5M_FILE_END && state!=O5M_FILE_RESET) |
315 | { |
316 | uint32_t length; |
317 | unsigned char *ptr; |
318 | |
319 | if(number_reset==0) |
320 | BEGIN(O5M_ERROR_RESET_NOT_FIRST); |
321 | |
322 | BUFFER_CHARS(4); |
323 | |
324 | ptr=buffer_ptr; |
325 | dataset_length=o5m_int32(&buffer_ptr); |
326 | |
327 | length=dataset_length-4+(buffer_ptr-ptr); |
328 | |
329 | BUFFER_CHARS(length); |
330 | } |
331 | else if(state==O5M_FILE_END) |
332 | ; |
333 | else if(state==O5M_FILE_RESET) |
334 | number_reset++; |
335 | |
336 | switch(state) |
337 | { |
338 | case O5M_FILE_NODE: |
339 | |
340 | process_node(); |
341 | |
342 | break; |
343 | |
344 | case O5M_FILE_WAY: |
345 | |
346 | process_way(); |
347 | |
348 | break; |
349 | |
350 | case O5M_FILE_RELATION: |
351 | |
352 | process_relation(); |
353 | |
354 | break; |
355 | |
356 | case O5M_FILE_BOUNDING_BOX: |
357 | |
358 | buffer_ptr+=dataset_length; |
359 | |
360 | break; |
361 | |
362 | case O5M_FILE_TIMESTAMP: |
363 | |
364 | buffer_ptr+=dataset_length; |
365 | |
366 | break; |
367 | |
368 | case O5M_FILE_HEADER: |
369 | |
370 | if(number_reset!=1) |
371 | BEGIN(O5M_ERROR_HEADER_NOT_FIRST); |
372 | |
373 | if(!changes && strncmp((char*)buffer_ptr,"o5m2",4)) |
374 | BEGIN(O5M_ERROR_EXPECTED_O5M); |
375 | |
376 | if( changes && strncmp((char*)buffer_ptr,"o5c2",4)) |
377 | BEGIN(O5M_ERROR_EXPECTED_O5C); |
378 | |
379 | buffer_ptr+=dataset_length; |
380 | |
381 | break; |
382 | |
383 | case O5M_FILE_SYNC: |
384 | |
385 | buffer_ptr+=dataset_length; |
386 | |
387 | break; |
388 | |
389 | case O5M_FILE_JUMP: |
390 | |
391 | buffer_ptr+=dataset_length; |
392 | |
393 | break; |
394 | |
395 | case O5M_FILE_END: |
396 | |
397 | BEGIN(O5M_EOF); |
398 | |
399 | break; |
400 | |
401 | case O5M_FILE_RESET: |
402 | |
403 | string_table_start=0; |
404 | id=0; |
405 | lat=0; |
406 | lon=0; |
407 | timestamp=0; |
408 | node_refid=0,way_refid=0,relation_refid=0; |
409 | |
410 | break; |
411 | |
412 | default: |
413 | |
414 | error=state; |
415 | BEGIN(O5M_ERROR_FILE_LEVEL); |
416 | } |
417 | } |
418 | |
419 | |
420 | finish_parsing: |
421 | |
422 | switch(state) |
423 | { |
424 | /* End of file */ |
425 | |
426 | case O5M_EOF: |
427 | break; |
428 | |
429 | |
430 | /* ================ Error states ================ */ |
431 | |
432 | |
433 | case O5M_ERROR_UNEXP_EOF: |
434 | fprintf(stderr,"O5M Parser: Error at byte %"PRIu64": unexpected end of file seen.\n",byteno); |
435 | break; |
436 | |
437 | case O5M_ERROR_RESET_NOT_FIRST: |
438 | fprintf(stderr,"O5M Parser: Error at byte %"PRIu64": Reset was not the first byte.\n",byteno); |
439 | break; |
440 | |
441 | case O5M_ERROR_HEADER_NOT_FIRST: |
442 | fprintf(stderr,"O5M Parser: Error at byte %"PRIu64": Header was not the first section.\n",byteno); |
443 | break; |
444 | |
445 | case O5M_ERROR_EXPECTED_O5M: |
446 | fprintf(stderr,"O5M Parser: Error at byte %"PRIu64": Expected O5M format but header disagrees.\n",byteno); |
447 | break; |
448 | |
449 | case O5M_ERROR_EXPECTED_O5C: |
450 | fprintf(stderr,"O5M Parser: Error at byte %"PRIu64": Expected O5C format but header disagrees.\n",byteno); |
451 | break; |
452 | |
453 | case O5M_ERROR_FILE_LEVEL: |
454 | fprintf(stderr,"O5M Parser: Error at byte %"PRIu64": Unexpected dataset type %02x.\n",byteno,error); |
455 | break; |
456 | } |
457 | |
458 | /* Free the parser variables */ |
459 | |
460 | for(i=0;i<STRING_TABLE_ALLOCATED;i++) |
461 | free(string_table[i]); |
462 | free(string_table); |
463 | |
464 | free(buffer); |
465 | |
466 | /* Print the final message */ |
467 | |
468 | printf_last("Read: Bytes=%"PRIu64" Nodes=%"PRIu64" Ways=%"PRIu64" Relations=%"PRIu64,byteno,nnodes,nways,nrelations); |
469 | |
470 | return(state); |
471 | } |
472 | |
473 | |
474 | /*++++++++++++++++++++++++++++++++++++++ |
475 | Process an O5M Node dataset. |
476 | ++++++++++++++++++++++++++++++++++++++*/ |
477 | |
478 | static void process_node(void) |
479 | { |
480 | int64_t delta_id; |
481 | int32_t delta_lat; |
482 | int32_t delta_lon; |
483 | TagList *tags=NULL,*result=NULL; |
484 | int mode=mode_change; |
485 | |
486 | delta_id=o5m_sint64(&buffer_ptr); |
487 | id+=delta_id; |
488 | |
489 | if(buffer_ptr<buffer_end) |
490 | { |
491 | if(*buffer_ptr!=0) |
492 | process_info(); |
493 | else |
494 | buffer_ptr++; |
495 | } |
496 | |
497 | if(buffer_ptr<buffer_end) |
498 | { |
499 | delta_lon=o5m_sint32(&buffer_ptr); |
500 | lon+=delta_lon; |
501 | |
502 | delta_lat=o5m_sint32(&buffer_ptr); |
503 | lat+=delta_lat; |
504 | } |
505 | else |
506 | mode=MODE_DELETE; |
507 | |
508 | /* Mangle the data and send it to the OSM parser */ |
509 | |
510 | nnodes++; |
511 | |
512 | if(!(nnodes%10000)) |
513 | printf_middle("Reading: Bytes=%"PRIu64" Nodes=%"PRIu64" Ways=%"PRIu64" Relations=%"PRIu64,byteno,nnodes,nways,nrelations); |
514 | |
515 | tags=NewTagList(); |
516 | |
517 | while(buffer_ptr<buffer_end) |
518 | { |
519 | unsigned char *key,*val; |
520 | |
521 | process_string(2,&buffer_ptr,&key,&val); |
522 | |
523 | AppendTag(tags,(char*)key,(char*)val); |
524 | } |
525 | |
526 | result=ApplyNodeTaggingRules(tags,id); |
527 | |
528 | ProcessNodeTags(result,id,O5M_LATITUDE(lat),O5M_LONGITUDE(lon),mode); |
529 | |
530 | DeleteTagList(tags); |
531 | DeleteTagList(result); |
532 | } |
533 | |
534 | |
535 | /*++++++++++++++++++++++++++++++++++++++ |
536 | Process an O5M Way dataset. |
537 | ++++++++++++++++++++++++++++++++++++++*/ |
538 | |
539 | static void process_way(void) |
540 | { |
541 | int64_t delta_id; |
542 | TagList *tags=NULL,*result=NULL; |
543 | int mode=mode_change; |
544 | unsigned char *refs=NULL,*refs_end; |
545 | |
546 | delta_id=o5m_sint64(&buffer_ptr); |
547 | id+=delta_id; |
548 | |
549 | if(buffer_ptr<buffer_end) |
550 | { |
551 | if(*buffer_ptr!=0) |
552 | process_info(); |
553 | else |
554 | buffer_ptr++; |
555 | } |
556 | |
557 | if(buffer_ptr<buffer_end) |
558 | { |
559 | uint32_t length; |
560 | |
561 | length=o5m_int32(&buffer_ptr); |
562 | |
563 | if(length) |
564 | { |
565 | refs=buffer_ptr; |
566 | refs_end=buffer_ptr+length; |
567 | |
568 | buffer_ptr=refs_end; |
569 | } |
570 | } |
571 | else |
572 | mode=MODE_DELETE; |
573 | |
574 | /* Mangle the data and send it to the OSM parser */ |
575 | |
576 | nways++; |
577 | |
578 | if(!(nways%1000)) |
579 | printf_middle("Reading: Bytes=%"PRIu64" Nodes=%"PRIu64" Ways=%"PRIu64" Relations=%"PRIu64,byteno,nnodes,nways,nrelations); |
580 | |
581 | AddWayRefs(0); |
582 | |
583 | if(refs) |
584 | while(refs<refs_end) |
585 | { |
586 | int64_t delta_ref; |
587 | |
588 | delta_ref=o5m_sint64(&refs); |
589 | node_refid+=delta_ref; |
590 | |
591 | AddWayRefs(node_refid); |
592 | } |
593 | |
594 | tags=NewTagList(); |
595 | |
596 | while(buffer_ptr<buffer_end) |
597 | { |
598 | unsigned char *key,*val; |
599 | |
600 | process_string(2,&buffer_ptr,&key,&val); |
601 | |
602 | AppendTag(tags,(char*)key,(char*)val); |
603 | } |
604 | |
605 | result=ApplyWayTaggingRules(tags,id); |
606 | |
607 | ProcessWayTags(result,id,mode); |
608 | |
609 | DeleteTagList(tags); |
610 | DeleteTagList(result); |
611 | } |
612 | |
613 | |
614 | /*++++++++++++++++++++++++++++++++++++++ |
615 | Process an O5M Relation dataset. |
616 | ++++++++++++++++++++++++++++++++++++++*/ |
617 | |
618 | static void process_relation() |
619 | { |
620 | int64_t delta_id; |
621 | TagList *tags=NULL,*result=NULL; |
622 | int mode=mode_change; |
623 | unsigned char *refs=NULL,*refs_end; |
624 | |
625 | delta_id=o5m_sint64(&buffer_ptr); |
626 | id+=delta_id; |
627 | |
628 | if(buffer_ptr<buffer_end) |
629 | { |
630 | if(*buffer_ptr!=0) |
631 | process_info(); |
632 | else |
633 | buffer_ptr++; |
634 | } |
635 | |
636 | if(buffer_ptr<buffer_end) |
637 | { |
638 | uint32_t length; |
639 | |
640 | length=o5m_int32(&buffer_ptr); |
641 | |
642 | if(length) |
643 | { |
644 | refs=buffer_ptr; |
645 | refs_end=buffer_ptr+length; |
646 | |
647 | buffer_ptr=refs_end; |
648 | } |
649 | } |
650 | else |
651 | mode=MODE_DELETE; |
652 | |
653 | /* Mangle the data and send it to the OSM parser */ |
654 | |
655 | nrelations++; |
656 | |
657 | if(!(nrelations%1000)) |
658 | printf_middle("Reading: Bytes=%"PRIu64" Nodes=%"PRIu64" Ways=%"PRIu64" Relations=%"PRIu64,byteno,nnodes,nways,nrelations); |
659 | |
660 | AddRelationRefs(0,0,0,NULL); |
661 | |
662 | if(refs) |
663 | while(refs<refs_end) |
664 | { |
665 | int64_t delta_ref; |
666 | unsigned char *typerole=NULL; |
667 | |
668 | delta_ref=o5m_sint64(&refs); |
669 | |
670 | typerole=process_string(1,&refs,NULL,NULL); |
671 | |
672 | if(*typerole=='0') |
673 | { |
674 | node_refid+=delta_ref; |
675 | |
676 | AddRelationRefs(node_refid,0,0,(char*)(typerole+1)); |
677 | } |
678 | else if(*typerole=='1') |
679 | { |
680 | way_refid+=delta_ref; |
681 | |
682 | AddRelationRefs(0,way_refid,0,(char*)(typerole+1)); |
683 | } |
684 | else if(*typerole=='2') |
685 | { |
686 | relation_refid+=delta_ref; |
687 | |
688 | AddRelationRefs(0,0,relation_refid,(char*)(typerole+1)); |
689 | } |
690 | } |
691 | |
692 | tags=NewTagList(); |
693 | |
694 | while(buffer_ptr<buffer_end) |
695 | { |
696 | unsigned char *key,*val; |
697 | |
698 | process_string(2,&buffer_ptr,&key,&val); |
699 | |
700 | AppendTag(tags,(char*)key,(char*)val); |
701 | } |
702 | |
703 | result=ApplyRelationTaggingRules(tags,id); |
704 | |
705 | ProcessRelationTags(result,id,mode); |
706 | |
707 | DeleteTagList(tags); |
708 | DeleteTagList(result); |
709 | } |
710 | |
711 | |
712 | /*++++++++++++++++++++++++++++++++++++++ |
713 | Process an O5M info message. |
714 | ++++++++++++++++++++++++++++++++++++++*/ |
715 | |
716 | static void process_info(void) |
717 | { |
718 | int64_t timestamp_delta; |
719 | |
720 | o5m_int32(&buffer_ptr); /* version */ |
721 | |
722 | timestamp_delta=o5m_sint64(&buffer_ptr); |
723 | timestamp+=timestamp_delta; |
724 | |
725 | if(timestamp!=0) |
726 | { |
727 | o5m_sint32(&buffer_ptr); /* changeset */ |
728 | |
729 | process_string(2,&buffer_ptr,NULL,NULL); /* user */ |
730 | } |
731 | } |
732 | |
733 | |
734 | /*++++++++++++++++++++++++++++++++++++++ |
735 | Process an O5M string and take care of maintaining the string table. |
736 | |
737 | unsigned char *process_string_pair Return a pointer to the concatenation of the two strings. |
738 | |
739 | int pair Set to 2 for a pair or 1 for a single string. |
740 | |
741 | unsigned char **buf_ptr The pointer to the buffer that is to be updated. |
742 | |
743 | unsigned char **string1 Returns a pointer to the first of the strings in the pair. |
744 | |
745 | unsigned char **string2 Returns a pointer to the second of the strings in the pair. |
746 | ++++++++++++++++++++++++++++++++++++++*/ |
747 | |
748 | static unsigned char *process_string(int pair,unsigned char **buf_ptr,unsigned char **string1,unsigned char **string2) |
749 | { |
750 | int lookup=0; |
751 | unsigned char *string; |
752 | unsigned char *p; |
753 | |
754 | if(**buf_ptr==0) |
755 | string=*buf_ptr+1; |
756 | else |
757 | { |
758 | uint32_t position=o5m_int32(buf_ptr); |
759 | |
760 | string=string_table[(string_table_start-position+STRING_TABLE_ALLOCATED)%STRING_TABLE_ALLOCATED]; |
761 | |
762 | lookup=1; |
763 | } |
764 | |
765 | p=string; |
766 | |
767 | if(pair==2) |
768 | { |
769 | if(string1) |
770 | *string1=p; |
771 | |
772 | while(*p) p++; |
773 | |
774 | p++; |
775 | |
776 | if(string2) |
777 | *string2=p; |
778 | } |
779 | |
780 | while(*p) p++; |
781 | |
782 | if(!lookup) |
783 | { |
784 | if((p-string)<252) |
785 | { |
786 | memcpy(string_table[string_table_start],string,p-string+1); |
787 | |
788 | string_table_start=(string_table_start+1)%STRING_TABLE_ALLOCATED; |
789 | } |
790 | |
791 | *buf_ptr=p+1; |
792 | } |
793 | |
794 | return(string); |
795 | } |
796 | |
797 | |
798 | /*++++++++++++++++++++++++++++++++++++++ |
799 | Parse an O5M format OSM file (from planet download). |
800 | |
801 | int ParseO5MFile Returns 0 if OK or something else in case of an error. |
802 | |
803 | int fd The file descriptor of the file to read from. |
804 | |
805 | NodesX *OSMNodes The data structure of nodes to fill in. |
806 | |
807 | WaysX *OSMWays The data structure of ways to fill in. |
808 | |
809 | RelationsX *OSMRelations The data structure of relations to fill in. |
810 | ++++++++++++++++++++++++++++++++++++++*/ |
811 | |
812 | int ParseO5MFile(int fd,NodesX *OSMNodes,WaysX *OSMWays,RelationsX *OSMRelations) |
813 | { |
814 | int retval; |
815 | |
816 | /* Initialise the parser */ |
817 | |
818 | InitialiseParser(OSMNodes,OSMWays,OSMRelations); |
819 | |
820 | /* Parse the file */ |
821 | |
822 | retval=ParseO5M(fd,0); |
823 | |
824 | /* Cleanup the parser */ |
825 | |
826 | CleanupParser(); |
827 | |
828 | return(retval); |
829 | } |
830 | |
831 | |
832 | /*++++++++++++++++++++++++++++++++++++++ |
833 | Parse an O5C format OSM file (from planet download). |
834 | |
835 | int ParseO5CFile Returns 0 if OK or something else in case of an error. |
836 | |
837 | int fd The file descriptor of the file to read from. |
838 | |
839 | NodesX *OSMNodes The data structure of nodes to fill in. |
840 | |
841 | WaysX *OSMWays The data structure of ways to fill in. |
842 | |
843 | RelationsX *OSMRelations The data structure of relations to fill in. |
844 | ++++++++++++++++++++++++++++++++++++++*/ |
845 | |
846 | int ParseO5CFile(int fd,NodesX *OSMNodes,WaysX *OSMWays,RelationsX *OSMRelations) |
847 | { |
848 | int retval; |
849 | |
850 | /* Initialise the parser */ |
851 | |
852 | InitialiseParser(OSMNodes,OSMWays,OSMRelations); |
853 | |
854 | /* Parse the file */ |
855 | |
856 | retval=ParseO5M(fd,1); |
857 | |
858 | /* Cleanup the parser */ |
859 | |
860 | CleanupParser(); |
861 | |
862 | return(retval); |
863 | } |