📄 gaparameter.c
字号:
// $Header: /usr/people/mbwall/src/galib/ga/RCS/GAParameter.C,v 1.4 1998/11/08 22:53:07 mbwall Exp $
/* ----------------------------------------------------------------------------
parameters.C
mbwall 28jul94
Copyright (c) 1995 Massachusetts Institute of Technology
all rights reserved
DESCRIPTION:
Definition of the parameter object and a container list for it. I did this
as a separate list implementation because I don't want all of the overhead of
a fullblown list. The parameter list is a special purpose, stripped down list
implementation.
---------------------------------------------------------------------------- */
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <ga/gaconfig.h>
#include <ga/gaerror.h>
#include <ga/GAParameter.h>
#define PRM_CHUNKSIZE 10
#define BUFSIZE 1024 // size of buffer for reading pairs
#define MAX_PAIRS 5000 // max number of name-value pairs in stream
#define NAMESIZE 128 // max length of name in name-value pair
extern char _gaerrbuf1[];
extern char _gaerrbuf2[];
static int IsNumeric(const char*);
GAParameter::GAParameter(const char* fn, const char* sn,
Type tp, const void* v){
if(fn){
fname = new char[strlen(fn)+1];
strcpy(fname, fn);
}
else fname = (char*)0;
if(sn){
sname = new char[strlen(sn)+1];
strcpy(sname, sn);
}
else sname = (char*)0;
t = tp;
memset(&val, 0, sizeof(Value));
setvalue(v);
}
GAParameter::GAParameter(const GAParameter& orig){
fname=sname = (char*)0;
memset(&val, 0, sizeof(Value));
copy(orig);
}
void
GAParameter::copy(const GAParameter& orig){
if(&orig == this) return;
delete [] fname;
delete [] sname;
if(orig.fname){
fname = new char[strlen(orig.fname)+1];
strcpy(fname, orig.fname);
}
else fname = (char *)0;
if(orig.sname){
sname = new char[strlen(orig.sname)+1];
strcpy(sname, orig.sname);
}
else sname = (char *)0;
t = orig.t;
setvalue(orig.value()); // do this directly...
}
GAParameter::~GAParameter(){
delete [] fname;
delete [] sname;
if(t == STRING) delete [] val.sval;
}
void
GAParameter::setvalue(const void* v){
switch(t){
case BOOLEAN:
case INT:
val.ival = *((int*)v);
break;
case CHAR:
val.cval = *((char*)v);
break;
case STRING:
if(v != val.sval) {
char* ptr=0;
if(strlen((char*)v) > 0){
ptr = new char[strlen((char*)v)+1];
strcpy(ptr, (char*)v);
}
delete [] val.sval;
val.sval = ptr;
}
break;
case FLOAT:
val.fval = *((float*)v);
break;
case DOUBLE:
val.dval = *((double*)v);
break;
case POINTER:
default:
val.pval = v;
break;
}
}
// The default parameter list is empty. Allocate space for the pointers, but
// don't allocate any parameters at this point.
GAParameterList::GAParameterList(){
N = n = cur = 0;
p = (GAParameter**)0;
}
GAParameterList::GAParameterList(const GAParameterList& list){
N = list.N;
n = list.n;
cur = list.cur;
p = new GAParameter * [N];
for(unsigned int i=0; i<n; i++)
p[i] = new GAParameter(*(list.p[i]));
}
// This is a rather stupid operator= implementation. Instead of doing a copy
// we just nuke everything the reallocate new stuff. If this were called a lot
// then we could end up with some fragmentation this way (rather than just
// doing copies on already-allocated memory).
GAParameterList&
GAParameterList::operator=(const GAParameterList& list){
if(&list == this) return *this;
unsigned int i;
for(i=0; i<n; i++)
delete p[i];
delete [] p;
N = list.N;
n = list.n;
cur = list.cur;
p = new GAParameter * [N];
for(i=0; i<n; i++)
p[i] = new GAParameter(*(list.p[i]));
return *this;
}
GAParameterList::~GAParameterList(){
for(unsigned int i=0; i<n; i++)
delete p[i];
delete [] p;
}
// Set the specified parameter (if we have it). If we don't recognize the name
// (ie it has not been added to the list) then we return the error code.
int
GAParameterList::set(const char* name, const void* v){
int found = 0;
for(unsigned int i=0; i<n && !found; i++){
if(strcmp(name, p[i]->fullname()) == 0 ||
strcmp(name, p[i]->shrtname()) == 0){
p[i]->value(v);
found = 1;
}
}
return found ? 0 : -1;
}
// Must do a special case for double/float. Any floats that get passed to this
// routine will be cast to doubles, but then we need to force them back to a
// float if FLOAT is the type that is expected. Kind of sucks, eh?
// We could check the parameter type against the type here, but we don't.
// (could do it for all of the 'set' members). Maybe in a later release.
int
GAParameterList::set(const char* name, double v) {
int found = 0;
for(unsigned int i=0; i<n; i++){
if(strcmp(name, p[i]->fullname()) == 0 ||
strcmp(name, p[i]->shrtname()) == 0){
if(p[i]->type() == GAParameter::FLOAT){
float fval = (float)v;
p[i]->value((void*)&fval);
}
else if(p[i]->type() == GAParameter::DOUBLE)
p[i]->value((void*)&v);
else
GAErr(GA_LOC, "GAParameterList", "set", gaErrBadTypeIndicator);
found = 1;
}
}
return found ? 0 : -1;
}
// This allocates space for strings, so be sure to free it!
int
GAParameterList::get(const char* name, void* value) const {
int status = 1;
for(unsigned int i=0; i<n; i++){
if(strcmp(name, p[i]->fullname()) == 0 ||
strcmp(name, p[i]->shrtname()) == 0){
switch(p[i]->type()){
case GAParameter::BOOLEAN:
case GAParameter::INT:
*((int*)value) = *((int*)p[i]->value());
break;
case GAParameter::CHAR:
*((char*)value) = *((char*)p[i]->value());
break;
case GAParameter::STRING:
break;
case GAParameter::FLOAT:
*((float*)value) = *((float*)p[i]->value());
break;
case GAParameter::DOUBLE:
*((double*)value) = *((double*)p[i]->value());
break;
case GAParameter::POINTER:
default:
break;
}
status = 0;
}
}
return status;
}
// Add the item to the list if it does not already exist. Return 0 if the add
// was OK, -1 if there was a problem.
int
GAParameterList::add(const char* fn, const char* sn,
GAParameter::Type t, const void* v) {
int status = -1;
if(n == N){
N += PRM_CHUNKSIZE;
GAParameter **tmp = p;
p = new GAParameter* [N];
memcpy(p, tmp, n * sizeof(GAParameter*));
delete [] tmp;
}
int found = 0;
for(unsigned int i=0; i<n && !found; i++){
if(strcmp(fn, p[i]->fullname()) == 0 &&
strcmp(sn, p[i]->shrtname()) == 0)
found = 1;
}
if(!found){
cur = n;
p[n++] = new GAParameter(fn, sn, t, v);
}
return status;
}
// When you remove a parameter from the list, the iterator is left pointing
// at the same location. If the item was the last in the list, then the
// iterator moves to the new last item in the list.
// Return 0 if everything was OK, -1 if error.
int
GAParameterList::remove(){
int status = -1;
if(cur > n) return status;
delete p[cur];
memmove(&(p[cur]), &(p[cur+1]), (n-cur-1)*sizeof(GAParameter*));
n--;
if(cur > n) cur = n;
status = 0;
return status;
}
GAParameter*
GAParameterList::operator()(const char* name){
for(unsigned int i=0; i<n; i++)
if(strcmp(name, p[i]->fullname())==0 || strcmp(name, p[i]->shrtname())==0)
return p[i];
return (GAParameter*)0;
}
#ifndef NO_STREAMS
// Dump the parameters to the specified stream. Just name-value pairs with a
// tab delimiter and newline separating pairs.
// If there is an error, return 1, otherwise return 0.
int
GAParameterList::write(ostream& os) const {
for(unsigned int i=0; i<n; i++){
int ival;
float fval;
double dval;
char cval;
char* sval;
os << p[i]->fullname() << "\t";
switch(p[i]->type()){
case GAParameter::BOOLEAN:
ival = *((int*)(p[i]->value()));
if(ival) os << "true\n";
else os << "false\n";
break;
case GAParameter::INT:
ival = *((int*)(p[i]->value()));
os << ival << "\n";
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -