[Mapserver-dev] speeding up mapserver

Mladen Turk mturk at apache.org
Tue Jun 1 14:35:08 EDT 2004


This is a multi-part message in MIME format.

------=_NextPart_000_0059_01C44817.DA87D840
Content-Type: text/plain;
	charset="US-ASCII"
Content-Transfer-Encoding: 7bit

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;
}
 
 

------=_NextPart_000_0059_01C44817.DA87D840
Content-Type: application/x-pkcs7-signature;
	name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
	filename="smime.p7s"

MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIJADCCAogw
ggHxoAMCAQICAwxGPTANBgkqhkiG9w0BAQQFADBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh
d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVt
YWlsIElzc3VpbmcgQ0EwHhcNMDQwNTA4MTc0OTIyWhcNMDUwNTA4MTc0OTIyWjBpMR8wHQYDVQQD
ExZUaGF3dGUgRnJlZW1haWwgTWVtYmVyMSUwIwYJKoZIhvcNAQkBFhZtbGFkZW4udHVya0BnaXNk
YXRhLmhyMR8wHQYJKoZIhvcNAQkBFhBtdHVya0BhcGFjaGUub3JnMIGfMA0GCSqGSIb3DQEBAQUA
A4GNADCBiQKBgQDDFpTL3QpMpzZNX4hMRwNoTAcJtSF18PnJf3oUryvGmggiy9cbJAuScvfVku2R
DDeBdJaVqDb83nYQydW6JvZI7m2oKApNRV9veadN/T7Fq81QcSBAQgXRyNWCMyl832zOxDrZNchH
kgQzkm67IMHXxDd8LYAxAj8eFFLuV+g29QIDAQABo0UwQzAzBgNVHREELDAqgRZtbGFkZW4udHVy
a0BnaXNkYXRhLmhygRBtdHVya0BhcGFjaGUub3JnMAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQEE
BQADgYEAtF/h4HA4Zt+3J1a3P0y4Yllqa3srAR+oHJMpQjFLSoUYHkwBQW7iuCWCuzthoIbW/Wuk
g9ww/RSSCJUOFuHham7kClwbWFoRZL9i61L3vfoM3AMKVOj2T0JmoAV+4Ib6lGSaX7DywGbZB5qd
9gpfITF2Cl56XdZ8EXHA2kj2I9cwggMtMIIClqADAgECAgEAMA0GCSqGSIb3DQEBBAUAMIHRMQsw
CQYDVQQGEwJaQTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xGjAY
BgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2Vz
IERpdmlzaW9uMSQwIgYDVQQDExtUaGF3dGUgUGVyc29uYWwgRnJlZW1haWwgQ0ExKzApBgkqhkiG
9w0BCQEWHHBlcnNvbmFsLWZyZWVtYWlsQHRoYXd0ZS5jb20wHhcNOTYwMTAxMDAwMDAwWhcNMjAx
MjMxMjM1OTU5WjCB0TELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UE
BxMJQ2FwZSBUb3duMRowGAYDVQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlm
aWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZyZWVt
YWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUuY29tMIGfMA0G
CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUadfUsJRkW3HpR9gMUbbqcpGwhF59LQ2PexLfhSV1KHQ6
QixjJ5+Ve0vvfhmHHYbqo925zpZkGsIUbkSsfOaP6E0PcR9AOKYAo4d49vmUhl6t6sBeduvZFKNd
bnp8DKVLVX8GGSl/npom1Wq7OCQIapjHsdqjmJH9edvlWsQcuQIDAQABoxMwETAPBgNVHRMBAf8E
BTADAQH/MA0GCSqGSIb3DQEBBAUAA4GBAMfskn5O+PWWpWdiKqTwTRFg0G+NYFhhrCa7UjVcCM8w
+6hKloofYkIjjBcP9LpknBesRynfnZhe0mxgcVyirNx54+duAEcftQ0o6AKd5Jr9E/Sm2Xyx+Nxf
IyYJkYBz0BQb3kOpgyXy5pwvFcr+pquKB3WLDN1RhGvk+NHOd6KBMIIDPzCCAqigAwIBAgIBDTAN
BgkqhkiG9w0BAQUFADCB0TELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAG
A1UEBxMJQ2FwZSBUb3duMRowGAYDVQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2Vy
dGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZy
ZWVtYWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUuY29tMB4X
DTAzMDcxNzAwMDAwMFoXDTEzMDcxNjIzNTk1OVowYjELMAkGA1UEBhMCWkExJTAjBgNVBAoTHFRo
YXd0ZSBDb25zdWx0aW5nIChQdHkpIEx0ZC4xLDAqBgNVBAMTI1RoYXd0ZSBQZXJzb25hbCBGcmVl
bWFpbCBJc3N1aW5nIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEpjxVc1X7TrnKmVoe
aMB1BHCd3+n/ox7svc31W/Iadr1/DDph8r9RzgHU5VAKMNcCY1osiRVwjt3J8CuFWqo/cVbLrzwL
B+fxH5E2JCoTzyvV84J3PQO+K/67GD4Hv0CAAmTXp6a7n2XRxSpUhQ9IBH+nttE8YQRAHmQZcmC3
+wIDAQABo4GUMIGRMBIGA1UdEwEB/wQIMAYBAf8CAQAwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDov
L2NybC50aGF3dGUuY29tL1RoYXd0ZVBlcnNvbmFsRnJlZW1haWxDQS5jcmwwCwYDVR0PBAQDAgEG
MCkGA1UdEQQiMCCkHjAcMRowGAYDVQQDExFQcml2YXRlTGFiZWwyLTEzODANBgkqhkiG9w0BAQUF
AAOBgQBIjNFQg+oLLswNo2asZw9/r6y+whehQ5aUnX9MIbj4Nh+qLZ82L8D0HFAgk3A8/a3hYWLD
2ToZfoSxmRsAxRoLgnSeJVCUYsfbJ3FXJY3dqZw5jowgT2Vfldr394fWxghOrvbqNOUQGls1TXfj
ViF4gtwhGTXeJLHTHUb/XV9lTzGCAs8wggLLAgEBMGkwYjELMAkGA1UEBhMCWkExJTAjBgNVBAoT
HFRoYXd0ZSBDb25zdWx0aW5nIChQdHkpIEx0ZC4xLDAqBgNVBAMTI1RoYXd0ZSBQZXJzb25hbCBG
cmVlbWFpbCBJc3N1aW5nIENBAgMMRj0wCQYFKw4DAhoFAKCCAbwwGAYJKoZIhvcNAQkDMQsGCSqG
SIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMDQwNjAxMTgzNDM2WjAjBgkqhkiG9w0BCQQxFgQUnSNz
OxOEg1fdEU3f+J0GpjqF64UwZwYJKoZIhvcNAQkPMVowWDAKBggqhkiG9w0DBzAOBggqhkiG9w0D
AgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwBwYFKw4DAhowCgYI
KoZIhvcNAgUweAYJKwYBBAGCNxAEMWswaTBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3Rl
IENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVtYWls
IElzc3VpbmcgQ0ECAwxGPTB6BgsqhkiG9w0BCRACCzFroGkwYjELMAkGA1UEBhMCWkExJTAjBgNV
BAoTHFRoYXd0ZSBDb25zdWx0aW5nIChQdHkpIEx0ZC4xLDAqBgNVBAMTI1RoYXd0ZSBQZXJzb25h
bCBGcmVlbWFpbCBJc3N1aW5nIENBAgMMRj0wDQYJKoZIhvcNAQEBBQAEgYAoT/wDEapJx57VVNd4
EIFbmMjFqHckkS6kQLQYDGywaIWEsvlEMU0c12jOcSP+EyzdxYgDapLyOaIBJOq6RhnhkNPw7pNL
fUnyOxatvi03KcBT+5CdYH7nCBvf4kdBuFM6nNJJ9jF6rfhkjnC1VRcTn7twOgHVtEGZOvcqpVXP
yQAAAAAAAA==

------=_NextPart_000_0059_01C44817.DA87D840--




More information about the mapserver-dev mailing list