File indexing completed on 2024-04-21 03:48:26
0001 // SPDX-FileCopyrightText: 2012-2015 Pavel Klinger 0002 // SPDX-License-Identifier: MIT 0003 0004 #include "o5mreader.h" 0005 #include <cstring> 0006 #include <cerrno> 0007 #include <cstdlib> 0008 #include <mutex> 0009 0010 0011 #define STR_PAIR_TABLE_SIZE 15000 0012 #define STR_PAIR_STRING_SIZE 256 0013 0014 std::mutex mtx; 0015 0016 O5mreaderRet o5mreader_readUInt(O5mreader *pReader, uint64_t *ret) { 0017 uint8_t b; 0018 uint8_t i = 0; 0019 *ret = 0LL; 0020 0021 do { 0022 if ( fread(&b,1,1,pReader->f) == 0 ) { 0023 o5mreader_setError(pReader, 0024 O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE, 0025 NULL 0026 ); 0027 return O5MREADER_RET_ERR; 0028 } 0029 *ret |= (long long)(b & 0x7f) << (i++ * 7); 0030 } while ( b & 0x80 ); 0031 0032 o5mreader_setNoError(pReader); 0033 0034 return O5MREADER_RET_OK; 0035 } 0036 0037 O5mreaderRet o5mreader_readInt(O5mreader *pReader, uint64_t *ret) { 0038 if ( o5mreader_readUInt(pReader, ret) == O5MREADER_RET_ERR ) 0039 return O5MREADER_RET_ERR; 0040 *ret = *ret & 1 0041 ? -(int64_t)(*ret >> 1) - 1 0042 : (int64_t)(*ret >> 1); 0043 return O5MREADER_RET_OK; 0044 } 0045 0046 0047 O5mreaderRet o5mreader_readStrPair(O5mreader *pReader, char **tagpair, int single) { 0048 static char buffer[1024]; 0049 char* pBuf; 0050 static uint64_t pointer = 0; 0051 int length; 0052 uint64_t key; 0053 int i; 0054 0055 if ( o5mreader_readUInt(pReader,&key) == O5MREADER_RET_ERR ) { 0056 return O5MREADER_RET_ERR; 0057 } 0058 0059 if ( key ) { 0060 *tagpair = pReader->strPairTable[(pointer+15000-key)%15000]; 0061 return key; 0062 } 0063 else { 0064 pBuf = buffer; 0065 for ( i=0; i<(single?1:2); i++ ) { 0066 do { 0067 if ( fread(pBuf,1,1,pReader->f) == 0 ) { 0068 o5mreader_setError(pReader, 0069 O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE, 0070 NULL 0071 ); 0072 return O5MREADER_RET_ERR; 0073 } 0074 } while ( *(pBuf++) ); 0075 } 0076 0077 length = strlen(buffer) + (single ? 1 : strlen(buffer+strlen(buffer) +1) + 2); 0078 0079 if ( length <= 252 ) { 0080 *tagpair = pReader->strPairTable[(pointer+15000)%15000]; 0081 memcpy(pReader->strPairTable[((pointer++)+15000)%15000],buffer,length); 0082 } 0083 else { 0084 *tagpair = buffer; 0085 } 0086 0087 } 0088 0089 return O5MREADER_RET_OK; 0090 } 0091 0092 O5mreaderRet o5mreader_reset(O5mreader *pReader) { 0093 pReader->nodeId = pReader->wayId = pReader->wayNodeId = pReader->relId = pReader->nodeRefId = pReader->wayRefId = pReader->relRefId = 0; 0094 pReader->lon = pReader->lat = 0; 0095 pReader->offset = 0; 0096 pReader->canIterateTags = pReader->canIterateNds = pReader->canIterateRefs = 0; 0097 return O5MREADER_RET_OK; 0098 } 0099 0100 O5mreaderRet o5mreader_open(O5mreader **ppReader,FILE* f) { 0101 uint8_t byte; 0102 int i; 0103 *ppReader = (O5mreader*)malloc(sizeof(O5mreader)); 0104 if ( !(*ppReader) ) { 0105 return O5MREADER_RET_ERR; 0106 } 0107 (*ppReader)->errMsg = NULL; 0108 (*ppReader)->f = f; 0109 (*ppReader)->strPairTable = NULL; 0110 if ( fread(&byte,1,1,(*ppReader)->f) == 0 ) { 0111 o5mreader_setError(*ppReader, 0112 O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE, 0113 NULL 0114 ); 0115 return O5MREADER_RET_ERR; 0116 } 0117 if ( byte != O5MREADER_DS_RESET ) { 0118 o5mreader_setError(*ppReader, 0119 O5MREADER_ERR_CODE_FILE_HAS_WRONG_START, 0120 NULL 0121 ); 0122 return O5MREADER_RET_ERR; 0123 } 0124 0125 o5mreader_reset(*ppReader); 0126 0127 (*ppReader)->strPairTable = (char**) malloc(STR_PAIR_TABLE_SIZE*sizeof(char*)); 0128 if ( (*ppReader)->strPairTable == 0 ) { 0129 o5mreader_setError(*ppReader, 0130 O5MREADER_ERR_CODE_MEMORY_ERROR, 0131 NULL 0132 ); 0133 return O5MREADER_RET_ERR; 0134 } 0135 for ( i = 0; i < STR_PAIR_TABLE_SIZE; ++i ) { 0136 (*ppReader)->strPairTable[i] = (char*) malloc(sizeof(char)*STR_PAIR_STRING_SIZE); 0137 if ( (*ppReader)->strPairTable[i] == 0 ) { 0138 o5mreader_setError(*ppReader, 0139 O5MREADER_ERR_CODE_MEMORY_ERROR, 0140 NULL 0141 ); 0142 return O5MREADER_RET_ERR; 0143 } 0144 } 0145 0146 o5mreader_setNoError(*ppReader); 0147 return O5MREADER_RET_OK; 0148 } 0149 0150 void o5mreader_close(O5mreader *pReader) { 0151 int i; 0152 if ( pReader ) { 0153 if ( pReader->strPairTable ) { 0154 for ( i = 0; i < STR_PAIR_TABLE_SIZE; ++i ) 0155 if ( pReader->strPairTable[i] ) 0156 free(pReader->strPairTable[i]); 0157 free(pReader->strPairTable); 0158 } 0159 o5mreader_setNoError(pReader); 0160 free(pReader); 0161 } 0162 } 0163 0164 const char* o5mreader_strerror(int errCode) { 0165 switch ( errCode ) { 0166 case O5MREADER_ERR_CODE_FILE_HAS_WRONG_START: 0167 return "'0xFF' isn't first byte of file."; 0168 case O5MREADER_ERR_CODE_MEMORY_ERROR: 0169 return "Memory error."; 0170 case O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE: 0171 return "Unexpected end of file."; 0172 case O5MREADER_ERR_CODE_CAN_NOT_ITERATE_TAGS_HERE: 0173 return "Tags iteration is not allowed here."; 0174 case O5MREADER_ERR_CODE_CAN_NOT_ITERATE_NDS_HERE: 0175 return "Nodes iteration is not allowed here."; 0176 case O5MREADER_ERR_CODE_CAN_NOT_ITERATE_REFS_HERE: 0177 return "References iteration is not allowed here."; 0178 default: 0179 return "Unknown error code"; 0180 } 0181 } 0182 0183 void o5mreader_setError(O5mreader *pReader,int code, const char* message) { 0184 pReader->errCode = code; 0185 if ( pReader->errMsg ) { 0186 free(pReader->errMsg); 0187 } 0188 if ( message ) { 0189 pReader->errMsg = (char*) malloc(strlen(message)+1); 0190 strcpy(pReader->errMsg,message); 0191 } 0192 } 0193 0194 void o5mreader_setNoError(O5mreader *pReader) { 0195 pReader->errCode = O5MREADER_ERR_CODE_OK; 0196 if ( pReader->errMsg ) { 0197 free(pReader->errMsg); 0198 } 0199 pReader->errMsg = NULL; 0200 } 0201 0202 O5mreaderIterateRet o5mreader_iterateDataSet(O5mreader *pReader, O5mreaderDataset* ds) { 0203 for (;;) { 0204 if ( pReader->offset ) { 0205 if ( o5mreader_skipTags(pReader) == O5MREADER_ITERATE_RET_ERR ) 0206 return O5MREADER_ITERATE_RET_ERR; 0207 0208 fseek( 0209 pReader->f, 0210 (pReader->current - ftell(pReader->f)) + pReader->offset, 0211 SEEK_CUR 0212 ); 0213 0214 pReader->offset = 0; 0215 } 0216 0217 if ( fread(&(ds->type),1,1,pReader->f) == 0 ) { 0218 o5mreader_setError(pReader, 0219 O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE, 0220 NULL 0221 ); 0222 return O5MREADER_ITERATE_RET_ERR; 0223 } 0224 0225 if ( O5MREADER_DS_END == ds->type ) 0226 return O5MREADER_ITERATE_RET_DONE; 0227 0228 if ( O5MREADER_DS_RESET == ds->type ) { 0229 o5mreader_reset(pReader); 0230 } 0231 else if ( 0xf0 == ds->type ) {} 0232 else { 0233 if ( o5mreader_readUInt(pReader,&pReader->offset) == O5MREADER_RET_ERR ) { 0234 return O5MREADER_ITERATE_RET_ERR; 0235 } 0236 pReader->current = ftell(pReader->f); 0237 0238 switch ( ds->type ) { 0239 case O5MREADER_DS_NODE: 0240 return o5mreader_readNode(pReader, ds); 0241 case O5MREADER_DS_WAY: 0242 return o5mreader_readWay(pReader, ds); 0243 case O5MREADER_DS_REL: 0244 return o5mreader_readRel(pReader, ds); 0245 /* 0246 case O5MREADER_DS_BBOX: 0247 case O5MREADER_DS_TSTAMP: 0248 case O5MREADER_DS_HEADER: 0249 case O5MREADER_DS_SYNC: 0250 case O5MREADER_DS_JUMP: 0251 default: 0252 break; 0253 */ 0254 } 0255 } 0256 } 0257 0258 0259 } 0260 0261 int o5mreader_thereAreNoMoreData(O5mreader *pReader) { 0262 return (int)((pReader->current - ftell(pReader->f)) + pReader->offset) <= 0; 0263 } 0264 0265 O5mreaderIterateRet o5mreader_readVersion(O5mreader *pReader, O5mreaderDataset* ds) { 0266 uint64_t tmp; 0267 if ( o5mreader_readUInt(pReader,&tmp) == O5MREADER_ITERATE_RET_ERR ) { 0268 return O5MREADER_ITERATE_RET_ERR; 0269 } 0270 ds->version = tmp; 0271 if ( tmp ) { 0272 if ( o5mreader_readUInt(pReader,&tmp) == O5MREADER_ITERATE_RET_ERR ) { 0273 return O5MREADER_ITERATE_RET_ERR; 0274 } 0275 0276 if ( o5mreader_readInt(pReader,&tmp) == O5MREADER_ITERATE_RET_ERR ) { 0277 return O5MREADER_ITERATE_RET_ERR; 0278 } 0279 0280 if ( o5mreader_thereAreNoMoreData(pReader) ) 0281 return O5MREADER_ITERATE_RET_DONE; 0282 0283 mtx.lock(); 0284 O5mreaderRet strPair = o5mreader_readStrPair(pReader,&pReader->tagPair,0); 0285 mtx.unlock(); 0286 if ( strPair == O5MREADER_ITERATE_RET_ERR ) { 0287 return O5MREADER_ITERATE_RET_ERR; 0288 } 0289 } 0290 0291 if ( o5mreader_thereAreNoMoreData(pReader) ) 0292 return O5MREADER_ITERATE_RET_DONE; 0293 0294 return O5MREADER_ITERATE_RET_NEXT; 0295 } 0296 0297 O5mreaderIterateRet o5mreader_iterateTags(O5mreader *pReader, char** pKey, char** pVal) { 0298 if ( pReader->canIterateRefs ) { 0299 if ( o5mreader_skipRefs(pReader) == O5MREADER_ITERATE_RET_ERR ) 0300 return O5MREADER_ITERATE_RET_ERR; 0301 } 0302 if ( pReader->canIterateNds ) { 0303 if ( o5mreader_skipNds(pReader) == O5MREADER_ITERATE_RET_ERR ) 0304 return O5MREADER_ITERATE_RET_ERR; 0305 } 0306 if ( !pReader->canIterateTags ) { 0307 o5mreader_setError(pReader, 0308 O5MREADER_ERR_CODE_CAN_NOT_ITERATE_TAGS_HERE, 0309 NULL 0310 ); 0311 return O5MREADER_ITERATE_RET_ERR; 0312 } 0313 if ( o5mreader_thereAreNoMoreData(pReader) ) { 0314 pReader->canIterateTags = 0; 0315 return O5MREADER_ITERATE_RET_DONE; 0316 } 0317 0318 mtx.lock(); 0319 O5mreaderRet strPair = o5mreader_readStrPair(pReader,&pReader->tagPair,0); 0320 mtx.unlock(); 0321 if ( strPair == O5MREADER_RET_ERR ) { 0322 return O5MREADER_ITERATE_RET_ERR; 0323 } 0324 if ( pKey ) 0325 *pKey = pReader->tagPair; 0326 if ( pVal ) 0327 *pVal = pReader->tagPair + strlen(pReader->tagPair) + 1; 0328 0329 return O5MREADER_ITERATE_RET_NEXT; 0330 } 0331 0332 O5mreaderIterateRet o5mreader_skipTags(O5mreader *pReader) { 0333 int ret = O5MREADER_ITERATE_RET_DONE; 0334 if ( pReader->canIterateTags ) { 0335 while ( O5MREADER_ITERATE_RET_NEXT == (ret = o5mreader_iterateTags(pReader, NULL, NULL)) ); 0336 } 0337 0338 return ret; 0339 } 0340 0341 O5mreaderIterateRet o5mreader_readNode(O5mreader *pReader, O5mreaderDataset* ds) { 0342 int64_t nodeId; 0343 int64_t lon,lat; 0344 if ( o5mreader_readInt(pReader,(uint64_t *)&nodeId) == O5MREADER_RET_ERR ) 0345 return O5MREADER_ITERATE_RET_ERR; 0346 0347 pReader->canIterateRefs = 0; 0348 pReader->canIterateNds = 0; 0349 pReader->canIterateTags = 1; 0350 0351 pReader->nodeId += nodeId; 0352 ds->id = pReader->nodeId; 0353 0354 0355 if ( o5mreader_readVersion(pReader, ds) == O5MREADER_ITERATE_RET_DONE ) { 0356 ds->isEmpty = 1; 0357 return O5MREADER_ITERATE_RET_NEXT; 0358 } 0359 else 0360 ds->isEmpty = 0; 0361 0362 if ( o5mreader_thereAreNoMoreData(pReader) ) { 0363 return O5MREADER_ITERATE_RET_NEXT; 0364 } 0365 0366 if ( o5mreader_readInt(pReader,(uint64_t *)&lon) == O5MREADER_RET_ERR ) 0367 return O5MREADER_ITERATE_RET_ERR; 0368 pReader->lon += (int32_t)lon; 0369 0370 if ( o5mreader_readInt(pReader,(uint64_t *)&lat) == O5MREADER_RET_ERR ) { 0371 return O5MREADER_ITERATE_RET_ERR; 0372 } 0373 pReader->lat += (int32_t)lat; 0374 0375 ds->lon = pReader->lon; 0376 ds->lat = pReader->lat; 0377 0378 return O5MREADER_ITERATE_RET_NEXT; 0379 } 0380 0381 O5mreaderIterateRet o5mreader_iterateNds(O5mreader *pReader, uint64_t *nodeId) { 0382 int64_t wayNodeId; 0383 0384 if ( !pReader->canIterateNds ) { 0385 o5mreader_setError(pReader, 0386 O5MREADER_ERR_CODE_CAN_NOT_ITERATE_NDS_HERE, 0387 NULL 0388 ); 0389 return O5MREADER_ITERATE_RET_ERR; 0390 } 0391 if ( ftell(pReader->f) >= long(pReader->offsetNd) ) { 0392 pReader->canIterateNds = 0; 0393 pReader->canIterateTags = 1; 0394 pReader->canIterateRefs = 0; 0395 return O5MREADER_ITERATE_RET_DONE; 0396 } 0397 0398 if ( o5mreader_readInt(pReader,(uint64_t *)&wayNodeId) == O5MREADER_RET_ERR ) 0399 return O5MREADER_ITERATE_RET_ERR; 0400 0401 pReader->wayNodeId += wayNodeId; 0402 0403 if ( nodeId ) 0404 *nodeId = pReader->wayNodeId; 0405 0406 return O5MREADER_ITERATE_RET_NEXT; 0407 } 0408 0409 O5mreaderIterateRet o5mreader_skipNds(O5mreader *pReader) { 0410 uint8_t ret; 0411 while ( pReader->canIterateNds && 0412 O5MREADER_ITERATE_RET_NEXT == (ret = o5mreader_iterateNds(pReader, NULL)) ); 0413 return ret; 0414 } 0415 0416 O5mreaderIterateRet o5mreader_readWay(O5mreader *pReader, O5mreaderDataset* ds) { 0417 int64_t wayId; 0418 if ( o5mreader_readInt(pReader,(uint64_t *)&wayId) == O5MREADER_RET_ERR) 0419 return O5MREADER_ITERATE_RET_ERR; 0420 0421 pReader->wayId += wayId; 0422 ds->id = pReader->wayId; 0423 if ( o5mreader_readVersion(pReader, ds) == O5MREADER_ITERATE_RET_DONE ) { 0424 ds->isEmpty = 1; 0425 return O5MREADER_ITERATE_RET_NEXT; 0426 } 0427 else 0428 ds->isEmpty = 0; 0429 if ( o5mreader_readUInt(pReader,&pReader->offsetNd) == O5MREADER_RET_ERR ) { 0430 return O5MREADER_ITERATE_RET_ERR; 0431 } 0432 pReader->offsetNd += ftell(pReader->f); 0433 pReader->canIterateRefs = 0; 0434 pReader->canIterateNds = 1; 0435 pReader->canIterateTags = 0; 0436 return O5MREADER_ITERATE_RET_NEXT; 0437 } 0438 0439 O5mreaderIterateRet o5mreader_iterateRefs(O5mreader *pReader, uint64_t *refId, uint8_t *type, char** pRole) { 0440 int64_t relRefId; 0441 0442 if ( !pReader->canIterateRefs ) { 0443 o5mreader_setError(pReader, 0444 O5MREADER_ERR_CODE_CAN_NOT_ITERATE_REFS_HERE, 0445 NULL 0446 ); 0447 return O5MREADER_ITERATE_RET_ERR; 0448 } 0449 if ( ftell(pReader->f) >= long(pReader->offsetRf) ) { 0450 pReader->canIterateNds = 0; 0451 pReader->canIterateTags = 1; 0452 pReader->canIterateRefs = 0; 0453 return O5MREADER_ITERATE_RET_DONE; 0454 } 0455 0456 if ( o5mreader_readInt(pReader, (uint64_t *)&relRefId) == O5MREADER_RET_ERR ) 0457 return O5MREADER_ITERATE_RET_ERR; 0458 0459 0460 //fread(_,1,1,pReader->f); 0461 0462 mtx.lock(); 0463 O5mreaderRet strPair = o5mreader_readStrPair(pReader, &pReader->tagPair,1); 0464 mtx.unlock(); 0465 if ( strPair == O5MREADER_RET_ERR ) { 0466 return O5MREADER_ITERATE_RET_ERR; 0467 } 0468 0469 switch( pReader->tagPair[0] ) { 0470 case '0': 0471 if ( type ) 0472 *type = O5MREADER_DS_NODE; 0473 pReader->nodeRefId += relRefId; 0474 if ( refId ) 0475 *refId = pReader->nodeRefId; 0476 break; 0477 case '1': 0478 if ( type ) 0479 *type = O5MREADER_DS_WAY; 0480 pReader->wayRefId += relRefId; 0481 if ( refId ) 0482 *refId = pReader->wayRefId; 0483 break; 0484 case '2': 0485 if ( type ) 0486 *type = O5MREADER_DS_REL; 0487 pReader->relRefId += relRefId; 0488 if ( refId ) 0489 *refId = pReader->relRefId; 0490 break; 0491 } 0492 0493 if ( pRole ) { 0494 *pRole = pReader->tagPair + 1; 0495 } 0496 0497 return O5MREADER_ITERATE_RET_NEXT; 0498 } 0499 0500 O5mreaderIterateRet o5mreader_skipRefs(O5mreader *pReader) { 0501 uint8_t ret; 0502 while ( pReader->canIterateRefs && 0503 O5MREADER_ITERATE_RET_NEXT == (ret = o5mreader_iterateRefs(pReader, NULL, NULL, NULL)) ); 0504 return ret; 0505 } 0506 0507 O5mreaderIterateRet o5mreader_readRel(O5mreader *pReader, O5mreaderDataset* ds) { 0508 int64_t relId; 0509 if ( o5mreader_readInt(pReader,(uint64_t *)&relId) == O5MREADER_RET_ERR ) 0510 return O5MREADER_ITERATE_RET_ERR; 0511 pReader->relId += relId; 0512 ds->id = pReader->relId; 0513 if ( o5mreader_readVersion(pReader,ds) == O5MREADER_ITERATE_RET_DONE ) { 0514 ds->isEmpty = 1; 0515 return O5MREADER_ITERATE_RET_NEXT; 0516 } 0517 else 0518 ds->isEmpty = 0; 0519 o5mreader_readUInt(pReader,&pReader->offsetRf); 0520 pReader->offsetRf += ftell(pReader->f); 0521 0522 pReader->canIterateRefs = 1; 0523 pReader->canIterateNds = 0; 0524 pReader->canIterateTags = 0; 0525 return O5MREADER_ITERATE_RET_NEXT; 0526 }