[osmctools] 01/09: Imported Upstream version 0.7
Bas Couwenberg
sebastic at debian.org
Fri Mar 31 09:34:49 UTC 2017
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch master
in repository osmctools.
commit 45b417a44fd5c612c80dd30bbc52b6623b6a8e15
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Fri Mar 31 10:51:40 2017 +0200
Imported Upstream version 0.7
---
src/osmconvert.c | 910 ++++++++++++++++++++++++++++++++++++++++++---
src/osmfilter.c | 1093 +++++++++++++++++++++++++++++++++++++++++++++---------
src/osmupdate.c | 149 +++++---
3 files changed, 1873 insertions(+), 279 deletions(-)
diff --git a/src/osmconvert.c b/src/osmconvert.c
index 159689b..6fbfb4b 100644
--- a/src/osmconvert.c
+++ b/src/osmconvert.c
@@ -1,10 +1,10 @@
-// osmconvert 2016-02-12 20:30
-#define VERSION "0.8.5"
+// osmconvert 2017-03-30 19:00
+#define VERSION "0.8.7"
//
// compile this file:
// gcc osmconvert.c -lz -O3 -o osmconvert
//
-// (c) 2011..2016 Markus Weber, Nuernberg
+// (c) 2011..2017 Markus Weber, Nuernberg
// Richard Russo contributed the initiative to --add-bbox-tags option
//
// This program is free software; you can redistribute it and/or
@@ -44,6 +44,8 @@ const char* shorthelptext=
"--drop-nodes delete all nodes\n"
"--drop-ways delete all ways\n"
"--drop-relations delete all relations\n"
+"--modify-tags= define which tags are to be modified\n"
+"--modify-...-tags= similar to --keep-...-tags= (see above)\n"
"--diff calculate differences between two files\n"
"--diff-contents same as before, but compare whole contents\n"
"--subtract subtract objects given by following files\n"
@@ -192,6 +194,22 @@ const char* helptext=
" According to the combination of these parameters, no members\n"
" of the referred section will be written.\n"
"\n"
+"--modify-tags=<tag_modification_list>\n"
+" The tag modification list determines which tags will be\n"
+" modified. The example\n"
+" --modify-tags=\"highway=primary to =secondary\"\n"
+" will change every \"primary\" highway into \"secondary\".\n"
+" You can also use comparisons or add additional tags:\n"
+" --modify-way-tags=\"maxspeed>200 add highspeed=yes\"\n"
+"\n"
+"--modify-node-tags=TAG_MODIFICATION_LIST\n"
+"--modify-way-tags=TAG_MODIFICATION_LIST\n"
+"--modify-relation-tags=TAG_MODIFICATION_LIST\n"
+"--modify-node-way-tags=TAG_MODIFICATION_LIST\n"
+"--modify-node-relation-tags=TAG_MODIFICATION_LIST\n"
+"--modify-way-relation-tags=TAG_MODIFICATION_LIST\n"
+" Same as above, but just for the specified object types.\n"
+"\n"
"--diff\n"
" Calculate difference between two files and create a new .osc\n"
" or .o5c file.\n"
@@ -456,6 +474,44 @@ typedef enum {false= 0,true= 1} bool;
typedef uint8_t byte;
typedef unsigned int uint;
#define isdig(x) isdigit((unsigned char)(x))
+static byte isdigi_tab[]= {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+#define isdigi(c) (isdigi_tab[(c)]) // digit
+static byte digival_tab[]= {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,2,3,4,5,6,7,8,9,10,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+#define digival(c) (digival_tab[(c)])
+ // value of a digit, starting with 1, for comparisons only
+
static int loglevel= 0; // logging to stderr;
// 0: no logging; 1: small logging; 2: normal logging;
// 3: extended logging;
@@ -1813,9 +1869,8 @@ return false;
if(s[0]!=' ' && s[0]!='\t') { // not inside a section
if(x0!=nil && x1!=nil && (x1!=x0 || y1!=y0)) {
// last polygon was not closed
- if(x1==x0) { // the edge would be vertical
- // we have to insert an additional edge
- x0+= 3;
+ if(x1!=x0) { // missing edge not in north-south direction
+ // close the polygon
if(x0>x1)
{ bep->x1= x1; bep->y1= y1; bep->x2= x0; bep->y2= y0; }
else
@@ -1823,24 +1878,10 @@ return false;
bep->chain= NULL;
if(loglevel>=1)
fprintf(stderr,
- "+ %i %"PRIi32",%"PRIi32",%"PRIi32",%"PRIi32"\n",
- (int)(bep-border__edge),
- bep->x1,bep->y1,bep->x2,bep->y2);
+ "c %i %"PRIi32",%"PRIi32",%"PRIi32",%"PRIi32"\n",
+ (int)(bep-border__edge),bep->x1,bep->y1,bep->x2,bep->y2);
bep++;
- x1= x0; y1= y0;
- x0-= 3;
- } // the edge would be vertical
- // close the polygon
- if(x0>x1)
- { bep->x1= x1; bep->y1= y1; bep->x2= x0; bep->y2= y0; }
- else
- { bep->x1= x0; bep->y1= y0; bep->x2= x1; bep->y2= y1; }
- bep->chain= NULL;
- if(loglevel>=1)
- fprintf(stderr,
- "c %i %"PRIi32",%"PRIi32",%"PRIi32",%"PRIi32"\n",
- (int)(bep-border__edge),bep->x1,bep->y1,bep->x2,bep->y2);
- bep++;
+ } // missing edge not in north-south direction
} // end last polygon was not closed
x0= x1= nil;
} // end not inside a section
@@ -1856,20 +1897,22 @@ return false;
}
if(x!=nil) { // data plausible
if(x1!=nil) { // there is a preceding coordinate
- if(x==x1) x+= 2; // do not accept exact north-south
- // lines, because then we may not be able to determine
- // if a point lies inside or outside the polygon;
- if(x>x1)
- { bep->x1= x1; bep->y1= y1; bep->x2= x; bep->y2= y; }
- else
- { bep->x1= x; bep->y1= y; bep->x2= x1; bep->y2= y1; }
- bep->chain= NULL;
- if(loglevel>=1)
- fprintf(stderr,
- "- %i %"PRIi32",%"PRIi32",%"PRIi32",%"PRIi32"\n",
- (int)(bep-border__edge),
- bep->x1,bep->y1,bep->x2,bep->y2);
- bep++;
+ if(x1!=x) { // new edge not in north-south direction;
+ // we do not accept exact north-south lines,
+ // because then we may not be able to determine
+ // if a point lies inside or outside the polygon;
+ if(x>x1)
+ { bep->x1= x1; bep->y1= y1; bep->x2= x; bep->y2= y; }
+ else
+ { bep->x1= x; bep->y1= y; bep->x2= x1; bep->y2= y1; }
+ bep->chain= NULL;
+ if(loglevel>=1)
+ fprintf(stderr,
+ "- %i %"PRIi32",%"PRIi32",%"PRIi32",%"PRIi32"\n",
+ (int)(bep-border__edge),
+ bep->x1,bep->y1,bep->x2,bep->y2);
+ bep++;
+ } // new edge not in north-south direction
} // end there is a preceding coordinate
x1= x; y1= y;
if(x0==nil)
@@ -2017,20 +2060,18 @@ return false;
return true;
cross= 0;
- /* binary-search the edge with the closest x1 */ {
+ /* binary-search the edge with the closest x1 | x1<=x */ {
int i,i1,i2; // iteration indexes
i1= 0; i2= border__edge_n;
while(i2>i1+1) {
i= (i1+i2)/2;
bep= border__edge+i;
-//fprintf(stderr,"s %i %i %i %li\n",i1,i,i2,bep->x1); ///
if(bep->x1 > x) i2= i;
else i1= i;
-//fprintf(stderr," %i %i %i\n",i1,i,i2); ///
}
bep= border__edge+i1;
- } // end binary-search the edge with the closest x1
+ } // binary-search the edge with the closest x1 | x1<=x
bcp= NULL;
// (default, because we want to examine the own edge first)
@@ -5865,6 +5906,710 @@ static inline void pw_relation_close() {
//------------------------------------------------------------
+// Module modi_ OSM tag modification module
+//------------------------------------------------------------
+
+// this module provides tag modification functionality;
+// as usual, all identifiers of a module have the same prefix,
+// in this case 'modi'; an underline will follow in case of a
+// global accessible object, two underlines in case of objects
+// which are not meant to be accessed from outside this module;
+// the sections of private and public definitions are separated
+// by a horizontal line: ----
+
+static inline void modi__stresccpy(char *dest, const char *src,
+ size_t len) {
+ // similar as strmpy(), but remove every initial '\\' character;
+ // len: length of the source string - without terminating zero;
+ while(len>0) {
+ if(*src=='\\') { src++; len--; }
+ if(!(len>0) || *src==0)
+ break;
+ len--;
+ *dest++= *src++;
+ }
+ *dest= 0;
+ } // end modi__stresccpy()
+
+static inline bool modi__cmp(const char* s1,const char* s2) {
+ // this procedure compares two character strings;
+ // s1[]: first string;
+ // s2[0]: operator which shall be used for comparison;
+ // 0: '=', and there are wildcards coded in s2[1]:
+ // s2[1]==1: wildcard at start;
+ // s2[1]==2: wildcard at end;
+ // s2[1]==3: wildcard at both, start and end;
+ // 1: '!=', and there are wildcards coded in s2[1];
+ // 2: '='
+ // 4: '<'
+ // 5: '>='
+ // 6: '>'
+ // 7: '<='
+ // 8: unused
+ // 9: unused
+ // 10: '=', numeric
+ // 11: '!=', numeric
+ // 12: '<', numeric
+ // 13: '>=', numeric
+ // 14: '>', numeric
+ // 15: '<=', numeric
+ // s2+1: string to compare with the first string;
+ // this string will start at s2+2 if wildcards are supplied;
+ // return: condition is met;
+ int op,wc; // operator, wildcard flags
+ int diff; // (for numeric comparison)
+ unsigned char s1v,s2v; // (for numeric comparison)
+
+ op= *s2++;
+ if(op==2) { // '='
+ // first we care about the 'equal' operator
+ // because it's the most frequently used option
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *s1==0 && *s2==0;
+ }
+ switch(op) { // depending on comparison operator
+ case 0: // '=', and there are wildcards
+ wc= *s2++;
+ if(wc==2) { // wildcard at end
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *s2==0;
+ } // wildcard at end
+ if(wc==1) { // wildcard at start
+ const char* s11,*s22;
+
+ while(*s1!=0) { // for all start positions in s1[]
+ s11= s1; s22= s2;
+ while(*s11==*s22 && *s11!=0) { s11++; s22++; }
+ if(*s11==0 && *s22==0)
+ return true;
+ s1++;
+ } // for all start positions in s1[]
+ return false;
+ } // wildcard at start
+ /* wildcards at start and end */ {
+ const char* s11,*s22;
+
+ while(*s1!=0) { // for all start positions in s1[]
+ s11= s1; s22= s2;
+ while(*s11==*s22 && *s11!=0) { s11++; s22++; }
+ if(*s22==0)
+ return true;
+ s1++;
+ } // for all start positions in s1[]
+ return false;
+ } // wildcards at start and end
+ case 1: // '!=', and there are wildcards
+ wc= *s2++;
+ if(wc==2) { // wildcard at end
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *s2!=0;
+ } // wildcard at end
+ if(wc==1) { // wildcard at start
+ const char* s11,*s22;
+
+ while(*s1!=0) { // for all start positions in s1[]
+ s11= s1; s22= s2;
+ while(*s11==*s22 && *s11!=0) { s11++; s22++; }
+ if(*s11==0 && *s22==0)
+ return false;
+ s1++;
+ } // for all start positions in s1[]
+ return true;
+ } // wildcard at start
+ /* wildcards at start and end */ {
+ const char* s11,*s22;
+
+ while(*s1!=0) { // for all start positions in s1[]
+ s11= s1; s22= s2;
+ while(*s11==*s22 && *s11!=0) { s11++; s22++; }
+ if(*s22==0)
+ return false;
+ s1++;
+ } // for all start positions in s1[]
+ return true;
+ } // wildcards at start and end
+ //case 2: // '=' (we already cared about this)
+ case 3: // '!='
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *s1!=0 || *s2!=0;
+ case 4: // '<'
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *(unsigned char*)s1 < *(unsigned char*)s2;
+ case 5: // '>='
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *(unsigned char*)s1 >= *(unsigned char*)s2;
+ case 6: // '>'
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *(unsigned char*)s1 > *(unsigned char*)s2;
+ case 7: // '<='
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *(unsigned char*)s1 <= *(unsigned char*)s2;
+ case 10: // '=', numeric
+ while(*s1=='0') s1++;
+ while(*s2=='0') s2++;
+ while(*s1==*s2 && isdigi(*(unsigned char*)s1))
+ { s1++; s2++; }
+ if(*s1=='.') {
+ if(*s2=='.') {
+ do { s1++; s2++; }
+ while(*s1==*s2 && isdigi(*(unsigned char*)s1));
+ if(!isdigi(*(unsigned char*)s1)) {
+ while(*s2=='0') s2++;
+ return !isdigi(*(unsigned char*)s2);
+ }
+ if(!isdigi(*(unsigned char*)s2)) {
+ while(*s1=='0') s1++;
+ return !isdigi(*(unsigned char*)s1);
+ }
+ return !isdigi(*(unsigned char*)s1) &&
+ !isdigi(*(unsigned char*)s2);
+ }
+ do s1++;
+ while(*s1=='0');
+ return !isdigi(*(unsigned char*)s1);
+ }
+ if(*s2=='.') {
+ do s2++;
+ while(*s2=='0');
+ return !isdigi(*(unsigned char*)s2);
+ }
+ return !isdigi(*(unsigned char*)s1) && !isdigi(*(unsigned char*)s2);
+ case 11: // '!=', numeric
+ while(*s1=='0') s1++;
+ while(*s2=='0') s2++;
+ while(*s1==*s2 && isdigi(*(unsigned char*)s1))
+ { s1++; s2++; }
+ if(*s1=='.') {
+ if(*s2=='.') {
+ do { s1++; s2++; }
+ while(*s1==*s2 && isdigi(*(unsigned char*)s1));
+ if(!isdigi(*(unsigned char*)s1)) {
+ while(*s2=='0') s2++;
+ return isdigi(*(unsigned char*)s2);
+ }
+ if(!isdigi(*(unsigned char*)s2)) {
+ while(*s1=='0') s1++;
+ return isdigi(*(unsigned char*)s1);
+ }
+ return isdigi(*(unsigned char*)s1) ||
+ isdigi(*(unsigned char*)s2);
+ }
+ do s1++;
+ while(*s1=='0');
+ return isdigi(*(unsigned char*)s1);
+ }
+ if(*s2=='.') {
+ do s2++;
+ while(*s2=='0');
+ return isdigi(*(unsigned char*)s2);
+ }
+ return isdigi(*(unsigned char*)s1) || isdigi(*(unsigned char*)s2);
+ case 12: /* '<', numeric */
+ #define Ds1 s1
+ #define Ds2 s2
+ s1v= *(unsigned char*)Ds1; s2v= *(unsigned char*)Ds2;
+ if(s1v=='-') {
+ if(s2v=='-') {
+ Ds1++; s2v= *(unsigned char*)Ds1;
+ Ds2++; s1v= *(unsigned char*)Ds2;
+ goto op_14;
+ }
+ return true;
+ }
+ else if(s2v=='-')
+ return false;
+ op_12:
+ while(s1v=='0') { Ds1++; s1v= *(unsigned char*)Ds1; }
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ while(s1v==s2v && isdigi(s1v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ diff= digival(s1v)-digival(s2v);
+ while(isdigi(s1v) && isdigi(s2v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ if(s1v=='.') {
+ if(s2v=='.') {
+ if(diff!=0)
+ return diff<0;
+ do {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ } while(s1v==s2v && isdigi(s1v));
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ return digival(s1v) < digival(s2v);
+ }
+ return isdigi(s2v) || diff<0;
+ }
+ if(s2v=='.') {
+ if(isdigi(s1v))
+ return false;
+ if(diff!=0)
+ return diff<0;
+ do { Ds2++; s2v= *(unsigned char*)Ds2; } while(s2v=='0');
+ return isdigi(s2v);
+ }
+ return isdigi(s2v) || (!isdigi(s1v) && diff<0);
+ #undef Ds1
+ #undef Ds2
+ case 13: /* '>=', numeric */
+ #define Ds1 s1
+ #define Ds2 s2
+ s1v= *(unsigned char*)Ds1; s2v= *(unsigned char*)Ds2;
+ if(s1v=='-') {
+ if(s2v=='-') {
+ Ds1++; s2v= *(unsigned char*)Ds1;
+ Ds2++; s1v= *(unsigned char*)Ds2;
+ goto op_15;
+ }
+ return false;
+ }
+ else if(s2v=='-')
+ return true;
+ op_13:
+ while(s1v=='0') { Ds1++; s1v= *(unsigned char*)Ds1; }
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ while(s1v==s2v && isdigi(s1v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ diff= digival(s1v)-digival(s2v);
+ while(isdigi(s1v) && isdigi(s2v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ if(s1v=='.') {
+ if(s2v=='.') {
+ if(diff!=0)
+ return diff>=0;
+ do {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ } while(s1v==s2v && isdigi(s1v));
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ return digival(s1v) >= digival(s2v);
+ }
+ return !isdigi(s2v) && diff>=0;
+ }
+ if(s2v=='.') {
+ if(isdigi(s1v))
+ return true;
+ if(diff!=0)
+ return diff>=0;
+ do { Ds2++; s2v= *(unsigned char*)Ds2; } while(s2v=='0');
+ return !isdigi(s2v);
+ }
+ return !isdigi(s2v) && (isdigi(s1v) || diff>=0);
+ #undef Ds1
+ #undef Ds2
+ case 14: /* '>', numeric */
+ #define Ds1 s2
+ #define Ds2 s1
+ s1v= *(unsigned char*)Ds1; s2v= *(unsigned char*)Ds2;
+ if(s1v=='-') {
+ if(s2v=='-') {
+ Ds1++; s2v= *(unsigned char*)Ds1;
+ Ds2++; s1v= *(unsigned char*)Ds2;
+ goto op_12;
+ }
+ return true;
+ }
+ else if(s2v=='-')
+ return false;
+ op_14:
+ while(s1v=='0') { Ds1++; s1v= *(unsigned char*)Ds1; }
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ while(s1v==s2v && isdigi(s1v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ diff= digival(s1v)-digival(s2v);
+ while(isdigi(s1v) && isdigi(s2v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ if(s1v=='.') {
+ if(s2v=='.') {
+ if(diff!=0)
+ return diff<0;
+ do {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ } while(s1v==s2v && isdigi(s1v));
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ return digival(s1v) < digival(s2v);
+ }
+ return isdigi(s2v) || diff<0;
+ }
+ if(s2v=='.') {
+ if(isdigi(s1v))
+ return false;
+ if(diff!=0)
+ return diff<0;
+ do { Ds2++; s2v= *(unsigned char*)Ds2; } while(s2v=='0');
+ return isdigi(s2v);
+ }
+ return isdigi(s2v) || (!isdigi(s1v) && diff<0);
+ #undef Ds1
+ #undef Ds2
+ case 15: /* '<=', numeric */
+ #define Ds1 s2
+ #define Ds2 s1
+ s1v= *(unsigned char*)Ds1; s2v= *(unsigned char*)Ds2;
+ if(s1v=='-') {
+ if(s2v=='-') {
+ Ds1++; s2v= *(unsigned char*)Ds1;
+ Ds2++; s1v= *(unsigned char*)Ds2;
+ goto op_13;
+ }
+ return false;
+ }
+ else if(s2v=='-')
+ return true;
+ op_15:
+ while(s1v=='0') { Ds1++; s1v= *(unsigned char*)Ds1; }
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ while(s1v==s2v && isdigi(s1v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ diff= digival(s1v)-digival(s2v);
+ while(isdigi(s1v) && isdigi(s2v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ if(s1v=='.') {
+ if(s2v=='.') {
+ if(diff!=0)
+ return diff>=0;
+ do {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ } while(s1v==s2v && isdigi(s1v));
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ return digival(s1v) >= digival(s2v);
+ }
+ return !isdigi(s2v) && diff>=0;
+ }
+ if(s2v=='.') {
+ if(isdigi(s1v))
+ return true;
+ if(diff!=0)
+ return diff>=0;
+ do { Ds2++; s2v= *(unsigned char*)Ds2; } while(s2v=='0');
+ return !isdigi(s2v);
+ }
+ return !isdigi(s2v) && (isdigi(s1v) || diff>=0);
+ #undef Ds1
+ #undef Ds2
+ // (no default)
+ } // depending on comparison operator
+ return false; // (we never get here)
+ } // end modi__cmp()
+
+#define modi__pairM 1000 // maximum number of key-val-pairs
+#define modi__pairkM 100 // maximum length of key or val;
+#define modi__pairtM 3 // maximum number of modification types;
+ // these modification types are defined as follows:
+ // 0: modify node tag;
+ // 1: modify way tag;
+ // 2: modify relation tag;
+struct modi__pair_struct {
+ // key/val pair for the include filter
+ char k[modi__pairkM+8]; // key to compare;
+ // [0]==0 && [1]==0: same key as previous key in list;
+ char v[modi__pairkM+8]; // value to the key in .k[];
+ // the first byte represents a comparison operator,
+ // see parameter s2[]in modi__cmp() for details;
+ // [0]==0 && [1]==0: any value will be accepted;
+ char nk[modi__pairkM+2]; // new key
+ char nv[modi__pairkM+2]; // new value
+ bool add; // new key/val pair shall be added instead of replacing
+ // the old key/val pair
+ } __attribute__((__packed__));
+typedef struct modi__pair_struct modi__pair_t;
+static modi__pair_t modi__pair[modi__pairtM][modi__pairM+2]=
+ {{{{0},{0},{0},{0}}}};
+static modi__pair_t* modi__paire[modi__pairtM]=
+ { &modi__pair[0][0],&modi__pair[1][0],&modi__pair[2][0] };
+static modi__pair_t* modi__pairee[modi__pairtM]=
+ { &modi__pair[0][modi__pairM],&modi__pair[1][modi__pairM],
+ &modi__pair[2][modi__pairM] };
+
+//------------------------------------------------------------
+
+static inline void modi_cpy(char *dest, const char *src,
+ size_t len,int op) {
+ // similar as strmpy(), but remove every initial '\\' character;
+ // len: length of the source string - without terminating zero;
+ // op: comparison operator;
+ // 2: '='
+ // 4: '<'
+ // 5: '>='
+ // 6: '>'
+ // 7: '<='
+ // return: dest[0]: comparison operator; additional possible values:
+ // 0: '=', and there are wildcards coded in dest[1]:
+ // dest[1]==1: wildcard at start;
+ // dest[1]==2: wildcard at end;
+ // dest[1]==3: wildcard at both, start and end;
+ // 1: '!=', and there are wildcards coded in dest[1];
+ // 10: '=', numeric
+ // 11: '!=', numeric
+ // 12: '<', numeric
+ // 13: '>=', numeric
+ // 14: '>', numeric
+ // 15: '<=', numeric
+ int wc; // wildcard indicator, see modi__cmp()
+
+ if(op<0) { // unknown operator
+ WARNv("unknown comparison at: %.80s",src)
+ op= 2; // assume '='
+ }
+ if(len>(modi__pairkM)) {
+ len= modi__pairkM; // delimit value length
+ WARNv("modification argument too long: %.*s",modi__pairkM,src)
+ }
+ wc= 0; // (default)
+ if(len>=2 && src[0]=='*') { // wildcard at start
+ wc|= 1;
+ src++; len--;
+ }
+ if((len>=2 && src[len-1]=='*' && src[len-2]!='\\') ||
+ (len==1 && src[len-1]=='*')) {
+ // wildcard at end
+ wc|= 2;
+ len--;
+ }
+ if(wc==0) { // no wildcard(s)
+ const char* v;
+
+ v= src;
+ if(*v=='-') v++; // jump over sign
+ if(isdig(*v)) // numeric value
+ op+= 8;
+ dest[0]= op;
+ modi__stresccpy(dest+1,src,len); // store this value
+ } // no wildcard(s)
+ else { // wildcard(s)
+ dest[0]= op&1;
+ dest[1]= wc;
+ modi__stresccpy(dest+2,src,len); // store this value
+ } // wildcard(s)
+ } // end modi_cpy()
+
+static bool modi_active= false;
+ // there is at least one modify criteria active;
+ // may be read by everyone but written only by this module;
+static bool modi_activetype[modi__pairtM]= {false,false,false};
+ // the related modify list has at least one element;
+ // may be read by everyone but written only by this module;
+
+static void modi_ini() {
+ // initialize this mudule;
+ int i;
+
+ modi_active= false;
+ for(i= 0; i<modi__pairtM; i++) {
+ modi__paire[i]= &modi__pair[i][0];
+ modi__pairee[i]= &modi__pair[i][modi__pairM];
+ modi_activetype[i]= false;
+ }
+ } // modi_ini()
+
+static void modi_parse(int ftype,const char* arg) {
+ // interprets a command line argument and stores modification
+ // information;
+ // ftype: object type; see explanation at modi__pairtM;
+ // arg[]: modification information; e.g.:
+ // "amenity=fire_hydrant to emergency=fire_hydrant"
+ modi__pair_t*fe,*fee;
+ const char* pk,*pv,*pe; // pointers in parameter for key/val pairs;
+ // pk: key; pv: val; pe: end of val;
+ int len; // string length
+ int op; // operator, see modi__cmp()
+
+ fe= modi__paire[ftype];
+ fee= modi__pairee[ftype];
+ if(loglevel>0)
+ PINFOv("Modify: %s tags:",ONAME(ftype%3))
+ pk= arg;
+ while(*pk==' ') pk++; // jump over spaces
+
+ while(pk!=NULL && fe<fee) { // for every key/val pair
+ while(*pk==' ') pk++; // jump over (additional) spaces
+ if(*pk==0)
+ break;
+ pe= pk;
+ while((*pe!=' ' || pe[-1]=='\\') && *pe!=0) pe++;
+ // get end of this pair
+ len= pe-pk; // length of this argument
+ pv= pk;
+ while(((*pv!='=' && *pv!='<' && *pv!='>' &&
+ (*pv!='!' || pv[1]!='=')) ||
+ (pv>pk && pv[-1]=='\\')) && pv<pe) pv++;
+ // find operator =, <, >, !=
+ if(pv>=pe-1) pv= pe; // there was no operator in this pair
+ len= pv-pk; // length of this key
+ if(len>(modi__pairkM)) {
+ len= modi__pairkM; // delimit key length
+ WARNv("modification key too long: %.*s",modi__pairkM,pk)
+ }
+ op= -1; // 'unknown operator' (default)
+ if(pv>=pe) { // there is a key but no value
+ if(len>0 && pk[len-1]=='=') len--;
+ modi_cpy(fe->k,pk,len,2); // store this key, op='='
+ memset(fe->v,0,3); // store empty value
+ }
+ else { // key and value
+ if(len==0) // no key given
+ memset(fe->k,0,3); // store empty key,
+ else
+ modi_cpy(fe->k,pk,len,2); // store this key, op='='
+ if(*pv=='=') op= 2;
+ else if(*pv=='!' && pv[1]=='=') op= 3;
+ else if(*pv=='<' && pv[1]!='=') op= 4;
+ else if(*pv=='>' && pv[1]=='=') op= 5;
+ else if(*pv=='>' && pv[1]!='=') op= 6;
+ else if(*pv=='<' && pv[1]=='=') op= 7;
+ if(op<0) { // unknown operator
+ WARNv("unknown comparison at: %.80s",pv)
+ op= 2; // assume '='
+ }
+ pv++; // jump over operator
+ if(pv<pe && *pv=='=') pv++;
+ // jump over second character of a two-character operator
+ len= pe-pv; // length of this value
+ modi_cpy(fe->v,pv,len,op); // store this value
+ } // key and value
+ // jump over ' to ' phrase
+ while(*pe==' ') pe++; // jump over spaces
+ if((fe->add= strzcmp(pe,"add ")==0)) pe+= 4;
+ else if(strzcmp(pe,"to ")==0) pe+= 3;
+ // get destination key/val
+ pk= pe; // jump to next key/val pair in parameter list
+ while(*pk==' ') pk++; // jump over (additional) spaces
+ pe= pk;
+ while((*pe!=' ' || pe[-1]=='\\') && *pe!=0) pe++;
+ // get end of this destination pair
+ len= pe-pk; // length of this argument
+ pv= pk;
+ while((*pv!='=' || (pv>pk && pv[-1]=='\\')) && pv<pe) pv++;
+ // find operator '='
+ if(pv>=pe-1) pv= pe; // there was no operator in this pair
+ len= pv-pk; // length of this key
+ if(len>(modi__pairkM)) {
+ len= modi__pairkM; // delimit key length
+ WARNv("modification key too long: %.*s",modi__pairkM,pk)
+ }
+ if(pv>=pe) { // there is a destination key but no value
+ if(len>0 && pk[len-1]=='=') len--;
+ modi__stresccpy(fe->nk,pk,len); // store this key
+ fe->nv[0]= 0; // store empty value
+ }
+ else { // destination key and value
+ if(len==0) // no key given
+ modi__stresccpy(fe->nk,fe->k[0]<=1? fe->k+2: fe->k+1,
+ modi__pairkM);
+ // store source key as destination key
+ else
+ modi__stresccpy(fe->nk,pk,len); // store this key
+ pv++; // jump over equation operator
+ if(pv<pe && *pv=='=') pv++;
+ // jump over second character of a two-character operator
+ len= pe-pv; // length of this value
+ if(len==0) // no value given
+ modi__stresccpy(fe->nv,fe->v[0]<=1? fe->v+2: fe->v+1,
+ modi__pairkM);
+ // store source value as destination value
+ else
+ modi__stresccpy(fe->nv,pv,len); // store this value
+ } // destination key and value
+ if(loglevel>0) {
+ static const char* ops[]= { "?",
+ "=","!=","=","!=","<",">=",">","<=",
+ "?","?","=(numeric)","!=(numeric)",
+ "<(numeric)",">=(numeric)",">(numeric)","<=(numeric)" };
+ PINFOv("Modify: %s\"%.80s\"%s %s %s\"%.80s\"%s",
+ fe->k[0]<=1 && (fe->k[1] & 1)? "*": "",
+ *(int16_t*)(fe->k)==0? "(last key)":
+ fe->k[0]>=2? fe->k+1: fe->k+2,
+ fe->k[0]<=1 && (fe->k[1] & 2)? "*": "",
+ ops[fe->v[0]+1],
+ fe->v[0]<=1 && (fe->v[1] & 1)? "*": "",
+ *(int16_t*)(fe->v)==0? "(anything)":
+ fe->v[0]>=2? fe->v+1: fe->v+2,
+ fe->v[0]<=1 && (fe->v[1] & 2)? "*": "");
+ }
+ fe++; // next pair in key/val table
+ pk= pe; // jump to next key/val pair in parameter list
+ } // end for every key/val pair
+ if(fe>=fee)
+ WARN("too many modification parameters.")
+ modi__paire[ftype]= fe;
+ modi_active= true;
+ modi_activetype[ftype]= true;
+ } // end modi_parse()
+
+static char* modi_check_key= "-",*modi_check_val= "-";
+ static bool modi_check_add= false;
+ // return values of procedure modi_check();
+ // the values are valid only if the previous call to modi_check()
+ // has returned 'true';
+
+static inline bool modi_check(int otype,char* key,char* val) {
+ // check if OSM object matches modification criteria;
+ // otype: 0: node; 1: way; 2: relation;
+ // key,val: key and value;
+ // return: given key/val pair matches modification criteria;
+ // modi_check_key,modi_check_val: destination key/val;
+ // modi_check_add: the destination key/val shall be added
+ // instead of replacing the old key/val pair;
+ modi__pair_t* fp,*fe;
+
+ fp= modi__pair[otype]; fe= modi__paire[otype];
+ while(fp<fe) { // for every key/val pair in filter
+ if(*(int16_t*)(fp->k)==0) { // no key given
+ if(modi__cmp(val,fp->v)) // just compare the value
+ goto modi_check_found;
+ }
+ else { // key given
+ if(modi__cmp(key,fp->k) &&
+ (*(int16_t*)(fp->k)==0 || modi__cmp(val,fp->v)))
+ // compare key and value (if any)
+ goto modi_check_found;
+ }
+ fp++;
+ } // for every key/val pair in filter
+ return false;
+modi_check_found:
+ if(fp->nk[0]!=0) // there is a destination key
+ modi_check_key= fp->nk; // take that destination key
+ else
+ modi_check_key= key;
+ // take source key instead
+ if(fp->nv[0]!=0) // there is a destination value
+ modi_check_val= fp->nv; // take that destination value
+ else
+ modi_check_val= val;
+ // take source value instead
+ modi_check_add= fp->add; // publish key/val add request
+ return true;
+ } // end modi_check()
+
+#define modi_CHECK(ot,k,v) \
+ (modi_active && modi_activetype[ot] && modi_check(ot,k,v))
+ // prevents procedure call in case there are no modifications applied
+
+//------------------------------------------------------------
+// end Module modi_ OSM tag modification module
+//------------------------------------------------------------
+
+
+
+//------------------------------------------------------------
// Module posi_ OSM position module
//------------------------------------------------------------
@@ -10761,8 +11506,15 @@ return 26;
wo_node(id,
hisver,histime,hiscset,hisuid,hisuser,lon,lat);
keyp= key; valp= val;
- while(keyp<keye) // for all key/val pairs of this object
- wo_node_keyval(*keyp++,*valp++);
+ while(keyp<keye) { // for all key/val pairs of this object
+ if(modi_CHECK(otype,*keyp,*valp)) {
+ if(modi_check_add) wo_node_keyval(*keyp++,*valp++);
+ else keyp++; valp++;
+ wo_node_keyval(modi_check_key,modi_check_val);
+ }
+ else
+ wo_node_keyval(*keyp++,*valp++);
+ } // for all key/val pairs of this object
wo_node_close();
} // end not to drop
} // end node lies inside
@@ -10896,8 +11648,16 @@ return 26;
if(global_add)
wo_addbboxtags(true,x_min,y_min,x_max,y_max);
keyp= key; valp= val;
- while(keyp<keye) // for all key/val pairs of this object
- wo_node_keyval(*keyp++,*valp++);
+ while(keyp<keye) {
+ // for all key/val pairs of this object
+ if(modi_CHECK(otype,*keyp,*valp)) {
+ if(modi_check_add) wo_node_keyval(*keyp++,*valp++);
+ else keyp++; valp++;
+ wo_node_keyval(modi_check_key,modi_check_val);
+ }
+ else
+ wo_node_keyval(*keyp++,*valp++);
+ } // for all key/val pairs of this object
wo_node_close();
} // there is at least one coordinate available
} // convert all objects to nodes
@@ -10913,8 +11673,16 @@ return 26;
if(global_add)
wo_addbboxtags(false,x_min,y_min,x_max,y_max);
keyp= key; valp= val;
- while(keyp<keye) // for all key/val pairs of this object
- wo_wayrel_keyval(*keyp++,*valp++);
+ while(keyp<keye) {
+ // for all key/val pairs of this object
+ if(modi_CHECK(otype,*keyp,*valp)) {
+ if(modi_check_add) wo_wayrel_keyval(*keyp++,*valp++);
+ else keyp++; valp++;
+ wo_wayrel_keyval(modi_check_key,modi_check_val);
+ }
+ else
+ wo_wayrel_keyval(*keyp++,*valp++);
+ } // for all key/val pairs of this object
wo_way_close();
} // objects are not to be converted to nodes
} // coordinates of ways shall be calculated
@@ -10928,8 +11696,16 @@ return 26;
refidp++;
} // end for every referenced node
keyp= key; valp= val;
- while(keyp<keye) // for all key/val pairs of this object
- wo_wayrel_keyval(*keyp++,*valp++);
+ while(keyp<keye) {
+ // for all key/val pairs of this object
+ if(modi_CHECK(otype,*keyp,*valp)) {
+ if(modi_check_add) wo_wayrel_keyval(*keyp++,*valp++);
+ else keyp++; valp++;
+ wo_wayrel_keyval(modi_check_key,modi_check_val);
+ }
+ else
+ wo_wayrel_keyval(*keyp++,*valp++);
+ } // for all key/val pairs of this object
wo_way_close();
} // coordinates of ways need not to be calculated
} // end not ways to drop
@@ -11044,8 +11820,16 @@ return 26;
wo_addbboxtags(true,
posi_xy[2],posi_xy[3],posi_xy[4],posi_xy[5]);
keyp= key; valp= val;
- while(keyp<keye) // for all key/val pairs of this object
- wo_node_keyval(*keyp++,*valp++);
+ while(keyp<keye) {
+ // for all key/val pairs of this object
+ if(modi_CHECK(otype,*keyp,*valp)) {
+ if(modi_check_add) wo_node_keyval(*keyp++,*valp++);
+ else keyp++; valp++;
+ wo_node_keyval(modi_check_key,modi_check_val);
+ }
+ else
+ wo_node_keyval(*keyp++,*valp++);
+ } // for all key/val pairs of this object
wo_node_close();
} // stored coordinates are valid
} // relations are to be converted to nodes
@@ -11095,8 +11879,16 @@ return 26;
posi_xy[2],posi_xy[3],posi_xy[4],posi_xy[5]);
}
keyp= key; valp= val;
- while(keyp<keye) // for all key/val pairs of this object
- wo_wayrel_keyval(*keyp++,*valp++);
+ while(keyp<keye) {
+ // for all key/val pairs of this object
+ if(modi_CHECK(otype,*keyp,*valp)) {
+ if(modi_check_add) wo_wayrel_keyval(*keyp++,*valp++);
+ else keyp++; valp++;
+ wo_wayrel_keyval(modi_check_key,modi_check_val);
+ }
+ else
+ wo_wayrel_keyval(*keyp++,*valp++);
+ } // for all key/val pairs of this object
wo_relation_close();
} // stage!=3 OR not --all-to-nodes
} // end no borders OR at least one node inside
@@ -11823,6 +12615,7 @@ int main(int argc,char** argv) {
// initializations
usesstdin= false;
h_n= h_w= h_r= 0;
+ modi_ini();
#if __WIN32__
setmode(fileno(stdout),O_BINARY);
setmode(fileno(stdin),O_BINARY);
@@ -12245,6 +13038,17 @@ return 4;
} // end border consideration by polygon file
continue; // take next parameter
}
+ #define F(t) modi_parse(t,a+l);
+ #define D(p,f) if((l= strzlcmp(a,#p))>0) { f continue; }
+ D(--modify-tags=,F(0)F(1)F(2))
+ D(--modify-node-tags=,F(0))
+ D(--modify-way-tags=,F(1))
+ D(--modify-relation-tags=,F(2))
+ D(--modify-node-way-tags=,F(0)F(1))
+ D(--modify-node-relation-tags=,F(0)F(2))
+ D(--modify-way-relation-tags=,F(1)F(2))
+ #undef D
+ #undef F
if(strcmp(a,"-")==0) { // use standard input
usesstdin= true;
if(oo_open(NULL)) // file cannot be read
diff --git a/src/osmfilter.c b/src/osmfilter.c
index adcd71f..946001f 100644
--- a/src/osmfilter.c
+++ b/src/osmfilter.c
@@ -1,10 +1,10 @@
-// osmfilter 2015-04-14 19:50
-#define VERSION "1.4.0"
+// osmfilter 2017-03-30 19:00
+#define VERSION "1.4.2"
//
// compile this file:
// gcc osmfilter.c -O3 -o osmfilter
//
-// (c) 2011..2015 Markus Weber, Nuernberg
+// (c) 2011..2017 Markus Weber, Nuernberg
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Affero General Public License
@@ -41,6 +41,8 @@ const char* shorthelptext=
"--keep-way-relation-tags=\n"
"--drop-tags= define which tags are to be dropped\n"
"--drop-...-tags= similar to --keep-...-tags= (see above)\n"
+"--modify-tags= define which tags are to be modified\n"
+"--modify-...-tags= similar to --keep-...-tags= (see above)\n"
"--drop-author delete changeset and user information\n"
"--drop-version same as before, but delete version as well\n"
"--drop-nodes delete all nodes\n"
@@ -138,6 +140,19 @@ const char* helptext=
"--drop-way-relation-tags=TAG_FILTER\n"
" Same as above, but just for the specified object types.\n"
"\n"
+"--modify-tags=TAG_MODIFICATION_LIST\n"
+" The specified tags will be modified. This is done after any\n"
+" filtering (see --keep, --keep-tags, --drop, --drop-tags).\n"
+" Please look below for a description of TAG_MODIFICATION_LIST.\n"
+"\n"
+"--modify-node-tags=TAG_MODIFICATION_LIST\n"
+"--modify-way-tags=TAG_MODIFICATION_LIST\n"
+"--modify-relation-tags=TAG_MODIFICATION_LIST\n"
+"--modify-node-way-tags=TAG_MODIFICATION_LIST\n"
+"--modify-node-relation-tags=TAG_MODIFICATION_LIST\n"
+"--modify-way-relation-tags=TAG_MODIFICATION_LIST\n"
+" Same as above, but just for the specified object types.\n"
+"\n"
"--drop-author\n"
" For most applications the author tags are not needed. If you\n"
" specify this option, no author information will be written:\n"
@@ -212,7 +227,8 @@ const char* helptext=
" their ids only.\n"
"\n"
"--out-osh\n"
-" For every OSM object, the appropriate \'visible\' tag will be\n" " added to meet \'full planet history\' specification.\n"
+" For every OSM object, the appropriate \'visible\' tag will be\n"
+" added to meet \'full planet history\' specification.\n"
"\n"
"--out-o5m\n"
" The .o5m format will be used. This format has the same\n"
@@ -269,7 +285,7 @@ const char* helptext=
" \"amenity=restaurant =pub =bar\"\n"
" It is allowed to omit the value. In this case, the program\n"
" will accept every value for the defined key. For example:\n"
-" \"all highway= lit=yes\"\n"
+" \"highway= and lit=yes\"\n"
" You may use wildcard characters for key or value, but only at\n"
" the beginning and/or at the end. For example:\n"
" wikipedia:*= highway=*ary ref_name=*central*\n"
@@ -289,6 +305,14 @@ const char* helptext=
" tag which is not mentioned in a list, use this example:\n"
" all highway= amenity= name=\n"
"\n"
+"TAG_MODIFICATION_LIST\n"
+" The tag modification list determines which tags will be\n"
+" modified. The example\n"
+" --modify-tags=\"highway=primary to =secondary\"\n"
+" will change every \"primary\" highway into \"secondary\".\n"
+" You can also use comparisons or add additional tags:\n"
+" --modify-way-tags=\"maxspeed>200 add highspeed=yes\"\n"
+"\n"
"Examples\n"
"\n"
"./osmfilter europe.o5m --keep=amenity=bar -o=new.o5m\n"
@@ -1111,7 +1135,7 @@ static inline bool read_input() {
// having available at least read_PREFETCH bytes at address
// read_bufp - with one exception: if there are not enough bytes
// left to read from standard input, every byte after the end of
- // the reminding part of the file in the buffer will be set to
+ // the remaining part of the file in the buffer will be set to
// 0x00 - up to read_bufp+read_PREFETCH;
int l,r;
@@ -1135,10 +1159,10 @@ static inline bool read_input() {
read_infop->eof= true;
// memorize that there we are at end of file
l= (read__buf+read__bufM)-read_bufe;
- // reminding space in buffer
+ // remaining space in buffer
if(l>read_PREFETCH) l= read_PREFETCH;
memset(read_bufe,0,l); // 2011-12-24
- // set reminding space up to prefetch bytes in buffer to 0
+ // set remaining space up to prefetch bytes in buffer to 0
break;
}
read_infop->read__counter+= r;
@@ -1894,7 +1918,7 @@ static void count_write() {
// the sections of private and public definitions are separated
// by a horizontal line: ----
-static inline void fil_stresccpy(char *dest, const char *src,
+static inline void fil__stresccpy(char *dest, const char *src,
size_t len) {
// similar as strmpy(), but remove every initial '\\' character;
// len: length of the source string - without terminating zero;
@@ -1906,7 +1930,7 @@ static inline void fil_stresccpy(char *dest, const char *src,
*dest++= *src++;
}
*dest= 0;
- } // end fil_stresccpy()
+ } // end fil__stresccpy()
static inline bool fil__cmp(const char* s1,const char* s2) {
// this procedure compares two character strings;
@@ -2392,12 +2416,12 @@ static inline void fil_cpy(char *dest, const char *src,
if(isdig(*v)) // numeric value
op+= 8;
dest[0]= op;
- fil_stresccpy(dest+1,src,len); // store this value
+ fil__stresccpy(dest+1,src,len); // store this value
} // no wildcard(s)
else { // wildcard(s)
dest[0]= op&1;
dest[1]= wc;
- fil_stresccpy(dest+2,src,len); // store this value
+ fil__stresccpy(dest+2,src,len); // store this value
} // wildcard(s)
} // end fil_cpy()
@@ -2834,160 +2858,864 @@ return result;
return result;
} // end fil_check0()
-static inline bool fil_check1(int otype,
- char** key,char** keye,char** val,char** vale) {
- // check if OSM object matches filter criteria;
- // at this procedure, filter type 4..6 is applied: 'drop object';
- // keyp,keye,valp,vale: tag list;
- // otype: 0: node; 1: way; 2: relation;
- // return: given tag list matches keep criteria;
- bool result;
- char** keyp,**valp;
- fil__pair_t* fp,*fe;
- int bracket_balance;
- int bb; // temporary for bracket_balance
- char* v; // previous value of a key which compared successfully
+static inline bool fil_check1(int otype,
+ char** key,char** keye,char** val,char** vale) {
+ // check if OSM object matches filter criteria;
+ // at this procedure, filter type 4..6 is applied: 'drop object';
+ // keyp,keye,valp,vale: tag list;
+ // otype: 0: node; 1: way; 2: relation;
+ // return: given tag list matches keep criteria;
+ bool result;
+ char** keyp,**valp;
+ fil__pair_t* fp,*fe;
+ int bracket_balance;
+ int bb; // temporary for bracket_balance
+ char* v; // previous value of a key which compared successfully
+
+ result= false;
+ v= NULL; // (default)
+ valp= &v; // (default)
+ bracket_balance= 0;
+ fp= fil__pair[3+otype]; fe= fil__paire[3+otype];
+ while(fp<fe) { // for every key/val pair in filter
+ bracket_balance+= fp->left_bracketn;
+ if(*(int16_t*)(fp->k)==0) {
+ if(v!=NULL)
+ result= fil__cmp(v,fp->v);
+ }
+ else {
+ result= false; // (default)
+ keyp= key; valp= val;
+ while(keyp<keye) { // for all key/val pairs of this object
+ if(fil__cmp(*keyp,fp->k)) { // right key
+ v= *valp;
+ if(*(int16_t*)(fp->k)==0 || fil__cmp(v,fp->v)) {
+ // right value
+ result= true;
+ break;
+ }
+ }
+ keyp++; valp++;
+ } // for all key/val pairs of this object
+ }
+ #if MAXLOGLEVEL>=3
+ if(loglevel>=3)
+ PINFOv("comparison[%i][%i]==%i",
+ 3+otype,fp-fil__pair[3+otype],result)
+ #endif
+ if(result) { // comparison satisfied
+ if(fp->operator) { // Boolean operator is AND
+ // (continue with next comparison)
+ } // Boolean operator is AND
+ else { // Boolean operator is OR
+ // at each encountered 'or':
+ // jump to after next operand at lower layer
+ bracket_balance-= fp->right_bracketn;
+ if(bracket_balance<=0) // we already are at lowest level
+return result;
+ bb= bracket_balance;
+ fp++;
+ while(fp<fe) {
+ bracket_balance+= fp->left_bracketn;
+ bracket_balance-= fp->right_bracketn;
+ if(bracket_balance>=bb) { // same level or higher
+ fp++;
+ continue;
+ }
+ if(fp->operator) { // next operator is 'and'
+ fp++;
+ break; // go on by evaluating this operator
+ }
+ // here: next operator is an 'or'
+ if(bracket_balance<=0) // we are at lowest level
+return result;
+ bb= bracket_balance; // from now on ignore this level
+ fp++;
+ }
+ v= NULL; // previous value no longer valid
+ continue;
+ } // Boolean operator is OR
+ } // comparison satisfied
+ else { // comparison not satisfied
+ if(fp->operator) { // Boolean operator is AND
+ // jump to after next 'or' within same brackets or
+ // lower layer, but not into the space between new brackets
+ bracket_balance-= fp->right_bracketn;
+ bb= bracket_balance;
+ fp++;
+ while(fp<fe) {
+ bracket_balance+= fp->left_bracketn;
+ bracket_balance-= fp->right_bracketn;
+ if(bracket_balance<bb)
+ bb= bracket_balance;
+ if(bracket_balance<=bb && !fp->operator) {
+ // not in a new bracket AND next operator is 'or'
+ fp++;
+ break;
+ }
+ fp++;
+ }
+ v= NULL; // previous value no longer valid
+ continue;
+ } // Boolean operator is AND
+ else { // Boolean operator is OR
+ // (continue with next comparison)
+ } // Boolean operator is OR
+ } // comparison not satisfied
+ bracket_balance-= fp->right_bracketn;
+ fp++;
+ } // for every key/val pair in filter
+ return result;
+ } // end fil_check1()
+
+static inline bool fil_check2(int otype,
+ const char* key,const char* val) {
+ // test if filter allows this tag to be kept;
+ // at this procedure, filters type 6..8 and 9..11 are applied:
+ // 'keep tag';
+ // otype: 0: node; 1: way; 2: relation;
+ // return: given key[] and val[] match keep criteria;
+ fil__pair_t* fp,*fe;
+ const char* k; // last key in filter
+ bool keymatch;
+
+ // apply keep-filter
+ if(fil_active[6+otype]) {
+ k= "name"; // (default)
+ keymatch= false;
+ fp= &fil__pair[6+otype][0]; fe= fil__paire[6+otype];
+ while(fp<fe) {
+ if(*(int16_t*)(fp->k)!=0) k= fp->k;
+ keymatch= fil__cmp(key,k);
+ if(keymatch && (*(int16_t*)(fp->v)==0 || fil__cmp(val,fp->v)))
+ goto keep;
+ fp++;
+ }
+ if(keymatch || fil_meetall[6+otype])
+return false;
+ }
+ keep:
+ // apply drop-filter
+ if(fil_active[9+otype]) {
+ k= "name"; // (default)
+ fp= &fil__pair[9+otype][0]; fe= fil__paire[9+otype];
+ while(fp<fe) {
+ if(*(int16_t*)(fp->k)!=0) k= fp->k;
+ if(fil__cmp(key,k) && (*(int16_t*)(fp->v)==0 ||
+ fil__cmp(val,fp->v)))
+return false;
+ fp++;
+ }
+ }
+ return true;
+ } // end fil_check2()
+
+//------------------------------------------------------------
+// end Module fil_ osm filter module
+//------------------------------------------------------------
+
+
+
+//------------------------------------------------------------
+// Module modi_ OSM tag modification module
+//------------------------------------------------------------
+
+// this module provides tag modification functionality;
+// as usual, all identifiers of a module have the same prefix,
+// in this case 'modi'; an underline will follow in case of a
+// global accessible object, two underlines in case of objects
+// which are not meant to be accessed from outside this module;
+// the sections of private and public definitions are separated
+// by a horizontal line: ----
+
+static inline void modi__stresccpy(char *dest, const char *src,
+ size_t len) {
+ // similar as strmpy(), but remove every initial '\\' character;
+ // len: length of the source string - without terminating zero;
+ while(len>0) {
+ if(*src=='\\') { src++; len--; }
+ if(!(len>0) || *src==0)
+ break;
+ len--;
+ *dest++= *src++;
+ }
+ *dest= 0;
+ } // end modi__stresccpy()
+
+static inline bool modi__cmp(const char* s1,const char* s2) {
+ // this procedure compares two character strings;
+ // s1[]: first string;
+ // s2[0]: operator which shall be used for comparison;
+ // 0: '=', and there are wildcards coded in s2[1]:
+ // s2[1]==1: wildcard at start;
+ // s2[1]==2: wildcard at end;
+ // s2[1]==3: wildcard at both, start and end;
+ // 1: '!=', and there are wildcards coded in s2[1];
+ // 2: '='
+ // 4: '<'
+ // 5: '>='
+ // 6: '>'
+ // 7: '<='
+ // 8: unused
+ // 9: unused
+ // 10: '=', numeric
+ // 11: '!=', numeric
+ // 12: '<', numeric
+ // 13: '>=', numeric
+ // 14: '>', numeric
+ // 15: '<=', numeric
+ // s2+1: string to compare with the first string;
+ // this string will start at s2+2 if wildcards are supplied;
+ // return: condition is met;
+ int op,wc; // operator, wildcard flags
+ int diff; // (for numeric comparison)
+ unsigned char s1v,s2v; // (for numeric comparison)
+
+ op= *s2++;
+ if(op==2) { // '='
+ // first we care about the 'equal' operator
+ // because it's the most frequently used option
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *s1==0 && *s2==0;
+ }
+ switch(op) { // depending on comparison operator
+ case 0: // '=', and there are wildcards
+ wc= *s2++;
+ if(wc==2) { // wildcard at end
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *s2==0;
+ } // wildcard at end
+ if(wc==1) { // wildcard at start
+ const char* s11,*s22;
+
+ while(*s1!=0) { // for all start positions in s1[]
+ s11= s1; s22= s2;
+ while(*s11==*s22 && *s11!=0) { s11++; s22++; }
+ if(*s11==0 && *s22==0)
+ return true;
+ s1++;
+ } // for all start positions in s1[]
+ return false;
+ } // wildcard at start
+ /* wildcards at start and end */ {
+ const char* s11,*s22;
+
+ while(*s1!=0) { // for all start positions in s1[]
+ s11= s1; s22= s2;
+ while(*s11==*s22 && *s11!=0) { s11++; s22++; }
+ if(*s22==0)
+ return true;
+ s1++;
+ } // for all start positions in s1[]
+ return false;
+ } // wildcards at start and end
+ case 1: // '!=', and there are wildcards
+ wc= *s2++;
+ if(wc==2) { // wildcard at end
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *s2!=0;
+ } // wildcard at end
+ if(wc==1) { // wildcard at start
+ const char* s11,*s22;
+
+ while(*s1!=0) { // for all start positions in s1[]
+ s11= s1; s22= s2;
+ while(*s11==*s22 && *s11!=0) { s11++; s22++; }
+ if(*s11==0 && *s22==0)
+ return false;
+ s1++;
+ } // for all start positions in s1[]
+ return true;
+ } // wildcard at start
+ /* wildcards at start and end */ {
+ const char* s11,*s22;
+
+ while(*s1!=0) { // for all start positions in s1[]
+ s11= s1; s22= s2;
+ while(*s11==*s22 && *s11!=0) { s11++; s22++; }
+ if(*s22==0)
+ return false;
+ s1++;
+ } // for all start positions in s1[]
+ return true;
+ } // wildcards at start and end
+ //case 2: // '=' (we already cared about this)
+ case 3: // '!='
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *s1!=0 || *s2!=0;
+ case 4: // '<'
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *(unsigned char*)s1 < *(unsigned char*)s2;
+ case 5: // '>='
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *(unsigned char*)s1 >= *(unsigned char*)s2;
+ case 6: // '>'
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *(unsigned char*)s1 > *(unsigned char*)s2;
+ case 7: // '<='
+ while(*s1==*s2 && *s1!=0) { s1++; s2++; }
+ return *(unsigned char*)s1 <= *(unsigned char*)s2;
+ case 10: // '=', numeric
+ while(*s1=='0') s1++;
+ while(*s2=='0') s2++;
+ while(*s1==*s2 && isdigi(*(unsigned char*)s1))
+ { s1++; s2++; }
+ if(*s1=='.') {
+ if(*s2=='.') {
+ do { s1++; s2++; }
+ while(*s1==*s2 && isdigi(*(unsigned char*)s1));
+ if(!isdigi(*(unsigned char*)s1)) {
+ while(*s2=='0') s2++;
+ return !isdigi(*(unsigned char*)s2);
+ }
+ if(!isdigi(*(unsigned char*)s2)) {
+ while(*s1=='0') s1++;
+ return !isdigi(*(unsigned char*)s1);
+ }
+ return !isdigi(*(unsigned char*)s1) &&
+ !isdigi(*(unsigned char*)s2);
+ }
+ do s1++;
+ while(*s1=='0');
+ return !isdigi(*(unsigned char*)s1);
+ }
+ if(*s2=='.') {
+ do s2++;
+ while(*s2=='0');
+ return !isdigi(*(unsigned char*)s2);
+ }
+ return !isdigi(*(unsigned char*)s1) && !isdigi(*(unsigned char*)s2);
+ case 11: // '!=', numeric
+ while(*s1=='0') s1++;
+ while(*s2=='0') s2++;
+ while(*s1==*s2 && isdigi(*(unsigned char*)s1))
+ { s1++; s2++; }
+ if(*s1=='.') {
+ if(*s2=='.') {
+ do { s1++; s2++; }
+ while(*s1==*s2 && isdigi(*(unsigned char*)s1));
+ if(!isdigi(*(unsigned char*)s1)) {
+ while(*s2=='0') s2++;
+ return isdigi(*(unsigned char*)s2);
+ }
+ if(!isdigi(*(unsigned char*)s2)) {
+ while(*s1=='0') s1++;
+ return isdigi(*(unsigned char*)s1);
+ }
+ return isdigi(*(unsigned char*)s1) ||
+ isdigi(*(unsigned char*)s2);
+ }
+ do s1++;
+ while(*s1=='0');
+ return isdigi(*(unsigned char*)s1);
+ }
+ if(*s2=='.') {
+ do s2++;
+ while(*s2=='0');
+ return isdigi(*(unsigned char*)s2);
+ }
+ return isdigi(*(unsigned char*)s1) || isdigi(*(unsigned char*)s2);
+ case 12: /* '<', numeric */
+ #define Ds1 s1
+ #define Ds2 s2
+ s1v= *(unsigned char*)Ds1; s2v= *(unsigned char*)Ds2;
+ if(s1v=='-') {
+ if(s2v=='-') {
+ Ds1++; s2v= *(unsigned char*)Ds1;
+ Ds2++; s1v= *(unsigned char*)Ds2;
+ goto op_14;
+ }
+ return true;
+ }
+ else if(s2v=='-')
+ return false;
+ op_12:
+ while(s1v=='0') { Ds1++; s1v= *(unsigned char*)Ds1; }
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ while(s1v==s2v && isdigi(s1v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ diff= digival(s1v)-digival(s2v);
+ while(isdigi(s1v) && isdigi(s2v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ if(s1v=='.') {
+ if(s2v=='.') {
+ if(diff!=0)
+ return diff<0;
+ do {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ } while(s1v==s2v && isdigi(s1v));
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ return digival(s1v) < digival(s2v);
+ }
+ return isdigi(s2v) || diff<0;
+ }
+ if(s2v=='.') {
+ if(isdigi(s1v))
+ return false;
+ if(diff!=0)
+ return diff<0;
+ do { Ds2++; s2v= *(unsigned char*)Ds2; } while(s2v=='0');
+ return isdigi(s2v);
+ }
+ return isdigi(s2v) || (!isdigi(s1v) && diff<0);
+ #undef Ds1
+ #undef Ds2
+ case 13: /* '>=', numeric */
+ #define Ds1 s1
+ #define Ds2 s2
+ s1v= *(unsigned char*)Ds1; s2v= *(unsigned char*)Ds2;
+ if(s1v=='-') {
+ if(s2v=='-') {
+ Ds1++; s2v= *(unsigned char*)Ds1;
+ Ds2++; s1v= *(unsigned char*)Ds2;
+ goto op_15;
+ }
+ return false;
+ }
+ else if(s2v=='-')
+ return true;
+ op_13:
+ while(s1v=='0') { Ds1++; s1v= *(unsigned char*)Ds1; }
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ while(s1v==s2v && isdigi(s1v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ diff= digival(s1v)-digival(s2v);
+ while(isdigi(s1v) && isdigi(s2v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ if(s1v=='.') {
+ if(s2v=='.') {
+ if(diff!=0)
+ return diff>=0;
+ do {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ } while(s1v==s2v && isdigi(s1v));
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ return digival(s1v) >= digival(s2v);
+ }
+ return !isdigi(s2v) && diff>=0;
+ }
+ if(s2v=='.') {
+ if(isdigi(s1v))
+ return true;
+ if(diff!=0)
+ return diff>=0;
+ do { Ds2++; s2v= *(unsigned char*)Ds2; } while(s2v=='0');
+ return !isdigi(s2v);
+ }
+ return !isdigi(s2v) && (isdigi(s1v) || diff>=0);
+ #undef Ds1
+ #undef Ds2
+ case 14: /* '>', numeric */
+ #define Ds1 s2
+ #define Ds2 s1
+ s1v= *(unsigned char*)Ds1; s2v= *(unsigned char*)Ds2;
+ if(s1v=='-') {
+ if(s2v=='-') {
+ Ds1++; s2v= *(unsigned char*)Ds1;
+ Ds2++; s1v= *(unsigned char*)Ds2;
+ goto op_12;
+ }
+ return true;
+ }
+ else if(s2v=='-')
+ return false;
+ op_14:
+ while(s1v=='0') { Ds1++; s1v= *(unsigned char*)Ds1; }
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ while(s1v==s2v && isdigi(s1v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ diff= digival(s1v)-digival(s2v);
+ while(isdigi(s1v) && isdigi(s2v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ if(s1v=='.') {
+ if(s2v=='.') {
+ if(diff!=0)
+ return diff<0;
+ do {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ } while(s1v==s2v && isdigi(s1v));
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ return digival(s1v) < digival(s2v);
+ }
+ return isdigi(s2v) || diff<0;
+ }
+ if(s2v=='.') {
+ if(isdigi(s1v))
+ return false;
+ if(diff!=0)
+ return diff<0;
+ do { Ds2++; s2v= *(unsigned char*)Ds2; } while(s2v=='0');
+ return isdigi(s2v);
+ }
+ return isdigi(s2v) || (!isdigi(s1v) && diff<0);
+ #undef Ds1
+ #undef Ds2
+ case 15: /* '<=', numeric */
+ #define Ds1 s2
+ #define Ds2 s1
+ s1v= *(unsigned char*)Ds1; s2v= *(unsigned char*)Ds2;
+ if(s1v=='-') {
+ if(s2v=='-') {
+ Ds1++; s2v= *(unsigned char*)Ds1;
+ Ds2++; s1v= *(unsigned char*)Ds2;
+ goto op_13;
+ }
+ return false;
+ }
+ else if(s2v=='-')
+ return true;
+ op_15:
+ while(s1v=='0') { Ds1++; s1v= *(unsigned char*)Ds1; }
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ while(s1v==s2v && isdigi(s1v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ diff= digival(s1v)-digival(s2v);
+ while(isdigi(s1v) && isdigi(s2v)) {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ }
+ if(s1v=='.') {
+ if(s2v=='.') {
+ if(diff!=0)
+ return diff>=0;
+ do {
+ Ds1++; s1v= *(unsigned char*)Ds1;
+ Ds2++; s2v= *(unsigned char*)Ds2;
+ } while(s1v==s2v && isdigi(s1v));
+ while(s2v=='0') { Ds2++; s2v= *(unsigned char*)Ds2; }
+ return digival(s1v) >= digival(s2v);
+ }
+ return !isdigi(s2v) && diff>=0;
+ }
+ if(s2v=='.') {
+ if(isdigi(s1v))
+ return true;
+ if(diff!=0)
+ return diff>=0;
+ do { Ds2++; s2v= *(unsigned char*)Ds2; } while(s2v=='0');
+ return !isdigi(s2v);
+ }
+ return !isdigi(s2v) && (isdigi(s1v) || diff>=0);
+ #undef Ds1
+ #undef Ds2
+ // (no default)
+ } // depending on comparison operator
+ return false; // (we never get here)
+ } // end modi__cmp()
+
+#define modi__pairM 1000 // maximum number of key-val-pairs
+#define modi__pairkM 100 // maximum length of key or val;
+#define modi__pairtM 3 // maximum number of modification types;
+ // these modification types are defined as follows:
+ // 0: modify node tag;
+ // 1: modify way tag;
+ // 2: modify relation tag;
+struct modi__pair_struct {
+ // key/val pair for the include filter
+ char k[modi__pairkM+8]; // key to compare;
+ // [0]==0 && [1]==0: same key as previous key in list;
+ char v[modi__pairkM+8]; // value to the key in .k[];
+ // the first byte represents a comparison operator,
+ // see parameter s2[]in modi__cmp() for details;
+ // [0]==0 && [1]==0: any value will be accepted;
+ char nk[modi__pairkM+2]; // new key
+ char nv[modi__pairkM+2]; // new value
+ bool add; // new key/val pair shall be added instead of replacing
+ // the old key/val pair
+ } __attribute__((__packed__));
+typedef struct modi__pair_struct modi__pair_t;
+static modi__pair_t modi__pair[modi__pairtM][modi__pairM+2]=
+ {{{{0},{0},{0},{0}}}};
+static modi__pair_t* modi__paire[modi__pairtM]=
+ { &modi__pair[0][0],&modi__pair[1][0],&modi__pair[2][0] };
+static modi__pair_t* modi__pairee[modi__pairtM]=
+ { &modi__pair[0][modi__pairM],&modi__pair[1][modi__pairM],
+ &modi__pair[2][modi__pairM] };
+
+//------------------------------------------------------------
+
+static inline void modi_cpy(char *dest, const char *src,
+ size_t len,int op) {
+ // similar as strmpy(), but remove every initial '\\' character;
+ // len: length of the source string - without terminating zero;
+ // op: comparison operator;
+ // 2: '='
+ // 4: '<'
+ // 5: '>='
+ // 6: '>'
+ // 7: '<='
+ // return: dest[0]: comparison operator; additional possible values:
+ // 0: '=', and there are wildcards coded in dest[1]:
+ // dest[1]==1: wildcard at start;
+ // dest[1]==2: wildcard at end;
+ // dest[1]==3: wildcard at both, start and end;
+ // 1: '!=', and there are wildcards coded in dest[1];
+ // 10: '=', numeric
+ // 11: '!=', numeric
+ // 12: '<', numeric
+ // 13: '>=', numeric
+ // 14: '>', numeric
+ // 15: '<=', numeric
+ int wc; // wildcard indicator, see modi__cmp()
+
+ if(op<0) { // unknown operator
+ WARNv("unknown comparison at: %.80s",src)
+ op= 2; // assume '='
+ }
+ if(len>(modi__pairkM)) {
+ len= modi__pairkM; // delimit value length
+ WARNv("modification argument too long: %.*s",modi__pairkM,src)
+ }
+ wc= 0; // (default)
+ if(len>=2 && src[0]=='*') { // wildcard at start
+ wc|= 1;
+ src++; len--;
+ }
+ if((len>=2 && src[len-1]=='*' && src[len-2]!='\\') ||
+ (len==1 && src[len-1]=='*')) {
+ // wildcard at end
+ wc|= 2;
+ len--;
+ }
+ if(wc==0) { // no wildcard(s)
+ const char* v;
+
+ v= src;
+ if(*v=='-') v++; // jump over sign
+ if(isdig(*v)) // numeric value
+ op+= 8;
+ dest[0]= op;
+ modi__stresccpy(dest+1,src,len); // store this value
+ } // no wildcard(s)
+ else { // wildcard(s)
+ dest[0]= op&1;
+ dest[1]= wc;
+ modi__stresccpy(dest+2,src,len); // store this value
+ } // wildcard(s)
+ } // end modi_cpy()
+
+static bool modi_active= false;
+ // there is at least one modify criteria active;
+ // may be read by everyone but written only by this module;
+static bool modi_activetype[modi__pairtM]= {false,false,false};
+ // the related modify list has at least one element;
+ // may be read by everyone but written only by this module;
- result= false;
- v= NULL; // (default)
- valp= &v; // (default)
- bracket_balance= 0;
- fp= fil__pair[3+otype]; fe= fil__paire[3+otype];
- while(fp<fe) { // for every key/val pair in filter
- bracket_balance+= fp->left_bracketn;
- if(*(int16_t*)(fp->k)==0) {
- if(v!=NULL)
- result= fil__cmp(v,fp->v);
+static void modi_ini() {
+ // initialize this mudule;
+ int i;
+
+ modi_active= false;
+ for(i= 0; i<modi__pairtM; i++) {
+ modi__paire[i]= &modi__pair[i][0];
+ modi__pairee[i]= &modi__pair[i][modi__pairM];
+ modi_activetype[i]= false;
+ }
+ } // modi_ini()
+
+static void modi_parse(int ftype,const char* arg) {
+ // interprets a command line argument and stores modification
+ // information;
+ // ftype: object type; see explanation at modi__pairtM;
+ // arg[]: modification information; e.g.:
+ // "amenity=fire_hydrant to emergency=fire_hydrant"
+ modi__pair_t*fe,*fee;
+ const char* pk,*pv,*pe; // pointers in parameter for key/val pairs;
+ // pk: key; pv: val; pe: end of val;
+ int len; // string length
+ int op; // operator, see modi__cmp()
+
+ fe= modi__paire[ftype];
+ fee= modi__pairee[ftype];
+ if(loglevel>0)
+ PINFOv("Modify: %s tags:",ONAME(ftype%3))
+ pk= arg;
+ while(*pk==' ') pk++; // jump over spaces
+
+ while(pk!=NULL && fe<fee) { // for every key/val pair
+ while(*pk==' ') pk++; // jump over (additional) spaces
+ if(*pk==0)
+ break;
+ pe= pk;
+ while((*pe!=' ' || pe[-1]=='\\') && *pe!=0) pe++;
+ // get end of this pair
+ len= pe-pk; // length of this argument
+ pv= pk;
+ while(((*pv!='=' && *pv!='<' && *pv!='>' &&
+ (*pv!='!' || pv[1]!='=')) ||
+ (pv>pk && pv[-1]=='\\')) && pv<pe) pv++;
+ // find operator =, <, >, !=
+ if(pv>=pe-1) pv= pe; // there was no operator in this pair
+ len= pv-pk; // length of this key
+ if(len>(modi__pairkM)) {
+ len= modi__pairkM; // delimit key length
+ WARNv("modification key too long: %.*s",modi__pairkM,pk)
}
- else {
- result= false; // (default)
- keyp= key; valp= val;
- while(keyp<keye) { // for all key/val pairs of this object
- if(fil__cmp(*keyp,fp->k)) { // right key
- v= *valp;
- if(*(int16_t*)(fp->k)==0 || fil__cmp(v,fp->v)) {
- // right value
- result= true;
- break;
- }
- }
- keyp++; valp++;
- } // for all key/val pairs of this object
+ op= -1; // 'unknown operator' (default)
+ if(pv>=pe) { // there is a key but no value
+ if(len>0 && pk[len-1]=='=') len--;
+ modi_cpy(fe->k,pk,len,2); // store this key, op='='
+ memset(fe->v,0,3); // store empty value
}
- #if MAXLOGLEVEL>=3
- if(loglevel>=3)
- PINFOv("comparison[%i][%i]==%i",
- 3+otype,fp-fil__pair[3+otype],result)
- #endif
- if(result) { // comparison satisfied
- if(fp->operator) { // Boolean operator is AND
- // (continue with next comparison)
- } // Boolean operator is AND
- else { // Boolean operator is OR
- // at each encountered 'or':
- // jump to after next operand at lower layer
- bracket_balance-= fp->right_bracketn;
- if(bracket_balance<=0) // we already are at lowest level
-return result;
- bb= bracket_balance;
- fp++;
- while(fp<fe) {
- bracket_balance+= fp->left_bracketn;
- bracket_balance-= fp->right_bracketn;
- if(bracket_balance>=bb) { // same level or higher
- fp++;
- continue;
- }
- if(fp->operator) { // next operator is 'and'
- fp++;
- break; // go on by evaluating this operator
- }
- // here: next operator is an 'or'
- if(bracket_balance<=0) // we are at lowest level
-return result;
- bb= bracket_balance; // from now on ignore this level
- fp++;
- }
- v= NULL; // previous value no longer valid
- continue;
- } // Boolean operator is OR
- } // comparison satisfied
- else { // comparison not satisfied
- if(fp->operator) { // Boolean operator is AND
- // jump to after next 'or' within same brackets or
- // lower layer, but not into the space between new brackets
- bracket_balance-= fp->right_bracketn;
- bb= bracket_balance;
- fp++;
- while(fp<fe) {
- bracket_balance+= fp->left_bracketn;
- bracket_balance-= fp->right_bracketn;
- if(bracket_balance<bb)
- bb= bracket_balance;
- if(bracket_balance<=bb && !fp->operator) {
- // not in a new bracket AND next operator is 'or'
- fp++;
- break;
- }
- fp++;
- }
- v= NULL; // previous value no longer valid
- continue;
- } // Boolean operator is AND
- else { // Boolean operator is OR
- // (continue with next comparison)
- } // Boolean operator is OR
- } // comparison not satisfied
- bracket_balance-= fp->right_bracketn;
- fp++;
- } // for every key/val pair in filter
- return result;
- } // end fil_check1()
-
-static inline bool fil_check2(int otype,
- const char* key,const char* val) {
- // test if filter allows this tag to be kept;
- // at this procedure, filters type 6..8 and 9..11 are applied:
- // 'keep tag';
+ else { // key and value
+ if(len==0) // no key given
+ memset(fe->k,0,3); // store empty key,
+ else
+ modi_cpy(fe->k,pk,len,2); // store this key, op='='
+ if(*pv=='=') op= 2;
+ else if(*pv=='!' && pv[1]=='=') op= 3;
+ else if(*pv=='<' && pv[1]!='=') op= 4;
+ else if(*pv=='>' && pv[1]=='=') op= 5;
+ else if(*pv=='>' && pv[1]!='=') op= 6;
+ else if(*pv=='<' && pv[1]=='=') op= 7;
+ if(op<0) { // unknown operator
+ WARNv("unknown comparison at: %.80s",pv)
+ op= 2; // assume '='
+ }
+ pv++; // jump over operator
+ if(pv<pe && *pv=='=') pv++;
+ // jump over second character of a two-character operator
+ len= pe-pv; // length of this value
+ modi_cpy(fe->v,pv,len,op); // store this value
+ } // key and value
+ // jump over ' to ' phrase
+ while(*pe==' ') pe++; // jump over spaces
+ if((fe->add= strzcmp(pe,"add ")==0)) pe+= 4;
+ else if(strzcmp(pe,"to ")==0) pe+= 3;
+ // get destination key/val
+ pk= pe; // jump to next key/val pair in parameter list
+ while(*pk==' ') pk++; // jump over (additional) spaces
+ pe= pk;
+ while((*pe!=' ' || pe[-1]=='\\') && *pe!=0) pe++;
+ // get end of this destination pair
+ len= pe-pk; // length of this argument
+ pv= pk;
+ while((*pv!='=' || (pv>pk && pv[-1]=='\\')) && pv<pe) pv++;
+ // find operator '='
+ if(pv>=pe-1) pv= pe; // there was no operator in this pair
+ len= pv-pk; // length of this key
+ if(len>(modi__pairkM)) {
+ len= modi__pairkM; // delimit key length
+ WARNv("modification key too long: %.*s",modi__pairkM,pk)
+ }
+ if(pv>=pe) { // there is a destination key but no value
+ if(len>0 && pk[len-1]=='=') len--;
+ modi__stresccpy(fe->nk,pk,len); // store this key
+ fe->nv[0]= 0; // store empty value
+ }
+ else { // destination key and value
+ if(len==0) // no key given
+ modi__stresccpy(fe->nk,fe->k[0]<=1? fe->k+2: fe->k+1,
+ modi__pairkM);
+ // store source key as destination key
+ else
+ modi__stresccpy(fe->nk,pk,len); // store this key
+ pv++; // jump over equation operator
+ if(pv<pe && *pv=='=') pv++;
+ // jump over second character of a two-character operator
+ len= pe-pv; // length of this value
+ if(len==0) // no value given
+ modi__stresccpy(fe->nv,fe->v[0]<=1? fe->v+2: fe->v+1,
+ modi__pairkM);
+ // store source value as destination value
+ else
+ modi__stresccpy(fe->nv,pv,len); // store this value
+ } // destination key and value
+ if(loglevel>0) {
+ static const char* ops[]= { "?",
+ "=","!=","=","!=","<",">=",">","<=",
+ "?","?","=(numeric)","!=(numeric)",
+ "<(numeric)",">=(numeric)",">(numeric)","<=(numeric)" };
+ PINFOv("Modify: %s\"%.80s\"%s %s %s\"%.80s\"%s",
+ fe->k[0]<=1 && (fe->k[1] & 1)? "*": "",
+ *(int16_t*)(fe->k)==0? "(last key)":
+ fe->k[0]>=2? fe->k+1: fe->k+2,
+ fe->k[0]<=1 && (fe->k[1] & 2)? "*": "",
+ ops[fe->v[0]+1],
+ fe->v[0]<=1 && (fe->v[1] & 1)? "*": "",
+ *(int16_t*)(fe->v)==0? "(anything)":
+ fe->v[0]>=2? fe->v+1: fe->v+2,
+ fe->v[0]<=1 && (fe->v[1] & 2)? "*": "");
+ }
+ fe++; // next pair in key/val table
+ pk= pe; // jump to next key/val pair in parameter list
+ } // end for every key/val pair
+ if(fe>=fee)
+ WARN("too many modification parameters.")
+ modi__paire[ftype]= fe;
+ modi_active= true;
+ modi_activetype[ftype]= true;
+ } // end modi_parse()
+
+static char* modi_check_key= "-",*modi_check_val= "-";
+ static bool modi_check_add= false;
+ // return values of procedure modi_check();
+ // the values are valid only if the previous call to modi_check()
+ // has returned 'true';
+
+static inline bool modi_check(int otype,char* key,char* val) {
+ // check if OSM object matches modification criteria;
// otype: 0: node; 1: way; 2: relation;
- // return: given key[] and val[] match keep criteria;
- fil__pair_t* fp,*fe;
- const char* k; // last key in filter
- bool keymatch;
-
- // apply keep-filter
- if(fil_active[6+otype]) {
- k= "name"; // (default)
- keymatch= false;
- fp= &fil__pair[6+otype][0]; fe= fil__paire[6+otype];
- while(fp<fe) {
- if(*(int16_t*)(fp->k)!=0) k= fp->k;
- keymatch= fil__cmp(key,k);
- if(keymatch && (*(int16_t*)(fp->v)==0 || fil__cmp(val,fp->v)))
- goto keep;
- fp++;
+ // key,val: key and value;
+ // return: given key/val pair matches modification criteria;
+ // modi_check_key,modi_check_val: destination key/val;
+ // modi_check_add: the destination key/val shall be added
+ // instead of replacing the old key/val pair;
+ modi__pair_t* fp,*fe;
+
+ fp= modi__pair[otype]; fe= modi__paire[otype];
+ while(fp<fe) { // for every key/val pair in filter
+ if(*(int16_t*)(fp->k)==0) { // no key given
+ if(modi__cmp(val,fp->v)) // just compare the value
+ goto modi_check_found;
}
- if(keymatch || fil_meetall[6+otype])
-return false;
- }
- keep:
- // apply drop-filter
- if(fil_active[9+otype]) {
- k= "name"; // (default)
- fp= &fil__pair[9+otype][0]; fe= fil__paire[9+otype];
- while(fp<fe) {
- if(*(int16_t*)(fp->k)!=0) k= fp->k;
- if(fil__cmp(key,k) && (*(int16_t*)(fp->v)==0 ||
- fil__cmp(val,fp->v)))
-return false;
- fp++;
+ else { // key given
+ if(modi__cmp(key,fp->k) &&
+ (*(int16_t*)(fp->k)==0 || modi__cmp(val,fp->v)))
+ // compare key and value (if any)
+ goto modi_check_found;
}
- }
+ fp++;
+ } // for every key/val pair in filter
+ return false;
+modi_check_found:
+ if(fp->nk[0]!=0) // there is a destination key
+ modi_check_key= fp->nk; // take that destination key
+ else
+ modi_check_key= key;
+ // take source key instead
+ if(fp->nv[0]!=0) // there is a destination value
+ modi_check_val= fp->nv; // take that destination value
+ else
+ modi_check_val= val;
+ // take source value instead
+ modi_check_add= fp->add; // publish key/val add request
return true;
- } // end fil_check2()
+ } // end modi_check()
+
+#define modi_CHECK(ot,k,v) \
+ (modi_active && modi_activetype[ot] && modi_check(ot,k,v))
+ // prevents procedure call in case there are no modifications applied
//------------------------------------------------------------
-// end Module fil_ osm filter module
+// end Module modi_ OSM tag modification module
//------------------------------------------------------------
@@ -5159,7 +5887,7 @@ static void oo__close() {
if(!oo__ifp->endoffile && oo_ifn>0) // missing logical end of file
fprintf(stderr,"osmfilter Warning: "
"unexpected end of input file: %.80s\n",oo__ifp->filename);
- read_close(oo__ifp->ri);
+ read_close(); //oo__ifp->ri);
oo__ifp->ri= NULL;
oo_ifn--;
}
@@ -5652,10 +6380,12 @@ return 18;
} // end xml
// care about possible array overflows
- if(refide>refidee)
- WARNv("way %"PRIi64" has too many noderefs.",id)
- if(refide>refidee)
- WARNv("relation %"PRIi64" has too many refs.",id)
+ if(refide>=refidee) {
+ if(otype==1)
+ WARNv("way %"PRIi64" has too many noderefs.",id)
+ else
+ WARNv("relation %"PRIi64" has too many refs.",id)
+ }
if(keye>=keyee)
WARNv("%s %"PRIi64" has too many key/val pairs.",
ONAME(otype),id)
@@ -5779,8 +6509,14 @@ return 18;
hisver,histime,hiscset,hisuid,hisuser,lon,lat);
keyp= key; valp= val;
while(keyp<keye) { // for all key/val pairs of this object
- if(!fil_activeo[otype] || fil_check2(otype,*keyp,*valp))
- wo_keyval(*keyp,*valp);
+ if(!fil_activeo[otype] || fil_check2(otype,*keyp,*valp)) {
+ if(modi_CHECK(otype,*keyp,*valp)) {
+ if(modi_check_add) wo_keyval(*keyp,*valp);
+ wo_keyval(modi_check_key,modi_check_val);
+ }
+ else
+ wo_keyval(*keyp,*valp);
+ }
keyp++; valp++;
}
} // end not to drop
@@ -5793,8 +6529,14 @@ return 18;
wo_noderef(*refidp++);
keyp= key; valp= val;
while(keyp<keye) { // for all key/val pairs of this object
- if(!fil_activeo[otype] || fil_check2(otype,*keyp,*valp))
+ if(!fil_activeo[otype] || fil_check2(otype,*keyp,*valp)) {
+ if(modi_CHECK(otype,*keyp,*valp)) {
+ if(modi_check_add) wo_keyval(*keyp,*valp);
+ wo_keyval(modi_check_key,modi_check_val);
+ }
+ else
wo_keyval(*keyp,*valp);
+ }
keyp++; valp++;
}
} // end not ways to drop
@@ -5807,8 +6549,14 @@ return 18;
wo_ref(*refidp++,*reftypep++,*refrolep++);
keyp= key; valp= val;
while(keyp<keye) { // for all key/val pairs of this object
- if(!fil_activeo[otype] || fil_check2(otype,*keyp,*valp))
+ if(!fil_activeo[otype] || fil_check2(otype,*keyp,*valp)) {
+ if(modi_CHECK(otype,*keyp,*valp)) {
+ if(modi_check_add) wo_keyval(*keyp,*valp);
+ wo_keyval(modi_check_key,modi_check_val);
+ }
+ else
wo_keyval(*keyp,*valp);
+ }
keyp++; valp++;
}
} // end not relations to drop
@@ -5864,6 +6612,7 @@ int main(int argc,const char** argv) {
// initializations
h_n= h_w= h_r= 0;
fil_ini();
+ modi_ini();
#if __WIN32__
setmode(fileno(stdout),O_BINARY);
setmode(fileno(stdin),O_BINARY);
@@ -6162,6 +6911,17 @@ return 0;
D(--drop-way-relation-tags=,F(10)F(11))
#undef D
#undef F
+ #define F(t) modi_parse(t,a+l);
+ #define D(p,f) if((l= strzlcmp(a,#p))>0) { f continue; }
+ D(--modify-tags=,F(0)F(1)F(2))
+ D(--modify-node-tags=,F(0))
+ D(--modify-way-tags=,F(1))
+ D(--modify-relation-tags=,F(2))
+ D(--modify-node-way-tags=,F(0)F(1))
+ D(--modify-node-relation-tags=,F(0)F(2))
+ D(--modify-way-relation-tags=,F(1)F(2))
+ #undef D
+ #undef F
if(a[0]=='-') {
PERRv("unrecognized option: %.80s",a)
return 1;
@@ -6257,3 +7017,4 @@ return 5;
} // verbose mode
return r;
} // end main()
+
diff --git a/src/osmupdate.c b/src/osmupdate.c
index d27ec84..5a6e737 100644
--- a/src/osmupdate.c
+++ b/src/osmupdate.c
@@ -1,10 +1,10 @@
-// osmupdate 2015-04-15 10:00
-#define VERSION "0.4.1"
+// osmupdate 2017-02-26 16:40
+#define VERSION "0.4.4"
//
// compile this file:
// gcc osmupdate.c -o osmupdate
//
-// (c) 2011..2015 Markus Weber, Nuernberg
+// (c) 2011..2017 Markus Weber, Nuernberg
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Affero General Public License
@@ -131,6 +131,14 @@ const char* helptext=
" change file sources (option --base-url). This would cause\n"
" severe data corruption.\n"
"\n"
+"--trust-tempfiles\n"
+" Use this option if you want to use the saved local copies\n"
+" of already downloaded changefiles without checking their\n"
+" lengths against to their server-hosted originals.\n"
+" Downloads will be limited to files not saved yet.\n"
+" Do not invoke this option if you suspect incomplete\n"
+" downloads.\n"
+"\n"
"--compression-level=LEVEL\n"
" Define level for gzip compression. Values between 1 (low\n"
" compression, but fast) and 9 (high compression, but slow).\n"
@@ -160,7 +168,6 @@ const char* helptext=
"Please send any bug reports to markus.weber at gmx.com\n\n";
#define _FILE_OFFSET_BITS 64
-#include <zlib.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
@@ -498,6 +505,8 @@ static char global_tempfile_name[450]= "";
// prefix of names for temporary files
static bool global_keep_tempfiles= false;
// temporary files shall not be deleted at program end
+static bool global_trust_tempfiles= false;
+ // Cached files are considered to be intact
static char global_osmconvert_arguments[2000]= "";
// general command line arguments for osmconvert;
#define max_number_of_changefiles_in_cache 100
@@ -917,58 +926,70 @@ static void process_changefile(
// assemble the URL and download the changefile
old_file_length= file_length(this_cachefile_name);
- if(loglevel>0 && old_file_length<10)
- // verbose mode AND file not downloaded yet
- PINFOv("%s changefile %i: downloading",
- CFTNAME(changefile_type),file_sequence_number)
- command_p= command;
- stecpy(&command_p,command_e,"wget -nv -c ");
- stecpy(&command_p,command_e,global_base_url);
- switch(changefile_type) { // changefile type
- case cft_MINUTELY:
- stecpy(&command_p,command_e,"/minute");
- break;
- case cft_HOURLY:
- stecpy(&command_p,command_e,"/hour");
- break;
- case cft_DAILY:
- stecpy(&command_p,command_e,"/day");
- break;
- case cft_SPORADIC:
- break;
- default: // invalid change file type
- return;
- } // changefile type
- stecpy(&command_p,command_e,global_base_url_suffix);
- stecpy(&command_p,command_e,"/");
-
- /* process sequence number */ {
- int l;
- l= sprintf(command_p,"%03i/%03i/%03i.osc.gz",
- file_sequence_number/1000000,file_sequence_number/1000%1000,
- file_sequence_number%1000);
- command_p+= l;
- } // process sequence number
-
- stecpy(&command_p,command_e," -O \"");
- steesccpy(&command_p,command_e,this_cachefile_name);
- stecpy(&command_p,command_e,"\" 2>&1 && echo \"Wget Command Ok\"");
- shell_command(command,result);
- if(strstr(result,"Wget Command Ok")==NULL) { // download error
- PERRv("Could not download %s changefile %i",
- CFTNAME(changefile_type),file_sequence_number)
- PINFOv("wget Error message:\n%s",result)
-exit(1);
- }
- if(loglevel>0 && old_file_length>=10) {
- // verbose mode AND file was already in cache
- if(file_length(this_cachefile_name)!=old_file_length)
- PINFOv("%s changefile %i: download completed",
+ if(global_trust_tempfiles && old_file_length>=10) {
+ // trusted file already in cache
+ if(loglevel>0) // verbose mode
+ PINFOv("%s changefile %i: trusting local copy",
CFTNAME(changefile_type),file_sequence_number)
- else
- PINFOv("%s changefile %i: already in cache",
+ } // trusted file already in cache
+ else { // file not in cache or not trusted
+ if(loglevel>0) { // verbose mode
+ if(old_file_length<10) // file not downloaded yet
+ PINFOv("%s changefile %i: downloading",
+ CFTNAME(changefile_type),file_sequence_number)
+ else // file had been downloaded at least partially
+ PINFOv("%s changefile %i: checking",
+ CFTNAME(changefile_type),file_sequence_number)
+ } // verbose mode
+ command_p= command;
+ stecpy(&command_p,command_e,"wget -nv -c ");
+ stecpy(&command_p,command_e,global_base_url);
+ switch(changefile_type) { // changefile type
+ case cft_MINUTELY:
+ stecpy(&command_p,command_e,"/minute");
+ break;
+ case cft_HOURLY:
+ stecpy(&command_p,command_e,"/hour");
+ break;
+ case cft_DAILY:
+ stecpy(&command_p,command_e,"/day");
+ break;
+ case cft_SPORADIC:
+ break;
+ default: // invalid change file type
+ return;
+ } // changefile type
+ stecpy(&command_p,command_e,global_base_url_suffix);
+ stecpy(&command_p,command_e,"/");
+
+ /* process sequence number */ {
+ int l;
+ l= sprintf(command_p,"%03i/%03i/%03i.osc.gz",
+ file_sequence_number/1000000,file_sequence_number/1000%1000,
+ file_sequence_number%1000);
+ command_p+= l;
+ } // process sequence number
+
+ stecpy(&command_p,command_e," -O \"");
+ steesccpy(&command_p,command_e,this_cachefile_name);
+ stecpy(&command_p,command_e,"\" 2>&1 && echo \"Wget Command Ok\"");
+ shell_command(command,result);
+ if(strstr(result,"Wget Command Ok")==NULL) { // download error
+ PERRv("Could not download %s changefile %i",
CFTNAME(changefile_type),file_sequence_number)
- } // verbose mode
+ PINFOv("wget Error message:\n%s",result)
+exit(1);
+ }
+ if(loglevel>0 && old_file_length>=10) {
+ // verbose mode AND file was already in cache
+ if(file_length(this_cachefile_name)!=old_file_length)
+ PINFOv("%s changefile %i: download completed",
+ CFTNAME(changefile_type),file_sequence_number)
+ else
+ PINFOv("%s changefile %i: already in cache",
+ CFTNAME(changefile_type),file_sequence_number)
+ } // verbose mode
+ } // file not in cache or not trusted
number_of_changefiles_in_cache++;
} // changefile download requested
@@ -1007,7 +1028,9 @@ exit(1);
shell_command(command,result);
if(file_length(master_cachefile_name_temp)<10 ||
strstr(result,"Error")!=NULL ||
- strstr(result,"error")!=NULL) { // merging failed
+ strstr(result,"error")!=NULL ||
+ strstr(result,"Warning")!=NULL ||
+ strstr(result,"warning")!=NULL) { // merging failed
PERRv("Merging of changefiles failed:\n%s",command)
if(result[0]!=0)
PERRv("%s",result)
@@ -1015,7 +1038,7 @@ exit(1);
} // merging failed
unlink(master_cachefile_name);
rename(master_cachefile_name_temp,master_cachefile_name);
- } // at lease one change files must be merged
+ } // at least one change file must be merged
} // process_changefile()
#if !__WIN32__
@@ -1105,7 +1128,7 @@ int main(int argc,const char** argv) {
// read command line parameters
if(argc<=1) { // no command line parameters given
fprintf(stderr,"osmupdate " VERSION "\n"
- "Updates .osm and .o5m files, downloads .osc and o5c files.\n"
+ "Updates .osm, .o5m, .pbf files, downloads .osc, .o5c files.\n"
"To get detailed help, please enter: ./osmupdate -h\n");
return 0; // end the program, because without having parameters
// we do not know what to do;
@@ -1146,7 +1169,7 @@ return 0;
}
if((strzcmp(a,"-t=")==0 || strzcmp(a,"--tempfiles=")==0) &&
global_tempfile_name[0]==0) {
- // user-defined prefix for names of temorary files
+ // user-defined prefix for names of temporary files
strmcpy(global_tempfile_name,strchr(a,'=')+1,
sizeof(global_tempfile_name)-50);
continue; // take next parameter
@@ -1156,6 +1179,11 @@ return 0;
global_keep_tempfiles= true;
continue; // take next parameter
}
+ if(strzcmp(a,"--trust-tempfiles")==0) {
+ // cached files are considered to be intact
+ global_trust_tempfiles= true;
+ continue; // take next parameter
+ }
if(strzcmp(a,"--compression-level=")==0) {
// gzip compression level
static char gzip_par[3]= "";
@@ -1364,7 +1392,7 @@ return 1;
// care about user defined processing categories
if(process_minutely || process_hourly ||
process_daily || process_sporadic) {
- // user wants specific type(s) of chancefiles to be processed
+ // user wants specific type(s) of changefiles to be processed
if(!process_minutely) no_minutely= true;
if(!process_hourly) no_hourly= true;
if(!process_daily) no_daily= true;
@@ -1646,4 +1674,5 @@ return 21;
PINFO("Completed successfully.")
return main_return_value;
- } // end main()
\ No newline at end of file
+ } // end main()
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/osmctools.git
More information about the Pkg-grass-devel
mailing list