summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Nienhüser <[email protected]>2016-03-27 12:32:14 +0200
committerDennis Nienhüser <[email protected]>2016-03-27 12:32:14 +0200
commite0ab27b0fef18547fb12ecad3138e3ac1ea20d39 (patch)
treee6ffc7feb27c9c5219f73090369f9c9e92bea346
parentf0dcfc5d25e4e2c727d7a2160b0941b29893254e (diff)
Add o5mreader from https://github.com/bigr/o5mreader
License: MIT
-rw-r--r--src/plugins/runner/osm/o5mreader.c513
-rw-r--r--src/plugins/runner/osm/o5mreader.h93
2 files changed, 606 insertions, 0 deletions
diff --git a/src/plugins/runner/osm/o5mreader.c b/src/plugins/runner/osm/o5mreader.c
new file mode 100644
index 0000000..6efc630
--- /dev/null
+++ b/src/plugins/runner/osm/o5mreader.c
@@ -0,0 +1,513 @@
+#include "o5mreader.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+
+#define STR_PAIR_TABLE_SIZE 15000
+#define STR_PAIR_STRING_SIZE 256
+
+
+O5mreaderRet o5mreader_readUInt(O5mreader *pReader, uint64_t *ret) {
+ uint8_t b;
+ uint8_t i = 0;
+ *ret = 0LL;
+
+ do {
+ if ( fread(&b,1,1,pReader->f) == 0 ) {
+ o5mreader_setError(pReader,
+ O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE,
+ NULL
+ );
+ return O5MREADER_RET_ERR;
+ }
+ *ret |= (long long)(b & 0x7f) << (i++ * 7);
+ } while ( b & 0x80 );
+
+ o5mreader_setNoError(pReader);
+
+ return O5MREADER_RET_OK;
+}
+
+O5mreaderRet o5mreader_readInt(O5mreader *pReader, uint64_t *ret) {
+ if ( o5mreader_readUInt(pReader, ret) == O5MREADER_RET_ERR )
+ return O5MREADER_RET_ERR;
+ *ret = *ret & 1
+ ? -(int64_t)(*ret >> 1) - 1
+ : (int64_t)(*ret >> 1);
+ return O5MREADER_RET_OK;
+}
+
+
+O5mreaderRet o5mreader_readStrPair(O5mreader *pReader, char **tagpair, int single) {
+ static char buffer[1024];
+ char* pBuf;
+ static uint64_t pointer = 0;
+ int length;
+ char byte;
+ uint64_t key;
+ int i;
+
+ if ( o5mreader_readUInt(pReader,&key) == O5MREADER_RET_ERR ) {
+ return O5MREADER_RET_ERR;
+ }
+
+ if ( key ) {
+ *tagpair = pReader->strPairTable[(pointer+15000-key)%15000];
+ return key;
+ }
+ else {
+ pBuf = buffer;
+ for ( i=0; i<(single?1:2); i++ ) {
+ do {
+ if ( fread(pBuf,1,1,pReader->f) == 0 ) {
+ o5mreader_setError(pReader,
+ O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE,
+ NULL
+ );
+ return O5MREADER_RET_ERR;
+ }
+ } while ( *(pBuf++) );
+ }
+
+ length = strlen(buffer) + (single ? 1 : strlen(buffer+strlen(buffer) +1) + 2);
+
+ if ( length <= 252 ) {
+ *tagpair = pReader->strPairTable[(pointer+15000)%15000];
+ memcpy(pReader->strPairTable[((pointer++)+15000)%15000],buffer,length);
+ }
+ else {
+ *tagpair = buffer;
+ }
+
+ }
+
+ return O5MREADER_RET_OK;
+}
+
+O5mreaderRet o5mreader_reset(O5mreader *pReader) {
+ pReader->nodeId = pReader->wayId = pReader->wayNodeId = pReader->relId = pReader->nodeRefId = pReader->wayRefId = pReader->relRefId = 0;
+ pReader->lon = pReader->lat = 0;
+ pReader->offset = 0;
+ pReader->canIterateTags = pReader->canIterateNds = pReader->canIterateRefs = 0;
+}
+
+O5mreaderRet o5mreader_open(O5mreader **ppReader,FILE* f) {
+ uint8_t byte;
+ int i;
+ *ppReader = malloc(sizeof(O5mreader));
+ if ( !(*ppReader) ) {
+ return O5MREADER_RET_ERR;
+ }
+ (*ppReader)->errMsg = NULL;
+ (*ppReader)->f = f;
+ if ( fread(&byte,1,1,(*ppReader)->f) == 0 ) {
+ o5mreader_setError(*ppReader,
+ O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE,
+ NULL
+ );
+ return O5MREADER_RET_ERR;
+ }
+ if ( byte != O5MREADER_DS_RESET ) {
+ o5mreader_setError(*ppReader,
+ O5MREADER_ERR_CODE_FILE_HAS_WRONG_START,
+ NULL
+ );
+ return O5MREADER_RET_ERR;
+ }
+
+ o5mreader_reset(*ppReader);
+
+ (*ppReader)->strPairTable = malloc(STR_PAIR_TABLE_SIZE*sizeof(char*));
+ if ( (*ppReader)->strPairTable == 0 ) {
+ o5mreader_setError(*ppReader,
+ O5MREADER_ERR_CODE_MEMORY_ERROR,
+ NULL
+ );
+ return O5MREADER_RET_ERR;
+ }
+ for ( i = 0; i < STR_PAIR_TABLE_SIZE; ++i ) {
+ (*ppReader)->strPairTable[i] = malloc(sizeof(char)*STR_PAIR_STRING_SIZE);
+ if ( (*ppReader)->strPairTable[i] == 0 ) {
+ o5mreader_setError(*ppReader,
+ O5MREADER_ERR_CODE_MEMORY_ERROR,
+ NULL
+ );
+ return O5MREADER_RET_ERR;
+ }
+ }
+
+ o5mreader_setNoError(*ppReader);
+ return O5MREADER_RET_OK;
+}
+
+void o5mreader_close(O5mreader *pReader) {
+ int i;
+ if ( pReader ) {
+ if ( pReader->strPairTable ) {
+ for ( i = 0; i < STR_PAIR_TABLE_SIZE; ++i )
+ if ( pReader->strPairTable[i] )
+ free(pReader->strPairTable[i]);
+ free(pReader->strPairTable);
+ }
+ o5mreader_setNoError(pReader);
+ free(pReader);
+ }
+}
+
+const char* o5mreader_strerror(int errCode) {
+ switch ( errCode ) {
+ case O5MREADER_ERR_CODE_FILE_HAS_WRONG_START:
+ return "'0xFF' isn't first byte of file.";
+ case O5MREADER_ERR_CODE_MEMORY_ERROR:
+ return "Memory error.";
+ case O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE:
+ return "Unexpected end of file.";
+ case O5MREADER_ERR_CODE_CAN_NOT_ITERATE_TAGS_HERE:
+ return "Tags iteration is not allowed here.";
+ case O5MREADER_ERR_CODE_CAN_NOT_ITERATE_NDS_HERE:
+ return "Nodes iteration is not allowed here.";
+ case O5MREADER_ERR_CODE_CAN_NOT_ITERATE_REFS_HERE:
+ return "References iteration is not allowed here.";
+ default:
+ return "Unknown error code";
+ }
+}
+
+o5mreader_setError(O5mreader *pReader,int code, const char* message) {
+ pReader->errCode = code;
+ if ( pReader->errMsg ) {
+ free(pReader->errMsg);
+ }
+ if ( message ) {
+ pReader->errMsg = malloc(strlen(message)+1);
+ strcpy(pReader->errMsg,message);
+ }
+}
+
+o5mreader_setNoError(O5mreader *pReader) {
+ pReader->errCode = O5MREADER_ERR_CODE_OK;
+ if ( pReader->errMsg ) {
+ free(pReader->errMsg);
+ }
+ pReader->errMsg = NULL;
+}
+
+O5mreaderIterateRet o5mreader_iterateDataSet(O5mreader *pReader, O5mreaderDataset* ds) {
+ for (;;) {
+ if ( pReader->offset ) {
+ if ( o5mreader_skipTags(pReader) == O5MREADER_ITERATE_RET_ERR )
+ return O5MREADER_ITERATE_RET_ERR;
+
+ fseek(
+ pReader->f,
+ (pReader->current - ftell(pReader->f)) + pReader->offset,
+ SEEK_CUR
+ );
+
+ pReader->offset = 0;
+ }
+
+ if ( fread(&(ds->type),1,1,pReader->f) == 0 ) {
+ o5mreader_setError(pReader,
+ O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE,
+ NULL
+ );
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+
+ if ( O5MREADER_DS_END == ds->type )
+ return O5MREADER_ITERATE_RET_DONE;
+
+ if ( O5MREADER_DS_RESET == ds->type ) {
+ o5mreader_reset(pReader);
+ }
+ else if ( 0xf0 == ds->type ) {}
+ else {
+ if ( o5mreader_readUInt(pReader,&pReader->offset) == O5MREADER_RET_ERR ) {
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+ pReader->current = ftell(pReader->f);
+
+ switch ( ds->type ) {
+ case O5MREADER_DS_NODE:
+ return o5mreader_readNode(pReader, ds);
+ case O5MREADER_DS_WAY:
+ return o5mreader_readWay(pReader, ds);
+ case O5MREADER_DS_REL:
+ return o5mreader_readRel(pReader, ds);
+ /*
+ case O5MREADER_DS_BBOX:
+ case O5MREADER_DS_TSTAMP:
+ case O5MREADER_DS_HEADER:
+ case O5MREADER_DS_SYNC:
+ case O5MREADER_DS_JUMP:
+ default:
+ break;
+ */
+ }
+ }
+ }
+
+
+}
+
+int o5mreader_thereAreNoMoreData(O5mreader *pReader) {
+ return (int)((pReader->current - ftell(pReader->f)) + pReader->offset) <= 0;
+}
+
+O5mreaderIterateRet o5mreader_readVersion(O5mreader *pReader, O5mreaderDataset* ds) {
+ uint64_t tmp;
+ if ( o5mreader_readUInt(pReader,&tmp) == O5MREADER_ITERATE_RET_ERR ) {
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+ ds->version = tmp;
+ if ( tmp ) {
+ if ( o5mreader_readUInt(pReader,&tmp) == O5MREADER_ITERATE_RET_ERR ) {
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+
+ if ( o5mreader_readInt(pReader,&tmp) == O5MREADER_ITERATE_RET_ERR ) {
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+
+ if ( o5mreader_thereAreNoMoreData(pReader) )
+ return O5MREADER_ITERATE_RET_DONE;
+
+ if ( o5mreader_readStrPair(pReader,&pReader->tagPair,0) == O5MREADER_ITERATE_RET_ERR ) {
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+ }
+
+ if ( o5mreader_thereAreNoMoreData(pReader) )
+ return O5MREADER_ITERATE_RET_DONE;
+
+ return O5MREADER_ITERATE_RET_NEXT;
+}
+
+O5mreaderIterateRet o5mreader_iterateTags(O5mreader *pReader, char** pKey, char** pVal) {
+ if ( pReader->canIterateRefs ) {
+ if ( o5mreader_skipRefs(pReader) == O5MREADER_ITERATE_RET_ERR )
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+ if ( pReader->canIterateNds ) {
+ if ( o5mreader_skipNds(pReader) == O5MREADER_ITERATE_RET_ERR )
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+ if ( !pReader->canIterateTags ) {
+ o5mreader_setError(pReader,
+ O5MREADER_ERR_CODE_CAN_NOT_ITERATE_TAGS_HERE,
+ NULL
+ );
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+ if ( o5mreader_thereAreNoMoreData(pReader) ) {
+ pReader->canIterateTags = 0;
+ return O5MREADER_ITERATE_RET_DONE;
+ }
+
+ if ( o5mreader_readStrPair(pReader,&pReader->tagPair,0) == O5MREADER_RET_ERR ) {
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+ if ( pKey )
+ *pKey = pReader->tagPair;
+ if ( pVal )
+ *pVal = pReader->tagPair + strlen(pReader->tagPair) + 1;
+
+ return O5MREADER_ITERATE_RET_NEXT;
+}
+
+O5mreaderIterateRet o5mreader_skipTags(O5mreader *pReader) {
+ int ret;
+ if ( pReader->canIterateTags ) {
+ while ( O5MREADER_ITERATE_RET_NEXT == (ret = o5mreader_iterateTags(pReader, NULL, NULL)) );
+ }
+
+ return ret;
+}
+
+O5mreaderIterateRet o5mreader_readNode(O5mreader *pReader, O5mreaderDataset* ds) {
+ int64_t nodeId;
+ int64_t lon,lat;
+ if ( o5mreader_readInt(pReader,&nodeId) == O5MREADER_RET_ERR )
+ return O5MREADER_ITERATE_RET_ERR;
+
+ pReader->canIterateRefs = 0;
+ pReader->canIterateNds = 0;
+ pReader->canIterateTags = 1;
+
+ pReader->nodeId += nodeId;
+ ds->id = pReader->nodeId;
+
+
+ if ( o5mreader_readVersion(pReader, ds) == O5MREADER_ITERATE_RET_DONE ) {
+ ds->isEmpty = 1;
+ return O5MREADER_ITERATE_RET_NEXT;
+ }
+ else
+ ds->isEmpty = 0;
+
+ if ( o5mreader_thereAreNoMoreData(pReader) ) {
+ return O5MREADER_ITERATE_RET_NEXT;
+ }
+
+ if ( o5mreader_readInt(pReader,&lon) == O5MREADER_RET_ERR )
+ return O5MREADER_ITERATE_RET_ERR;
+ pReader->lon += (int32_t)lon;
+
+ if ( o5mreader_readInt(pReader,&lat) == O5MREADER_RET_ERR ) {
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+ pReader->lat += (int32_t)lat;
+
+ ds->lon = pReader->lon;
+ ds->lat = pReader->lat;
+
+ return O5MREADER_ITERATE_RET_NEXT;
+}
+
+O5mreaderIterateRet o5mreader_iterateNds(O5mreader *pReader, uint64_t *nodeId) {
+ int64_t wayNodeId;
+
+ if ( !pReader->canIterateNds ) {
+ o5mreader_setError(pReader,
+ O5MREADER_ERR_CODE_CAN_NOT_ITERATE_NDS_HERE,
+ NULL
+ );
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+ if ( ftell(pReader->f) >= pReader->offsetNd ) {
+ pReader->canIterateNds = 0;
+ pReader->canIterateTags = 1;
+ pReader->canIterateRefs = 0;
+ return O5MREADER_ITERATE_RET_DONE;
+ }
+
+ if ( o5mreader_readInt(pReader,&wayNodeId) == O5MREADER_RET_ERR )
+ return O5MREADER_ITERATE_RET_ERR;
+
+ pReader->wayNodeId += wayNodeId;
+
+ if ( nodeId )
+ *nodeId = pReader->wayNodeId;
+
+ return O5MREADER_ITERATE_RET_NEXT;
+}
+
+O5mreaderIterateRet o5mreader_skipNds(O5mreader *pReader) {
+ uint8_t ret;
+ while ( pReader->canIterateNds &&
+ O5MREADER_ITERATE_RET_NEXT == (ret = o5mreader_iterateNds(pReader, NULL)) );
+ return ret;
+}
+
+O5mreaderIterateRet o5mreader_readWay(O5mreader *pReader, O5mreaderDataset* ds) {
+ int64_t wayId;
+ if ( o5mreader_readInt(pReader,&wayId) == O5MREADER_RET_ERR)
+ return O5MREADER_ITERATE_RET_ERR;
+
+ pReader->wayId += wayId;
+ ds->id = pReader->wayId;
+ if ( o5mreader_readVersion(pReader, ds) == O5MREADER_ITERATE_RET_DONE ) {
+ ds->isEmpty = 1;
+ return O5MREADER_ITERATE_RET_NEXT;
+ }
+ else
+ ds->isEmpty = 0;
+ if ( o5mreader_readUInt(pReader,&pReader->offsetNd) == O5MREADER_RET_ERR ) {
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+ pReader->offsetNd += ftell(pReader->f);
+ pReader->canIterateRefs = 0;
+ pReader->canIterateNds = 1;
+ pReader->canIterateTags = 0;
+ return O5MREADER_ITERATE_RET_NEXT;
+}
+
+O5mreaderIterateRet o5mreader_iterateRefs(O5mreader *pReader, uint64_t *refId, uint8_t *type, char** pRole) {
+ int64_t relRefId;
+
+ if ( !pReader->canIterateRefs ) {
+ o5mreader_setError(pReader,
+ O5MREADER_ERR_CODE_CAN_NOT_ITERATE_REFS_HERE,
+ NULL
+ );
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+ if ( ftell(pReader->f) >= pReader->offsetRf ) {
+ pReader->canIterateNds = 0;
+ pReader->canIterateTags = 1;
+ pReader->canIterateRefs = 0;
+ return O5MREADER_ITERATE_RET_DONE;
+ }
+
+ if ( o5mreader_readInt(pReader, &relRefId) == O5MREADER_RET_ERR )
+ return O5MREADER_ITERATE_RET_ERR;
+
+
+ //fread(_,1,1,pReader->f);
+
+ if ( o5mreader_readStrPair(pReader, &pReader->tagPair,1) == O5MREADER_RET_ERR ) {
+ return O5MREADER_ITERATE_RET_ERR;
+ }
+
+ switch( pReader->tagPair[0] ) {
+ case '0':
+ if ( type )
+ *type = O5MREADER_DS_NODE;
+ pReader->nodeRefId += relRefId;
+ if ( refId )
+ *refId = pReader->nodeRefId;
+ break;
+ case '1':
+ if ( type )
+ *type = O5MREADER_DS_WAY;
+ pReader->wayRefId += relRefId;
+ if ( refId )
+ *refId = pReader->wayRefId;
+ break;
+ case '2':
+ if ( type )
+ *type = O5MREADER_DS_REL;
+ pReader->relRefId += relRefId;
+ if ( refId )
+ *refId = pReader->relRefId;
+ break;
+ }
+
+ if ( pRole ) {
+ *pRole = pReader->tagPair + 1;
+ }
+
+ return O5MREADER_ITERATE_RET_NEXT;
+}
+
+O5mreaderIterateRet o5mreader_skipRefs(O5mreader *pReader) {
+ uint8_t ret;
+ while ( pReader->canIterateRefs &&
+ O5MREADER_ITERATE_RET_NEXT == (ret = o5mreader_iterateRefs(pReader, NULL, NULL, NULL)) );
+ return ret;
+}
+
+O5mreaderIterateRet o5mreader_readRel(O5mreader *pReader, O5mreaderDataset* ds) {
+ int64_t relId;
+ if ( o5mreader_readInt(pReader,&relId) == O5MREADER_RET_ERR )
+ return O5MREADER_ITERATE_RET_ERR;
+ pReader->relId += relId;
+ ds->id = pReader->relId;
+ if ( o5mreader_readVersion(pReader,ds) == O5MREADER_ITERATE_RET_DONE ) {
+ ds->isEmpty = 1;
+ return O5MREADER_ITERATE_RET_NEXT;
+ }
+ else
+ ds->isEmpty = 0;
+ o5mreader_readUInt(pReader,&pReader->offsetRf);
+ pReader->offsetRf += ftell(pReader->f);
+
+ pReader->canIterateRefs = 1;
+ pReader->canIterateNds = 0;
+ pReader->canIterateTags = 0;
+ return O5MREADER_ITERATE_RET_NEXT;
+}
diff --git a/src/plugins/runner/osm/o5mreader.h b/src/plugins/runner/osm/o5mreader.h
new file mode 100644
index 0000000..08ce5c3
--- /dev/null
+++ b/src/plugins/runner/osm/o5mreader.h
@@ -0,0 +1,93 @@
+#ifndef __O5MREADER__H__
+#define __O5MREADER__H__
+
+#include <stdint.h>
+#include <stdio.h>
+
+
+#define O5MREADER_RET_OK 1
+#define O5MREADER_RET_ERR 0
+
+#define O5MREADER_ITERATE_RET_DONE 0
+#define O5MREADER_ITERATE_RET_ERR -1
+#define O5MREADER_ITERATE_RET_NEXT 1
+
+#define O5MREADER_DS_END 0xfe
+#define O5MREADER_DS_NODE 0x10
+#define O5MREADER_DS_WAY 0x11
+#define O5MREADER_DS_REL 0x12
+#define O5MREADER_DS_BBOX 0xdb
+#define O5MREADER_DS_TSTAMP 0xdc
+#define O5MREADER_DS_HEADER 0xe0
+#define O5MREADER_DS_SYNC 0xee
+#define O5MREADER_DS_JUMP 0xef
+#define O5MREADER_DS_RESET 0xff
+
+
+#define O5MREADER_ERR_CODE_OK 0
+#define O5MREADER_ERR_CODE_FILE_HAS_WRONG_START 1
+#define O5MREADER_ERR_CODE_UNEXPECTED_END_OF_FILE 2
+#define O5MREADER_ERR_CODE_MEMORY_ERROR 3
+#define O5MREADER_ERR_CODE_CAN_NOT_ITERATE_TAGS_HERE 4
+#define O5MREADER_ERR_CODE_CAN_NOT_ITERATE_NDS_HERE 5
+#define O5MREADER_ERR_CODE_CAN_NOT_ITERATE_REFS_HERE 6
+
+typedef int O5mreaderRet;
+typedef int O5mreaderIterateRet;
+
+typedef struct {
+ int errCode;
+ char* errMsg;
+ FILE *f;
+ uint64_t offset;
+ uint64_t offsetNd;
+ uint64_t offsetRf;
+ uint64_t current;
+ char* tagPair;
+ int64_t nodeId;
+ int64_t wayId;
+ int64_t wayNodeId;
+ int64_t relId;
+ int64_t nodeRefId;
+ int64_t wayRefId;
+ int64_t relRefId;
+ int32_t lon;
+ int32_t lat;
+ uint8_t canIterateTags;
+ uint8_t canIterateNds;
+ uint8_t canIterateRefs;
+ char** strPairTable;
+} O5mreader;
+
+typedef struct {
+ uint8_t type;
+ uint64_t id;
+ uint32_t version;
+ uint8_t isEmpty;
+ int32_t lon;
+ int32_t lat;
+} O5mreaderDataset;
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+O5mreaderRet o5mreader_open(O5mreader **ppReader,FILE* f);
+
+void o5mreader_close(O5mreader *pReader);
+
+const char* o5mreader_strerror(int errCode);
+
+O5mreaderIterateRet o5mreader_iterateDataSet(O5mreader *pReader, O5mreaderDataset* ds);
+
+O5mreaderIterateRet o5mreader_iterateTags(O5mreader *pReader, char** pKey, char** pVal);
+
+O5mreaderIterateRet o5mreader_iterateNds(O5mreader *pReader, uint64_t *nodeId);
+
+O5mreaderIterateRet o5mreader_iterateRefs(O5mreader *pReader, uint64_t *refId, uint8_t *type, char** pRole);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif //__O5MREADER__H__