[Mapserver-dev] speeding up mapserver
Steve Lime
steve.lime at dnr.state.mn.us
Tue Jun 1 17:05:14 EDT 2004
Man, you've got a lot of time on your hands! ;-) Seriously, we
appreciate the help and
feedback. Give me a bit of time to digest your message and I'll get
back to you ASAP.
BTW Are you with the Apache Project? Just wondering...
Steve
>>> "Mladen Turk" <mturk at apache.org> 6/1/2004 1:35:08 PM >>>
Hi all,
Perhaps someone will find me too boring, but what the heck...
I would like to propose two things.
a) make the loadForm functionality 'public'
b) make the loadForm 'smarter'
The loadForm from mapserv/mapserv_fastcgi is a quite useful function
usable
from more then simple CGI app, cause it is a simple param/value parser
after
all.
Inside the docs, there is a statement that the map file is case
insensitive,
but when looking in the source I found a whole bunch of 'strcasecmp'
that
for each char makes a function call to 'tolower'. If the configuration
parameters 'are' case insensitive, then IMHO making them lowercase on
the
'input' stream (either file or request) would make case sensitive
comparator
unneeded.
Also, having a fixed set of comparable strings makes me thinking...
Here is my proposal.
I someone heard of 'gperf', then IMO for larger subset of comparable
string
params something like this can be used:
gperf -L ANSI-C -S 1 -s 3 -t -T -D -k '1-126,$' -l <mapparserx.g
>mapparserx.c
with mapparserx.g
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "maptemplate.h"
#include "mapparserx.h"
%}
struct mapParseKeywords {
const char *name;
int id;
int type;
};
%%
"service", MSP_SERVICE, MST_SERV
"queryfile", MSP_QUERYFILE, MST_FORM
"savequery", MSP_SAVEQUERY, MST_FORM
"zoom", MSP_ZOOM, MST_FORM
"zoomdir", MSP_ZOOMDIR, MST_FORM
"zoomsize", MSP_ZOOMSIZE, MST_FORM
"imgext", MSP_IMGEXT, MST_FORM
"searchmap", MSP_SEARCHMAP, MST_FORM
"mapext", MSP_MAPEXT, MST_FORM
"minx", MSP_MINX, MST_FORM
"maxx", MSP_MAXX, MST_FORM
"miny", MSP_MINY, MST_FORM
"maxy", MSP_MAXY, MST_FORM
"mapxy", MSP_MAPXY, MST_FORM
"mapshape", MSP_MAPSHAPE, MST_FORM
"img.x", MSP_IMG_X, MST_FORM
"img.y", MSP_IMG_Y, MST_FORM
"imgxy", MSP_IMGXY, MST_FORM
"imgbox", MSP_IMGBOX, MST_FORM
"imgshape", MSP_IMGSHAPE, MST_FORM
"ref.x", MSP_REF_X, MST_FORM
"ref.y", MSP_REF_Y, MST_FORM
"refxy", MSP_REFXY, MST_FORM
"buffer", MSP_BUFFER, MST_FORM
"imgsize", MSP_IMGSIZE, MST_FORM
"mapsize", MSP_MAPSIZE, MST_FORM
"layers", MSP_LAYERS, MST_FORM
"layer", MSP_LAYER, MST_FORM
"qlayer", MSP_QLAYER, MST_FORM
"qitem", MSP_QITEM, MST_FORM
"qstring", MSP_QSTRING, MST_FORM
"slayer", MSP_SLAYER, MST_FORM
"shapeindex", MSP_SHAPEINDEX, MST_FORM
"tileindex", MSP_TILEINDEX, MST_FORM
"mode", MSP_MODE, MST_FORM
"id", MSP_ID, MST_FORM
"scale", MSP_SCALE, MST_FORM
"browse", BROWSE, MST_MODE
"zoomin", ZOOMIN, MST_MODE
"zoomout", ZOOMOUT, MST_MODE
"map", MAP, MST_MODE
"legend", LEGEND, MST_MODE
"reference", REFERENCE, MST_MODE
"scalebar", SCALEBAR, MST_MODE
"coordinate", COORDINATE, MST_MODE
"query", QUERY, MST_MODE
"querymap", QUERYMAP, MST_MODE
"nquery", NQUERY, MST_MODE
"nquerymap", NQUERYMAP, MST_MODE
"itemquery", ITEMQUERY, MST_MODE
"itemquerymap", ITEMQUERYMAP, MST_MODE
"itemnquery", ITEMNQUERY, MST_MODE
"itemnquerymap", ITEMNQUERYMAP, MST_MODE
"featurequery", FEATUREQUERY, MST_MODE
"featurequerymap", FEATUREQUERYMAP, MST_MODE
"featurenquery", FEATURENQUERY, MST_MODE
"featurenquerymap", FEATURENQUERYMAP, MST_MODE
"itemfeaturequery", ITEMFEATUREQUERY, MST_MODE
"itemfeaturequerymap", ITEMFEATUREQUERYMAP, MST_MODE
"itemfeaturenquery", ITEMFEATURENQUERY, MST_MODE
"itemfeaturenquerymap", ITEMFEATURENQUERYMAP, MST_MODE
"indexquery", INDEXQUERY, MST_MODE
"indexquerymap", INDEXQUERYMAP, MST_MODE
And mapparserx.h
#ifndef MAPPARSERX_H
#define MAPPARSERX_H
/*
** Keyword definitions for the mapdefines (used by gperf)
*/
typedef struct mapParseKeywords mapParseKeywords;
struct mapParseKeywords {
const char *name;
int id;
int type;
};
struct mapParseKeywords *in_word_set (const char *str,
unsigned int len);
#define MST_FORM 1
#define MST_MODE 2
#define MST_SERV 3
#define MSP_QUERYFILE 101
#define MSP_SAVEQUERY 102
#define MSP_ZOOM 103
#define MSP_ZOOMDIR 104
#define MSP_ZOOMSIZE 105
#define MSP_IMGEXT 106
#define MSP_SEARCHMAP 107
#define MSP_MAPEXT 108
#define MSP_MINX 109
#define MSP_MAXX 110
#define MSP_MINY 111
#define MSP_MAXY 112
#define MSP_MAPXY 113
#define MSP_MAPSHAPE 114
#define MSP_IMG_X 115
#define MSP_IMG_Y 116
#define MSP_IMGXY 117
#define MSP_IMGBOX 118
#define MSP_IMGSHAPE 119
#define MSP_REF_X 120
#define MSP_REF_Y 121
#define MSP_REFXY 122
#define MSP_BUFFER 123
#define MSP_IMGSIZE 124
#define MSP_MAPSIZE 125
#define MSP_LAYERS 126
#define MSP_LAYER 127
#define MSP_QLAYER 128
#define MSP_QITEM 129
#define MSP_QSTRING 130
#define MSP_SLAYER 131
#define MSP_SHAPEINDEX 132
#define MSP_TILEINDEX 133
#define MSP_MODE 134
#define MSP_ID 135
#define MSP_SCALE 136
/* TODO: WMS Server params */
#define MSP_SERVICE 137
#define MSP_VERSION 138
#define MSP_WMTVER 139
#define MSP_REQUEST 140
#define MSP_EXCEPTIONS 141
#define MSP_FORMAT 142
/* TODO: WFS Server params */
#define MSP_MAXFEATURES 143
#define MSP_BBOX 144
#define MSP_TYPENAME 145
#define MSP_FILTER 146
#define MSP_OUTPUTFORMAT 147
#endif /* MAPPARSERX_H */
So, it will produce the 'almost' perfect hash for each param.
Here is my snapshot of the rewritten loadForm:
static double atofx(const char *str, int *err)
{
char b[64];
char *p, *c, *s;
double r;
s = &b[0];
strncpy(s, str, 62);
s[63] = '\0';
p = strrchr(s, '.');
c = strrchr(s, ',');
if (p && c) {
if (p < c) {
/* remove all points */
rmallch(s, '.');
for (p = s; *p; p++) {
if (*p == ',')
*p = '.';
}
}
else
rmallch(s, ',');
}
else if (c && !p) {
if (strchr(s, ',') == c)
s[c-s] = '.';
rmallch(s, ',');
}
else if (p && !c) {
if (strchr(s, '.') != c)
rmallch(s, '.');
}
r = strtod(s, &p);
if (err && *p)
*err = -1;
return r;
}
static double satof(const char *str)
{
return atofx(str, NULL);
}
static int atoix(const char *str, int *err)
{
char *p;
long l;
l = strtol(str, &p, 10);
if (err && *p)
*err = -1;
return (int)l;
}
static char *strncpyx(char *dst, const char *src, size_t n)
{
char *d = dst;
--n;
if (n > 0) {
const char *s = src;
do {
if ((*d++ = *s++) == 0) {
/* NUL pad the remaining n-1 bytes */
while (--n != 0)
*d++ = 0;
break;
}
} while (--n != 0);
}
*d = 0;
return (dst);
}
int msLoadMapParam(mapObj *map, const char *name,
const char *value, int loadCustom)
{
int j, k;
char tmpstr[1024];
if (strncmp(name, "map_", 4) == 0) {
if (msLoadMapString(map, (char *)name, (char *)value) == -1) {
return -1;
}
}
if (!loadCustom)
return 0;
if (_snprintf(tmpstr, sizeof(tmpstr) - 1, "%%%s%%", name) < 1) {
return -1;
}
for (j = 0; j < map->numlayers; j++) {
if (map->layers[j].data && (strstr(map->layers[j].data, tmpstr)
!=
NULL))
map->layers[j].data = gsub(map->layers[j].data, tmpstr,
value);
if (map->layers[j].connection &&
(strstr(map->layers[j].connection,
tmpstr) != NULL))
map->layers[j].connection =
gsub(map->layers[j].connection,
tmpstr, value);
if (map->layers[j].filter.string &&
(strstr(map->layers[j].filter.string, tmpstr) != NULL))
map->layers[j].filter.string =
gsub(map->layers[j].filter.string, tmpstr, value);
for (k = 0; k < map->layers[j].numclasses; k++) {
if ( map->layers[j].class[k].expression.string &&
(strstr(map->layers[j].class[k].expression.string, tmpstr) != NULL))
map->layers[j].class[k].expression.string =
gsub(map->layers[j].class[k].expression.string, tmpstr, value);
}
}
return 0;
}
#define CONVERSION_ERROR(x) \
do { \
if (x != 0) { \
msSetError(MS_WEBERR, "Parameter number conversion.",
"loadForm()");
\
return -1; \
} } while (0)
int msLoadFormParam(mapservObj *msObj,
const char *name, const char *value)
{
int j, n, cve = 0;
char **tokens = NULL;
struct mapParseKeywords *kwd;
kwd = in_word_set(name, strlen(name));
if (!kwd || kwd->type != MST_FORM) {
msSetError(MS_WEBERR, "Unreckognized keyword.", "loadForm()");
return -1;
}
switch (kwd->id) {
case MSP_QUERYFILE:
if (msObj->QueryFile)
free(msObj->QueryFile);
msObj->QueryFile = strdup(value);
break;
case MSP_SAVEQUERY:
msObj->SaveQuery = MS_TRUE;
break;
case MSP_ZOOM:
msObj->Zoom = atofx(value, &cve);
CONVERSION_ERROR(cve);
if ((msObj->Zoom > MAXZOOM) || (msObj->Zoom < MINZOOM)) {
msSetError(MS_WEBERR, "Zoom value out of range.",
"loadForm()");
return -1;
}
break;
case MSP_ZOOMDIR:
msObj->ZoomDirection = atoix(value, &cve);
CONVERSION_ERROR(cve);
if((msObj->ZoomDirection != -1) && (msObj->ZoomDirection != 1)
&&
(msObj->ZoomDirection != 0)) {
msSetError(MS_WEBERR, "Zoom direction must be 1, 0 or
-1.",
"loadForm()");
return -1;
}
break;
case MSP_ZOOMSIZE: // absolute zoom magnitude
msObj->ZoomSize = atoix(value, &cve);
CONVERSION_ERROR(cve);
if ((msObj->ZoomSize > MAXZOOM) || (msObj->ZoomSize < 1)) {
msSetError(MS_WEBERR, "Invalid zoom size.", "loadForm()");
return -1;
}
break;
case MSP_IMGEXT: // extent of an existing image in a web
application
tokens = split(value, ' ', &n);
if (!tokens || n != 4) {
msSetError(MS_WEBERR, "Not enough arguments for imgext.",
"loadForm()");
return -1;
}
msObj->ImgExt.minx = atofx(tokens[0], &cve);
msObj->ImgExt.miny = atofx(tokens[1], &cve);
msObj->ImgExt.maxx = atofx(tokens[2], &cve);
msObj->ImgExt.maxy = atofx(tokens[3], &cve);
msFreeCharArray(tokens, 4);
CONVERSION_ERROR(cve);
break;
case MSP_SEARCHMAP:
msObj->SearchMap = MS_TRUE;
break;
case MSP_ID:
strncpyx(msObj->Id, value, IDSIZE);
break;
case MSP_MAPEXT: // extent of the new map or query
if (strncasecmp(value, "shape", 5) == 0)
msObj->UseShapes = MS_TRUE;
else {
tokens = split(value, ' ', &n);
if(!tokens) {
msSetError(MS_MEMERR, NULL, "loadForm()");
return -1;
}
if(n != 4) {
msSetError(MS_WEBERR, "Not enough arguments for
mapext.",
"loadForm()");
return -1;
}
msObj->Map->extent.minx = atofx(tokens[0], &cve);
msObj->Map->extent.miny = atofx(tokens[1], &cve);
msObj->Map->extent.maxx = atofx(tokens[2], &cve);
msObj->Map->extent.maxy = atofx(tokens[3], &cve);
msFreeCharArray(tokens, 4);
CONVERSION_ERROR(cve);
#ifdef USE_PROJ
// make sure both coordinates are in range!
if (msObj->Map->projection.proj &&
!pj_is_latlong(msObj->Map->projection.proj)
&& (msObj->Map->extent.minx >= -180.0 &&
msObj->Map->extent.minx <= 180.0)
&& (msObj->Map->extent.miny >= -90.0 &&
msObj->Map->extent.miny <= 90.0)
&& (msObj->Map->extent.maxx >= -180.0 &&
msObj->Map->extent.maxx <= 180.0)
&& (msObj->Map->extent.maxy >= -90.0 &&
msObj->Map->extent.maxy <= 90.0))
msProjectRect(&(msObj->Map->latlon),
&(msObj->Map->projection),
&(msObj->Map->extent)); // extent is a in lat/lon
#endif
if ((msObj->Map->extent.minx != msObj->Map->extent.maxx)
&&
(msObj->Map->extent.miny != msObj->Map->extent.maxy)) {
//
extent seems ok
msObj->CoordSource = FROMUSERBOX;
msObj->QueryCoordSource = FROMUSERBOX;
}
}
break;
case MSP_MINX: // extent of the new map, in pieces
msObj->Map->extent.minx = atofx(value, &cve);
CONVERSION_ERROR(cve);
break;
case MSP_MAXX:
msObj->Map->extent.maxx = atofx(value, &cve);
CONVERSION_ERROR(cve);
break;
case MSP_MINY:
msObj->Map->extent.miny = atofx(value, &cve);
CONVERSION_ERROR(cve);
break;
case MSP_MAXY:
msObj->Map->extent.maxy = atofx(value, &cve);
CONVERSION_ERROR(cve);
msObj->CoordSource = FROMUSERBOX;
msObj->QueryCoordSource = FROMUSERBOX;
break;
case MSP_MAPXY: // user map coordinate
if (strncasecmp(value, "shape", 5) == 0) {
msObj->UseShapes = MS_TRUE;
}
else {
tokens = split(value, ' ', &n);
if(!tokens || n != 2) {
msSetError(MS_WEBERR, "Not enough arguments for
mapxy.",
"loadForm()");
return -1;
}
msObj->MapPnt.x = atofx(tokens[0], &cve);
msObj->MapPnt.y = atofx(tokens[1], &cve);
msFreeCharArray(tokens, 2);
CONVERSION_ERROR(cve);
#ifdef USE_PROJ
if (msObj->Map->projection.proj &&
!pj_is_latlong(msObj->Map->projection.proj)
&& (msObj->MapPnt.x >= -180.0 && msObj->MapPnt.x <=
180.0)
&& (msObj->MapPnt.y >= -90.0 && msObj->MapPnt.y <=
90.0))
msProjectPoint(&(msObj->Map->projection),
&(msObj->Map->projection),
&msObj->MapPnt); // point is a in lat/lon
#endif
if (msObj->CoordSource == NONE) { // don't override
previous
settings (i.e. buffer or scale )
msObj->CoordSource = FROMUSERPNT;
msObj->QueryCoordSource = FROMUSERPNT;
}
}
break;
case MSP_MAPSHAPE: // query shape
{
lineObj line = {0, NULL};
tokens = split(value, ' ', &n);
if ((line.point = (pointObj
*)malloc(sizeof(pointObj)*(n/2))) ==
NULL) {
msSetError(MS_MEMERR, NULL, "loadForm()");
return -1;
}
line.numpoints = n/2;
msInitShape(&(msObj->SelectShape));
msObj->SelectShape.type = MS_SHAPE_POLYGON;
for (j = 0; j < n/2; j++) {
line.point[j].x = atof(tokens[2 * j]);
line.point[j].y = atof(tokens[2 * j + 1]);
#ifdef USE_PROJ
if (msObj->Map->projection.proj &&
!pj_is_latlong(msObj->Map->projection.proj)
&& (line.point[j].x >= -180.0 && line.point[j].x
<=
180.0)
&& (line.point[j].y >= -90.0 && line.point[j].y <=
90.0))
msProjectPoint(&(msObj->Map->latlon),
&(msObj->Map->projection),
&line.point[j]); // point is a in lat/lon
#endif
}
cve = msAddLine(&msObj->SelectShape, &line);
msFree(line.point);
msFreeCharArray(tokens, n);
if (cve == -1)
return -1;
msObj->QueryCoordSource = FROMUSERSHAPE;
}
break;
case MSP_IMG_X: // mouse click, in pieces
msObj->ImgPnt.x = atofx(value, &cve);
CONVERSION_ERROR(cve);
if ((msObj->ImgPnt.x > (2*msObj->Map->maxsize)) ||
(msObj->ImgPnt.x < (-2*msObj->Map->maxsize))) {
msSetError(MS_WEBERR, "Coordinate out of range.",
"loadForm()");
return -1;
}
msObj->CoordSource = FROMIMGPNT;
msObj->QueryCoordSource = FROMIMGPNT;
break;
case MSP_IMG_Y:
msObj->ImgPnt.y = atofx(value, &cve);
CONVERSION_ERROR(cve);
if ((msObj->ImgPnt.y > (2*msObj->Map->maxsize)) ||
(msObj->ImgPnt.y < (-2*msObj->Map->maxsize))) {
msSetError(MS_WEBERR, "Coordinate out of range.",
"loadForm()");
return -1;
}
msObj->CoordSource = FROMIMGPNT;
msObj->QueryCoordSource = FROMIMGPNT;
break;
case MSP_IMGXY: // mouse click, single variable
if(msObj->CoordSource == FROMIMGPNT)
return 0;
tokens = split(value, ' ', &n);
if(!tokens || n != 2) {
msSetError(MS_WEBERR, "Not enough arguments for imgxy.",
"loadForm()");
return -1;
}
msObj->ImgPnt.x = atofx(tokens[0], &cve);
msObj->ImgPnt.y = atofx(tokens[1], &cve);
msFreeCharArray(tokens, 2);
CONVERSION_ERROR(cve);
if ((msObj->ImgPnt.x > (2*msObj->Map->maxsize)) ||
(msObj->ImgPnt.x < (-2*msObj->Map->maxsize)) ||
(msObj->ImgPnt.y > (2*msObj->Map->maxsize)) ||
(msObj->ImgPnt.y < (-2*msObj->Map->maxsize))) {
msSetError(MS_WEBERR, "Reference map coordinate out of
range.",
"loadForm()");
return -1;
}
if (msObj->CoordSource == NONE) { // override nothing since
this
parameter is usually used to hold a default value
msObj->CoordSource = FROMIMGPNT;
msObj->QueryCoordSource = FROMIMGPNT;
}
break;
case MSP_IMGBOX: // selection box (eg. mouse drag)
tokens = split(value, ' ', &n);
if(!tokens || n != 4) {
msSetError(MS_WEBERR, "Not enough arguments for imgbox.",
"loadForm()");
return -1;
}
msObj->ImgBox.minx = atofx(tokens[0], &cve);
msObj->ImgBox.miny = atofx(tokens[1], &cve);
msObj->ImgBox.maxx = atofx(tokens[2], &cve);
msObj->ImgBox.maxy = atofx(tokens[3], &cve);
msFreeCharArray(tokens, 4);
CONVERSION_ERROR(cve);
if ((msObj->ImgBox.minx != msObj->ImgBox.maxx) &&
(msObj->ImgBox.miny != msObj->ImgBox.maxy)) { // must not
degenerate into a point
msObj->CoordSource = FROMIMGBOX;
msObj->QueryCoordSource = FROMIMGBOX;
}
break;
case MSP_IMGSHAPE: // shape given in image coordinates
{
lineObj line = {0,NULL};
tokens = split(value, ' ', &n);
if((line.point = (pointObj
*)malloc(sizeof(pointObj)*(n/2))) ==
NULL) {
msSetError(MS_MEMERR, NULL, "loadForm()");
return -1;
}
line.numpoints = n/2;
msInitShape(&msObj->SelectShape);
msObj->SelectShape.type = MS_SHAPE_POLYGON;
for (j = 0; j < n/2; j++) {
line.point[j].x = atof(tokens[2 * j]);
line.point[j].y = atof(tokens[2 * j + 1]);
}
cve = msAddLine(&msObj->SelectShape, &line);
msFree(line.point);
msFreeCharArray(tokens, n);
if (cve == -1)
return -1;
msObj->QueryCoordSource = FROMIMGSHAPE;
}
break;
case MSP_REF_X: // mouse click in reference image, in pieces
msObj->RefPnt.x = atofx(value, &cve);
CONVERSION_ERROR(cve);
if ((msObj->RefPnt.x > (2 * msObj->Map->maxsize)) ||
(msObj->RefPnt.x < (-2*msObj->Map->maxsize))) {
msSetError(MS_WEBERR, "Coordinate out of range.",
"loadForm()");
return -1;
}
msObj->CoordSource = FROMREFPNT;
break;
case MSP_REF_Y:
msObj->RefPnt.y = atofx(value, &cve);
CONVERSION_ERROR(cve);
if((msObj->RefPnt.y > (2 * msObj->Map->maxsize)) ||
(msObj->RefPnt.y < (-2*msObj->Map->maxsize))) {
msSetError(MS_WEBERR, "Coordinate out of range.",
"loadForm()");
return -1;
}
msObj->CoordSource = FROMREFPNT;
break;
case MSP_REFXY: /* mouse click in reference image, single variable
*/
tokens = split(value, ' ', &n);
if(!tokens || n != 2) {
msSetError(MS_WEBERR, "Not enough arguments for imgxy.",
"loadForm()");
return -1;
}
msObj->RefPnt.x = atofx(tokens[0], &cve);
msObj->RefPnt.y = atofx(tokens[1], &cve);
msFreeCharArray(tokens, 2);
CONVERSION_ERROR(cve);
if ((msObj->RefPnt.x > (2 * msObj->Map->maxsize)) ||
(msObj->RefPnt.x < (-2*msObj->Map->maxsize)) ||
(msObj->RefPnt.y
> (2*msObj->Map->maxsize)) || (msObj->RefPnt.y <
(-2*msObj->Map->maxsize)))
{
msSetError(MS_WEBERR, "Reference map coordinate out of
range.",
"loadForm()");
return -1;
}
msObj->CoordSource = FROMREFPNT;
break;
case MSP_BUFFER: // radius (map units), actually 1/2 square side
msObj->Buffer = atofx(value, &cve);
CONVERSION_ERROR(cve);
msObj->CoordSource = FROMBUF;
msObj->QueryCoordSource = FROMUSERPNT;
break;
case MSP_SCALE: // scale for new map
msObj->Scale = atofx(value, &cve);
CONVERSION_ERROR(cve);
if (msObj->Scale <= 0) {
msSetError(MS_WEBERR, "Scale out of range.",
"loadForm()");
return -1;
}
msObj->CoordSource = FROMSCALE;
msObj->QueryCoordSource = FROMUSERPNT;
break;
case MSP_IMGSIZE: // size of existing image (pixels)
tokens = split(value, ' ', &n);
if(!tokens) {
msSetError(MS_MEMERR, NULL, "loadForm()");
return -1;
}
if (!tokens || n != 2) {
msSetError(MS_WEBERR, "Not enough arguments for imgsize.",
"loadForm()");
return -1;
}
msObj->ImgCols = atoix(tokens[0], &cve);
msObj->ImgRows = atoix(tokens[1], &cve);
msFreeCharArray(tokens, 2);
CONVERSION_ERROR(cve);
if (msObj->ImgCols > msObj->Map->maxsize ||
msObj->ImgRows > msObj->Map->maxsize ||
msObj->ImgCols < 0 || msObj->ImgRows < 0) {
msSetError(MS_WEBERR, "Image size out of range.",
"loadForm()");
return -1;
}
break;
case MSP_MAPSIZE: // size of new map (pixels)
tokens = split(value, ' ', &n);
if(!tokens || n != 2) {
msSetError(MS_WEBERR, "Not enough arguments for mapsize.",
"loadForm()");
return -1;
}
msObj->Map->width = atoix(tokens[0], &cve);
msObj->Map->height = atoix(tokens[1], &cve);
msFreeCharArray(tokens, 2);
CONVERSION_ERROR(cve);
if (msObj->Map->width > msObj->Map->maxsize ||
msObj->Map->height > msObj->Map->maxsize ||
msObj->Map->width < 0 || msObj->Map->height < 0) {
msSetError(MS_WEBERR, "Image size out of range.",
"loadForm()");
return -1;
}
break;
case MSP_LAYERS: // turn a set of layers, delimited by spaces, on
{
char **layers = split(value, ' ', &n);
for (j = n; j < n; j++)
msObj->Layers[msObj->NumLayers + j] =
strdup(layers[j]);
msObj->NumLayers += j;
msFreeCharArray(layers, n);
}
break;
case MSP_LAYER: // turn a single layer/group on
msObj->Layers[msObj->NumLayers] = strdup(value);
msObj->NumLayers++;
break;
case MSP_QLAYER: // layer to query (i.e search)
if (msObj->QueryLayer)
free(msObj->QueryLayer);
msObj->QueryLayer = strdup(value);
break;
case MSP_QITEM: // attribute to query on (optional)
if (msObj->QueryItem)
free(msObj->QueryItem);
msObj->QueryItem = strdup(value);
break;
case MSP_QSTRING: // attribute query string
if (msObj->QueryString)
free(msObj->QueryString);
msObj->QueryString = strdup(value);
break;
case MSP_SLAYER: // layer to select (for feature based search)
if (msObj->SelectLayer)
free(msObj->SelectLayer);
msObj->SelectLayer = strdup(value);
break;
case MSP_SHAPEINDEX: // used for index queries
msObj->ShapeIndex = atoix(value, &cve);
CONVERSION_ERROR(cve);
break;
case MSP_TILEINDEX:
msObj->TileIndex = atoix(value, &cve);
CONVERSION_ERROR(cve);
break;
case MSP_MODE: // set operation mode
kwd = in_word_set(value, strlen(value));
if (!kwd || kwd->type != MST_MODE) {
msSetError(MS_WEBERR, "Invalid mode.", "loadForm()");
return-1;
}
msObj->Mode = kwd->id;
if(msObj->Mode == ZOOMIN) {
msObj->ZoomDirection = 1;
msObj->Mode = BROWSE;
}
else if(msObj->Mode == ZOOMOUT) {
msObj->ZoomDirection = -1;
msObj->Mode = BROWSE;
}
break;
default:
break;
}
return 0;
}
More information about the mapserver-dev
mailing list