[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