1 : /******************************************************************************
2 : * $Id: osm_parser.cpp 25191 2012-10-29 22:47:59Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
6 : * Purpose: OSM XML and OSM PBF parser
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2012, Even Rouault, <even dot rouault at mines dash paris dot org>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "osm_parser.h"
31 : #include "gpb.h"
32 :
33 : #include "cpl_conv.h"
34 : #include "cpl_string.h"
35 : #include "cpl_vsi.h"
36 :
37 : #include <zlib.h>
38 :
39 : #ifdef HAVE_EXPAT
40 : #include "ogr_expat.h"
41 : #endif
42 :
43 : /* The buffer that are passed to GPB decoding are extended with 0's */
44 : /* to be sure that we will be able to read a single 64bit value without */
45 : /* doing checks for each byte */
46 : #define EXTRA_BYTES 1
47 :
48 : #define XML_BUFSIZE 64*1024
49 :
50 : CPL_CVSID("$Id: osm_parser.cpp 25191 2012-10-29 22:47:59Z rouault $");
51 :
52 : /************************************************************************/
53 : /* INIT_INFO() */
54 : /************************************************************************/
55 :
56 : #define INIT_INFO(sInfo) \
57 : sInfo.ts.nTimeStamp = 0; \
58 : sInfo.nChangeset = 0; \
59 : sInfo.nVersion = 0; \
60 : sInfo.nUID = 0; \
61 : sInfo.bTimeStampIsStr = 0; \
62 : sInfo.pszUserSID = NULL;
63 : /* \ sInfo.nVisible = 1; */
64 :
65 :
66 : /************************************************************************/
67 : /* _OSMContext */
68 : /************************************************************************/
69 :
70 : struct _OSMContext
71 : {
72 : char *pszStrBuf;
73 : int *panStrOff;
74 : unsigned int nStrCount;
75 : unsigned int nStrAllocated;
76 :
77 : OSMNode *pasNodes;
78 : unsigned int nNodesAllocated;
79 :
80 : OSMTag *pasTags;
81 : unsigned int nTagsAllocated;
82 :
83 : OSMMember *pasMembers;
84 : unsigned int nMembersAllocated;
85 :
86 : GIntBig *panNodeRefs;
87 : unsigned int nNodeRefsAllocated;
88 :
89 : int nGranularity;
90 : int nDateGranularity;
91 : GIntBig nLatOffset;
92 : GIntBig nLonOffset;
93 :
94 : unsigned int nBlobSizeAllocated;
95 : GByte *pabyBlob;
96 :
97 : GByte *pabyUncompressed;
98 : unsigned int nUncompressedAllocated;
99 :
100 : #ifdef HAVE_EXPAT
101 : XML_Parser hXMLParser;
102 : int bEOF;
103 : int bStopParsing;
104 : int bHasFoundFeature;
105 : int nWithoutEventCounter;
106 : int nDataHandlerCounter;
107 :
108 : unsigned int nStrLength;
109 : unsigned int nTags;
110 :
111 : int bInNode;
112 : int bInWay;
113 : int bInRelation;
114 :
115 : OSMWay sWay;
116 : OSMRelation sRelation;
117 :
118 : int bTryToFetchBounds;
119 : #endif
120 :
121 : VSILFILE *fp;
122 :
123 : int bPBF;
124 :
125 : double dfLeft;
126 : double dfRight;
127 : double dfTop;
128 : double dfBottom;
129 :
130 : GUIntBig nBytesRead;
131 :
132 : NotifyNodesFunc pfnNotifyNodes;
133 : NotifyWayFunc pfnNotifyWay;
134 : NotifyRelationFunc pfnNotifyRelation;
135 : NotifyBoundsFunc pfnNotifyBounds;
136 : void *user_data;
137 : };
138 :
139 : /************************************************************************/
140 : /* ReadBlobHeader() */
141 : /************************************************************************/
142 :
143 : #define BLOBHEADER_IDX_TYPE 1
144 : #define BLOBHEADER_IDX_INDEXDATA 2
145 : #define BLOBHEADER_IDX_DATASIZE 3
146 :
147 : typedef enum
148 : {
149 : BLOB_UNKNOW,
150 : BLOB_OSMHEADER,
151 : BLOB_OSMDATA
152 : } BlobType;
153 :
154 : static
155 38 : int ReadBlobHeader(GByte* pabyData, GByte* pabyDataLimit,
156 : unsigned int* pnBlobSize, BlobType* peBlobType)
157 : {
158 38 : *pnBlobSize = 0;
159 38 : *peBlobType = BLOB_UNKNOW;
160 :
161 152 : while(pabyData < pabyDataLimit)
162 : {
163 : int nKey;
164 76 : READ_FIELD_KEY(nKey);
165 :
166 76 : if (nKey == MAKE_KEY(BLOBHEADER_IDX_TYPE, WT_DATA))
167 : {
168 : unsigned int nDataLength;
169 38 : READ_SIZE(pabyData, pabyDataLimit, nDataLength);
170 :
171 57 : if (nDataLength == 7 && memcmp(pabyData, "OSMData", 7) == 0)
172 : {
173 19 : *peBlobType = BLOB_OSMDATA;
174 : }
175 19 : else if (nDataLength == 9 && memcmp(pabyData, "OSMHeader", 9) == 0)
176 : {
177 19 : *peBlobType = BLOB_OSMHEADER;
178 : }
179 :
180 38 : pabyData += nDataLength;
181 : }
182 38 : else if (nKey == MAKE_KEY(BLOBHEADER_IDX_INDEXDATA, WT_DATA))
183 : {
184 : /* Ignored if found */
185 : unsigned int nDataLength;
186 0 : READ_SIZE(pabyData, pabyDataLimit, nDataLength);
187 0 : pabyData += nDataLength;
188 : }
189 38 : else if (nKey == MAKE_KEY(BLOBHEADER_IDX_DATASIZE, WT_VARINT))
190 : {
191 : unsigned int nBlobSize;
192 38 : READ_VARUINT32(pabyData, pabyDataLimit, nBlobSize);
193 : /* printf("nBlobSize = %d\n", nBlobSize); */
194 38 : *pnBlobSize = nBlobSize;
195 : }
196 : else
197 : {
198 0 : SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, TRUE);
199 : }
200 : }
201 :
202 38 : return pabyData == pabyDataLimit;
203 :
204 : end_error:
205 0 : return FALSE;
206 : }
207 :
208 : /************************************************************************/
209 : /* ReadHeaderBBox() */
210 : /************************************************************************/
211 :
212 : #define HEADERBBOX_IDX_LEFT 1
213 : #define HEADERBBOX_IDX_RIGHT 2
214 : #define HEADERBBOX_IDX_TOP 3
215 : #define HEADERBBOX_IDX_BOTTOM 4
216 :
217 : static
218 0 : int ReadHeaderBBox(GByte* pabyData, GByte* pabyDataLimit,
219 : OSMContext* psCtxt)
220 : {
221 0 : psCtxt->dfLeft = 0.0;
222 0 : psCtxt->dfRight = 0.0;
223 0 : psCtxt->dfTop = 0.0;
224 0 : psCtxt->dfBottom = 0.0;
225 :
226 : /* printf(">ReadHeaderBBox\n"); */
227 :
228 0 : while(pabyData < pabyDataLimit)
229 : {
230 : int nKey;
231 0 : READ_FIELD_KEY(nKey);
232 :
233 0 : if (nKey == MAKE_KEY(HEADERBBOX_IDX_LEFT, WT_VARINT))
234 : {
235 : GIntBig nLeft;
236 0 : READ_VARSINT64(pabyData, pabyDataLimit, nLeft);
237 0 : psCtxt->dfLeft = nLeft * 1e-9;
238 : }
239 0 : else if (nKey == MAKE_KEY(HEADERBBOX_IDX_RIGHT, WT_VARINT))
240 : {
241 : GIntBig nRight;
242 0 : READ_VARSINT64(pabyData, pabyDataLimit, nRight);
243 0 : psCtxt->dfRight = nRight * 1e-9;
244 : }
245 0 : else if (nKey == MAKE_KEY(HEADERBBOX_IDX_TOP, WT_VARINT))
246 : {
247 : GIntBig nTop;
248 0 : READ_VARSINT64(pabyData, pabyDataLimit, nTop);
249 0 : psCtxt->dfTop = nTop * 1e-9;
250 : }
251 0 : else if (nKey == MAKE_KEY(HEADERBBOX_IDX_BOTTOM, WT_VARINT))
252 : {
253 : GIntBig nBottom;
254 0 : READ_VARSINT64(pabyData, pabyDataLimit, nBottom);
255 0 : psCtxt->dfBottom = nBottom * 1e-9;
256 : }
257 : else
258 : {
259 0 : SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, TRUE);
260 : }
261 : }
262 :
263 : psCtxt->pfnNotifyBounds(psCtxt->dfLeft, psCtxt->dfBottom,
264 : psCtxt->dfRight, psCtxt->dfTop,
265 0 : psCtxt, psCtxt->user_data);
266 :
267 : /* printf("<ReadHeaderBBox\n"); */
268 0 : return pabyData == pabyDataLimit;
269 :
270 : end_error:
271 : /* printf("<ReadHeaderBBox\n"); */
272 0 : return FALSE;
273 : }
274 :
275 : /************************************************************************/
276 : /* ReadOSMHeader() */
277 : /************************************************************************/
278 :
279 : #define OSMHEADER_IDX_BBOX 1
280 : #define OSMHEADER_IDX_REQUIRED_FEATURES 4
281 : #define OSMHEADER_IDX_OPTIONAL_FEATURES 5
282 : #define OSMHEADER_IDX_WRITING_PROGRAM 16
283 : #define OSMHEADER_IDX_SOURCE 17
284 :
285 : static
286 19 : int ReadOSMHeader(GByte* pabyData, GByte* pabyDataLimit,
287 : OSMContext* psCtxt)
288 : {
289 : char* pszTxt;
290 :
291 95 : while(pabyData < pabyDataLimit)
292 : {
293 : int nKey;
294 57 : READ_FIELD_KEY(nKey);
295 :
296 57 : if (nKey == MAKE_KEY(OSMHEADER_IDX_BBOX, WT_DATA))
297 : {
298 : unsigned int nBBOXSize;
299 0 : READ_SIZE(pabyData, pabyDataLimit, nBBOXSize);
300 :
301 0 : if (!ReadHeaderBBox(pabyData, pabyData + nBBOXSize, psCtxt)) GOTO_END_ERROR;
302 :
303 0 : pabyData += nBBOXSize;
304 : }
305 57 : else if (nKey == MAKE_KEY(OSMHEADER_IDX_REQUIRED_FEATURES, WT_DATA))
306 : {
307 38 : READ_TEXT(pabyData, pabyDataLimit, pszTxt);
308 : /* printf("OSMHEADER_IDX_REQUIRED_FEATURES = %s\n", pszTxt); */
309 38 : if (!(strcmp(pszTxt, "OsmSchema-V0.6") == 0 ||
310 : strcmp(pszTxt, "DenseNodes") == 0))
311 : {
312 0 : fprintf(stderr, "Error: unsupported required feature : %s\n", pszTxt);
313 0 : VSIFree(pszTxt);
314 0 : GOTO_END_ERROR;
315 : }
316 38 : VSIFree(pszTxt);
317 : }
318 19 : else if (nKey == MAKE_KEY(OSMHEADER_IDX_OPTIONAL_FEATURES, WT_DATA))
319 : {
320 0 : READ_TEXT(pabyData, pabyDataLimit, pszTxt);
321 : /* printf("OSMHEADER_IDX_OPTIONAL_FEATURES = %s\n", pszTxt); */
322 0 : VSIFree(pszTxt);
323 : }
324 19 : else if (nKey == MAKE_KEY(OSMHEADER_IDX_WRITING_PROGRAM, WT_DATA))
325 : {
326 19 : READ_TEXT(pabyData, pabyDataLimit, pszTxt);
327 : /* printf("OSMHEADER_IDX_WRITING_PROGRAM = %s\n", pszTxt); */
328 19 : VSIFree(pszTxt);
329 : }
330 0 : else if (nKey == MAKE_KEY(OSMHEADER_IDX_SOURCE, WT_DATA))
331 : {
332 0 : READ_TEXT(pabyData, pabyDataLimit, pszTxt);
333 : /* printf("OSMHEADER_IDX_SOURCE = %s\n", pszTxt); */
334 0 : VSIFree(pszTxt);
335 : }
336 : else
337 : {
338 0 : SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, TRUE);
339 : }
340 : }
341 :
342 19 : return pabyData == pabyDataLimit;
343 :
344 : end_error:
345 0 : return FALSE;
346 : }
347 :
348 : /************************************************************************/
349 : /* ReadStringTable() */
350 : /************************************************************************/
351 :
352 : #define READSTRINGTABLE_IDX_STRING 1
353 :
354 : static
355 19 : int ReadStringTable(GByte* pabyData, GByte* pabyDataLimit,
356 : OSMContext* psCtxt)
357 : {
358 19 : char* pszStrBuf = (char*)pabyData;
359 :
360 19 : unsigned int nStrCount = 0;
361 19 : int* panStrOff = psCtxt->panStrOff;
362 :
363 19 : psCtxt->pszStrBuf = pszStrBuf;
364 :
365 19 : if (pabyDataLimit - pabyData > psCtxt->nStrAllocated)
366 : {
367 : int* panStrOffNew;
368 : psCtxt->nStrAllocated = MAX(psCtxt->nStrAllocated * 2,
369 9 : pabyDataLimit - pabyData);
370 : panStrOffNew = (int*) VSIRealloc(
371 9 : panStrOff, psCtxt->nStrAllocated * sizeof(int));
372 9 : if( panStrOffNew == NULL )
373 0 : GOTO_END_ERROR;
374 9 : panStrOff = panStrOffNew;
375 : }
376 :
377 57 : while(pabyData < pabyDataLimit)
378 : {
379 : int nKey;
380 19 : READ_FIELD_KEY(nKey);
381 :
382 437 : while (nKey == MAKE_KEY(READSTRINGTABLE_IDX_STRING, WT_DATA))
383 : {
384 : GByte* pbSaved;
385 : unsigned int nDataLength;
386 418 : READ_SIZE(pabyData, pabyDataLimit, nDataLength);
387 :
388 418 : panStrOff[nStrCount ++] = pabyData - (GByte*)pszStrBuf;
389 418 : pbSaved = &pabyData[nDataLength];
390 :
391 418 : pabyData += nDataLength;
392 :
393 418 : if (pabyData < pabyDataLimit)
394 : {
395 399 : READ_FIELD_KEY(nKey);
396 399 : *pbSaved = 0;
397 : /* printf("string[%d] = %s\n", nStrCount-1, pbSaved - nDataLength); */
398 : }
399 : else
400 : {
401 19 : *pbSaved = 0;
402 : /* printf("string[%d] = %s\n", nStrCount-1, pbSaved - nDataLength); */
403 19 : break;
404 : }
405 : }
406 :
407 19 : if (pabyData < pabyDataLimit)
408 : {
409 0 : SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, TRUE);
410 : }
411 : }
412 :
413 19 : psCtxt->panStrOff = panStrOff;
414 19 : psCtxt->nStrCount = nStrCount;
415 :
416 19 : return pabyData == pabyDataLimit;
417 :
418 : end_error:
419 :
420 0 : psCtxt->panStrOff = panStrOff;
421 0 : psCtxt->nStrCount = nStrCount;
422 :
423 0 : return FALSE;
424 : }
425 :
426 : /************************************************************************/
427 : /* ReadDenseNodes() */
428 : /************************************************************************/
429 :
430 : #define DENSEINFO_IDX_VERSION 1
431 : #define DENSEINFO_IDX_TIMESTAMP 2
432 : #define DENSEINFO_IDX_CHANGESET 3
433 : #define DENSEINFO_IDX_UID 4
434 : #define DENSEINFO_IDX_USER_SID 5
435 : #define DENSEINFO_IDX_VISIBLE 6
436 :
437 : #define DENSENODES_IDX_ID 1
438 : #define DENSENODES_IDX_DENSEINFO 5
439 : #define DENSENODES_IDX_LAT 8
440 : #define DENSENODES_IDX_LON 9
441 : #define DENSENODES_IDX_KEYVALS 10
442 :
443 : static
444 19 : int ReadDenseNodes(GByte* pabyData, GByte* pabyDataLimit,
445 : OSMContext* psCtxt)
446 : {
447 19 : GByte* pabyDataIDs = NULL;
448 19 : GByte* pabyDataIDsLimit = NULL;
449 19 : GByte* pabyDataLat = NULL;
450 19 : GByte* pabyDataLon = NULL;
451 19 : GByte* apabyData[DENSEINFO_IDX_VISIBLE] = {NULL, NULL, NULL, NULL, NULL, NULL};
452 19 : GByte* pabyDataKeyVal = NULL;
453 :
454 : /* printf(">ReadDenseNodes\n"); */
455 133 : while(pabyData < pabyDataLimit)
456 : {
457 : int nKey;
458 95 : READ_FIELD_KEY(nKey);
459 :
460 95 : if( nKey == MAKE_KEY(DENSENODES_IDX_ID, WT_DATA) )
461 : {
462 : unsigned int nSize;
463 :
464 19 : if (pabyDataIDs != NULL)
465 0 : GOTO_END_ERROR;
466 19 : READ_SIZE(pabyData, pabyDataLimit, nSize);
467 :
468 19 : if (nSize > psCtxt->nNodesAllocated)
469 : {
470 : OSMNode* pasNodesNew;
471 : psCtxt->nNodesAllocated = MAX(psCtxt->nNodesAllocated * 2,
472 9 : nSize);
473 : pasNodesNew = (OSMNode*) VSIRealloc(
474 9 : psCtxt->pasNodes, psCtxt->nNodesAllocated * sizeof(OSMNode));
475 9 : if( pasNodesNew == NULL )
476 0 : GOTO_END_ERROR;
477 9 : psCtxt->pasNodes = pasNodesNew;
478 : }
479 :
480 19 : pabyDataIDs = pabyData;
481 19 : pabyDataIDsLimit = pabyData + nSize;
482 19 : pabyData += nSize;
483 : }
484 76 : else if( nKey == MAKE_KEY(DENSENODES_IDX_DENSEINFO, WT_DATA) )
485 : {
486 : unsigned int nSize;
487 : GByte* pabyDataNewLimit;
488 :
489 19 : READ_SIZE(pabyData, pabyDataLimit, nSize);
490 :
491 : /* Inline reading of DenseInfo structure */
492 :
493 19 : pabyDataNewLimit = pabyData + nSize;
494 133 : while(pabyData < pabyDataNewLimit)
495 : {
496 : int nFieldNumber;
497 95 : READ_FIELD_KEY(nKey);
498 :
499 95 : nFieldNumber = GET_FIELDNUMBER(nKey);
500 190 : if (GET_WIRETYPE(nKey) == WT_DATA &&
501 : nFieldNumber >= DENSEINFO_IDX_VERSION && nFieldNumber <= DENSEINFO_IDX_VISIBLE)
502 : {
503 95 : if( apabyData[nFieldNumber - 1] != NULL) GOTO_END_ERROR;
504 95 : READ_SIZE(pabyData, pabyDataNewLimit, nSize);
505 :
506 95 : apabyData[nFieldNumber - 1] = pabyData;
507 95 : pabyData += nSize;
508 : }
509 : else
510 : {
511 0 : SKIP_UNKNOWN_FIELD(pabyData, pabyDataNewLimit, TRUE);
512 : }
513 : }
514 :
515 19 : if( pabyData != pabyDataNewLimit )
516 0 : GOTO_END_ERROR;
517 : }
518 57 : else if( nKey == MAKE_KEY(DENSENODES_IDX_LAT, WT_DATA) )
519 : {
520 : unsigned int nSize;
521 19 : if (pabyDataLat != NULL)
522 0 : GOTO_END_ERROR;
523 19 : READ_SIZE(pabyData, pabyDataLimit, nSize);
524 19 : pabyDataLat = pabyData;
525 19 : pabyData += nSize;
526 : }
527 38 : else if( nKey == MAKE_KEY(DENSENODES_IDX_LON, WT_DATA) )
528 : {
529 : unsigned int nSize;
530 19 : if (pabyDataLon != NULL)
531 0 : GOTO_END_ERROR;
532 19 : READ_SIZE(pabyData, pabyDataLimit, nSize);
533 19 : pabyDataLon = pabyData;
534 19 : pabyData += nSize;
535 : }
536 19 : else if( nKey == MAKE_KEY(DENSENODES_IDX_KEYVALS, WT_DATA) )
537 : {
538 : unsigned int nSize;
539 19 : if( pabyDataKeyVal != NULL )
540 0 : GOTO_END_ERROR;
541 19 : READ_SIZE(pabyData, pabyDataLimit, nSize);
542 :
543 19 : pabyDataKeyVal = pabyData;
544 :
545 19 : if (nSize > psCtxt->nTagsAllocated)
546 : {
547 : OSMTag* pasTagsNew;
548 :
549 : psCtxt->nTagsAllocated = MAX(
550 9 : psCtxt->nTagsAllocated * 2, nSize);
551 : pasTagsNew = (OSMTag*) VSIRealloc(
552 : psCtxt->pasTags,
553 9 : psCtxt->nTagsAllocated * sizeof(OSMTag));
554 9 : if( pasTagsNew == NULL )
555 0 : GOTO_END_ERROR;
556 9 : psCtxt->pasTags = pasTagsNew;
557 : }
558 :
559 19 : pabyData += nSize;
560 : }
561 : else
562 : {
563 0 : SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, TRUE);
564 : }
565 : }
566 :
567 19 : if( pabyData != pabyDataLimit )
568 0 : GOTO_END_ERROR;
569 :
570 19 : if( pabyDataIDs != NULL && pabyDataLat != NULL && pabyDataLon != NULL )
571 : {
572 19 : GByte* pabyDataVersion = apabyData[DENSEINFO_IDX_VERSION - 1];
573 19 : GByte* pabyDataTimeStamp = apabyData[DENSEINFO_IDX_TIMESTAMP - 1];
574 19 : GByte* pabyDataChangeset = apabyData[DENSEINFO_IDX_CHANGESET - 1];
575 19 : GByte* pabyDataUID = apabyData[DENSEINFO_IDX_UID - 1];
576 19 : GByte* pabyDataUserSID = apabyData[DENSEINFO_IDX_USER_SID - 1];
577 : /* GByte* pabyDataVisible = apabyData[DENSEINFO_IDX_VISIBLE - 1]; */
578 :
579 19 : GIntBig nID = 0;
580 19 : GIntBig nLat = 0;
581 19 : GIntBig nLon = 0;
582 19 : GIntBig nTimeStamp = 0;
583 19 : GIntBig nChangeset = 0;
584 19 : int nUID = 0;
585 19 : unsigned int nUserSID = 0;
586 19 : int nTags = 0;
587 19 : int nNodes = 0;
588 :
589 19 : const char* pszStrBuf = psCtxt->pszStrBuf;
590 19 : int* panStrOff = psCtxt->panStrOff;
591 19 : const unsigned int nStrCount = psCtxt->nStrCount;
592 19 : OSMTag* pasTags = psCtxt->pasTags;
593 19 : OSMNode* pasNodes = psCtxt->pasNodes;
594 :
595 19 : int nVersion = 0;
596 : /* int nVisible = 1; */
597 :
598 209 : while(pabyDataIDs < pabyDataIDsLimit)
599 : {
600 : GIntBig nDelta1, nDelta2;
601 171 : int nKVIndexStart = nTags;
602 :
603 171 : READ_VARSINT64_NOCHECK(pabyDataIDs, pabyDataIDsLimit, nDelta1);
604 171 : READ_VARSINT64(pabyDataLat, pabyDataLimit, nDelta2);
605 171 : nID += nDelta1;
606 171 : nLat += nDelta2;
607 :
608 171 : READ_VARSINT64(pabyDataLon, pabyDataLimit, nDelta1);
609 171 : nLon += nDelta1;
610 :
611 171 : if( pabyDataTimeStamp )
612 : {
613 171 : READ_VARSINT64(pabyDataTimeStamp, pabyDataLimit, nDelta2);
614 171 : nTimeStamp += nDelta2;
615 : }
616 171 : if( pabyDataChangeset )
617 : {
618 171 : READ_VARSINT64(pabyDataChangeset, pabyDataLimit, nDelta1);
619 171 : nChangeset += nDelta1;
620 : }
621 171 : if( pabyDataVersion )
622 : {
623 171 : READ_VARINT32(pabyDataVersion, pabyDataLimit, nVersion);
624 : }
625 171 : if( pabyDataUID )
626 : {
627 : int nDeltaUID;
628 171 : READ_VARSINT32(pabyDataUID, pabyDataLimit, nDeltaUID);
629 171 : nUID += nDeltaUID;
630 : }
631 171 : if( pabyDataUserSID )
632 : {
633 : int nDeltaUserSID;
634 171 : READ_VARSINT32(pabyDataUserSID, pabyDataLimit, nDeltaUserSID);
635 171 : nUserSID += nDeltaUserSID;
636 171 : if (nUserSID >= nStrCount)
637 0 : GOTO_END_ERROR;
638 : }
639 : /* if( pabyDataVisible )
640 : READ_VARINT32(pabyDataVisible, pabyDataLimit, nVisible); */
641 :
642 171 : if( pabyDataKeyVal )
643 : {
644 19 : while (TRUE)
645 : {
646 : unsigned int nKey, nVal;
647 190 : READ_VARUINT32(pabyDataKeyVal, pabyDataLimit, nKey);
648 190 : if (nKey == 0)
649 171 : break;
650 19 : if (nKey >= nStrCount)
651 0 : GOTO_END_ERROR;
652 :
653 19 : READ_VARUINT32(pabyDataKeyVal, pabyDataLimit, nVal);
654 19 : if (nVal >= nStrCount)
655 0 : GOTO_END_ERROR;
656 :
657 19 : pasTags[nTags].pszK = pszStrBuf + panStrOff[nKey];
658 19 : pasTags[nTags].pszV = pszStrBuf + panStrOff[nVal];
659 19 : nTags ++;
660 :
661 : /* printf("nKey = %d, nVal = %d\n", nKey, nVal); */
662 : }
663 : }
664 :
665 171 : if( nTags > nKVIndexStart )
666 19 : pasNodes[nNodes].pasTags = pasTags + nKVIndexStart;
667 : else
668 152 : pasNodes[nNodes].pasTags = NULL;
669 171 : pasNodes[nNodes].nTags = nTags - nKVIndexStart;
670 :
671 171 : pasNodes[nNodes].nID = nID;
672 171 : pasNodes[nNodes].dfLat = .000000001 * (psCtxt->nLatOffset + (psCtxt->nGranularity * nLat));
673 171 : pasNodes[nNodes].dfLon = .000000001 * (psCtxt->nLonOffset + (psCtxt->nGranularity * nLon));
674 171 : pasNodes[nNodes].sInfo.bTimeStampIsStr = FALSE;
675 171 : pasNodes[nNodes].sInfo.ts.nTimeStamp = nTimeStamp;
676 171 : pasNodes[nNodes].sInfo.nChangeset = nChangeset;
677 171 : pasNodes[nNodes].sInfo.nVersion = nVersion;
678 171 : pasNodes[nNodes].sInfo.nUID = nUID;
679 171 : pasNodes[nNodes].sInfo.pszUserSID = pszStrBuf + panStrOff[nUserSID];
680 : /* pasNodes[nNodes].sInfo.nVisible = nVisible; */
681 171 : nNodes ++;
682 : /* printf("nLat = " CPL_FRMT_GIB "\n", nLat); printf("nLon = " CPL_FRMT_GIB "\n", nLon); */
683 : }
684 :
685 19 : psCtxt->pfnNotifyNodes(nNodes, pasNodes, psCtxt, psCtxt->user_data);
686 :
687 19 : if(pabyDataIDs != pabyDataIDsLimit)
688 0 : GOTO_END_ERROR;
689 : }
690 :
691 : /* printf("<ReadDenseNodes\n"); */
692 :
693 19 : return TRUE;
694 :
695 : end_error:
696 : /* printf("<ReadDenseNodes\n"); */
697 :
698 0 : return FALSE;
699 : }
700 :
701 : /************************************************************************/
702 : /* ReadOSMInfo() */
703 : /************************************************************************/
704 :
705 : #define INFO_IDX_VERSION 1
706 : #define INFO_IDX_TIMESTAMP 2
707 : #define INFO_IDX_CHANGESET 3
708 : #define INFO_IDX_UID 4
709 : #define INFO_IDX_USER_SID 5
710 : #define INFO_IDX_VISIBLE 6
711 :
712 : static
713 : int ReadOSMInfo(GByte* pabyData, GByte* pabyDataLimit,
714 : OSMInfo* psInfo, OSMContext* psContext) CPL_NO_INLINE;
715 :
716 : static
717 247 : int ReadOSMInfo(GByte* pabyData, GByte* pabyDataLimit,
718 : OSMInfo* psInfo, OSMContext* psContext)
719 : {
720 : /* printf(">ReadOSMInfo\n"); */
721 1729 : while(pabyData < pabyDataLimit)
722 : {
723 : int nKey;
724 1235 : READ_FIELD_KEY(nKey);
725 :
726 1235 : if (nKey == MAKE_KEY(INFO_IDX_VERSION, WT_VARINT))
727 : {
728 247 : READ_VARINT32(pabyData, pabyDataLimit, psInfo->nVersion);
729 : }
730 988 : else if (nKey == MAKE_KEY(INFO_IDX_TIMESTAMP, WT_VARINT))
731 : {
732 247 : READ_VARINT64(pabyData, pabyDataLimit, psInfo->ts.nTimeStamp);
733 : }
734 741 : else if (nKey == MAKE_KEY(INFO_IDX_CHANGESET, WT_VARINT))
735 : {
736 247 : READ_VARINT64(pabyData, pabyDataLimit, psInfo->nChangeset);
737 : }
738 494 : else if (nKey == MAKE_KEY(INFO_IDX_UID, WT_VARINT))
739 : {
740 247 : READ_VARINT32(pabyData, pabyDataLimit, psInfo->nUID);
741 : }
742 247 : else if (nKey == MAKE_KEY(INFO_IDX_USER_SID, WT_VARINT))
743 : {
744 : unsigned int nUserSID;
745 247 : READ_VARUINT32(pabyData, pabyDataLimit, nUserSID);
746 247 : if( nUserSID < psContext->nStrCount)
747 : psInfo->pszUserSID = psContext->pszStrBuf +
748 247 : psContext->panStrOff[nUserSID];
749 : }
750 0 : else if (nKey == MAKE_KEY(INFO_IDX_VISIBLE, WT_VARINT))
751 : {
752 : int nVisible;
753 0 : READ_VARINT32(pabyData, pabyDataLimit, /*psInfo->*/nVisible);
754 : }
755 : else
756 : {
757 0 : SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, TRUE);
758 : }
759 : }
760 : /* printf("<ReadOSMInfo\n"); */
761 :
762 247 : return pabyData == pabyDataLimit;
763 :
764 : end_error:
765 : /* printf("<ReadOSMInfo\n"); */
766 :
767 0 : return FALSE;
768 : }
769 :
770 : /************************************************************************/
771 : /* ReadNode() */
772 : /************************************************************************/
773 :
774 : #define NODE_IDX_ID 1
775 : #define NODE_IDX_LAT 7
776 : #define NODE_IDX_LON 8
777 : #define NODE_IDX_KEYS 9
778 : #define NODE_IDX_VALS 10
779 : #define NODE_IDX_INFO 11
780 :
781 : static
782 0 : int ReadNode(GByte* pabyData, GByte* pabyDataLimit,
783 : OSMContext* psCtxt)
784 : {
785 : OSMNode sNode;
786 :
787 0 : sNode.nID = 0;
788 0 : INIT_INFO(sNode.sInfo);
789 :
790 : /* printf(">ReadNode\n"); */
791 0 : while(pabyData < pabyDataLimit)
792 : {
793 : int nKey;
794 0 : READ_FIELD_KEY(nKey);
795 :
796 0 : if (nKey == MAKE_KEY(NODE_IDX_ID, WT_VARINT))
797 : {
798 0 : READ_VARSINT64_NOCHECK(pabyData, pabyDataLimit, sNode.nID);
799 : }
800 0 : else if (nKey == MAKE_KEY(NODE_IDX_LAT, WT_VARINT))
801 : {
802 : GIntBig nLat;
803 0 : READ_VARSINT64_NOCHECK(pabyData, pabyDataLimit, nLat);
804 0 : sNode.dfLat = .000000001 * (psCtxt->nLatOffset + (psCtxt->nGranularity * nLat));
805 : }
806 0 : else if (nKey == MAKE_KEY(NODE_IDX_LON, WT_VARINT))
807 : {
808 : GIntBig nLon;
809 0 : READ_VARSINT64_NOCHECK(pabyData, pabyDataLimit, nLon);
810 0 : sNode.dfLon = .000000001 * (psCtxt->nLonOffset + (psCtxt->nGranularity * nLon));
811 : }
812 0 : else if (nKey == MAKE_KEY(NODE_IDX_KEYS, WT_DATA))
813 : {
814 : unsigned int nSize;
815 : GByte* pabyDataNewLimit;
816 0 : if (sNode.nTags != 0)
817 0 : GOTO_END_ERROR;
818 0 : READ_SIZE(pabyData, pabyDataLimit, nSize);
819 :
820 0 : if (nSize > psCtxt->nTagsAllocated)
821 : {
822 : OSMTag* pasTagsNew;
823 :
824 : psCtxt->nTagsAllocated = MAX(
825 0 : psCtxt->nTagsAllocated * 2, nSize);
826 : pasTagsNew = (OSMTag*) VSIRealloc(
827 : psCtxt->pasTags,
828 0 : psCtxt->nTagsAllocated * sizeof(OSMTag));
829 0 : if( pasTagsNew == NULL )
830 0 : GOTO_END_ERROR;
831 0 : psCtxt->pasTags = pasTagsNew;
832 : }
833 :
834 0 : pabyDataNewLimit = pabyData + nSize;
835 0 : while (pabyData < pabyDataNewLimit)
836 : {
837 : unsigned int nKey;
838 0 : READ_VARUINT32(pabyData, pabyDataNewLimit, nKey);
839 :
840 0 : if (nKey >= psCtxt->nStrCount)
841 0 : GOTO_END_ERROR;
842 :
843 0 : psCtxt->pasTags[sNode.nTags].pszK = psCtxt->pszStrBuf +
844 0 : psCtxt->panStrOff[nKey];
845 0 : psCtxt->pasTags[sNode.nTags].pszV = NULL;
846 0 : sNode.nTags ++;
847 : }
848 0 : if (pabyData != pabyDataNewLimit)
849 0 : GOTO_END_ERROR;
850 : }
851 0 : else if (nKey == MAKE_KEY(NODE_IDX_VALS, WT_DATA))
852 : {
853 : unsigned int nSize;
854 0 : unsigned int nIter = 0;
855 0 : if (sNode.nTags == 0)
856 0 : GOTO_END_ERROR;
857 0 : READ_VARUINT32(pabyData, pabyDataLimit, nSize);
858 :
859 0 : for(; nIter < sNode.nTags; nIter ++)
860 : {
861 : unsigned int nVal;
862 0 : READ_VARUINT32(pabyData, pabyDataLimit, nVal);
863 :
864 0 : if (nVal >= psCtxt->nStrCount)
865 0 : GOTO_END_ERROR;
866 :
867 0 : psCtxt->pasTags[nIter].pszV = psCtxt->pszStrBuf +
868 0 : psCtxt->panStrOff[nVal];
869 : }
870 : }
871 0 : else if (nKey == MAKE_KEY(NODE_IDX_INFO, WT_DATA))
872 : {
873 : unsigned int nSize;
874 0 : READ_SIZE(pabyData, pabyDataLimit, nSize);
875 :
876 0 : if (!ReadOSMInfo(pabyData, pabyDataLimit + nSize, &sNode.sInfo, psCtxt))
877 0 : GOTO_END_ERROR;
878 :
879 0 : pabyData += nSize;
880 : }
881 : else
882 : {
883 0 : SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, TRUE);
884 : }
885 : }
886 :
887 0 : if( pabyData != pabyDataLimit )
888 0 : GOTO_END_ERROR;
889 :
890 0 : if (sNode.nTags)
891 0 : sNode.pasTags = psCtxt->pasTags;
892 : else
893 0 : sNode.pasTags = NULL;
894 0 : psCtxt->pfnNotifyNodes(1, &sNode, psCtxt, psCtxt->user_data);
895 :
896 : /* printf("<ReadNode\n"); */
897 :
898 0 : return TRUE;
899 :
900 : end_error:
901 : /* printf("<ReadNode\n"); */
902 :
903 0 : return FALSE;
904 : }
905 :
906 :
907 : /************************************************************************/
908 : /* ReadWay() */
909 : /************************************************************************/
910 :
911 : #define WAY_IDX_ID 1
912 : #define WAY_IDX_KEYS 2
913 : #define WAY_IDX_VALS 3
914 : #define WAY_IDX_INFO 4
915 : #define WAY_IDX_REFS 8
916 :
917 : static
918 152 : int ReadWay(GByte* pabyData, GByte* pabyDataLimit,
919 : OSMContext* psCtxt)
920 : {
921 : OSMWay sWay;
922 152 : sWay.nID = 0;
923 152 : INIT_INFO(sWay.sInfo);
924 152 : sWay.nTags = 0;
925 152 : sWay.nRefs = 0;
926 :
927 : /* printf(">ReadWay\n"); */
928 1026 : while(pabyData < pabyDataLimit)
929 : {
930 : int nKey;
931 722 : READ_FIELD_KEY(nKey);
932 :
933 722 : if (nKey == MAKE_KEY(WAY_IDX_ID, WT_VARINT))
934 : {
935 152 : READ_VARINT64(pabyData, pabyDataLimit, sWay.nID);
936 : }
937 570 : else if (nKey == MAKE_KEY(WAY_IDX_KEYS, WT_DATA))
938 : {
939 : unsigned int nSize;
940 : GByte* pabyDataNewLimit;
941 133 : if (sWay.nTags != 0)
942 0 : GOTO_END_ERROR;
943 133 : READ_SIZE(pabyData, pabyDataLimit, nSize);
944 :
945 133 : if (nSize > psCtxt->nTagsAllocated)
946 : {
947 : OSMTag* pasTagsNew;
948 :
949 : psCtxt->nTagsAllocated = MAX(
950 0 : psCtxt->nTagsAllocated * 2, nSize);
951 : pasTagsNew = (OSMTag*) VSIRealloc(
952 : psCtxt->pasTags,
953 0 : psCtxt->nTagsAllocated * sizeof(OSMTag));
954 0 : if( pasTagsNew == NULL )
955 0 : GOTO_END_ERROR;
956 0 : psCtxt->pasTags = pasTagsNew;
957 : }
958 :
959 133 : pabyDataNewLimit = pabyData + nSize;
960 437 : while (pabyData < pabyDataNewLimit)
961 : {
962 : unsigned int nKey;
963 171 : READ_VARUINT32(pabyData, pabyDataNewLimit, nKey);
964 :
965 171 : if (nKey >= psCtxt->nStrCount)
966 0 : GOTO_END_ERROR;
967 :
968 171 : psCtxt->pasTags[sWay.nTags].pszK = psCtxt->pszStrBuf +
969 171 : psCtxt->panStrOff[nKey];
970 171 : psCtxt->pasTags[sWay.nTags].pszV = NULL;
971 171 : sWay.nTags ++;
972 : }
973 133 : if (pabyData != pabyDataNewLimit)
974 0 : GOTO_END_ERROR;
975 : }
976 437 : else if (nKey == MAKE_KEY(WAY_IDX_VALS, WT_DATA))
977 : {
978 : unsigned int nSize;
979 133 : unsigned int nIter = 0;
980 133 : if (sWay.nTags == 0)
981 0 : GOTO_END_ERROR;
982 133 : READ_VARUINT32(pabyData, pabyDataLimit, nSize);
983 :
984 304 : for(; nIter < sWay.nTags; nIter ++)
985 : {
986 : unsigned int nVal;
987 171 : READ_VARUINT32(pabyData, pabyDataLimit, nVal);
988 :
989 171 : if (nVal >= psCtxt->nStrCount)
990 0 : GOTO_END_ERROR;
991 :
992 171 : psCtxt->pasTags[nIter].pszV = psCtxt->pszStrBuf +
993 171 : psCtxt->panStrOff[nVal];
994 : }
995 : }
996 304 : else if (nKey == MAKE_KEY(WAY_IDX_INFO, WT_DATA))
997 : {
998 : unsigned int nSize;
999 152 : READ_SIZE(pabyData, pabyDataLimit, nSize);
1000 :
1001 152 : if (!ReadOSMInfo(pabyData, pabyData + nSize, &sWay.sInfo, psCtxt))
1002 0 : GOTO_END_ERROR;
1003 :
1004 152 : pabyData += nSize;
1005 : }
1006 152 : else if (nKey == MAKE_KEY(WAY_IDX_REFS, WT_DATA))
1007 : {
1008 152 : GIntBig nRefVal = 0;
1009 : unsigned int nSize;
1010 : GByte* pabyDataNewLimit;
1011 152 : if (sWay.nRefs != 0)
1012 0 : GOTO_END_ERROR;
1013 152 : READ_SIZE(pabyData, pabyDataLimit, nSize);
1014 :
1015 152 : if (nSize > psCtxt->nNodeRefsAllocated)
1016 : {
1017 : GIntBig* panNodeRefsNew;
1018 : psCtxt->nNodeRefsAllocated =
1019 27 : MAX(psCtxt->nNodeRefsAllocated * 2, nSize);
1020 : panNodeRefsNew = (GIntBig*) VSIRealloc(
1021 : psCtxt->panNodeRefs,
1022 27 : psCtxt->nNodeRefsAllocated * sizeof(GIntBig));
1023 27 : if( panNodeRefsNew == NULL )
1024 0 : GOTO_END_ERROR;
1025 27 : psCtxt->panNodeRefs = panNodeRefsNew;
1026 : }
1027 :
1028 152 : pabyDataNewLimit = pabyData + nSize;
1029 874 : while (pabyData < pabyDataNewLimit)
1030 : {
1031 : GIntBig nDeltaRef;
1032 570 : READ_VARSINT64_NOCHECK(pabyData, pabyDataNewLimit, nDeltaRef);
1033 570 : nRefVal += nDeltaRef;
1034 :
1035 570 : psCtxt->panNodeRefs[sWay.nRefs ++] = nRefVal;
1036 : }
1037 :
1038 152 : if (pabyData != pabyDataNewLimit)
1039 0 : GOTO_END_ERROR;
1040 : }
1041 : else
1042 : {
1043 0 : SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, TRUE);
1044 : }
1045 : }
1046 :
1047 152 : if( pabyData != pabyDataLimit )
1048 0 : GOTO_END_ERROR;
1049 :
1050 : /* printf("<ReadWay\n"); */
1051 :
1052 152 : if (sWay.nTags)
1053 133 : sWay.pasTags = psCtxt->pasTags;
1054 : else
1055 19 : sWay.pasTags = NULL;
1056 152 : sWay.panNodeRefs = psCtxt->panNodeRefs;
1057 :
1058 152 : psCtxt->pfnNotifyWay(&sWay, psCtxt, psCtxt->user_data);
1059 :
1060 152 : return TRUE;
1061 :
1062 : end_error:
1063 : /* printf("<ReadWay\n"); */
1064 :
1065 0 : return FALSE;
1066 : }
1067 :
1068 : /************************************************************************/
1069 : /* ReadRelation() */
1070 : /************************************************************************/
1071 :
1072 : #define RELATION_IDX_ID 1
1073 : #define RELATION_IDX_KEYS 2
1074 : #define RELATION_IDX_VALS 3
1075 : #define RELATION_IDX_INFO 4
1076 : #define RELATION_IDX_ROLES_SID 8
1077 : #define RELATION_IDX_MEMIDS 9
1078 : #define RELATION_IDX_TYPES 10
1079 :
1080 : static
1081 95 : int ReadRelation(GByte* pabyData, GByte* pabyDataLimit,
1082 : OSMContext* psCtxt)
1083 : {
1084 : OSMRelation sRelation;
1085 95 : sRelation.nID = 0;
1086 95 : INIT_INFO(sRelation.sInfo);
1087 95 : sRelation.nTags = 0;
1088 95 : sRelation.nMembers = 0;
1089 :
1090 : /* printf(">ReadRelation\n"); */
1091 855 : while(pabyData < pabyDataLimit)
1092 : {
1093 : int nKey;
1094 665 : READ_FIELD_KEY(nKey);
1095 :
1096 665 : if (nKey == MAKE_KEY(RELATION_IDX_ID, WT_VARINT))
1097 : {
1098 95 : READ_VARINT64(pabyData, pabyDataLimit, sRelation.nID);
1099 : }
1100 570 : else if (nKey == MAKE_KEY(RELATION_IDX_KEYS, WT_DATA))
1101 : {
1102 : unsigned int nSize;
1103 : GByte* pabyDataNewLimit;
1104 95 : if (sRelation.nTags != 0)
1105 0 : GOTO_END_ERROR;
1106 95 : READ_SIZE(pabyData, pabyDataLimit, nSize);
1107 :
1108 95 : if (nSize > psCtxt->nTagsAllocated)
1109 : {
1110 : OSMTag* pasTagsNew;
1111 :
1112 : psCtxt->nTagsAllocated = MAX(
1113 0 : psCtxt->nTagsAllocated * 2, nSize);
1114 : pasTagsNew = (OSMTag*) VSIRealloc(
1115 : psCtxt->pasTags,
1116 0 : psCtxt->nTagsAllocated * sizeof(OSMTag));
1117 0 : if( pasTagsNew == NULL )
1118 0 : GOTO_END_ERROR;
1119 0 : psCtxt->pasTags = pasTagsNew;
1120 : }
1121 :
1122 95 : pabyDataNewLimit = pabyData + nSize;
1123 304 : while (pabyData < pabyDataNewLimit)
1124 : {
1125 : unsigned int nKey;
1126 114 : READ_VARUINT32(pabyData, pabyDataNewLimit, nKey);
1127 :
1128 114 : if (nKey >= psCtxt->nStrCount)
1129 0 : GOTO_END_ERROR;
1130 :
1131 114 : psCtxt->pasTags[sRelation.nTags].pszK = psCtxt->pszStrBuf +
1132 114 : psCtxt->panStrOff[nKey];
1133 114 : psCtxt->pasTags[sRelation.nTags].pszV = NULL;
1134 114 : sRelation.nTags ++;
1135 : }
1136 95 : if (pabyData != pabyDataNewLimit)
1137 0 : GOTO_END_ERROR;
1138 : }
1139 475 : else if (nKey == MAKE_KEY(RELATION_IDX_VALS, WT_DATA))
1140 : {
1141 : unsigned int nSize;
1142 95 : unsigned int nIter = 0;
1143 95 : if (sRelation.nTags == 0)
1144 0 : GOTO_END_ERROR;
1145 95 : READ_VARUINT32(pabyData, pabyDataLimit, nSize);
1146 :
1147 209 : for(; nIter < sRelation.nTags; nIter ++)
1148 : {
1149 : unsigned int nVal;
1150 114 : READ_VARUINT32(pabyData, pabyDataLimit, nVal);
1151 :
1152 114 : if (nVal >= psCtxt->nStrCount)
1153 0 : GOTO_END_ERROR;
1154 :
1155 114 : psCtxt->pasTags[nIter].pszV = psCtxt->pszStrBuf +
1156 114 : psCtxt->panStrOff[nVal];
1157 : }
1158 : }
1159 380 : else if (nKey == MAKE_KEY(RELATION_IDX_INFO, WT_DATA))
1160 : {
1161 : unsigned int nSize;
1162 95 : READ_SIZE(pabyData, pabyDataLimit, nSize);
1163 :
1164 95 : if (!ReadOSMInfo(pabyData, pabyData + nSize, &sRelation.sInfo, psCtxt))
1165 0 : GOTO_END_ERROR;
1166 :
1167 95 : pabyData += nSize;
1168 : }
1169 285 : else if (nKey == MAKE_KEY(RELATION_IDX_ROLES_SID, WT_DATA))
1170 : {
1171 : unsigned int nSize;
1172 : GByte* pabyDataNewLimit;
1173 95 : if (sRelation.nMembers != 0)
1174 0 : GOTO_END_ERROR;
1175 95 : READ_SIZE(pabyData, pabyDataLimit, nSize);
1176 :
1177 95 : if (nSize > psCtxt->nMembersAllocated)
1178 : {
1179 : OSMMember* pasMembersNew;
1180 : psCtxt->nMembersAllocated =
1181 9 : MAX(psCtxt->nMembersAllocated * 2, nSize);
1182 : pasMembersNew = (OSMMember*) VSIRealloc(
1183 : psCtxt->pasMembers,
1184 9 : psCtxt->nMembersAllocated * sizeof(OSMMember));
1185 9 : if( pasMembersNew == NULL )
1186 0 : GOTO_END_ERROR;
1187 9 : psCtxt->pasMembers = pasMembersNew;
1188 : }
1189 :
1190 95 : pabyDataNewLimit = pabyData + nSize;
1191 361 : while (pabyData < pabyDataNewLimit)
1192 : {
1193 : unsigned int nRoleSID;
1194 171 : READ_VARUINT32(pabyData, pabyDataNewLimit, nRoleSID);
1195 171 : if (nRoleSID >= psCtxt->nStrCount)
1196 0 : GOTO_END_ERROR;
1197 :
1198 171 : psCtxt->pasMembers[sRelation.nMembers].pszRole =
1199 171 : psCtxt->pszStrBuf + psCtxt->panStrOff[nRoleSID];
1200 171 : psCtxt->pasMembers[sRelation.nMembers].nID = 0;
1201 171 : psCtxt->pasMembers[sRelation.nMembers].eType = MEMBER_NODE;
1202 171 : sRelation.nMembers ++;
1203 : }
1204 :
1205 95 : if (pabyData != pabyDataNewLimit)
1206 0 : GOTO_END_ERROR;
1207 : }
1208 190 : else if (nKey == MAKE_KEY(RELATION_IDX_MEMIDS, WT_DATA))
1209 : {
1210 95 : unsigned int nIter = 0;
1211 95 : GIntBig nMemID = 0;
1212 : unsigned int nSize;
1213 95 : if (sRelation.nMembers == 0)
1214 0 : GOTO_END_ERROR;
1215 95 : READ_VARUINT32(pabyData, pabyDataLimit, nSize);
1216 :
1217 266 : for(; nIter < sRelation.nMembers; nIter++)
1218 : {
1219 : GIntBig nDeltaMemID;
1220 171 : READ_VARSINT64(pabyData, pabyDataLimit, nDeltaMemID);
1221 171 : nMemID += nDeltaMemID;
1222 :
1223 171 : psCtxt->pasMembers[nIter].nID = nMemID;
1224 : }
1225 : }
1226 95 : else if (nKey == MAKE_KEY(RELATION_IDX_TYPES, WT_DATA))
1227 : {
1228 95 : unsigned int nIter = 0;
1229 : unsigned int nSize;
1230 95 : if (sRelation.nMembers == 0)
1231 0 : GOTO_END_ERROR;
1232 95 : READ_SIZE(pabyData, pabyDataLimit, nSize);
1233 95 : if (nSize != sRelation.nMembers)
1234 0 : GOTO_END_ERROR;
1235 :
1236 266 : for(; nIter < sRelation.nMembers; nIter++)
1237 : {
1238 171 : unsigned int nType = pabyData[nIter];
1239 171 : if (nType > MEMBER_RELATION)
1240 0 : GOTO_END_ERROR;
1241 :
1242 171 : psCtxt->pasMembers[nIter].eType = (OSMMemberType) nType;
1243 : }
1244 95 : pabyData += nSize;
1245 : }
1246 : else
1247 : {
1248 0 : SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, TRUE);
1249 : }
1250 : }
1251 : /* printf("<ReadRelation\n"); */
1252 :
1253 95 : if( pabyData != pabyDataLimit )
1254 0 : GOTO_END_ERROR;
1255 :
1256 95 : if (sRelation.nTags)
1257 95 : sRelation.pasTags = psCtxt->pasTags;
1258 : else
1259 0 : sRelation.pasTags = NULL;
1260 :
1261 95 : sRelation.pasMembers = psCtxt->pasMembers;
1262 :
1263 95 : psCtxt->pfnNotifyRelation(&sRelation, psCtxt, psCtxt->user_data);
1264 :
1265 95 : return TRUE;
1266 :
1267 : end_error:
1268 : /* printf("<ReadRelation\n"); */
1269 :
1270 0 : return FALSE;
1271 : }
1272 :
1273 : /************************************************************************/
1274 : /* ReadPrimitiveGroup() */
1275 : /************************************************************************/
1276 :
1277 : #define PRIMITIVEGROUP_IDX_NODES 1
1278 : #define PRIMITIVEGROUP_IDX_DENSE 2
1279 : #define PRIMITIVEGROUP_IDX_WAYS 3
1280 : #define PRIMITIVEGROUP_IDX_RELATIONS 4
1281 : #define PRIMITIVEGROUP_IDX_CHANGESETS 5
1282 :
1283 : typedef int (*PrimitiveFuncType)(GByte* pabyData, GByte* pabyDataLimit,
1284 : OSMContext* psCtxt);
1285 :
1286 : static const PrimitiveFuncType apfnPrimitives[] =
1287 : {
1288 : ReadNode,
1289 : ReadDenseNodes,
1290 : ReadWay,
1291 : ReadRelation
1292 : };
1293 :
1294 : static
1295 57 : int ReadPrimitiveGroup(GByte* pabyData, GByte* pabyDataLimit,
1296 : OSMContext* psCtxt)
1297 : {
1298 : /* printf(">ReadPrimitiveGroup\n"); */
1299 380 : while(pabyData < pabyDataLimit)
1300 : {
1301 : int nKey;
1302 : int nFieldNumber;
1303 266 : READ_FIELD_KEY(nKey);
1304 :
1305 266 : nFieldNumber = GET_FIELDNUMBER(nKey) - 1;
1306 532 : if( GET_WIRETYPE(nKey) == WT_DATA &&
1307 : nFieldNumber >= PRIMITIVEGROUP_IDX_NODES - 1 &&
1308 : nFieldNumber <= PRIMITIVEGROUP_IDX_RELATIONS - 1 )
1309 : {
1310 : unsigned int nSize;
1311 266 : READ_SIZE(pabyData, pabyDataLimit, nSize);
1312 :
1313 266 : if (!apfnPrimitives[nFieldNumber](pabyData, pabyData + nSize, psCtxt))
1314 0 : GOTO_END_ERROR;
1315 :
1316 266 : pabyData += nSize;
1317 : }
1318 : else
1319 : {
1320 0 : SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, TRUE);
1321 : }
1322 : }
1323 : /* printf("<ReadPrimitiveGroup\n"); */
1324 :
1325 57 : return pabyData == pabyDataLimit;
1326 :
1327 : end_error:
1328 : /* printf("<ReadPrimitiveGroup\n"); */
1329 :
1330 0 : return FALSE;
1331 : }
1332 :
1333 : /************************************************************************/
1334 : /* ReadPrimitiveBlock() */
1335 : /************************************************************************/
1336 :
1337 : #define PRIMITIVEBLOCK_IDX_STRINGTABLE 1
1338 : #define PRIMITIVEBLOCK_IDX_PRIMITIVEGROUP 2
1339 : #define PRIMITIVEBLOCK_IDX_GRANULARITY 17
1340 : #define PRIMITIVEBLOCK_IDX_DATE_GRANULARITY 18
1341 : #define PRIMITIVEBLOCK_IDX_LAT_OFFSET 19
1342 : #define PRIMITIVEBLOCK_IDX_LON_OFFSET 20
1343 :
1344 : static
1345 19 : int ReadPrimitiveBlock(GByte* pabyData, GByte* pabyDataLimit,
1346 : OSMContext* psCtxt)
1347 : {
1348 19 : GByte* pabyDataSave = pabyData;
1349 :
1350 19 : psCtxt->pszStrBuf = NULL;
1351 19 : psCtxt->nStrCount = 0;
1352 19 : psCtxt->nGranularity = 100;
1353 19 : psCtxt->nDateGranularity = 1000;
1354 19 : psCtxt->nLatOffset = 0;
1355 19 : psCtxt->nLonOffset = 0;
1356 :
1357 152 : while(pabyData < pabyDataLimit)
1358 : {
1359 : int nKey;
1360 114 : READ_FIELD_KEY(nKey);
1361 :
1362 114 : if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_GRANULARITY, WT_VARINT))
1363 : {
1364 19 : READ_VARINT32(pabyData, pabyDataLimit, psCtxt->nGranularity);
1365 : }
1366 95 : else if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_DATE_GRANULARITY, WT_VARINT))
1367 : {
1368 19 : READ_VARINT32(pabyData, pabyDataLimit, psCtxt->nDateGranularity);
1369 : }
1370 76 : else if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_LAT_OFFSET, WT_VARINT))
1371 : {
1372 0 : READ_VARINT64(pabyData, pabyDataLimit, psCtxt->nLatOffset);
1373 : }
1374 76 : else if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_LON_OFFSET, WT_VARINT))
1375 : {
1376 0 : READ_VARINT64(pabyData, pabyDataLimit, psCtxt->nLonOffset);
1377 : }
1378 : else
1379 : {
1380 76 : SKIP_UNKNOWN_FIELD_INLINE(pabyData, pabyDataLimit, FALSE);
1381 : }
1382 : }
1383 :
1384 19 : if (pabyData != pabyDataLimit)
1385 0 : GOTO_END_ERROR;
1386 :
1387 19 : pabyData = pabyDataSave;
1388 133 : while(pabyData < pabyDataLimit)
1389 : {
1390 : int nKey;
1391 95 : READ_FIELD_KEY(nKey);
1392 :
1393 95 : if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_STRINGTABLE, WT_DATA))
1394 : {
1395 : GByte bSaveAfterByte;
1396 : GByte* pbSaveAfterByte;
1397 : unsigned int nSize;
1398 19 : if (psCtxt->nStrCount != 0)
1399 0 : GOTO_END_ERROR;
1400 19 : READ_SIZE(pabyData, pabyDataLimit, nSize);
1401 :
1402 : /* Dirty little trick */
1403 : /* ReadStringTable() will over-write the byte after the */
1404 : /* StringTable message with a NUL charachter, so we backup */
1405 : /* it to be able to restore it just before issuing the next */
1406 : /* READ_FIELD_KEY. Then we will re-NUL it to have valid */
1407 : /* NUL terminated strings */
1408 : /* This trick enable us to keep the strings where there are */
1409 : /* in RAM */
1410 19 : pbSaveAfterByte = pabyData + nSize;
1411 19 : bSaveAfterByte = *pbSaveAfterByte;
1412 :
1413 19 : if (!ReadStringTable(pabyData, pabyData + nSize,
1414 : psCtxt))
1415 0 : GOTO_END_ERROR;
1416 :
1417 19 : pabyData += nSize;
1418 :
1419 19 : *pbSaveAfterByte = bSaveAfterByte;
1420 19 : if (pabyData == pabyDataLimit)
1421 0 : break;
1422 :
1423 19 : READ_FIELD_KEY(nKey);
1424 19 : *pbSaveAfterByte = 0;
1425 :
1426 19 : if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_STRINGTABLE, WT_DATA))
1427 0 : GOTO_END_ERROR;
1428 :
1429 : /* Yes we go on ! */
1430 : }
1431 :
1432 95 : if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_PRIMITIVEGROUP, WT_DATA))
1433 : {
1434 : unsigned int nSize;
1435 57 : READ_SIZE(pabyData, pabyDataLimit, nSize);
1436 :
1437 57 : if (!ReadPrimitiveGroup(pabyData, pabyData + nSize,
1438 : psCtxt))
1439 0 : GOTO_END_ERROR;
1440 :
1441 57 : pabyData += nSize;
1442 : }
1443 : else
1444 : {
1445 38 : SKIP_UNKNOWN_FIELD_INLINE(pabyData, pabyDataLimit, FALSE);
1446 : }
1447 : }
1448 :
1449 19 : return pabyData == pabyDataLimit;
1450 :
1451 : end_error:
1452 :
1453 0 : return FALSE;
1454 : }
1455 :
1456 : /************************************************************************/
1457 : /* ReadBlob() */
1458 : /************************************************************************/
1459 :
1460 : #define BLOB_IDX_RAW 1
1461 : #define BLOB_IDX_RAW_SIZE 2
1462 : #define BLOB_IDX_ZLIB_DATA 3
1463 :
1464 : static
1465 38 : int ReadBlob(GByte* pabyData, unsigned int nDataSize, BlobType eType,
1466 : OSMContext* psCtxt)
1467 : {
1468 38 : unsigned int nUncompressedSize = 0;
1469 38 : int bRet = TRUE;
1470 38 : GByte* pabyDataLimit = pabyData + nDataSize;
1471 :
1472 152 : while(pabyData < pabyDataLimit)
1473 : {
1474 : int nKey;
1475 76 : READ_FIELD_KEY(nKey);
1476 :
1477 76 : if (nKey == MAKE_KEY(BLOB_IDX_RAW, WT_DATA))
1478 : {
1479 : unsigned int nDataLength;
1480 0 : READ_SIZE(pabyData, pabyDataLimit, nDataLength);
1481 0 : if (nDataLength > 64 * 1024 * 1024) GOTO_END_ERROR;
1482 :
1483 : /* printf("raw data size = %d\n", nDataLength); */
1484 :
1485 0 : if (eType == BLOB_OSMHEADER)
1486 : {
1487 0 : bRet = ReadOSMHeader(pabyData, pabyData + nDataLength, psCtxt);
1488 : }
1489 0 : else if (eType == BLOB_OSMDATA)
1490 : {
1491 : bRet = ReadPrimitiveBlock(pabyData, pabyData + nDataLength,
1492 0 : psCtxt);
1493 : }
1494 :
1495 0 : pabyData += nDataLength;
1496 : }
1497 76 : else if (nKey == MAKE_KEY(BLOB_IDX_RAW_SIZE, WT_VARINT))
1498 : {
1499 38 : READ_VARUINT32(pabyData, pabyDataLimit, nUncompressedSize);
1500 : /* printf("nUncompressedSize = %d\n", nUncompressedSize); */
1501 : }
1502 38 : else if (nKey == MAKE_KEY(BLOB_IDX_ZLIB_DATA, WT_DATA))
1503 : {
1504 : unsigned int nZlibCompressedSize;
1505 38 : READ_VARUINT32(pabyData, pabyDataLimit, nZlibCompressedSize);
1506 38 : if (CHECK_OOB && nZlibCompressedSize > nDataSize) GOTO_END_ERROR;
1507 :
1508 : /* printf("nZlibCompressedSize = %d\n", nZlibCompressedSize); */
1509 :
1510 38 : if (nUncompressedSize != 0)
1511 : {
1512 : int nStatus;
1513 : z_stream sStream;
1514 38 : if (nUncompressedSize > psCtxt->nUncompressedAllocated)
1515 : {
1516 : GByte* pabyUncompressedNew;
1517 : psCtxt->nUncompressedAllocated =
1518 18 : MAX(psCtxt->nUncompressedAllocated * 2, nUncompressedSize);
1519 : pabyUncompressedNew = (GByte*)VSIRealloc(psCtxt->pabyUncompressed,
1520 18 : psCtxt->nUncompressedAllocated + EXTRA_BYTES);
1521 18 : if( pabyUncompressedNew == NULL )
1522 0 : GOTO_END_ERROR;
1523 18 : psCtxt->pabyUncompressed = pabyUncompressedNew;
1524 : }
1525 38 : memset(psCtxt->pabyUncompressed + nUncompressedSize, 0, EXTRA_BYTES);
1526 :
1527 : /* printf("inflate %d -> %d\n", nZlibCompressedSize, nUncompressedSize); */
1528 :
1529 38 : sStream.next_in = pabyData;
1530 38 : sStream.avail_in = nZlibCompressedSize;
1531 38 : sStream.zalloc = NULL;
1532 38 : sStream.zfree = NULL;
1533 38 : sStream.opaque = NULL;
1534 38 : if( inflateInit(&sStream) != Z_OK )
1535 0 : GOTO_END_ERROR;
1536 :
1537 38 : sStream.next_out = psCtxt->pabyUncompressed;
1538 38 : sStream.avail_out = nUncompressedSize;
1539 38 : nStatus = inflate(&sStream, Z_FINISH);
1540 :
1541 38 : inflateEnd(&sStream);
1542 :
1543 38 : if (nStatus != Z_OK && nStatus != Z_STREAM_END)
1544 0 : GOTO_END_ERROR;
1545 :
1546 38 : if (eType == BLOB_OSMHEADER)
1547 : {
1548 : bRet = ReadOSMHeader(psCtxt->pabyUncompressed,
1549 : psCtxt->pabyUncompressed + nUncompressedSize,
1550 19 : psCtxt);
1551 : }
1552 19 : else if (eType == BLOB_OSMDATA)
1553 : {
1554 : bRet = ReadPrimitiveBlock(psCtxt->pabyUncompressed,
1555 : psCtxt->pabyUncompressed + nUncompressedSize,
1556 19 : psCtxt);
1557 : }
1558 : }
1559 :
1560 38 : pabyData += nZlibCompressedSize;
1561 : }
1562 : else
1563 : {
1564 0 : SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, TRUE);
1565 : }
1566 : }
1567 :
1568 38 : return bRet;
1569 :
1570 : end_error:
1571 0 : return FALSE;
1572 : }
1573 :
1574 : /************************************************************************/
1575 : /* EmptyNotifyNodesFunc() */
1576 : /************************************************************************/
1577 :
1578 0 : static void EmptyNotifyNodesFunc(unsigned int nNodes, OSMNode* pasNodes,
1579 : OSMContext* psCtxt, void* user_data)
1580 : {
1581 0 : }
1582 :
1583 :
1584 : /************************************************************************/
1585 : /* EmptyNotifyWayFunc() */
1586 : /************************************************************************/
1587 :
1588 0 : static void EmptyNotifyWayFunc(OSMWay* psWay,
1589 : OSMContext* psCtxt, void* user_data)
1590 : {
1591 0 : }
1592 :
1593 : /************************************************************************/
1594 : /* EmptyNotifyRelationFunc() */
1595 : /************************************************************************/
1596 :
1597 0 : static void EmptyNotifyRelationFunc(OSMRelation* psRelation,
1598 : OSMContext* psCtxt, void* user_data)
1599 : {
1600 0 : }
1601 :
1602 : /************************************************************************/
1603 : /* EmptyNotifyBoundsFunc() */
1604 : /************************************************************************/
1605 :
1606 0 : static void EmptyNotifyBoundsFunc( double dfXMin, double dfYMin,
1607 : double dfXMax, double dfYMax,
1608 : OSMContext* psCtxt, void* user_data )
1609 : {
1610 0 : }
1611 :
1612 : #ifdef HAVE_EXPAT
1613 :
1614 : /************************************************************************/
1615 : /* OSM_AddString() */
1616 : /************************************************************************/
1617 :
1618 85 : static const char* OSM_AddString(OSMContext* psCtxt, const char* pszStr)
1619 : {
1620 : char* pszRet;
1621 85 : int nLen = (int)strlen(pszStr);
1622 85 : if( psCtxt->nStrLength + nLen + 1 > psCtxt->nStrAllocated )
1623 : {
1624 0 : CPLError(CE_Failure, CPLE_AppDefined, "String buffer too small");
1625 0 : return "";
1626 : }
1627 85 : pszRet = psCtxt->pszStrBuf + psCtxt->nStrLength;
1628 85 : memcpy(pszRet, pszStr, nLen);
1629 85 : pszRet[nLen] = '\0';
1630 85 : psCtxt->nStrLength += nLen + 1;
1631 85 : return pszRet;
1632 : }
1633 :
1634 :
1635 : /************************************************************************/
1636 : /* OSM_Atoi64() */
1637 : /************************************************************************/
1638 :
1639 83 : static GIntBig OSM_Atoi64( const char *pszString )
1640 : {
1641 : GIntBig iValue;
1642 :
1643 : #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
1644 : iValue = (GIntBig)_atoi64( pszString );
1645 : # elif HAVE_ATOLL
1646 83 : iValue = atoll( pszString );
1647 : #else
1648 : iValue = atol( pszString );
1649 : #endif
1650 :
1651 83 : return iValue;
1652 : }
1653 :
1654 : /************************************************************************/
1655 : /* OSM_XML_startElementCbk() */
1656 : /************************************************************************/
1657 :
1658 79 : static void XMLCALL OSM_XML_startElementCbk(void *pUserData, const char *pszName,
1659 : const char **ppszAttr)
1660 : {
1661 79 : OSMContext* psCtxt = (OSMContext*) pUserData;
1662 79 : const char** ppszIter = ppszAttr;
1663 :
1664 79 : if (psCtxt->bStopParsing) return;
1665 :
1666 79 : psCtxt->nWithoutEventCounter = 0;
1667 :
1668 79 : if( psCtxt->bTryToFetchBounds )
1669 : {
1670 2 : if( strcmp(pszName, "bounds") == 0 ||
1671 : strcmp(pszName, "bound") == 0 /* osmosis uses bound */ )
1672 : {
1673 1 : int nCountCoords = 0;
1674 :
1675 1 : psCtxt->bTryToFetchBounds = FALSE;
1676 :
1677 1 : if( ppszIter )
1678 : {
1679 6 : while( ppszIter[0] != NULL )
1680 : {
1681 4 : if( strcmp(ppszIter[0], "minlon") == 0 )
1682 : {
1683 1 : psCtxt->dfLeft = CPLAtof( ppszIter[1] );
1684 1 : nCountCoords ++;
1685 : }
1686 3 : else if( strcmp(ppszIter[0], "minlat") == 0 )
1687 : {
1688 1 : psCtxt->dfBottom = CPLAtof( ppszIter[1] );
1689 1 : nCountCoords ++;
1690 : }
1691 2 : else if( strcmp(ppszIter[0], "maxlon") == 0 )
1692 : {
1693 1 : psCtxt->dfRight = CPLAtof( ppszIter[1] );
1694 1 : nCountCoords ++;
1695 : }
1696 1 : else if( strcmp(ppszIter[0], "maxlat") == 0 )
1697 : {
1698 1 : psCtxt->dfTop = CPLAtof( ppszIter[1] );
1699 1 : nCountCoords ++;
1700 : }
1701 0 : else if( strcmp(ppszIter[0], "box") == 0 /* osmosis uses box */ )
1702 : {
1703 0 : char** papszTokens = CSLTokenizeString2( ppszIter[1], ",", 0 );
1704 0 : if( CSLCount(papszTokens) == 4 )
1705 : {
1706 0 : psCtxt->dfBottom = CPLAtof( papszTokens[0] );
1707 0 : psCtxt->dfLeft = CPLAtof( papszTokens[1] );
1708 0 : psCtxt->dfTop = CPLAtof( papszTokens[2] );
1709 0 : psCtxt->dfRight = CPLAtof( papszTokens[3] );
1710 0 : nCountCoords = 4;
1711 : }
1712 0 : CSLDestroy(papszTokens);
1713 : }
1714 4 : ppszIter += 2;
1715 : }
1716 : }
1717 :
1718 1 : if( nCountCoords == 4 )
1719 : {
1720 : psCtxt->pfnNotifyBounds(psCtxt->dfLeft, psCtxt->dfBottom,
1721 : psCtxt->dfRight, psCtxt->dfTop,
1722 1 : psCtxt, psCtxt->user_data);
1723 : }
1724 : }
1725 : }
1726 :
1727 88 : if( !psCtxt->bInNode && !psCtxt->bInWay && !psCtxt->bInRelation &&
1728 : strcmp(pszName, "node") == 0 )
1729 : {
1730 9 : psCtxt->bInNode = TRUE;
1731 9 : psCtxt->bTryToFetchBounds = FALSE;
1732 :
1733 9 : psCtxt->nStrLength = 0;
1734 9 : psCtxt->pszStrBuf[0] = '\0';
1735 9 : psCtxt->nTags = 0;
1736 :
1737 9 : memset( &(psCtxt->pasNodes[0]), 0, sizeof(OSMNode) );
1738 9 : psCtxt->pasNodes[0].sInfo.pszUserSID = "";
1739 :
1740 9 : if( ppszIter )
1741 : {
1742 90 : while( ppszIter[0] != NULL )
1743 : {
1744 72 : if( strcmp(ppszIter[0], "id") == 0 )
1745 : {
1746 9 : psCtxt->pasNodes[0].nID = OSM_Atoi64( ppszIter[1] );
1747 : }
1748 63 : else if( strcmp(ppszIter[0], "lat") == 0 )
1749 : {
1750 9 : psCtxt->pasNodes[0].dfLat = CPLAtof( ppszIter[1] );
1751 : }
1752 54 : else if( strcmp(ppszIter[0], "lon") == 0 )
1753 : {
1754 9 : psCtxt->pasNodes[0].dfLon = CPLAtof( ppszIter[1] );
1755 : }
1756 45 : else if( strcmp(ppszIter[0], "version") == 0 )
1757 : {
1758 9 : psCtxt->pasNodes[0].sInfo.nVersion = atoi( ppszIter[1] );
1759 : }
1760 36 : else if( strcmp(ppszIter[0], "changeset") == 0 )
1761 : {
1762 9 : psCtxt->pasNodes[0].sInfo.nChangeset = OSM_Atoi64( ppszIter[1] );
1763 : }
1764 27 : else if( strcmp(ppszIter[0], "user") == 0 )
1765 : {
1766 9 : psCtxt->pasNodes[0].sInfo.pszUserSID = OSM_AddString(psCtxt, ppszIter[1]);
1767 : }
1768 18 : else if( strcmp(ppszIter[0], "uid") == 0 )
1769 : {
1770 9 : psCtxt->pasNodes[0].sInfo.nUID = atoi( ppszIter[1] );
1771 : }
1772 9 : else if( strcmp(ppszIter[0], "timestamp") == 0 )
1773 : {
1774 9 : psCtxt->pasNodes[0].sInfo.ts.pszTimeStamp = OSM_AddString(psCtxt, ppszIter[1]);
1775 9 : psCtxt->pasNodes[0].sInfo.bTimeStampIsStr = 1;
1776 : }
1777 72 : ppszIter += 2;
1778 : }
1779 : }
1780 : }
1781 :
1782 78 : else if( !psCtxt->bInNode && !psCtxt->bInWay && !psCtxt->bInRelation &&
1783 : strcmp(pszName, "way") == 0 )
1784 : {
1785 8 : psCtxt->bInWay = TRUE;
1786 :
1787 8 : psCtxt->nStrLength = 0;
1788 8 : psCtxt->pszStrBuf[0] = '\0';
1789 8 : psCtxt->nTags = 0;
1790 :
1791 8 : memset( &(psCtxt->sWay), 0, sizeof(OSMWay) );
1792 8 : psCtxt->sWay.sInfo.pszUserSID = "";
1793 :
1794 8 : if( ppszIter )
1795 : {
1796 64 : while( ppszIter[0] != NULL )
1797 : {
1798 48 : if( strcmp(ppszIter[0], "id") == 0 )
1799 : {
1800 8 : psCtxt->sWay.nID = OSM_Atoi64( ppszIter[1] );
1801 : }
1802 40 : else if( strcmp(ppszIter[0], "version") == 0 )
1803 : {
1804 8 : psCtxt->sWay.sInfo.nVersion = atoi( ppszIter[1] );
1805 : }
1806 32 : else if( strcmp(ppszIter[0], "changeset") == 0 )
1807 : {
1808 8 : psCtxt->sWay.sInfo.nChangeset = OSM_Atoi64( ppszIter[1] );
1809 : }
1810 24 : else if( strcmp(ppszIter[0], "user") == 0 )
1811 : {
1812 8 : psCtxt->sWay.sInfo.pszUserSID = OSM_AddString(psCtxt, ppszIter[1]);
1813 : }
1814 16 : else if( strcmp(ppszIter[0], "uid") == 0 )
1815 : {
1816 8 : psCtxt->sWay.sInfo.nUID = atoi( ppszIter[1] );
1817 : }
1818 8 : else if( strcmp(ppszIter[0], "timestamp") == 0 )
1819 : {
1820 8 : psCtxt->sWay.sInfo.ts.pszTimeStamp = OSM_AddString(psCtxt, ppszIter[1]);
1821 8 : psCtxt->sWay.sInfo.bTimeStampIsStr = 1;
1822 : }
1823 48 : ppszIter += 2;
1824 : }
1825 : }
1826 : }
1827 :
1828 67 : else if( !psCtxt->bInNode && !psCtxt->bInWay && !psCtxt->bInRelation &&
1829 : strcmp(pszName, "relation") == 0 )
1830 : {
1831 5 : psCtxt->bInRelation = TRUE;
1832 :
1833 5 : psCtxt->nStrLength = 0;
1834 5 : psCtxt->pszStrBuf[0] = '\0';
1835 5 : psCtxt->nTags = 0;
1836 :
1837 5 : memset( &(psCtxt->sRelation), 0, sizeof(OSMRelation) );
1838 5 : psCtxt->sRelation.sInfo.pszUserSID = "";
1839 :
1840 5 : if( ppszIter )
1841 : {
1842 40 : while( ppszIter[0] != NULL )
1843 : {
1844 30 : if( strcmp(ppszIter[0], "id") == 0 )
1845 : {
1846 5 : psCtxt->sRelation.nID = OSM_Atoi64( ppszIter[1] );
1847 : }
1848 25 : else if( strcmp(ppszIter[0], "version") == 0 )
1849 : {
1850 5 : psCtxt->sRelation.sInfo.nVersion = atoi( ppszIter[1] );
1851 : }
1852 20 : else if( strcmp(ppszIter[0], "changeset") == 0 )
1853 : {
1854 5 : psCtxt->sRelation.sInfo.nChangeset = OSM_Atoi64( ppszIter[1] );
1855 : }
1856 15 : else if( strcmp(ppszIter[0], "user") == 0 )
1857 : {
1858 5 : psCtxt->sRelation.sInfo.pszUserSID = OSM_AddString(psCtxt, ppszIter[1]);
1859 : }
1860 10 : else if( strcmp(ppszIter[0], "uid") == 0 )
1861 : {
1862 5 : psCtxt->sRelation.sInfo.nUID = atoi( ppszIter[1] );
1863 : }
1864 5 : else if( strcmp(ppszIter[0], "timestamp") == 0 )
1865 : {
1866 5 : psCtxt->sRelation.sInfo.ts.pszTimeStamp = OSM_AddString(psCtxt, ppszIter[1]);
1867 5 : psCtxt->sRelation.sInfo.bTimeStampIsStr = 1;
1868 :
1869 : }
1870 30 : ppszIter += 2;
1871 : }
1872 : }
1873 : }
1874 :
1875 87 : else if( psCtxt->bInWay &&
1876 : strcmp(pszName, "nd") == 0 )
1877 : {
1878 30 : if( ppszAttr != NULL && ppszAttr[0] != NULL &&
1879 : strcmp(ppszAttr[0], "ref") == 0 )
1880 : {
1881 30 : if( psCtxt->sWay.nRefs < psCtxt->nNodeRefsAllocated )
1882 : {
1883 30 : psCtxt->panNodeRefs[psCtxt->sWay.nRefs] = OSM_Atoi64( ppszAttr[1] );
1884 30 : psCtxt->sWay.nRefs ++;
1885 : }
1886 : else
1887 : {
1888 : CPLError(CE_Failure, CPLE_AppDefined,
1889 : "Too many nodes referenced in way " CPL_FRMT_GIB,
1890 0 : psCtxt->sWay.nID);
1891 : }
1892 : }
1893 : }
1894 :
1895 36 : else if( psCtxt->bInRelation &&
1896 : strcmp(pszName, "member") == 0 )
1897 : {
1898 9 : if( psCtxt->sRelation.nMembers < psCtxt->nMembersAllocated )
1899 : {
1900 9 : OSMMember* psMember = &(psCtxt->pasMembers[psCtxt->sRelation.nMembers]);
1901 9 : psCtxt->sRelation.nMembers ++;
1902 :
1903 9 : psMember->nID = 0;
1904 9 : psMember->pszRole = "";
1905 9 : psMember->eType = MEMBER_NODE;
1906 :
1907 9 : if( ppszIter )
1908 : {
1909 45 : while( ppszIter[0] != NULL )
1910 : {
1911 27 : if( strcmp(ppszIter[0], "ref") == 0 )
1912 : {
1913 9 : psMember->nID = OSM_Atoi64( ppszIter[1] );
1914 : }
1915 18 : else if( strcmp(ppszIter[0], "type") == 0 )
1916 : {
1917 9 : if( strcmp( ppszIter[1], "node") == 0 )
1918 1 : psMember->eType = MEMBER_NODE;
1919 8 : else if( strcmp( ppszIter[1], "way") == 0 )
1920 8 : psMember->eType = MEMBER_WAY;
1921 0 : else if( strcmp( ppszIter[1], "relation") == 0 )
1922 0 : psMember->eType = MEMBER_RELATION;
1923 : }
1924 9 : else if( strcmp(ppszIter[0], "role") == 0 )
1925 : {
1926 9 : psMember->pszRole = OSM_AddString(psCtxt, ppszIter[1]);
1927 : }
1928 27 : ppszIter += 2;
1929 : }
1930 : }
1931 : }
1932 : else
1933 : {
1934 : CPLError(CE_Failure, CPLE_AppDefined,
1935 : "Too many members referenced in relation " CPL_FRMT_GIB,
1936 0 : psCtxt->sRelation.nID);
1937 : }
1938 : }
1939 18 : else if( (psCtxt->bInNode || psCtxt->bInWay || psCtxt->bInRelation) &&
1940 : strcmp(pszName, "tag") == 0 )
1941 : {
1942 16 : if( psCtxt->nTags < psCtxt->nTagsAllocated )
1943 : {
1944 16 : OSMTag* psTag = &(psCtxt->pasTags[psCtxt->nTags]);
1945 16 : psCtxt->nTags ++;
1946 :
1947 16 : psTag->pszK = "";
1948 16 : psTag->pszV = "";
1949 :
1950 16 : if( ppszIter )
1951 : {
1952 64 : while( ppszIter[0] != NULL )
1953 : {
1954 32 : if( ppszIter[0][0] == 'k' )
1955 : {
1956 16 : psTag->pszK = OSM_AddString(psCtxt, ppszIter[1]);
1957 : }
1958 16 : else if( ppszIter[0][0] == 'v' )
1959 : {
1960 16 : psTag->pszV = OSM_AddString(psCtxt, ppszIter[1]);
1961 : }
1962 32 : ppszIter += 2;
1963 : }
1964 : }
1965 : }
1966 : else
1967 : {
1968 0 : if (psCtxt->bInNode)
1969 : CPLError(CE_Failure, CPLE_AppDefined,
1970 : "Too many tags in node " CPL_FRMT_GIB,
1971 0 : psCtxt->pasNodes[0].nID);
1972 0 : else if (psCtxt->bInWay)
1973 : CPLError(CE_Failure, CPLE_AppDefined,
1974 : "Too many tags in way " CPL_FRMT_GIB,
1975 0 : psCtxt->sWay.nID);
1976 0 : else if (psCtxt->bInRelation)
1977 : CPLError(CE_Failure, CPLE_AppDefined,
1978 : "Too many tags in relation " CPL_FRMT_GIB,
1979 0 : psCtxt->sRelation.nID);
1980 : }
1981 : }
1982 : }
1983 :
1984 : /************************************************************************/
1985 : /* OSM_XML_endElementCbk() */
1986 : /************************************************************************/
1987 :
1988 79 : static void XMLCALL OSM_XML_endElementCbk(void *pUserData, const char *pszName)
1989 : {
1990 79 : OSMContext* psCtxt = (OSMContext*) pUserData;
1991 :
1992 79 : if (psCtxt->bStopParsing) return;
1993 :
1994 79 : psCtxt->nWithoutEventCounter = 0;
1995 :
1996 88 : if( psCtxt->bInNode && strcmp(pszName, "node") == 0 )
1997 : {
1998 9 : psCtxt->pasNodes[0].nTags = psCtxt->nTags;
1999 9 : psCtxt->pasNodes[0].pasTags = psCtxt->pasTags;
2000 :
2001 9 : psCtxt->pfnNotifyNodes(1, psCtxt->pasNodes, psCtxt, psCtxt->user_data);
2002 :
2003 9 : psCtxt->bHasFoundFeature = TRUE;
2004 :
2005 9 : psCtxt->bInNode = FALSE;
2006 : }
2007 :
2008 : else
2009 78 : if( psCtxt->bInWay && strcmp(pszName, "way") == 0 )
2010 : {
2011 8 : psCtxt->sWay.nTags = psCtxt->nTags;
2012 8 : psCtxt->sWay.pasTags = psCtxt->pasTags;
2013 :
2014 8 : psCtxt->sWay.panNodeRefs = psCtxt->panNodeRefs;
2015 :
2016 8 : psCtxt->pfnNotifyWay(&(psCtxt->sWay), psCtxt, psCtxt->user_data);
2017 :
2018 8 : psCtxt->bHasFoundFeature = TRUE;
2019 :
2020 8 : psCtxt->bInWay = FALSE;
2021 : }
2022 :
2023 : else
2024 62 : if( psCtxt->bInRelation && strcmp(pszName, "relation") == 0 )
2025 : {
2026 5 : psCtxt->sRelation.nTags = psCtxt->nTags;
2027 5 : psCtxt->sRelation.pasTags = psCtxt->pasTags;
2028 :
2029 5 : psCtxt->sRelation.pasMembers = psCtxt->pasMembers;
2030 :
2031 5 : psCtxt->pfnNotifyRelation(&(psCtxt->sRelation), psCtxt, psCtxt->user_data);
2032 :
2033 5 : psCtxt->bHasFoundFeature = TRUE;
2034 :
2035 5 : psCtxt->bInRelation = FALSE;
2036 : }
2037 : }
2038 : /************************************************************************/
2039 : /* dataHandlerCbk() */
2040 : /************************************************************************/
2041 :
2042 194 : static void XMLCALL OSM_XML_dataHandlerCbk(void *pUserData, const char *data, int nLen)
2043 : {
2044 194 : OSMContext* psCtxt = (OSMContext*) pUserData;
2045 :
2046 194 : if (psCtxt->bStopParsing) return;
2047 :
2048 194 : psCtxt->nWithoutEventCounter = 0;
2049 :
2050 194 : psCtxt->nDataHandlerCounter ++;
2051 194 : if (psCtxt->nDataHandlerCounter >= XML_BUFSIZE)
2052 : {
2053 : CPLError(CE_Failure, CPLE_AppDefined,
2054 0 : "File probably corrupted (million laugh pattern)");
2055 0 : XML_StopParser(psCtxt->hXMLParser, XML_FALSE);
2056 0 : psCtxt->bStopParsing = TRUE;
2057 0 : return;
2058 : }
2059 : }
2060 :
2061 : /************************************************************************/
2062 : /* XML_ProcessBlock() */
2063 : /************************************************************************/
2064 :
2065 2 : static OSMRetCode XML_ProcessBlock(OSMContext* psCtxt)
2066 : {
2067 2 : if( psCtxt->bEOF )
2068 1 : return OSM_EOF;
2069 1 : if( psCtxt->bStopParsing )
2070 0 : return OSM_ERROR;
2071 :
2072 1 : psCtxt->bHasFoundFeature = FALSE;
2073 1 : psCtxt->nWithoutEventCounter = 0;
2074 :
2075 1 : do
2076 : {
2077 : int eErr;
2078 : unsigned int nLen;
2079 :
2080 1 : psCtxt->nDataHandlerCounter = 0;
2081 :
2082 : nLen = (unsigned int)VSIFReadL( psCtxt->pabyBlob, 1,
2083 1 : XML_BUFSIZE, psCtxt->fp );
2084 :
2085 1 : psCtxt->nBytesRead += nLen;
2086 :
2087 1 : psCtxt->bEOF = VSIFEofL(psCtxt->fp);
2088 : eErr = XML_Parse(psCtxt->hXMLParser, (const char*) psCtxt->pabyBlob,
2089 1 : nLen, psCtxt->bEOF );
2090 :
2091 1 : if (eErr == XML_STATUS_ERROR)
2092 : {
2093 : CPLError(CE_Failure, CPLE_AppDefined,
2094 : "XML parsing of OSM file failed : %s "
2095 : "at line %d, column %d",
2096 : XML_ErrorString(XML_GetErrorCode(psCtxt->hXMLParser)),
2097 : (int)XML_GetCurrentLineNumber(psCtxt->hXMLParser),
2098 0 : (int)XML_GetCurrentColumnNumber(psCtxt->hXMLParser));
2099 0 : psCtxt->bStopParsing = TRUE;
2100 : }
2101 1 : psCtxt->nWithoutEventCounter ++;
2102 : } while (!psCtxt->bEOF && !psCtxt->bStopParsing &&
2103 : psCtxt->bHasFoundFeature == FALSE &&
2104 : psCtxt->nWithoutEventCounter < 10);
2105 :
2106 1 : if (psCtxt->nWithoutEventCounter == 10)
2107 : {
2108 : CPLError(CE_Failure, CPLE_AppDefined,
2109 0 : "Too much data inside one element. File probably corrupted");
2110 0 : psCtxt->bStopParsing = TRUE;
2111 : }
2112 :
2113 1 : return psCtxt->bStopParsing ? OSM_ERROR : psCtxt->bEOF ? OSM_EOF : OSM_OK;
2114 : }
2115 :
2116 : #endif
2117 :
2118 : /************************************************************************/
2119 : /* OSM_Open() */
2120 : /************************************************************************/
2121 :
2122 10 : OSMContext* OSM_Open( const char* pszFilename,
2123 : NotifyNodesFunc pfnNotifyNodes,
2124 : NotifyWayFunc pfnNotifyWay,
2125 : NotifyRelationFunc pfnNotifyRelation,
2126 : NotifyBoundsFunc pfnNotifyBounds,
2127 : void* user_data )
2128 : {
2129 : OSMContext* psCtxt;
2130 : GByte abyHeader[1024];
2131 : int nRead;
2132 : VSILFILE* fp;
2133 : int i;
2134 10 : int bPBF = FALSE;
2135 :
2136 10 : fp = VSIFOpenL(pszFilename, "rb");
2137 10 : if (fp == NULL)
2138 0 : return NULL;
2139 :
2140 10 : nRead = (int)VSIFReadL(abyHeader, 1, sizeof(abyHeader)-1, fp);
2141 10 : abyHeader[nRead] = '\0';
2142 :
2143 10 : if( strstr((const char*)abyHeader, "<osm") != NULL )
2144 : {
2145 : /* OSM XML */
2146 : #ifndef HAVE_EXPAT
2147 : CPLError(CE_Failure, CPLE_AppDefined,
2148 : "OSM XML detected, but Expat parser not available");
2149 : VSIFCloseL(fp);
2150 : return NULL;
2151 : #endif
2152 : }
2153 : else
2154 : {
2155 9 : int nLimitI = nRead - strlen("OSMHeader");
2156 63 : for(i = 0; i < nLimitI; i++)
2157 : {
2158 63 : if( memcmp(abyHeader + i, "OSMHeader", strlen("OSMHeader") ) == 0 )
2159 : {
2160 9 : bPBF = TRUE;
2161 9 : break;
2162 : }
2163 : }
2164 9 : if( !bPBF )
2165 : {
2166 0 : VSIFCloseL(fp);
2167 0 : return NULL;
2168 : }
2169 : }
2170 :
2171 10 : VSIFSeekL(fp, 0, SEEK_SET);
2172 :
2173 10 : psCtxt = (OSMContext*) VSIMalloc(sizeof(OSMContext));
2174 10 : if (psCtxt == NULL)
2175 : {
2176 0 : VSIFCloseL(fp);
2177 0 : return NULL;
2178 : }
2179 10 : memset(psCtxt, 0, sizeof(OSMContext));
2180 10 : psCtxt->bPBF = bPBF;
2181 10 : psCtxt->fp = fp;
2182 10 : psCtxt->pfnNotifyNodes = pfnNotifyNodes;
2183 10 : if( pfnNotifyNodes == NULL )
2184 0 : psCtxt->pfnNotifyNodes = EmptyNotifyNodesFunc;
2185 10 : psCtxt->pfnNotifyWay = pfnNotifyWay;
2186 10 : if( pfnNotifyWay == NULL )
2187 0 : psCtxt->pfnNotifyWay = EmptyNotifyWayFunc;
2188 10 : psCtxt->pfnNotifyRelation = pfnNotifyRelation;
2189 10 : if( pfnNotifyRelation == NULL )
2190 0 : psCtxt->pfnNotifyRelation = EmptyNotifyRelationFunc;
2191 10 : psCtxt->pfnNotifyBounds = pfnNotifyBounds;
2192 10 : if( pfnNotifyBounds == NULL )
2193 0 : psCtxt->pfnNotifyBounds = EmptyNotifyBoundsFunc;
2194 10 : psCtxt->user_data = user_data;
2195 :
2196 10 : if( bPBF )
2197 : {
2198 9 : psCtxt->nBlobSizeAllocated = 64 * 1024 + EXTRA_BYTES;
2199 : }
2200 : #ifdef HAVE_EXPAT
2201 : else
2202 : {
2203 1 : psCtxt->nBlobSizeAllocated = XML_BUFSIZE;
2204 :
2205 1 : psCtxt->nStrAllocated = 65536;
2206 1 : psCtxt->pszStrBuf = (char*) VSIMalloc(psCtxt->nStrAllocated);
2207 1 : if( psCtxt->pszStrBuf )
2208 1 : psCtxt->pszStrBuf[0] = '\0';
2209 :
2210 1 : psCtxt->hXMLParser = OGRCreateExpatXMLParser();
2211 1 : XML_SetUserData(psCtxt->hXMLParser, psCtxt);
2212 : XML_SetElementHandler(psCtxt->hXMLParser,
2213 : OSM_XML_startElementCbk,
2214 1 : OSM_XML_endElementCbk);
2215 1 : XML_SetCharacterDataHandler(psCtxt->hXMLParser, OSM_XML_dataHandlerCbk);
2216 :
2217 1 : psCtxt->bTryToFetchBounds = TRUE;
2218 :
2219 1 : psCtxt->nNodesAllocated = 1;
2220 1 : psCtxt->pasNodes = (OSMNode*) VSIMalloc(sizeof(OSMNode) * psCtxt->nNodesAllocated);
2221 :
2222 1 : psCtxt->nTagsAllocated = 256;
2223 1 : psCtxt->pasTags = (OSMTag*) VSIMalloc(sizeof(OSMTag) * psCtxt->nTagsAllocated);
2224 :
2225 1 : psCtxt->nMembersAllocated = 2000;
2226 1 : psCtxt->pasMembers = (OSMMember*) VSIMalloc(sizeof(OSMMember) * psCtxt->nMembersAllocated);
2227 :
2228 1 : psCtxt->nNodeRefsAllocated = 2000;
2229 1 : psCtxt->panNodeRefs = (GIntBig*) VSIMalloc(sizeof(GIntBig) * psCtxt->nNodeRefsAllocated);
2230 :
2231 1 : if( psCtxt->pszStrBuf == NULL ||
2232 : psCtxt->pasNodes == NULL ||
2233 : psCtxt->pasTags == NULL ||
2234 : psCtxt->pasMembers == NULL ||
2235 : psCtxt->panNodeRefs == NULL )
2236 : {
2237 0 : OSM_Close(psCtxt);
2238 0 : return NULL;
2239 : }
2240 :
2241 : }
2242 : #endif
2243 :
2244 10 : psCtxt->pabyBlob = (GByte*)VSIMalloc(psCtxt->nBlobSizeAllocated);
2245 10 : if( psCtxt->pabyBlob == NULL )
2246 : {
2247 0 : OSM_Close(psCtxt);
2248 0 : return NULL;
2249 : }
2250 :
2251 10 : return psCtxt;
2252 : }
2253 :
2254 : /************************************************************************/
2255 : /* OSM_Close() */
2256 : /************************************************************************/
2257 :
2258 134 : void OSM_Close(OSMContext* psCtxt)
2259 : {
2260 134 : if( psCtxt == NULL )
2261 124 : return;
2262 :
2263 : #ifdef HAVE_EXPAT
2264 10 : if( !psCtxt->bPBF )
2265 : {
2266 1 : if (psCtxt->hXMLParser)
2267 1 : XML_ParserFree(psCtxt->hXMLParser);
2268 :
2269 1 : CPLFree(psCtxt->pszStrBuf); /* only for XML case ! */
2270 : }
2271 : #endif
2272 :
2273 10 : VSIFree(psCtxt->pabyBlob);
2274 10 : VSIFree(psCtxt->pabyUncompressed);
2275 10 : VSIFree(psCtxt->panStrOff);
2276 10 : VSIFree(psCtxt->pasNodes);
2277 10 : VSIFree(psCtxt->pasTags);
2278 10 : VSIFree(psCtxt->pasMembers);
2279 10 : VSIFree(psCtxt->panNodeRefs);
2280 :
2281 10 : VSIFCloseL(psCtxt->fp);
2282 10 : VSIFree(psCtxt);
2283 : }
2284 : /************************************************************************/
2285 : /* OSM_ResetReading() */
2286 : /************************************************************************/
2287 :
2288 23 : void OSM_ResetReading( OSMContext* psCtxt )
2289 : {
2290 23 : VSIFSeekL(psCtxt->fp, 0, SEEK_SET);
2291 :
2292 23 : psCtxt->nBytesRead = 0;
2293 :
2294 : #ifdef HAVE_EXPAT
2295 23 : if( !psCtxt->bPBF )
2296 : {
2297 0 : XML_ParserFree(psCtxt->hXMLParser);
2298 0 : psCtxt->hXMLParser = OGRCreateExpatXMLParser();
2299 0 : XML_SetUserData(psCtxt->hXMLParser, psCtxt);
2300 : XML_SetElementHandler(psCtxt->hXMLParser,
2301 : OSM_XML_startElementCbk,
2302 0 : OSM_XML_endElementCbk);
2303 0 : XML_SetCharacterDataHandler(psCtxt->hXMLParser, OSM_XML_dataHandlerCbk);
2304 0 : psCtxt->bEOF = FALSE;
2305 0 : psCtxt->bStopParsing = FALSE;
2306 0 : psCtxt->nStrLength = 0;
2307 0 : psCtxt->pszStrBuf[0] = '\0';
2308 0 : psCtxt->nTags = 0;
2309 :
2310 0 : psCtxt->bTryToFetchBounds = TRUE;
2311 0 : psCtxt->bInNode = FALSE;
2312 0 : psCtxt->bInWay = FALSE;
2313 0 : psCtxt->bInRelation = FALSE;
2314 : }
2315 : #endif
2316 23 : }
2317 :
2318 : /************************************************************************/
2319 : /* OSM_ProcessBlock() */
2320 : /************************************************************************/
2321 :
2322 48 : static OSMRetCode PBF_ProcessBlock(OSMContext* psCtxt)
2323 : {
2324 48 : int nRet = FALSE;
2325 : GByte abyHeaderSize[4];
2326 : unsigned int nHeaderSize;
2327 48 : unsigned int nBlobSize = 0;
2328 : BlobType eType;
2329 :
2330 48 : if (VSIFReadL(abyHeaderSize, 4, 1, psCtxt->fp) != 1)
2331 : {
2332 10 : return OSM_EOF;
2333 : }
2334 76 : nHeaderSize = (abyHeaderSize[0] << 24) | (abyHeaderSize[1] << 16) |
2335 76 : (abyHeaderSize[2] << 8) | abyHeaderSize[3];
2336 :
2337 38 : psCtxt->nBytesRead += 4;
2338 :
2339 : /* printf("nHeaderSize = %d\n", nHeaderSize); */
2340 38 : if (nHeaderSize > 64 * 1024)
2341 0 : GOTO_END_ERROR;
2342 38 : if (VSIFReadL(psCtxt->pabyBlob, 1, nHeaderSize, psCtxt->fp) != nHeaderSize)
2343 0 : GOTO_END_ERROR;
2344 :
2345 38 : psCtxt->nBytesRead += nHeaderSize;
2346 :
2347 38 : memset(psCtxt->pabyBlob + nHeaderSize, 0, EXTRA_BYTES);
2348 38 : nRet = ReadBlobHeader(psCtxt->pabyBlob, psCtxt->pabyBlob + nHeaderSize, &nBlobSize, &eType);
2349 38 : if (!nRet || eType == BLOB_UNKNOW)
2350 : GOTO_END_ERROR;
2351 :
2352 38 : if (nBlobSize > 64*1024*1024)
2353 0 : GOTO_END_ERROR;
2354 38 : if (nBlobSize > psCtxt->nBlobSizeAllocated)
2355 : {
2356 : GByte* pabyBlobNew;
2357 0 : psCtxt->nBlobSizeAllocated = MAX(psCtxt->nBlobSizeAllocated * 2, nBlobSize);
2358 : pabyBlobNew = (GByte*)VSIRealloc(psCtxt->pabyBlob,
2359 0 : psCtxt->nBlobSizeAllocated + EXTRA_BYTES);
2360 0 : if( pabyBlobNew == NULL )
2361 0 : GOTO_END_ERROR;
2362 0 : psCtxt->pabyBlob = pabyBlobNew;
2363 : }
2364 38 : if (VSIFReadL(psCtxt->pabyBlob, 1, nBlobSize, psCtxt->fp) != nBlobSize)
2365 0 : GOTO_END_ERROR;
2366 :
2367 38 : psCtxt->nBytesRead += nBlobSize;
2368 :
2369 38 : memset(psCtxt->pabyBlob + nBlobSize, 0, EXTRA_BYTES);
2370 : nRet = ReadBlob(psCtxt->pabyBlob, nBlobSize, eType,
2371 38 : psCtxt);
2372 38 : if (!nRet)
2373 0 : GOTO_END_ERROR;
2374 :
2375 38 : return OSM_OK;
2376 :
2377 : end_error:
2378 :
2379 0 : return OSM_ERROR;
2380 : }
2381 :
2382 : /************************************************************************/
2383 : /* OSM_ProcessBlock() */
2384 : /************************************************************************/
2385 :
2386 50 : OSMRetCode OSM_ProcessBlock(OSMContext* psCtxt)
2387 : {
2388 : #ifdef HAVE_EXPAT
2389 50 : if( psCtxt->bPBF )
2390 48 : return PBF_ProcessBlock(psCtxt);
2391 : else
2392 2 : return XML_ProcessBlock(psCtxt);
2393 : #else
2394 : return PBF_ProcessBlock(psCtxt);
2395 : #endif
2396 : }
2397 :
2398 : /************************************************************************/
2399 : /* OSM_GetBytesRead() */
2400 : /************************************************************************/
2401 :
2402 10 : GUIntBig OSM_GetBytesRead( OSMContext* psCtxt )
2403 : {
2404 10 : return psCtxt->nBytesRead;
2405 : }
|