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