Skip to content

Commit 93600d2

Browse files
committed
RFC86 implementation (MapServer#4538)
1 parent 523c005 commit 93600d2

8 files changed

+2156
-1338
lines changed

mapcopy.c

+26
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,24 @@ int msCopyLegend(legendObj *dst, legendObj *src, mapObj *map)
840840
return MS_SUCCESS;
841841
}
842842

843+
int msCopyScaleTokenEntry(scaleTokenEntryObj *src, scaleTokenEntryObj *dst) {
844+
MS_COPYSTRING(dst->value,src->value);
845+
MS_COPYSTELEM(minscale);
846+
MS_COPYSTELEM(maxscale);
847+
return MS_SUCCESS;
848+
}
849+
850+
int msCopyScaleToken(scaleTokenObj *src, scaleTokenObj *dst) {
851+
int i;
852+
MS_COPYSTRING(dst->name,src->name);
853+
MS_COPYSTELEM(n_entries);
854+
dst->tokens = (scaleTokenEntryObj*)msSmallCalloc(src->n_entries,sizeof(scaleTokenEntryObj));
855+
for(i=0;i<src->n_entries;i++) {
856+
msCopyScaleTokenEntry(&src->tokens[i],&dst->tokens[i]);
857+
}
858+
return MS_SUCCESS;
859+
}
860+
843861
/***********************************************************************
844862
* msCopyLayer() *
845863
* *
@@ -860,6 +878,14 @@ int msCopyLayer(layerObj *dst, layerObj *src)
860878

861879
MS_COPYSTELEM(classitemindex);
862880

881+
for(i = 0; i < src->numscaletokens; i++) {
882+
if(msGrowLayerScaletokens(dst) == NULL)
883+
return MS_FAILURE;
884+
initScaleToken(&dst->scaletokens[i]);
885+
msCopyScaleToken(&src->scaletokens[i],&dst->scaletokens[i]);
886+
dst->numscaletokens++;
887+
}
888+
863889
for (i = 0; i < src->numclasses; i++) {
864890
if (msGrowLayerClasses(dst) == NULL)
865891
return MS_FAILURE;

mapfile.c

+137
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <stdarg.h>
3333
#include <assert.h>
3434
#include <ctype.h>
35+
#include <float.h>
3536

3637
#include "mapserver.h"
3738
#include "mapfile.h"
@@ -768,6 +769,23 @@ int loadJoin(joinObj *join)
768769
} /* next token */
769770
}
770771

772+
static void writeScaleToken(FILE *stream, int indent, scaleTokenObj *token) {
773+
int i;
774+
indent++;
775+
writeBlockBegin(stream,indent,"SCALETOKEN");
776+
writeString(stream, indent, "NAME", NULL, token->name);
777+
indent++;
778+
writeBlockBegin(stream,indent,"VALUES");
779+
for(i=0;i<token->n_entries;i++) {
780+
char minscale[32];
781+
sprintf(minscale,"%g",token->tokens[i].minscale);
782+
writeNameValuePair(stream, indent, minscale, token->tokens[i].value);
783+
}
784+
writeBlockEnd(stream,indent,"VALUES");
785+
indent--;
786+
writeBlockEnd(stream,indent,"SCALETOKEN");
787+
}
788+
771789
static void writeJoin(FILE *stream, int indent, joinObj *join)
772790
{
773791
indent++;
@@ -3687,6 +3705,9 @@ int initLayer(layerObj *layer, mapObj *map)
36873705
layer->maxfeatures = -1; /* no quota */
36883706
layer->startindex = -1; /*used for pagination*/
36893707

3708+
layer->scaletokens = NULL;
3709+
layer->numscaletokens = 0;
3710+
36903711
layer->template = layer->header = layer->footer = NULL;
36913712

36923713
layer->transform = MS_TRUE;
@@ -3770,6 +3791,28 @@ int initLayer(layerObj *layer, mapObj *map)
37703791
return(0);
37713792
}
37723793

3794+
int initScaleToken(scaleTokenObj* token) {
3795+
token->n_entries = 0;
3796+
token->name = NULL;
3797+
token->tokens = NULL;
3798+
return MS_SUCCESS;
3799+
}
3800+
3801+
int freeScaleTokenEntry( scaleTokenEntryObj *token) {
3802+
msFree(token->value);
3803+
return MS_SUCCESS;
3804+
}
3805+
3806+
int freeScaleToken(scaleTokenObj *scaletoken) {
3807+
int i;
3808+
msFree(scaletoken->name);
3809+
for(i=0;i<scaletoken->n_entries;i++) {
3810+
freeScaleTokenEntry(&scaletoken->tokens[i]);
3811+
}
3812+
msFree(scaletoken->tokens);
3813+
return MS_SUCCESS;
3814+
}
3815+
37733816
int freeLayer(layerObj *layer)
37743817
{
37753818
int i;
@@ -3815,6 +3858,13 @@ int freeLayer(layerObj *layer)
38153858
}
38163859
msFree(layer->class);
38173860

