Permalink
Browse files

RFC86 implementation (#4538)

  • Loading branch information...
1 parent 523c005 commit 93600d27ababddb002ed78abb5a3a3417647676a @tbonfort tbonfort committed Dec 14, 2012
Showing with 2,156 additions and 1,338 deletions.
  1. +26 −0 mapcopy.c
  2. +137 −0 mapfile.c
  3. +4 −0 mapfile.h
  4. +112 −1 maplayer.c
  5. +1,846 −1,336 maplexer.c
  6. +2 −0 maplexer.l
  7. +28 −0 mapserver.h
  8. +1 −1 msautotest
View
@@ -840,6 +840,24 @@ int msCopyLegend(legendObj *dst, legendObj *src, mapObj *map)
return MS_SUCCESS;
}
+int msCopyScaleTokenEntry(scaleTokenEntryObj *src, scaleTokenEntryObj *dst) {
+ MS_COPYSTRING(dst->value,src->value);
+ MS_COPYSTELEM(minscale);
+ MS_COPYSTELEM(maxscale);
+ return MS_SUCCESS;
+}
+
+int msCopyScaleToken(scaleTokenObj *src, scaleTokenObj *dst) {
+ int i;
+ MS_COPYSTRING(dst->name,src->name);
+ MS_COPYSTELEM(n_entries);
+ dst->tokens = (scaleTokenEntryObj*)msSmallCalloc(src->n_entries,sizeof(scaleTokenEntryObj));
+ for(i=0;i<src->n_entries;i++) {
+ msCopyScaleTokenEntry(&src->tokens[i],&dst->tokens[i]);
+ }
+ return MS_SUCCESS;
+}
+
/***********************************************************************
* msCopyLayer() *
* *
@@ -860,6 +878,14 @@ int msCopyLayer(layerObj *dst, layerObj *src)
MS_COPYSTELEM(classitemindex);
+ for(i = 0; i < src->numscaletokens; i++) {
+ if(msGrowLayerScaletokens(dst) == NULL)
+ return MS_FAILURE;
+ initScaleToken(&dst->scaletokens[i]);
+ msCopyScaleToken(&src->scaletokens[i],&dst->scaletokens[i]);
+ dst->numscaletokens++;
+ }
+
for (i = 0; i < src->numclasses; i++) {
if (msGrowLayerClasses(dst) == NULL)
return MS_FAILURE;
View
@@ -32,6 +32,7 @@
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
+#include <float.h>
#include "mapserver.h"
#include "mapfile.h"
@@ -768,6 +769,23 @@ int loadJoin(joinObj *join)
} /* next token */
}
+static void writeScaleToken(FILE *stream, int indent, scaleTokenObj *token) {
+ int i;
+ indent++;
+ writeBlockBegin(stream,indent,"SCALETOKEN");
+ writeString(stream, indent, "NAME", NULL, token->name);
+ indent++;
+ writeBlockBegin(stream,indent,"VALUES");
+ for(i=0;i<token->n_entries;i++) {
+ char minscale[32];
+ sprintf(minscale,"%g",token->tokens[i].minscale);
+ writeNameValuePair(stream, indent, minscale, token->tokens[i].value);
+ }
+ writeBlockEnd(stream,indent,"VALUES");
+ indent--;
+ writeBlockEnd(stream,indent,"SCALETOKEN");
+}
+
static void writeJoin(FILE *stream, int indent, joinObj *join)
{
indent++;
@@ -3687,6 +3705,9 @@ int initLayer(layerObj *layer, mapObj *map)
layer->maxfeatures = -1; /* no quota */
layer->startindex = -1; /*used for pagination*/
+ layer->scaletokens = NULL;
+ layer->numscaletokens = 0;
+
layer->template = layer->header = layer->footer = NULL;
layer->transform = MS_TRUE;
@@ -3770,6 +3791,28 @@ int initLayer(layerObj *layer, mapObj *map)
return(0);
}
+int initScaleToken(scaleTokenObj* token) {
+ token->n_entries = 0;
+ token->name = NULL;
+ token->tokens = NULL;
+ return MS_SUCCESS;
+}
+
+int freeScaleTokenEntry( scaleTokenEntryObj *token) {
+ msFree(token->value);
+ return MS_SUCCESS;
+}
+
+int freeScaleToken(scaleTokenObj *scaletoken) {
+ int i;
+ msFree(scaletoken->name);
+ for(i=0;i<scaletoken->n_entries;i++) {
+ freeScaleTokenEntry(&scaletoken->tokens[i]);
+ }
+ msFree(scaletoken->tokens);
+ return MS_SUCCESS;
+}
+
int freeLayer(layerObj *layer)
{
int i;
@@ -3815,6 +3858,13 @@ int freeLayer(layerObj *layer)
}
msFree(layer->class);
+ if(layer->numscaletokens>0) {
+ for(i=0;i<layer->numscaletokens;i++) {
+ freeScaleToken(&layer->scaletokens[i]);
+ }
+ msFree(layer->scaletokens);
+ }
+
if(layer->features)
freeFeatureList(layer->features);
@@ -3895,6 +3945,85 @@ classObj *msGrowLayerClasses( layerObj *layer )
return layer->class[layer->numclasses];
}
+scaleTokenObj *msGrowLayerScaletokens( layerObj *layer )
+{
+ layer->scaletokens = msSmallRealloc(layer->scaletokens,(layer->numscaletokens+1)*sizeof(scaleTokenObj));
+ memset(&layer->scaletokens[layer->numscaletokens],0,sizeof(scaleTokenObj));
+ return &layer->scaletokens[layer->numscaletokens];
+}
+
+int loadScaletoken(scaleTokenObj *token, layerObj *layer) {
+ for(;;) {
+ int stop = 0;
+ switch(msyylex()) {
+ case(EOF):
+ msSetError(MS_EOFERR, NULL, "loadScaletoken()");
+ return(MS_FAILURE);
+ case(NAME):
+ if(getString(&token->name) == MS_FAILURE) return(MS_FAILURE);
+ break;
+ case(VALUES):
+ for(;;) {
+ if(stop) break;
+ switch(msyylex()) {
+ case(EOF):
+ msSetError(MS_EOFERR, NULL, "loadScaletoken()");
+ return(MS_FAILURE);
+ case(END):
+ stop = 1;
+ if(token->n_entries == 0) {
+ msSetError(MS_PARSEERR,"Scaletoken (line:%d) has no VALUES defined","loadScaleToken()",msyylineno);
+ return(MS_FAILURE);
+ }
+ token->tokens[token->n_entries-1].maxscale = DBL_MAX;
+ break;
+ case(MS_STRING):
+ /* we have a key */
+ token->tokens = msSmallRealloc(token->tokens,(token->n_entries+1)*sizeof(scaleTokenEntryObj));
+
+ if(1 != sscanf(msyystring_buffer,"%lf",&token->tokens[token->n_entries].minscale)) {
+ msSetError(MS_PARSEERR, "failed to parse SCALETOKEN VALUE (%s):(line %d), expecting \"minscale\"", "loadScaletoken()",
+ msyystring_buffer,msyylineno);
+ return(MS_FAILURE);
+ }
+ if(token->n_entries == 0) {
+ /* check supplied value was 0*/
+ if(token->tokens[0].minscale != 0) {
+ msSetError(MS_PARSEERR, "First SCALETOKEN VALUE (%s):(line %d) must be zero, expecting \"0\"", "loadScaletoken()",
+ msyystring_buffer,msyylineno);
+ return(MS_FAILURE);
+ }
+ } else {
+ /* set max scale of previous token */
+ token->tokens[token->n_entries-1].maxscale = token->tokens[token->n_entries].minscale;
+ }
+ token->tokens[token->n_entries].value = NULL;
+ if(getString(&(token->tokens[token->n_entries].value)) == MS_FAILURE) return(MS_FAILURE);
+ token->n_entries++;
+ break;
+ default:
+ msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadScaletoken()", msyystring_buffer, msyylineno );
+ return(MS_FAILURE);
+ }
+ }
+ break;
+ case(END):
+ if(!token->name || !*(token->name)) {
+ msSetError(MS_PARSEERR,"ScaleToken missing mandatory NAME entry (line %d)","loadScaleToken()",msyylineno);
+ return MS_FAILURE;
+ }
+ if(token->n_entries == 0) {
+ msSetError(MS_PARSEERR,"ScaleToken missing at least one VALUES entry (line %d)","loadScaleToken()",msyylineno);
+ return MS_FAILURE;
+ }
+ return MS_SUCCESS;
+ default:
+ msSetError(MS_IDENTERR, "Parsing error 2 near (%s):(line %d)", "loadScaletoken()", msyystring_buffer, msyylineno );
+ return(MS_FAILURE);
+ }
+ } /* next token*/
+}
+
int loadLayer(layerObj *layer, mapObj *map)
{
int type;
@@ -4211,6 +4340,13 @@ int loadLayer(layerObj *layer, mapObj *map)
}
}
break;
+ case(SCALETOKEN):
+ if (msGrowLayerScaletokens(layer) == NULL)
+ return(-1);
+ initScaleToken(&layer->scaletokens[layer->numscaletokens]);
+ if(loadScaletoken(&layer->scaletokens[layer->numscaletokens], layer) == -1) return(-1);
+ layer->numscaletokens++;
+ break;
case(SIZEUNITS):
if((layer->sizeunits = getSymbol(8, MS_INCHES,MS_FEET,MS_MILES,MS_METERS,MS_KILOMETERS,MS_NAUTICALMILES,MS_DD,MS_PIXELS)) == -1) return(-1);
break;
@@ -4391,6 +4527,7 @@ static void writeLayer(FILE *stream, int indent, layerObj *layer)
writeHashTable(stream, indent, "VALIDATION", &(layer->validation));
/* write potentially multiply occuring objects last */
+ for(i=0; i<layer->numscaletokens; i++) writeScaleToken(stream, indent, &(layer->scaletokens[i]));
for(i=0; i<layer->numjoins; i++) writeJoin(stream, indent, &(layer->joins[i]));
for(i=0; i<layer->numclasses; i++) writeClass(stream, indent, layer->class[i]);
View
@@ -308,6 +308,10 @@ enum MS_TOKEN_SOURCES {MS_FILE_TOKENS=0, MS_STRING_TOKENS, MS_URL_TOKENS};
#define LEADER 1260
#define GRIDSTEP 1261
+/* rfc 86 scale-dependant token substitutions */
+#define SCALETOKEN 1270
+#define VALUES 1271
+
/* rfc59 bindvals objects */
#define BINDVALS 2000
View
@@ -68,11 +68,121 @@ void msLayerFreeItemInfo(layerObj *layer)
layer->vtable->LayerFreeItemInfo(layer);
}
+int msLayerRestoreFromScaletokens(layerObj *layer)
+{
+ if(!layer->scaletokens) {
+ return MS_SUCCESS;
+ }
+ if(layer->orig_data) {
+ msFree(layer->data);
+ layer->data = layer->orig_data;
+ layer->orig_data = NULL;
+ }
+ if(layer->orig_tileindex) {
+ msFree(layer->tileindex);
+ layer->tileindex = layer->orig_tileindex;
+ layer->orig_tileindex = NULL;
+ }
+ if(layer->orig_tileitem) {
+ msFree(layer->tileitem);
+ layer->tileitem = layer->orig_tileitem;
+ layer->orig_tileitem = NULL;
+ }
+ if(layer->orig_filter) {
+ msLoadExpressionString(&(layer->filter),layer->orig_filter);
+ msFree(layer->orig_filter);
+ layer->orig_filter = NULL;
+ }
+ if(layer->orig_filteritem) {
+ msFree(layer->filteritem);
+ layer->filteritem = layer->orig_filteritem;
+ layer->orig_filteritem = NULL;
+ }
+ return MS_SUCCESS;
+}
+
+int msLayerApplyScaletokens(layerObj *layer, double scale)
+{
+ int i;
+ if(!layer->scaletokens) {
+ return MS_SUCCESS;
+ }
+ msLayerRestoreFromScaletokens(layer);
+ for(i=0;i<layer->numscaletokens;i++) {
+ int tokenindex=0;
+ scaleTokenObj *st = &layer->scaletokens[i];
+ scaleTokenEntryObj *ste = NULL;
+ while(tokenindex<st->n_entries) {
+ ste = &(st->tokens[tokenindex]);
+ if(scale < ste->maxscale && scale >= ste->minscale) break; /* current token is the correct one */
+ tokenindex++;
+ ste = NULL;
+ }
+ assert(ste);
+ if(layer->data && strstr(layer->data,st->name)) {
+ if(layer->debug >= MS_DEBUGLEVEL_DEBUG) {
+ msDebug("replacing scaletoken (%s) with (%s) in layer->data (%s) for scale=%f\n",
+ st->name,ste->value,layer->name,scale);
+ }
+ layer->orig_data = layer->data;
+ layer->data = msStrdup(layer->data);
+ layer->data = msReplaceSubstring(layer->data,st->name,ste->value);
+ }
+ if(layer->tileindex && strstr(layer->tileindex,st->name)) {
+ if(layer->debug >= MS_DEBUGLEVEL_DEBUG) {
+ msDebug("replacing scaletoken (%s) with (%s) in layer->tileindex (%s) for scale=%f\n",
+ st->name,ste->value,layer->name,scale);
+ }
+ layer->orig_tileindex = layer->tileindex;
+ layer->tileindex = msStrdup(layer->tileindex);
+ layer->tileindex = msReplaceSubstring(layer->tileindex,st->name,ste->value);
+ }
+ if(layer->tileitem && strstr(layer->tileitem,st->name)) {
+ if(layer->debug >= MS_DEBUGLEVEL_DEBUG) {
+ msDebug("replacing scaletoken (%s) with (%s) in layer->tileitem (%s) for scale=%f\n",
+ st->name,ste->value,layer->name,scale);
+ }
+ layer->orig_tileitem = layer->tileitem;
+ layer->tileitem = msStrdup(layer->tileitem);
+ layer->tileitem = msReplaceSubstring(layer->tileitem,st->name,ste->value);
+ }
+ if(layer->filteritem && strstr(layer->filteritem,st->name)) {
+ if(layer->debug >= MS_DEBUGLEVEL_DEBUG) {
+ msDebug("replacing scaletoken (%s) with (%s) in layer->filteritem (%s) for scale=%f\n",
+ st->name,ste->value,layer->name,scale);
+ }
+ layer->orig_filteritem = layer->filteritem;
+ layer->filteritem = msStrdup(layer->filteritem);
+ layer->filteritem = msReplaceSubstring(layer->filteritem,st->name,ste->value);
+ }
+ if(layer->filter.string && strstr(layer->filter.string,st->name)) {
+ char *tmpval;
+ if(layer->debug >= MS_DEBUGLEVEL_DEBUG) {
+ msDebug("replacing scaletoken (%s) with (%s) in layer->filter (%s) for scale=%f\n",
+ st->name,ste->value,layer->name,scale);
+ }
+ layer->orig_filter = msStrdup(layer->filter.string);
+ tmpval = msStrdup(layer->filter.string);
+ tmpval = msReplaceSubstring(tmpval,st->name,ste->value);
+ if(msLoadExpressionString(&(layer->filter),tmpval) == -1) return(MS_FAILURE); /* loadExpression() cleans up previously allocated expression */
+ msFree(tmpval);
+ }
+ }
+ return MS_SUCCESS;
+}
+
+
/*
** Does exactly what it implies, readies a layer for processing.
*/
int msLayerOpen(layerObj *layer)
{
+ int rv;
+
+ /* RFC-86 Scale dependant token replacements*/
+ rv = msLayerApplyScaletokens(layer,(layer->map)?layer->map->scaledenom:-1);
+ if (rv != MS_SUCCESS) return rv;
+
/* RFC-69 clustering support */
if (layer->cluster.region)
return msClusterLayerOpen(layer);
@@ -87,7 +197,7 @@ int msLayerOpen(layerObj *layer)
layer->connectiontype = MS_RASTER;
if ( ! layer->vtable) {
- int rv = msInitializeVirtualTable(layer);
+ rv = msInitializeVirtualTable(layer);
if (rv != MS_SUCCESS)
return rv;
}
@@ -232,6 +342,7 @@ void msLayerClose(layerObj *layer)
if (layer->vtable) {
layer->vtable->LayerClose(layer);
}
+ msLayerRestoreFromScaletokens(layer);
}
/*
Oops, something went wrong.

0 comments on commit 93600d2

Please sign in to comment.