/* ARISA - generic settings structure manipulation functions * Copyright (C) 2004 Carl Ritson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include "arisa.h" #define SET_FUNC(x) \ static int set_##x(setting_t *setting, void *data, value_t *var) #define GET_PTR(type,set,ptr) ((type)(((char*)ptr) + set->offset)) SET_FUNC(int) { int *i = GET_PTR(int*,setting,data); int min = 0, max = 0; int flags = VALUE_USE_DEFAULT | setting->flags; if(setting->min != NULL) { min = atoi(setting->min); flags |= VALUE_USE_MIN; } if(setting->max != NULL) { max = atoi(setting->max); flags |= VALUE_USE_MAX; } *i = value_as_int32(var,flags,min,max,*i); return 0; } SET_FUNC(uint) { unsigned int *i = GET_PTR(unsigned int*,setting,data); unsigned int min = 0, max = 0; int flags = VALUE_USE_DEFAULT | setting->flags; if(setting->min != NULL) { min = (unsigned int)strtoul(setting->min,NULL,10); flags |= VALUE_USE_MIN; } if(setting->max != NULL) { max = (unsigned int)strtoul(setting->max,NULL,10); flags |= VALUE_USE_MAX; } *i = value_as_uint32(var,flags,min,max,*i); return 0; } SET_FUNC(float) { float *f = GET_PTR(float*,setting,data); float min = 0, max = 0; int flags = VALUE_USE_DEFAULT | setting->flags; if(setting->min != NULL) { min = strtof(setting->min,NULL); flags |= VALUE_USE_MIN; } if(setting->max != NULL) { max = strtof(setting->max,NULL); flags |= VALUE_USE_MAX; } *f = value_as_float(var,flags,min,max,*f); return 0; } SET_FUNC(double) { double *d = GET_PTR(double*,setting,data); double min = 0, max = 0; int flags = VALUE_USE_DEFAULT | setting->flags; if(setting->min != NULL) { min = strtod(setting->min,NULL); flags |= VALUE_USE_MIN; } if(setting->max != NULL) { max = strtod(setting->max,NULL); flags |= VALUE_USE_MAX; } *d = value_as_double(var,flags,min,max,*d); return 0; } SET_FUNC(str) { char **s = GET_PTR(char**,setting,data); *s = value_as_string(var,VALUE_FREE_DEFAULT | setting->flags,NULL,0,*s); return 0; } SET_FUNC(nstr) { char buffer[16]; char **s = GET_PTR(char**,setting,data); if(strcmp(value_as_string(var,0,buffer,sizeof(buffer),NULL),"-") == 0) { if(*s != NULL) xfree(*s); *s = NULL; } else *s = value_as_string(var,VALUE_FREE_DEFAULT | VALUE_USE_DEFAULT | VALUE_ALLOW_NULL | setting->flags,NULL,0,*s); return 0; } SET_FUNC(bool) { int *i = GET_PTR(int*,setting,data); *i = value_as_bool(var,VALUE_USE_DEFAULT | setting->flags,*i); return 0; } SET_FUNC(enum) { int *i = GET_PTR(int*,setting,data); *i = value_as_enum(var,VALUE_USE_DEFAULT | setting->flags,*i); return 0; } SET_FUNC(off) { off_t *o = GET_PTR(off_t*,setting,data); off_t min = 0, max = 0; int flags = VALUE_USE_DEFAULT | setting->flags; if(setting->min != NULL) { min = (off_t)strtoull(setting->min,NULL,10); flags |= VALUE_USE_MIN; } if(setting->max != NULL) { max = (off_t)strtoull(setting->max,NULL,10); flags |= VALUE_USE_MAX; } *o = (off_t)value_as_uint64(var,flags,min,max,(uint64_t)*o); return 0; } static setting_t *find_setting(setting_t *settings, value_t *var) { setting_t *ret = NULL; size_t namelen = strlen(var->name); int i,match; for(i = 0, match = 0; settings[i].name != NULL; ++i) { if(strncasecmp(settings[i].name,var->name,namelen) == 0) { ret = &(settings[i]); match++; if(strlen(settings[i].name) == namelen) { match = 1; break; } } } if(match == 1) return ret; else return NULL; } int apply_setting(setting_t *settings, void *data, value_t *var) { setting_t *setting = find_setting(settings,var); int ret = -1; if(setting == NULL) return -1; switch(setting->type) { case ST_INT: ret = set_int(setting,data,var); break; case ST_UINT: ret = set_uint(setting,data,var); break; case ST_FLOAT: ret = set_float(setting,data,var); break; case ST_DOUBLE: ret = set_double(setting,data,var); break; case ST_STR: ret = set_str(setting,data,var); break; case ST_NSTR: ret = set_nstr(setting,data,var); break; case ST_BOOL: ret = set_bool(setting,data,var); break; case ST_ENUM: ret = value_set_enumeration(var, setting->str_to_enum, setting->enum_to_str); if(ret != -1) ret = set_enum(setting,data,var); break; case ST_OFF: ret = set_off(setting,data,var); break; default: assert(0); break; } return ret; } int read_settings(setting_t *settings, void *data, pqueue_t *out) { int i; for(i = 0; settings[i].name != NULL; ++i) { setting_t *s = &(settings[i]); value_t *v; switch(s->type) { case ST_INT: v = value_int32(s->name,*GET_PTR(int*,s,data)); break; case ST_UINT: v = value_uint32(s->name, *GET_PTR(unsigned int*,s,data)); break; case ST_FLOAT: v = value_float(s->name, *GET_PTR(float*,s,data)); break; case ST_DOUBLE: v = value_double(s->name, *GET_PTR(double*,s,data)); break; case ST_STR: case ST_NSTR: v = value_string(s->name, *GET_PTR(char**,s,data)); break; case ST_BOOL: v = value_bool(s->name,s->flags, *GET_PTR(int*,s,data)); break; case ST_ENUM: v = value_enum_val(s->name, *GET_PTR(int*,s,data),s->enum_to_str); break; case ST_OFF: v = value_uint64(s->name,(uint64_t) *GET_PTR(off_t*,s,data)); break; default: assert(0); } pqueue_push_back(out,v); } return i; } /** Settings Data for settings_t (global settings structure) **/ static setting_t global_settings_data[] = { {"admin-socket", ST_NSTR,OFFSETOF(settings_t,admin_socket), 0,NULL,NULL,NULL,NULL}, {"autosave-interval", ST_INT, OFFSETOF(settings_t,autosave_interval), 0,"30",NULL,NULL,NULL}, {"config", ST_STR, OFFSETOF(settings_t,config), 0,NULL,NULL,NULL,NULL}, {"hash-packs", ST_BOOL,OFFSETOF(settings_t,hash_packs), VALUE_BOOL_YESNO,NULL,NULL,NULL,NULL}, {"hashing-io-usage", ST_INT, OFFSETOF(settings_t,hashing_io_usage), 0,"1","100",NULL,NULL}, {"list-frequency", ST_INT, OFFSETOF(settings_t,list_frequency), 0,"0",NULL,NULL,NULL}, {"log", ST_NSTR,OFFSETOF(settings_t,log), 0,NULL,NULL,NULL,NULL}, {"log-interval", ST_INT, OFFSETOF(settings_t,log_interval), 0,"1",NULL,NULL,NULL}, {"pid", ST_NSTR,OFFSETOF(settings_t,pid), 0,NULL,NULL,NULL,NULL}, {"tick-interval", ST_INT, OFFSETOF(settings_t,tick_interval), 0,"0",NULL,NULL,NULL}, {NULL} }; int global_apply_setting(const char *name, const char *value) { value_t *v = value_string(name,value); int ret; LOCK(global->settings); ret = apply_setting(global_settings_data,global->settings,v); UNLOCK(global->settings); xfree(v); return ret; } int global_read_settings(pqueue_t *out) { int ret; LOCK(global->settings); ret = read_settings(global_settings_data,global->settings,out); UNLOCK(global->settings); return ret; }