3861+
if(layer->numscaletokens>0) {
3862+
for(i=0;i<layer->numscaletokens;i++) {
3863+
freeScaleToken(&layer->scaletokens[i]);
3864+
}
3865+
msFree(layer->scaletokens);
3866+
}
3867+
38183868
if(layer->features)
38193869
freeFeatureList(layer->features);
38203870

@@ -3895,6 +3945,85 @@ classObj *msGrowLayerClasses( layerObj *layer )
38953945
return layer->class[layer->numclasses];
38963946
}
38973947

3948+
scaleTokenObj *msGrowLayerScaletokens( layerObj *layer )
3949+
{
3950+
layer->scaletokens = msSmallRealloc(layer->scaletokens,(layer->numscaletokens+1)*sizeof(scaleTokenObj));
3951+
memset(&layer->scaletokens[layer->numscaletokens],0,sizeof(scaleTokenObj));
3952+
return &layer->scaletokens[layer->numscaletokens];
3953+
}
3954+
3955+
int loadScaletoken(scaleTokenObj *token, layerObj *layer) {
3956+
for(;;) {
3957+
int stop = 0;
3958+
switch(msyylex()) {
3959+
case(EOF):
3960+
msSetError(MS_EOFERR, NULL, "loadScaletoken()");
3961+
return(MS_FAILURE);
3962+
case(NAME):
3963+
if(getString(&token->name) == MS_FAILURE) return(MS_FAILURE);
3964+
break;
3965+
case(VALUES):
3966+
for(;;) {
3967+
if(stop) break;
3968+
switch(msyylex()) {
3969+
case(EOF):
3970+
msSetError(MS_EOFERR, NULL, "loadScaletoken()");
3971+
return(MS_FAILURE);
3972+
case(END):
3973+
stop = 1;
3974+
if(token->n_entries == 0) {
3975+
msSetError(MS_PARSEERR,"Scaletoken (line:%d) has no VALUES defined","loadScaleToken()",msyylineno);
3976+
return(MS_FAILURE);
3977+
}
3978+
token->tokens[token->n_entries-1].maxscale = DBL_MAX;
3979+
break;
3980+
case(MS_STRING):
3981+
/* we have a key */
3982+
token->tokens = msSmallRealloc(token->tokens,(token->n_entries+1)*sizeof(scaleTokenEntryObj));
3983+
3984+
if(1 != sscanf(msyystring_buffer,"%lf",&token->tokens[token->n_entries].minscale)) {
3985+
msSetError(MS_PARSEERR, "failed to parse SCALETOKEN VALUE (%s):(line %d), expecting \"minscale\"", "loadScaletoken()",
3986+
msyystring_buffer,msyylineno);
3987+
return(MS_FAILURE);
3988+
}
3989+
if(token->n_entries == 0) {
3990+
/* check supplied value was 0*/
3991+
if(token->tokens[0].minscale != 0) {
3992+
msSetError(MS_PARSEERR, "First SCALETOKEN VALUE (%s):(line %d) must be zero, expecting \"0\"", "loadScaletoken()",
3993+
msyystring_buffer,msyylineno);
3994+
return(MS_FAILURE);
3995+
}
3996+
} else {
3997+
/* set max scale of previous token */
3998+
token->tokens[token->n_entries-1].maxscale = token->tokens[token->n_entries].minscale;
3999+
}
4000+
token->tokens[token->n_entries].value = NULL;
4001+
if(getString(&(token->tokens[token->n_entries].value)) == MS_FAILURE) return(MS_FAILURE);
4002+
token->n_entries++;
4003+
break;
4004+
default:
4005+
msSetError(MS_IDENTERR, "Parsing error near (%s):(line %d)", "loadScaletoken()", msyystring_buffer, msyylineno );
4006+
return(MS_FAILURE);
4007+
}
4008+
}
4009+
break;
4010+
case(END):
4011+
if(!token->name || !*(token->name)) {
4012+
msSetError(MS_PARSEERR,"ScaleToken missing mandatory NAME entry (line %d)","loadScaleToken()",msyylineno);
4013+
return MS_FAILURE;
4014+
}
4015+
if(token->n_entries == 0) {
4016+
msSetError(MS_PARSEERR,"ScaleToken missing at least one VALUES entry (line %d)","loadScaleToken()",msyylineno);
4017+
return MS_FAILURE;
4018+
}
4019+
return MS_SUCCESS;
4020+
default:
4021+
msSetError(MS_IDENTERR, "Parsing error 2 near (%s):(line %d)", "loadScaletoken()", msyystring_buffer, msyylineno );
4022+
return(MS_FAILURE);
4023+
}
4024+
} /* next token*/
4025+
}
4026+
38984027
int loadLayer(layerObj *layer, mapObj *map)
38994028
{
39004029
int type;
@@ -4211,6 +4340,13 @@ int loadLayer(layerObj *layer, mapObj *map)
42114340
}
42124341
}
42134342
break;
4343+
case(SCALETOKEN):
4344+
if (msGrowLayerScaletokens(layer) == NULL)
4345+
return(-1);
4346+
initScaleToken(&layer->scaletokens[layer->numscaletokens]);
4347+
if(loadScaletoken(&layer->scaletokens[layer->numscaletokens], layer) == -1) return(-1);
4348+
layer->numscaletokens++;
4349+
break;
42144350
case(SIZEUNITS):
42154351
if((layer->sizeunits = getSymbol(8, MS_INCHES,MS_FEET,MS_MILES,MS_METERS,MS_KILOMETERS,MS_NAUTICALMILES,MS_DD,MS_PIXELS)) == -1) return(-1);
42164352
break;
@@ -4391,6 +4527,7 @@ static void writeLayer(FILE *stream, int indent, layerObj *layer)
43914527
writeHashTable(stream, indent, "VALIDATION", &(layer->validation));
43924528

