/* Copyright (c) 2001, Stanford University
* All rights reserved
*
* See the file LICENSE.txt for information on redistributing this software.
*/
#include "cr_spu.h"
#include "cr_error.h"
#include "cr_string.h"
#include <stdio.h>
/**
* \mainpage spu_loader
*
* \section Spu_loaderIntroduction Introduction
*
* Chromium consists of all the top-level files in the cr
* directory. The spu_loader module basically takes care of API dispatch,
* and OpenGL state management.
*
*/
void crSPUInitDispatchTable( SPUDispatchTable *table )
{
table->copyList = NULL;
table->copy_of = NULL;
table->mark = 0;
table->server = NULL;
}
static int validate_int( const char *response,
const char *min,
const char *max )
{
int i, imin, imax;
if (sscanf(response, "%d", &i) != 1)
return 0;
if (min && sscanf(min, "%d", &imin) == 1 && imin > i)
return 0;
if (max && sscanf(max, "%d", &imax) == 1 && imax < i)
return 0;
return 1;
}
static int validate_float( const char *response,
const char *min,
const char *max )
{
float f, fmin, fmax;
if (sscanf(response, "%f", &f) != 1)
return 0;
if (min && sscanf(min, "%f", &fmin) == 1 && fmin > f)
return 0;
if (max && sscanf(max, "%f", &fmax) == 1 && fmax < f)
return 0;
return 1;
}
static int validate_one_option( const SPUOptions *opt,
const char *response,
const char *min,
const char *max )
{
switch (opt->type) {
case CR_BOOL:
return validate_int( response, "0", "1" );
case CR_INT:
return validate_int( response, min, max );
case CR_FLOAT:
return validate_float( response, min, max );
case CR_ENUM:
/* Make sure response string is present in the min string.
* For enums, the min string is a comma-separated list of valid values.
*/
CRASSERT(opt->numValues == 1); /* an enum limitation for now */
{
const char *p = crStrstr(min, response);
if (!p)
return 0; /* invalid value! */
if (p[-1] != '\'')
return 0; /* right substring */
if (p[crStrlen(response)] != '\'')
return 0; /* left substring */
return 1;
}
default:
return 0;
}
}
/**
* Make sure the response matches the opt's parameters (right number
* and type of values, etc.)
* Return 1 if OK, 0 if error.
*/
static int validate_option( const SPUOptions *opt, const char *response )
{
const char *min = opt->min;
const char *max = opt->max;
int i = 0;
int retval;
if (opt->type == CR_STRING)
return 1;
CRASSERT(opt->numValues > 0);
/* skip leading [ for multi-value options */
if (opt->numValues > 1) {
/* multi-valued options must be enclosed in brackets */
if (*response != '[')
return 0;
response++; /* skip [ */
/* make sure min and max are bracketed as well */
if (min) {
CRASSERT(*min == '['); /* error in <foo>spu_config.c code!!! */
min++;
}
if (max) {
CRASSERT(*max == '['); /* error in <foo>spu_config.c code!!! */
max++;
}
}
for (;;)
{
if (!validate_one_option( opt, response, min, max ))
{
retval = 0;
break;
}
if (++i == opt->numValues)
{
retval = 1; /* all done! */
break;
}
/* advance pointers to next item */
if (min)
{
while (*min != ' ' && *min)
min++;
while (*min == ' ')
min++;
}
if (max)
{
while (*max != ' ' && *max)
max++;
while (*max == ' ')
max++;
}
if (response)
{
while (*response != ' ' && *response)
response++;
while (*response == ' ')
response++;
}
}
return retval;
}
/** Use the default values for all the options:
*/
void crSPUSetDefaultParams( void *spu, SPUOptions *options )
{
int i;
for (i = 0 ; options[i].option ; i++)
{
SPUOptions *opt = &options[i];
opt->cb( spu, opt->deflt );
}
}
/**
* Find the index of the given enum value in the SPUOption's list of
* possible enum values.
* Return the enum index, or -1 if not found.
*/
int crSPUGetEnumIndex( const SPUOptions *options, const char *optName, const char *value )
{
const SPUOptions *opt;
const int valueLen = crStrlen(value);
/* first, find the right option */
for (opt = options; opt->option; opt++) {
if (crStrcmp(opt->option, optName) == 0) {
char **values;
int i;
CRASSERT(opt->type == CR_ENUM);
/* break into array of strings */
/* min string should be of form "'enum1', 'enum2', 'enum3', etc" */
values = crStrSplit(opt->min, ",");
/* search the array */
for (i = 0; values[i]; i++) {
/* find leading quote */
const char *e = crStrchr(values[i], '\'');
CRASSERT(e);
if (e) {
/* test for match */
if (crStrncmp(value, e + 1, valueLen) == 0 && e[valueLen + 1] == '\'') {
crFreeStrings(values);
return i;
}
}
}
/* enum value not found! */
crFreeStrings(values);
return -1;
}
}
return -1;
}