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 }