43934529
/* write potentially multiply occuring objects last */
4530+
for(i=0; i<layer->numscaletokens; i++) writeScaleToken(stream, indent, &(layer->scaletokens[i]));
43944531
for(i=0; i<layer->numjoins; i++) writeJoin(stream, indent, &(layer->joins[i]));
43954532
for(i=0; i<layer->numclasses; i++) writeClass(stream, indent, layer->class[i]);
43964533

mapfile.h

+4
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,10 @@ enum MS_TOKEN_SOURCES {MS_FILE_TOKENS=0, MS_STRING_TOKENS, MS_URL_TOKENS};
308308
#define LEADER 1260
309309
#define GRIDSTEP 1261
310310

311+
/* rfc 86 scale-dependant token substitutions */
312+
#define SCALETOKEN 1270
313+
#define VALUES 1271
314+
311315
/* rfc59 bindvals objects */
312316
#define BINDVALS 2000
313317

maplayer.c

+112-1
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,121 @@ void msLayerFreeItemInfo(layerObj *layer)
6868
layer->vtable->LayerFreeItemInfo(layer);
6969
}
7070

71+
int msLayerRestoreFromScaletokens(layerObj *layer)
72+
{
73+
if(!layer->scaletokens) {
74+
return MS_SUCCESS;
75+
}
76+
if(layer->orig_data) {
77+
msFree(layer->data);
78+
layer->data = layer->orig_data;
79+
layer->orig_data = NULL;
80+
}
81+
if(layer->orig_tileindex) {
82+
msFree(layer->tileindex);
83+
layer->tileindex = layer->orig_tileindex;
84+
layer->orig_tileindex = NULL;
85+
}
86+
if(layer->orig_tileitem) {
87+
msFree(layer->tileitem);
88+
layer->tileitem = layer->orig_tileitem;
89+
layer->orig_tileitem = NULL;
90+
}
91+
if(layer->orig_filter) {
92+
msLoadExpressionString(&(layer->filter),layer->orig_filter);
93+
msFree(layer->orig_filter);
94+
layer->orig_filter = NULL;
95+
}
96+
if(layer->orig_filteritem) {
97+
msFree(layer->filteritem);
98+
layer->filteritem = layer->orig_filteritem;
99+
layer->orig_filteritem = NULL;
100+
}
101+
return MS_SUCCESS;
102+
}
103+
104+
int msLayerApplyScaletokens(layerObj *layer, double scale)
105+
{
106+
int i;
107+
if(!layer->scaletokens) {
108+
return MS_SUCCESS;
109+
}
110+
msLayerRestoreFromScaletokens(layer);
111+
for(i=0;i<layer->numscaletokens;i++) {
112+
int tokenindex=0;
113+
scaleTokenObj *st = &layer->scaletokens[i];
114+
scaleTokenEntryObj *ste = NULL;
115+
while(tokenindex<st->n_entries) {
116+
ste = &(st->tokens[tokenindex]);
117+
if(scale < ste->maxscale && scale >= ste->minscale) break; /* current token is the correct one */
118+
tokenindex++;
119+
ste = NULL;
120+
}
121+
assert(ste);
122+
if(layer->data && strstr(layer->data,st->name)) {
123+
if(layer->debug >= MS_DEBUGLEVEL_DEBUG) {
124+
msDebug("replacing scaletoken (%s) with (%s) in layer->data (%s) for scale=%f\n",
125+
st->name,ste->value,layer->name,scale);
126+
}
127+
layer->orig_data = layer->data;
128+
layer->data = msStrdup(layer->data);
129+
layer->data = msReplaceSubstring(layer->data,st->name,ste->value);
130+
}
131+
if(layer->tileindex && strstr(layer->tileindex,st->name)) {
132+
if(layer->debug >= MS_DEBUGLEVEL_DEBUG) {
133+
msDebug("replacing scaletoken (%s) with (%s) in layer->tileindex (%s) for scale=%f\n",
134+
st->name,ste->value,layer->name,scale);
135+
}
136+
layer->orig_tileindex = layer->tileindex;
137+
layer->tileindex = msStrdup(layer->tileindex);
138+
layer->tileindex = msReplaceSubstring(layer->tileindex,st->name,ste->value);
139+
}
140+
if(layer->tileitem && strstr(layer->tileitem,st->name)) {
141+
if(layer->debug >= MS_DEBUGLEVEL_DEBUG) {
142+
msDebug("replacing scaletoken (%s) with (%s) in layer->tileitem (%s) for scale=%f\n",
143+
st->name,ste->value,layer->name,scale);
144+
}
145+
layer->orig_tileitem = layer->tileitem;
146+
layer->tileitem = msStrdup(layer->tileitem);
147+
layer->tileitem = msReplaceSubstring(layer->tileitem,st->name,ste->value);
148+
}
149+
if(layer->filteritem && strstr(layer->filteritem,st->name)) {
150+
if(layer->debug >= MS_DEBUGLEVEL_DEBUG) {
151+
msDebug("replacing scaletoken (%s) with (%s) in layer->filteritem (%s) for scale=%f\n",
152+
st->name,ste->value,layer->name,scale);
153+
}
154+
layer->orig_filteritem = layer->filteritem;
155+
layer->filteritem = msStrdup(layer->filteritem);
156+
layer->filteritem = msReplaceSubstring(layer->filteritem,st->name,ste->value);
157+
}
158+
if(layer->filter.string && strstr(layer->filter.string,st->name)) {
159+
char *tmpval;
160+
if(layer->debug >= MS_DEBUGLEVEL_DEBUG) {
161+
msDebug("replacing scaletoken (%s) with (%s) in layer->filter (%s) for scale=%f\n",
162+
st->name,ste->value,layer->name,scale);
163+
}
164+
layer->orig_filter = msStrdup(layer->filter.string);
165+
tmpval = msStrdup(layer->filter.string);
166+
tmpval = msReplaceSubstring(tmpval,st->name,ste->value);
167+
if(msLoadExpressionString(&(layer->filter),tmpval) == -1) return(MS_FAILURE); /* loadExpression() cleans up previously allocated expression */
168+
msFree(tmpval);
169+
}
170+
}
171+
return MS_SUCCESS;
172+
}
173+
174+
71175
/*
72176
** Does exactly what it implies, readies a layer for processing.
73177
*/
74178
int msLayerOpen(layerObj *layer)
75179
{
180+
int rv;
181+
182+
/* RFC-86 Scale dependant token replacements*/
183+
rv = msLayerApplyScaletokens(layer,(layer->map)?layer->map->scaledenom:-1);
184+
if (rv != MS_SUCCESS) return rv;
185+
76186
/* RFC-69 clustering support */
77187
if (layer->cluster.region)
78188
return msClusterLayerOpen(layer);
@@ -87,7 +197,7 @@ int msLayerOpen(layerObj *layer)
87197
layer->connectiontype = MS_RASTER;
88198

89199
if ( ! layer->vtable) {
90-
int rv = msInitializeVirtualTable(layer);
200+
rv = msInitializeVirtualTable(layer);
91201
if (rv != MS_SUCCESS)
92202
return rv;
93203
}
@@ -232,6 +342,7 @@ void msLayerClose(layerObj *layer)
232342
if (layer->vtable) {
233343
layer->vtable->LayerClose(layer);
234344
}
345+
msLayerRestoreFromScaletokens(layer);
235346
}
236347

237348
/*

0 commit comments

Comments
 (0)