2022-07-31 01:22:11 +02:00
|
|
|
#include <string.h>
|
2022-07-31 09:49:14 +02:00
|
|
|
#include <ctype.h>
|
2022-07-31 01:22:11 +02:00
|
|
|
|
|
|
|
#include <mavl.h>
|
|
|
|
|
2022-07-31 17:15:32 +02:00
|
|
|
#include "val.h"
|
2022-08-13 09:47:12 +02:00
|
|
|
#include "cfg.h"
|
|
|
|
|
|
|
|
|
2022-08-09 21:47:39 +02:00
|
|
|
#include "dbg.h"
|
2022-08-13 09:47:12 +02:00
|
|
|
#include "log.h"
|
|
|
|
#include "cw.h"
|
2022-07-31 01:22:11 +02:00
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
static const char *nextc(const char *s)
|
|
|
|
{
|
|
|
|
while (isdigit(*s))
|
|
|
|
s++;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmp0(const char *s1, const char *s2)
|
|
|
|
{
|
|
|
|
|
|
|
|
const char *d1, *d2;
|
|
|
|
int i1, i2, i;
|
|
|
|
|
|
|
|
d1 = strchr(s1, '.');
|
|
|
|
if (d1 == NULL)
|
|
|
|
return strcmp(s1, s2);
|
|
|
|
|
|
|
|
d2 = strchr(s2, '.');
|
|
|
|
if (d2 == NULL)
|
|
|
|
return strcmp(s1, s2);
|
|
|
|
|
|
|
|
if ((d1 - s1) != (d2 - s2))
|
|
|
|
return strcmp(s1, s2);
|
|
|
|
|
|
|
|
if (strncmp(s1, s2, (d1 - s1)) != 0)
|
|
|
|
return strcmp(s1, s2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isdigit(d1[1])) {
|
|
|
|
i1 = atoi(d1 + 1);
|
|
|
|
} else {
|
|
|
|
return cmp0(d1 + 1, d2 + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isdigit(d2[1])) {
|
|
|
|
i2 = atoi(d2 + 1);
|
|
|
|
} else {
|
|
|
|
return cmp0(d1 + 1, d2 + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
i = i1 - i2;
|
|
|
|
if (i == 0) {
|
|
|
|
return cmp0(nextc(d1 + 1), nextc(d2 + 1));
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmp(const void *k1, const void *k2)
|
|
|
|
{
|
|
|
|
struct cw_Cfg_entry *e1, *e2;
|
|
|
|
e1 = (struct cw_Cfg_entry *) k1;
|
|
|
|
e2 = (struct cw_Cfg_entry *) k2;
|
|
|
|
|
|
|
|
|
|
|
|
return cmp0(e1->key, e2->key);
|
|
|
|
/* return strcmp(e1->key,e2->key);*/
|
2022-07-31 01:22:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void del(void *ptr)
|
|
|
|
{
|
2022-08-08 23:11:27 +02:00
|
|
|
struct cw_Cfg_entry *e;
|
|
|
|
e = (struct cw_Cfg_entry *) ptr;
|
|
|
|
free((void *) e->key);
|
|
|
|
free((void *) e->val);
|
2022-07-31 01:22:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
cw_Cfg_t *cw_cfg_create()
|
2022-07-31 01:22:11 +02:00
|
|
|
{
|
2022-08-20 22:03:06 +02:00
|
|
|
cw_Cfg_t * cfg;
|
|
|
|
cfg = malloc(sizeof(cw_Cfg_t));
|
|
|
|
if (cfg == NULL)
|
|
|
|
return NULL;
|
2022-08-21 00:53:41 +02:00
|
|
|
memset(cfg,0,sizeof(cw_Cfg_t));
|
2022-08-20 22:03:06 +02:00
|
|
|
cfg->cfg = mavl_create(cmp, del, sizeof(struct cw_Cfg_entry));
|
|
|
|
if (cfg->cfg==NULL){
|
|
|
|
cw_cfg_destroy(cfg);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return cfg;
|
2022-08-08 23:11:27 +02:00
|
|
|
}
|
2022-07-31 01:22:11 +02:00
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
int cw_cfg_set(cw_Cfg_t * cfg, const char *key, const char *val)
|
2022-07-31 01:22:11 +02:00
|
|
|
{
|
2022-08-21 00:53:41 +02:00
|
|
|
cw_dbg(cfg->dbg_level, "%s%s: %s",cfg->dbg_prefix,key,val);
|
2022-08-09 21:47:39 +02:00
|
|
|
|
2022-07-31 10:50:37 +02:00
|
|
|
struct cw_Cfg_entry e;
|
2022-07-31 01:22:11 +02:00
|
|
|
int replaced;
|
|
|
|
|
|
|
|
e.key = cw_strdup(key);
|
|
|
|
if (!e.key)
|
|
|
|
return 0;
|
|
|
|
e.val = cw_strdup(val);
|
2022-08-08 23:11:27 +02:00
|
|
|
if (!e.val) {
|
|
|
|
free((void *) e.key);
|
2022-07-31 01:22:11 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2022-08-20 22:03:06 +02:00
|
|
|
void *rc = mavl_replace(cfg->cfg, &e, &replaced);
|
2022-08-08 23:11:27 +02:00
|
|
|
if (!rc) {
|
2022-07-31 01:22:11 +02:00
|
|
|
del(&e);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!replaced)
|
|
|
|
return 1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
const char *cw_cfg_get(cw_Cfg_t * cfg, const char *key, const char *def)
|
2022-07-31 10:50:37 +02:00
|
|
|
{
|
2022-08-08 23:11:27 +02:00
|
|
|
struct cw_Cfg_entry e, *r;
|
2022-07-31 10:50:37 +02:00
|
|
|
e.key = key;
|
2022-08-20 22:03:06 +02:00
|
|
|
r = mavl_get(cfg->cfg, &e);
|
2022-07-31 10:50:37 +02:00
|
|
|
if (!r)
|
2022-08-01 10:05:14 +02:00
|
|
|
return def;
|
2022-07-31 10:50:37 +02:00
|
|
|
return r->val;
|
|
|
|
}
|
|
|
|
|
2022-08-14 12:26:34 +02:00
|
|
|
const char *cw_cfg_get_l(cw_Cfg_t ** cfg, const char * key, const char *def)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct cw_Cfg_entry e, *r;
|
|
|
|
for(i=0; cfg[i]!=NULL; i++){
|
2022-08-17 18:41:17 +02:00
|
|
|
// cw_dbg(DBG_X,"GET_L IN: %p",cfg[i]);
|
2022-08-14 12:26:34 +02:00
|
|
|
e.key = key;
|
2022-08-20 22:03:06 +02:00
|
|
|
r = mavl_get(cfg[i]->cfg, &e);
|
2022-08-14 12:26:34 +02:00
|
|
|
if (r!=NULL)
|
|
|
|
return r->val;
|
|
|
|
}
|
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-13 09:47:12 +02:00
|
|
|
const char *cw_cfg_get2(cw_Cfg_t *cfg1, cw_Cfg_t *cfg2, const char *key, const char *def)
|
|
|
|
{
|
|
|
|
return cw_cfg_get(cfg1, key, cw_cfg_get(cfg2,key,def));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bstr16_t cw_cfg_get_bstr16(cw_Cfg_t * cfg, const char * key, const char *def)
|
|
|
|
{
|
|
|
|
const char *s;
|
|
|
|
|
|
|
|
s = cw_cfg_get(cfg,key,def);
|
|
|
|
if(s==NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return bstr16_create_from_str(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
int cw_cfg_set_bstr16(cw_Cfg_t * cfg, const char * key, bstr16_t str)
|
|
|
|
{
|
|
|
|
CW_TYPE_BSTR16->read(cfg,key,bstr16_data(str),bstr16_len(str),NULL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-07-31 17:15:32 +02:00
|
|
|
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
void cw_cfg_dump(cw_Cfg_t * cfg)
|
2022-07-31 01:22:11 +02:00
|
|
|
{
|
|
|
|
mavliter_t it;
|
2022-07-31 10:50:37 +02:00
|
|
|
struct cw_Cfg_entry *e;
|
2022-08-20 22:03:06 +02:00
|
|
|
mavliter_init(&it, cfg->cfg);
|
2022-08-08 23:11:27 +02:00
|
|
|
mavliter_foreach(&it) {
|
|
|
|
|
2022-07-31 01:22:11 +02:00
|
|
|
e = mavliter_get(&it);
|
2022-08-08 23:11:27 +02:00
|
|
|
printf("%s: '%s'\n", e->key, e->val);
|
2022-07-31 01:22:11 +02:00
|
|
|
//cw_dbg(dbglevel,"%s%s :%s: %s",prefix,data->key,type->get_type_name(data), value);
|
|
|
|
}
|
|
|
|
}
|
2022-07-31 09:49:14 +02:00
|
|
|
|
2022-08-24 00:29:26 +02:00
|
|
|
void cw_cfg_fdump(FILE *f, cw_Cfg_t * cfg)
|
|
|
|
{
|
|
|
|
mavliter_t it;
|
|
|
|
struct cw_Cfg_entry *e;
|
|
|
|
mavliter_init(&it, cfg->cfg);
|
|
|
|
mavliter_foreach(&it) {
|
|
|
|
|
|
|
|
e = mavliter_get(&it);
|
|
|
|
fprintf(f,"%s: '%s'\n", e->key, e->val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-07-31 09:49:14 +02:00
|
|
|
|
|
|
|
struct parser {
|
|
|
|
int line;
|
|
|
|
int pos;
|
|
|
|
int prevpos;
|
|
|
|
char error[256];
|
|
|
|
int quote;
|
|
|
|
FILE *f;
|
|
|
|
int (*getc)(struct parser *);
|
|
|
|
void (*ungetc)(struct parser *);
|
|
|
|
};
|
|
|
|
|
|
|
|
static int get_char(struct parser *p)
|
|
|
|
{
|
|
|
|
int c;
|
2022-08-08 23:11:27 +02:00
|
|
|
c = fgetc(p->f);
|
2022-07-31 09:49:14 +02:00
|
|
|
p->pos++;
|
2022-08-08 23:11:27 +02:00
|
|
|
if (c == '\n') {
|
|
|
|
p->prevpos = p->pos;
|
|
|
|
p->line++;
|
|
|
|
p->pos = 0;
|
2022-07-31 09:49:14 +02:00
|
|
|
}
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
static void unget_char(struct parser *p, int c)
|
|
|
|
{
|
|
|
|
ungetc(c, p->f);
|
|
|
|
if (c == '\n') {
|
2022-07-31 09:49:14 +02:00
|
|
|
p->line--;
|
2022-08-08 23:11:27 +02:00
|
|
|
p->pos = p->prevpos;
|
|
|
|
} else
|
2022-07-31 09:49:14 +02:00
|
|
|
p->pos--;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int get_char_q(struct parser *p)
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
while (1) {
|
2022-07-31 09:49:14 +02:00
|
|
|
c = get_char(p);
|
2022-08-08 23:11:27 +02:00
|
|
|
if (c == EOF || c == '\n')
|
2022-07-31 09:49:14 +02:00
|
|
|
return c;
|
2022-08-08 23:11:27 +02:00
|
|
|
|
|
|
|
if (c == '"' && !p->quote) {
|
|
|
|
p->quote = 1;
|
2022-07-31 09:49:14 +02:00
|
|
|
continue;
|
|
|
|
}
|
2022-08-08 23:11:27 +02:00
|
|
|
if (c == '"' && p->quote) {
|
|
|
|
p->quote = 0;
|
2022-07-31 09:49:14 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2022-08-08 23:11:27 +02:00
|
|
|
|
|
|
|
|
2022-07-31 09:49:14 +02:00
|
|
|
if (!p->quote)
|
|
|
|
return c;
|
2022-08-08 23:11:27 +02:00
|
|
|
|
|
|
|
if (c != '\\')
|
2022-07-31 09:49:14 +02:00
|
|
|
return c;
|
2022-08-08 23:11:27 +02:00
|
|
|
|
2022-07-31 09:49:14 +02:00
|
|
|
c = get_char(p);
|
2022-08-08 23:11:27 +02:00
|
|
|
switch (c) {
|
2022-07-31 09:49:14 +02:00
|
|
|
case EOF:
|
|
|
|
return c;
|
|
|
|
case 'n':
|
|
|
|
return '\n';
|
2022-08-08 23:11:27 +02:00
|
|
|
|
2022-07-31 09:49:14 +02:00
|
|
|
case '\\':
|
|
|
|
return '\\';
|
|
|
|
case '"':
|
|
|
|
return '"';
|
|
|
|
default:
|
2022-08-08 23:11:27 +02:00
|
|
|
unget_char(p, c);
|
2022-07-31 09:49:14 +02:00
|
|
|
return '\\';
|
|
|
|
}
|
2022-08-08 23:11:27 +02:00
|
|
|
|
2022-07-31 09:49:14 +02:00
|
|
|
/* We will never reach here */
|
2022-08-08 23:11:27 +02:00
|
|
|
/* return c; */
|
2022-07-31 09:49:14 +02:00
|
|
|
}
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
static int skip_chars(struct parser *p, const char *chars)
|
2022-07-31 09:49:14 +02:00
|
|
|
{
|
|
|
|
int c;
|
2022-08-08 23:11:27 +02:00
|
|
|
|
|
|
|
while ((c = get_char(p)) != EOF) {
|
|
|
|
if (strchr(chars, c))
|
2022-07-31 09:49:14 +02:00
|
|
|
continue;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
static int skip_to_chars(struct parser *p, const char *chars)
|
2022-07-31 09:49:14 +02:00
|
|
|
{
|
|
|
|
int c;
|
2022-08-08 23:11:27 +02:00
|
|
|
|
|
|
|
while ((c = get_char(p)) != EOF) {
|
|
|
|
if (strchr(chars, c))
|
2022-07-31 09:49:14 +02:00
|
|
|
return c;
|
|
|
|
}
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
static int read_key(struct parser *p, char *key, int max_len)
|
2022-07-31 09:49:14 +02:00
|
|
|
{
|
2022-08-08 23:11:27 +02:00
|
|
|
int c, n;
|
2022-07-31 09:49:14 +02:00
|
|
|
|
|
|
|
do {
|
2022-08-08 23:11:27 +02:00
|
|
|
c = skip_chars(p, " \t\n\a\v");
|
2022-07-31 09:49:14 +02:00
|
|
|
if (c == '#') {
|
2022-08-08 23:11:27 +02:00
|
|
|
c = skip_to_chars(p, "\n\a");
|
|
|
|
|
2022-07-31 09:49:14 +02:00
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (c != EOF);
|
2022-08-08 23:11:27 +02:00
|
|
|
|
|
|
|
unget_char(p, c);
|
|
|
|
c = get_char_q(p);
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
while (c != EOF && n < max_len) {
|
|
|
|
if (!p->quote && !isalnum(c)
|
|
|
|
&& !strchr("._/-()@#|{}[]\\", c) /*strchr(": \t\n\a",c) */ ) {
|
|
|
|
unget_char(p, c);
|
2022-07-31 09:49:14 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
key[n] = c;
|
2022-07-31 09:49:14 +02:00
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
c = get_char_q(p);
|
2022-07-31 09:49:14 +02:00
|
|
|
n++;
|
|
|
|
|
|
|
|
}
|
2022-08-08 23:11:27 +02:00
|
|
|
key[n] = 0;
|
2022-07-31 09:49:14 +02:00
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
static int skip_to_colon(FILE * f, struct parser *p)
|
2022-07-31 09:49:14 +02:00
|
|
|
{
|
|
|
|
int c;
|
2022-08-08 23:11:27 +02:00
|
|
|
c = skip_chars(p, " \t");
|
|
|
|
if (c != ':') {
|
|
|
|
if (c == '\n') {
|
|
|
|
unget_char(p, c);
|
|
|
|
sprintf(p->error,
|
|
|
|
"Error at line %d, pos %d: Unexpected EOL, collon expected.",
|
|
|
|
p->line, p->pos);
|
2022-07-31 09:49:14 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2022-08-08 23:11:27 +02:00
|
|
|
sprintf(p->error, "Error at line %d, pos %d: Collon expected.",
|
|
|
|
p->line, p->pos);
|
2022-07-31 09:49:14 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
static int read_val(struct parser *p, char *val, int max_len)
|
|
|
|
{
|
|
|
|
int c, n, quote;
|
|
|
|
if (!skip_to_colon(p->f, p))
|
2022-07-31 09:49:14 +02:00
|
|
|
return -1;
|
2022-08-08 23:11:27 +02:00
|
|
|
c = skip_chars(p, " \t");
|
|
|
|
if (c == '"') {
|
|
|
|
quote = 1;
|
|
|
|
c = get_char(p);
|
|
|
|
} else {
|
|
|
|
quote = 0;
|
2022-07-31 09:49:14 +02:00
|
|
|
}
|
2022-08-08 23:11:27 +02:00
|
|
|
n = 0;
|
|
|
|
while (c != EOF && n < max_len) {
|
|
|
|
if (quote && c == '"') {
|
2022-07-31 09:49:14 +02:00
|
|
|
break;
|
|
|
|
}
|
2022-08-08 23:11:27 +02:00
|
|
|
if (c == '\n') {
|
2022-07-31 09:49:14 +02:00
|
|
|
break;
|
|
|
|
}
|
2022-08-08 23:11:27 +02:00
|
|
|
if (quote) {
|
|
|
|
if (c == '\\') {
|
2022-07-31 09:49:14 +02:00
|
|
|
c = get_char(p);
|
2022-08-08 23:11:27 +02:00
|
|
|
switch (c) {
|
2022-07-31 09:49:14 +02:00
|
|
|
case 'n':
|
2022-08-08 23:11:27 +02:00
|
|
|
c = '\n';
|
2022-07-31 09:49:14 +02:00
|
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
break;
|
|
|
|
case '"':
|
|
|
|
break;
|
|
|
|
default:
|
2022-08-08 23:11:27 +02:00
|
|
|
unget_char(p, c);
|
|
|
|
c = '\\';
|
2022-07-31 09:49:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-08 23:11:27 +02:00
|
|
|
val[n++] = c;
|
|
|
|
c = get_char(p);
|
2022-07-31 09:49:14 +02:00
|
|
|
}
|
2022-08-08 23:11:27 +02:00
|
|
|
|
|
|
|
|
|
|
|
if (!quote && n > 0) {
|
|
|
|
while (n > 0) {
|
|
|
|
if (isspace(val[n - 1]))
|
2022-07-31 09:49:14 +02:00
|
|
|
n--;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-08-08 23:11:27 +02:00
|
|
|
|
|
|
|
val[n] = 0;
|
2022-07-31 09:49:14 +02:00
|
|
|
|
|
|
|
return n;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
int cw_cfg_read_line(FILE * f, struct parser *p, char *key, char *val)
|
2022-07-31 09:49:14 +02:00
|
|
|
{
|
|
|
|
int n;
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
|
|
|
|
n = read_key(p, key, CW_CFG_MAX_KEY_LEN);
|
|
|
|
if (n == 0)
|
2022-07-31 09:49:14 +02:00
|
|
|
return 1;
|
2022-08-08 23:11:27 +02:00
|
|
|
if (n == -1) {
|
2022-07-31 09:49:14 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
n = read_val(p, val, CW_CFG_MAX_KEY_LEN);
|
|
|
|
if (n == -1) {
|
2022-07-31 09:49:14 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int cw_cfg_read_from_file(FILE * f, cw_Cfg_t * cfg)
|
|
|
|
{
|
|
|
|
char key[CW_CFG_MAX_KEY_LEN];
|
|
|
|
char val[2048];
|
|
|
|
struct parser p;
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
p.line = 1;
|
|
|
|
p.pos = 0;
|
|
|
|
p.prevpos = 0;
|
|
|
|
p.quote = 0;
|
|
|
|
p.f = f;
|
|
|
|
|
2022-07-31 09:49:14 +02:00
|
|
|
int rc;
|
2022-08-08 23:11:27 +02:00
|
|
|
int errs = 0;
|
|
|
|
|
2022-07-31 09:49:14 +02:00
|
|
|
|
|
|
|
do {
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
rc = cw_cfg_read_line(f, &p, key, val);
|
|
|
|
if (rc == -1) {
|
|
|
|
fprintf(stderr, "Error: %s\n", p.error);
|
2022-07-31 21:42:48 +02:00
|
|
|
errs++;
|
2022-07-31 09:49:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
if (rc != 0) {
|
2022-07-31 09:49:14 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
cw_cfg_set(cfg, key, val);
|
|
|
|
|
|
|
|
|
|
|
|
} while (rc == 0);
|
2022-07-31 09:49:14 +02:00
|
|
|
|
2022-07-31 21:42:48 +02:00
|
|
|
return errs;
|
2022-07-31 09:49:14 +02:00
|
|
|
}
|
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
int cw_cfg_load(const char *filename, cw_Cfg_t * cfg)
|
2022-07-31 09:49:14 +02:00
|
|
|
{
|
2022-07-31 21:42:48 +02:00
|
|
|
int errs;
|
2022-08-08 23:11:27 +02:00
|
|
|
FILE *f = fopen(filename, "rb");
|
2022-07-31 09:49:14 +02:00
|
|
|
if (!f)
|
|
|
|
return errno;
|
2022-08-08 23:11:27 +02:00
|
|
|
errs = cw_cfg_read_from_file(f, cfg);
|
2022-07-31 21:42:48 +02:00
|
|
|
fclose(f);
|
2022-07-31 23:58:43 +02:00
|
|
|
|
|
|
|
if (errs)
|
|
|
|
errno = EINVAL;
|
|
|
|
return errno;
|
2022-07-31 09:49:14 +02:00
|
|
|
}
|
2022-08-01 10:05:14 +02:00
|
|
|
|
2022-08-24 16:24:57 +02:00
|
|
|
int cw_cfg_read_from_string(const char *str, cw_Cfg_t *cfg)
|
|
|
|
{
|
|
|
|
int errs;
|
|
|
|
FILE * f = fmemopen((void*)str,strlen(str),"rb");
|
|
|
|
if(!f)
|
|
|
|
return errno;
|
|
|
|
errs = cw_cfg_read_from_file(f, cfg);
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
if (errs)
|
|
|
|
errno = EINVAL;
|
|
|
|
return errno;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-08-17 18:41:17 +02:00
|
|
|
int cw_cfg_write_to_file(FILE *f, cw_Cfg_t * cfg)
|
|
|
|
{
|
|
|
|
mavliter_t it;
|
|
|
|
struct cw_Cfg_entry *e;
|
2022-08-20 22:03:06 +02:00
|
|
|
mavliter_init(&it, cfg->cfg);
|
2022-08-17 18:41:17 +02:00
|
|
|
mavliter_foreach(&it) {
|
|
|
|
int n;
|
|
|
|
e = mavliter_get(&it);
|
|
|
|
n=strlen(e->val);
|
|
|
|
if (n>0)
|
|
|
|
n-=1;
|
|
|
|
|
|
|
|
//printf("Write %s: \"%s\" - %d %d (%02x)\n",e->key,e->val,n,isspace(e->val[n]),e->val[n]);
|
|
|
|
if(isspace(e->val[0]) || isspace(e->val[n]))
|
|
|
|
fprintf(f,"%s: \"%s\"\n", e->key, e->val);
|
|
|
|
else
|
|
|
|
fprintf(f,"%s: %s\n", e->key, e->val);
|
|
|
|
|
|
|
|
//cw_dbg(dbglevel,"%s%s :%s: %s",prefix,data->key,type->get_type_name(data), value);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-19 22:23:55 +02:00
|
|
|
int cw_cfg_save(const char *filename, cw_Cfg_t *cfg, const char *format, ...)
|
2022-08-17 18:41:17 +02:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
FILE *f = fopen(filename, "wb");
|
|
|
|
if (!f)
|
|
|
|
return errno;
|
2022-08-19 22:23:55 +02:00
|
|
|
if (format !=NULL){
|
|
|
|
va_list args;
|
|
|
|
va_start(args,format);
|
|
|
|
vfprintf(f,format,args);
|
|
|
|
va_end(args);
|
|
|
|
}
|
2022-08-17 18:41:17 +02:00
|
|
|
rc = cw_cfg_write_to_file(f, cfg);
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2022-08-01 10:05:14 +02:00
|
|
|
|
2022-08-08 23:11:27 +02:00
|
|
|
void cw_cfg_iter_init(cw_Cfg_t * cfg, struct cw_Cfg_iter *cfi, const char *base)
|
|
|
|
{
|
|
|
|
struct cw_Cfg_entry search;
|
|
|
|
search.key = base;
|
|
|
|
|
2022-08-20 22:03:06 +02:00
|
|
|
mavliter_init(&(cfi->it), cfg->cfg);
|
2022-08-08 23:11:27 +02:00
|
|
|
mavliter_seek(&(cfi->it), &search, 0);
|
|
|
|
cfi->base = base;
|
2022-08-01 10:05:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-19 22:23:55 +02:00
|
|
|
struct cw_Cfg_entry *cw_cfg_iter_next(struct cw_Cfg_iter *cfi, const char *nnkey)
|
2022-08-08 23:11:27 +02:00
|
|
|
{
|
|
|
|
struct cw_Cfg_entry *e;
|
|
|
|
int bl, kl;
|
|
|
|
const char *d;
|
|
|
|
|
|
|
|
e = mavliter_get(&(cfi->it));
|
|
|
|
if (e == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
bl = strlen(cfi->base);
|
|
|
|
kl = strlen(e->key);
|
|
|
|
|
|
|
|
if (bl > kl)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (bl == kl) {
|
|
|
|
if (strcmp(cfi->base, e->key) != 0)
|
|
|
|
return NULL;
|
|
|
|
else {
|
|
|
|
mavliter_next(&(cfi->it));
|
2022-08-19 22:23:55 +02:00
|
|
|
return e;
|
2022-08-08 23:11:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
d = strchr(e->key, '.');
|
|
|
|
if (d == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (d - e->key != bl)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (strncmp(cfi->base, e->key, bl) != 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
mavliter_next(&(cfi->it));
|
2022-08-19 22:23:55 +02:00
|
|
|
return e;
|
2022-08-08 23:11:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-17 18:41:17 +02:00
|
|
|
int cw_cfg_get_bool(cw_Cfg_t * cfg, const char * key, int def)
|
2022-08-08 23:11:27 +02:00
|
|
|
{
|
|
|
|
struct cw_Val v;
|
2022-08-17 18:41:17 +02:00
|
|
|
const char *s = cw_cfg_get(cfg,key,NULL);
|
|
|
|
if (s==NULL)
|
|
|
|
return def;
|
2022-08-08 23:11:27 +02:00
|
|
|
CW_TYPE_BOOL->from_str(&v,s);
|
|
|
|
return v.val.boolean;
|
|
|
|
}
|
|
|
|
|
2022-08-11 00:21:01 +02:00
|
|
|
|
2022-08-13 09:47:12 +02:00
|
|
|
uint8_t cw_cfg_get_byte(cw_Cfg_t * cfg, char *key, uint8_t def)
|
2022-08-11 00:21:01 +02:00
|
|
|
{
|
|
|
|
struct cw_Val v;
|
2022-08-13 09:47:12 +02:00
|
|
|
memset(&v,0,sizeof(struct cw_Val));
|
|
|
|
const char *s = cw_cfg_get(cfg,key,NULL);
|
|
|
|
if (s==NULL)
|
|
|
|
return def;
|
2022-08-11 00:21:01 +02:00
|
|
|
CW_TYPE_BYTE->from_str(&v,s);
|
2022-08-14 12:26:34 +02:00
|
|
|
return v.val.byte;
|
2022-08-11 00:21:01 +02:00
|
|
|
}
|
|
|
|
|
2022-08-15 16:31:26 +02:00
|
|
|
uint8_t cw_cfg_get_byte_l(cw_Cfg_t ** cfgs, char *key, uint8_t def)
|
|
|
|
{
|
|
|
|
struct cw_Val v;
|
|
|
|
memset(&v,0,sizeof(struct cw_Val));
|
|
|
|
const char *s = cw_cfg_get_l(cfgs,key,NULL);
|
|
|
|
if (s==NULL)
|
|
|
|
return def;
|
|
|
|
CW_TYPE_BYTE->from_str(&v,s);
|
|
|
|
return v.val.byte;
|
|
|
|
}
|
|
|
|
|
2022-08-11 00:21:01 +02:00
|
|
|
|
|
|
|
|
2022-08-26 08:05:41 +02:00
|
|
|
uint16_t cw_cfg_get_word(cw_Cfg_t * cfg, const char *key, uint16_t def)
|
2022-08-08 23:11:27 +02:00
|
|
|
{
|
|
|
|
struct cw_Val v;
|
2022-08-13 09:47:12 +02:00
|
|
|
const char *s = cw_cfg_get(cfg,key,NULL);
|
|
|
|
if (s==NULL)
|
|
|
|
return def;
|
2022-08-08 23:11:27 +02:00
|
|
|
CW_TYPE_WORD->from_str(&v,s);
|
|
|
|
return v.val.word;
|
|
|
|
}
|
|
|
|
|
2022-08-26 08:05:41 +02:00
|
|
|
uint16_t cw_cfg_get_word_l(cw_Cfg_t ** cfg, const char *key, uint16_t def)
|
2022-08-22 01:59:23 +02:00
|
|
|
{
|
|
|
|
struct cw_Val v;
|
|
|
|
const char *s = cw_cfg_get_l(cfg,key,NULL);
|
|
|
|
if (s==NULL)
|
|
|
|
return def;
|
|
|
|
CW_TYPE_WORD->from_str(&v,s);
|
|
|
|
return v.val.word;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-08-13 09:47:12 +02:00
|
|
|
/*
|
|
|
|
int cw_cfg_get_word(cw_Cfg_t * cfg, char *key, const char * def)
|
|
|
|
{
|
|
|
|
const char *s;
|
|
|
|
s=cw_cfg_get(cfg,key,def);
|
|
|
|
if (s==NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2022-08-09 09:52:30 +02:00
|
|
|
void cw_cfg_set_int(cw_Cfg_t * cfg, const char * key, int val)
|
|
|
|
{
|
|
|
|
char a[128];
|
|
|
|
sprintf(a,"%d",val);
|
|
|
|
cw_cfg_set(cfg,key,a);
|
|
|
|
}
|
2022-08-13 09:47:12 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cw_cfg_get_next_index(cw_Cfg_t * cfg, const char *key)
|
|
|
|
{
|
|
|
|
char ikey[CW_CFG_MAX_KEY_LEN];
|
|
|
|
struct cw_Cfg_entry search, * result;
|
|
|
|
char *d;
|
|
|
|
|
|
|
|
sprintf(ikey,"%s.%d",key,65536);
|
|
|
|
|
|
|
|
search.key=ikey;
|
|
|
|
/*//result = ktvn(ktv,&search);*/
|
|
|
|
|
2022-08-20 22:03:06 +02:00
|
|
|
result = mavl_get_last(cfg->cfg,&search);
|
2022-08-13 09:47:12 +02:00
|
|
|
if (result == NULL){
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
d = strchr(result->key,'.');
|
|
|
|
if (d==NULL){
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strncmp(result->key,ikey,d-result->key)!=0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return atoi(d+1)+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int cw_cfg_set_val(cw_Cfg_t * cfg, const char *key, const struct cw_Type *type, const void * valguard, const uint8_t * data, int len)
|
|
|
|
{
|
|
|
|
cw_Val_t mdata, *mresult;
|
|
|
|
char str[2048];
|
|
|
|
memset(&mdata,0,sizeof(cw_Val_t));
|
|
|
|
mdata.type=type;
|
|
|
|
mdata.valguard=valguard;
|
|
|
|
mresult = type->get(&mdata,data,len);
|
|
|
|
if (!mresult){
|
|
|
|
cw_log(LOG_ERR, "Can't create cfg element for key %s of type %s: %s",
|
|
|
|
key,type->name, strerror(errno));
|
|
|
|
free(mdata.key);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
type->to_str(&mdata,str,2048);
|
|
|
|
cw_cfg_set(cfg,key,str);
|
|
|
|
|
|
|
|
if (type->del)
|
|
|
|
type->del(&mdata);
|
|
|
|
return 1;
|
|
|
|
}
|
2022-08-14 12:26:34 +02:00
|
|
|
|
2022-08-15 00:51:38 +02:00
|
|
|
//int cw_cfg_put(cw_Cfg_t *cfg, const char *key, const struct cw_Type *type,const void
|
|
|
|
|
|
|
|
|
2022-08-14 12:26:34 +02:00
|
|
|
|
2022-08-21 00:53:41 +02:00
|
|
|
void cw_cfg_copy(cw_Cfg_t *src, cw_Cfg_t *dst,int dbg_level,const char *dbg_prefix)
|
2022-08-14 12:26:34 +02:00
|
|
|
{
|
|
|
|
mavliter_t it;
|
2022-08-20 22:03:06 +02:00
|
|
|
mavliter_init(&it, src->cfg);
|
2022-08-14 12:26:34 +02:00
|
|
|
mavliter_foreach(&it) {
|
|
|
|
int exists;
|
|
|
|
struct cw_Cfg_entry * old_elem,*e, new_elem;
|
|
|
|
|
2022-08-19 22:23:55 +02:00
|
|
|
|
2022-08-14 12:26:34 +02:00
|
|
|
e = mavliter_get(&it);
|
|
|
|
new_elem.key = cw_strdup(e->key);
|
|
|
|
new_elem.val = cw_strdup(e->val);
|
|
|
|
|
2022-08-19 22:23:55 +02:00
|
|
|
/* if (1){
|
|
|
|
const char *ov;
|
|
|
|
ov = cw_cfg_get(dst,e->key,NULL);
|
|
|
|
cw_dbg(DBG_X, " REAL OV HERE: %s",ov);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2022-08-20 22:03:06 +02:00
|
|
|
old_elem = mavl_insert(dst->cfg,&new_elem,&exists);
|
2022-08-19 22:23:55 +02:00
|
|
|
|
|
|
|
/* cw_dbg(DBG_X, "CPY: %s: %s -> %s [%d]",new_elem.key,new_elem.val,old_elem->val,exists);
|
|
|
|
if (exists){
|
|
|
|
const char *ov;
|
|
|
|
ov = cw_cfg_get(dst,e->key,NULL);
|
|
|
|
cw_dbg(DBG_X, " OV HERE: %s",ov);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2022-08-14 12:26:34 +02:00
|
|
|
if (!exists){
|
2022-08-21 00:53:41 +02:00
|
|
|
cw_dbg(dbg_level, "%s: [undef] -> %s",new_elem.key,new_elem.val);
|
2022-08-14 12:26:34 +02:00
|
|
|
continue;
|
|
|
|
}
|
2022-08-19 22:23:55 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2022-08-14 12:26:34 +02:00
|
|
|
if (strcmp(new_elem.val,old_elem->val)==0){
|
|
|
|
free((void*)new_elem.key);
|
|
|
|
free((void*)new_elem.val);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-08-21 00:53:41 +02:00
|
|
|
cw_dbg(dbg_level, "%s: %s -> %s",new_elem.key,old_elem->val,new_elem.val);
|
|
|
|
// cw_dbg(DBG_X, "Replace: %s: %s (old: %s)",new_elem.key, new_elem.val, old_elem->val);
|
2022-08-20 22:03:06 +02:00
|
|
|
if(dst->cfg->del){
|
|
|
|
dst->cfg->del(old_elem);
|
2022-08-14 12:26:34 +02:00
|
|
|
}
|
2022-08-20 22:03:06 +02:00
|
|
|
memcpy(old_elem,&new_elem,dst->cfg->data_size);
|
2022-08-14 12:26:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void cw_cfg_destroy(cw_Cfg_t *cfg)
|
|
|
|
{
|
2022-08-20 22:03:06 +02:00
|
|
|
if (cfg->cfg)
|
|
|
|
mavl_destroy(cfg->cfg);
|
|
|
|
free(cfg);
|
2022-08-14 12:26:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void cw_cfg_clear(cw_Cfg_t *cfg)
|
|
|
|
{
|
2022-08-20 22:03:06 +02:00
|
|
|
mavl_del_all(cfg->cfg);
|
2022-08-14 12:26:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int cw_cfg_base_exists(cw_Cfg_t * cfg, const char *key)
|
|
|
|
{
|
|
|
|
struct cw_Cfg_entry e, *result;
|
2022-08-17 18:41:17 +02:00
|
|
|
//cw_dbg(DBG_X,"LOOX FOR: %s",key);
|
2022-08-14 12:26:34 +02:00
|
|
|
e.key=key;
|
2022-08-20 22:03:06 +02:00
|
|
|
result = mavl_get_first(cfg->cfg,&e);
|
2022-08-14 12:26:34 +02:00
|
|
|
if (result == NULL)
|
|
|
|
return 0;
|
2022-08-17 18:41:17 +02:00
|
|
|
//cw_dbg(DBG_X,"BASEXXX: %s",result->key);
|
2022-08-14 12:26:34 +02:00
|
|
|
|
|
|
|
if (strlen(result->key)<strlen(key))
|
|
|
|
return 0;
|
2022-08-17 18:41:17 +02:00
|
|
|
//cw_dbg(DBG_X,"BASEXXX1: %d",strlen(key));
|
2022-08-14 12:26:34 +02:00
|
|
|
if (result->key[strlen(key)]!='/' && result->key[strlen(key)]!='.')
|
|
|
|
return 0;
|
2022-08-17 18:41:17 +02:00
|
|
|
//cw_dbg(DBG_X,"BASEXXX2: ");
|
2022-08-14 12:26:34 +02:00
|
|
|
if (strncmp(result->key,key,strlen(key))==0)
|
|
|
|
return 1;
|
2022-08-17 18:41:17 +02:00
|
|
|
cw_dbg(DBG_X,"BASEXXX3: ");
|
2022-08-14 12:26:34 +02:00
|
|
|
|
|
|
|
return 0;
|
2022-08-17 18:41:17 +02:00
|
|
|
}
|
2022-08-14 12:26:34 +02:00
|
|
|
|
2022-08-17 18:41:17 +02:00
|
|
|
int cw_cfg_base_exists_l(cw_Cfg_t ** cfgs, const char *key)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i=0; cfgs[i]; i++){
|
|
|
|
if (cw_cfg_base_exists(cfgs[i],key))
|
|
|
|
return 1;
|
|
|
|
}
|
2022-08-19 22:23:55 +02:00
|
|
|
// cw_dbg(DBG_X,"NOX EXISIS: %s in %d",key,i);
|
2022-08-17 18:41:17 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cw_Val_t * cw_cfg_get_val_l(cw_Cfg_t ** cfgs, const char *key, const struct cw_Type *type)
|
|
|
|
{
|
|
|
|
const char *s;
|
|
|
|
cw_Val_t * val;
|
|
|
|
s = cw_cfg_get_l(cfgs,key,NULL);
|
|
|
|
val = malloc(sizeof(cw_Val_t));
|
|
|
|
if (val==NULL)
|
|
|
|
return NULL;
|
|
|
|
val->type=type;
|
|
|
|
val->type->from_str(val,s);
|
|
|
|
return val;
|
2022-08-14 12:26:34 +02:00
|
|
|
}
|