mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-24 06:05:56 -05:00
slowly working on the config changes
This commit is contained in:
parent
9bfbfa8615
commit
49e9b3be32
283
src/bag.c
283
src/bag.c
@ -1,283 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* Simple collection as linked lists
|
||||
*
|
||||
* Copyright (C) 2006 Ron Pedde (rpedde@users.sourceforge.net)
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bag.h"
|
||||
#include "err.h"
|
||||
|
||||
typedef struct _BAGITEM {
|
||||
int type;
|
||||
char *name;
|
||||
union {
|
||||
int as_int;
|
||||
char *as_string;
|
||||
struct _BAG *as_bag;
|
||||
} value;
|
||||
struct _BAGITEM *next;
|
||||
} BAG_ITEM;
|
||||
|
||||
struct _BAG {
|
||||
unsigned int flags;
|
||||
struct _BAGITEM *tailptr;
|
||||
struct _BAGITEM itemlist;
|
||||
};
|
||||
|
||||
/** Globals */
|
||||
pthread_mutex_t bag_mutex=PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/** Internal functions */
|
||||
void _bag_lock(void);
|
||||
void _bag_unlock(void);
|
||||
int _bag_delete(BAG_HANDLE pb);
|
||||
BAG_ITEM *_bag_fetch_item(BAG_HANDLE pb, char *key);
|
||||
int _bag_add_item(BAG_HANDLE pb, void* vpval, int ival, int type);
|
||||
|
||||
/**
|
||||
* lock the mutex. This could be done on a bag-by-bag basis,
|
||||
* and it could further be done as a reader-writer lock, but
|
||||
* I don't think performance is going to be an issue, so I'll just
|
||||
* use a global lock.
|
||||
*/
|
||||
void _bag_lock(void) {
|
||||
int err;
|
||||
|
||||
if((err=pthread_mutex_lock(&bag_mutex))) {
|
||||
DPRINTF(E_FATAL,L_MISC,"Could not lock mutex: %s\n",strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* unlock the mutex
|
||||
*/
|
||||
void _bag_unlock(void) {
|
||||
int err;
|
||||
|
||||
if((err = pthread_mutex_unlock(&bag_mutex))) {
|
||||
DPRINTF(E_FATAL,L_MISC,"Could not unlock mutex: %s\n",strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create a bag
|
||||
*
|
||||
* @param pbp pointer to a BAG_HANDLE. Returns valid handle on BAG_E_SUCCESS
|
||||
* @returns BAG_E_SUCCESS on success, error code otherwise
|
||||
*/
|
||||
int bag_create(BAG_HANDLE *ppb) {
|
||||
*ppb = (BAG_HANDLE)malloc(sizeof(struct _BAG));
|
||||
if(!*ppb)
|
||||
return BAG_E_MALLOC;
|
||||
|
||||
memset(*ppb,0x0,sizeof(struct _BAG));
|
||||
return BAG_E_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* destroy a bag, recusively, if neccesary
|
||||
*
|
||||
* @param pb bag to destroy
|
||||
* @returns BAG_E_SUCCESS
|
||||
*/
|
||||
int bag_destroy(BAG_HANDLE pb) {
|
||||
_bag_lock();
|
||||
_bag_delete(pb);
|
||||
_bag_unlock();
|
||||
return BAG_E_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* internal function to implement the actual delete.
|
||||
* assumes that the semaphore is held
|
||||
*
|
||||
* @param pb bag to delete
|
||||
* @returns BAG_E_SUCCESS
|
||||
*/
|
||||
int _bag_delete(BAG_HANDLE pb) {
|
||||
BAG_ITEM *current,*last;
|
||||
|
||||
last = &(pb->itemlist);
|
||||
current = pb->itemlist.next;
|
||||
|
||||
while(current) {
|
||||
switch(current->type) {
|
||||
case BAG_TYPE_BAG:
|
||||
bag_delete(current->value.as_bag);
|
||||
break;
|
||||
case BAG_TYPE_STRING:
|
||||
free(current->value.as_string);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
last = current;
|
||||
current = current->next;
|
||||
free(last);
|
||||
}
|
||||
|
||||
free(pb);
|
||||
|
||||
return BAG_E_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* thin wrapper for _bag_add_item
|
||||
*/
|
||||
int bag_add_string(BAG_HANDLE pb, char *cval) {
|
||||
return _bag_add_item(pb,cval,0,BAG_TYPE_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* thin wrapper for _bag_add_item
|
||||
*/
|
||||
int bag_add_int(BAG_HANDLE pb, int ival) {
|
||||
return _bag_add_item(pb,NULL,ival,BAG_TYPE_INT);
|
||||
}
|
||||
|
||||
/**
|
||||
* thin wrapper for _bag_add_item
|
||||
*/
|
||||
int bag_add_bag(BAG_HANDLE pb, BAG_HANDLE pnew) {
|
||||
return _bag_add_item(pb,(void*)pnew,0,BAG_TYPE_BAG);
|
||||
}
|
||||
|
||||
/**
|
||||
* add an item to a bag
|
||||
*/
|
||||
int _bag_add_item(BAG_HANDLE pb, void* vpval, int ival, int type) {
|
||||
BAG_ITEM *pbi;
|
||||
|
||||
pbi=(BAG_ITEM *)malloc(sizeof(BAG_ITEM));
|
||||
if(!pbi) {
|
||||
return BAG_E_MALLOC;
|
||||
}
|
||||
|
||||
pbi->type = type;
|
||||
switch(type) {
|
||||
case BAG_TYPE_INT:
|
||||
pbi->value.as_int = ival;
|
||||
break;
|
||||
case BAG_TYPE_BAG:
|
||||
pbi->value.as_bag = (BAG_HANDLE)vpval;
|
||||
break;
|
||||
case BAG_TYPE_STRING:
|
||||
pbi->value.as_string = strdup((char*)vpval);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_bag_lock();
|
||||
|
||||
if(pb->flags & BAG_FLAG_HEADINSERT) {
|
||||
pbi->next = pb->itemlist.next;
|
||||
pb->itemlist.next = pbi;
|
||||
} else {
|
||||
pbi->next = NULL;
|
||||
pb->tailptr->next = pbi;
|
||||
pb->tailptr = pbi;
|
||||
}
|
||||
|
||||
_bag_unlock();
|
||||
return BAG_E_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* internal function to get the bag item associated with
|
||||
* a specific key, using the case sensitivity specified
|
||||
* by the bag flags. This assumes that the lock is held!
|
||||
*
|
||||
* @param pb bag to fetch item from
|
||||
* @param key key name to fetch
|
||||
* @returns pointer to bagitem, or null if not found
|
||||
*/
|
||||
BAG_ITEM *_bag_fetch_item(BAG_HANDLE pb, char *key) {
|
||||
BAG_ITEM *current;
|
||||
|
||||
current = pb->itemlist.next;
|
||||
while(current) {
|
||||
if(pb->flags & BAG_FLAG_HONORCASE) {
|
||||
if(!strcasecmp(current->name,key))
|
||||
break;
|
||||
if(!strcmp(current->name,key))
|
||||
break;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* set flags
|
||||
*
|
||||
* @param pb bag to set flags for
|
||||
* @returns BAG_E_SUCCESS
|
||||
*/
|
||||
int bag_set_flags(BAG_HANDLE pb, unsigned int flags) {
|
||||
pb->flags = flags;
|
||||
return BAG_E_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* get flags
|
||||
*
|
||||
* @param pb bag to get flags from
|
||||
* @returns BAG_E_SUCCESS
|
||||
*/
|
||||
int bag_get_flags(BAG_HANDLE pb, unsigned int *flags) {
|
||||
*flags = pb->flags;
|
||||
return BAG_E_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get the type for a particular key in a bag.
|
||||
*
|
||||
* @param pb bag to search in
|
||||
* @param key key to search for
|
||||
* @param type return value for type of bag (BAG_TYPE_*)
|
||||
* @returns BAG_E_SUCCESS or BAG_E_NOKEY on failure
|
||||
*/
|
||||
int bag_get_type(BAG_HANDLE pb, char *key, int *type) {
|
||||
BAG_ITEM *pitem;
|
||||
|
||||
_bag_lock();
|
||||
|
||||
pitem = _bag_fetch_item(pb, key);
|
||||
if(!pitem) {
|
||||
_bag_unlock();
|
||||
return BAG_E_NOKEY;
|
||||
}
|
||||
|
||||
*type = pitem->type;
|
||||
_bag_unlock;
|
||||
|
||||
return BAG_E_SUCCESS;
|
||||
}
|
||||
|
53
src/bag.h
53
src/bag.h
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
* Simple collection as linked lists
|
||||
*
|
||||
* Copyright (C) 2006 Ron Pedde (rpedde@users.sourceforge.net)
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef _BAG_H_
|
||||
#define _BAG_H_
|
||||
|
||||
#define BAG_TYPE_INT 0
|
||||
#define BAG_TYPE_STRING 1
|
||||
#define BAG_TYPE_BAG 2
|
||||
|
||||
|
||||
#define BAG_E_SUCCESS 0
|
||||
#define BAG_E_MALLOC 1
|
||||
#define BAG_E_NOKEY 2
|
||||
|
||||
#define BAG_FLAG_HONORCASE 1 /** Make keys case sensitive */
|
||||
#define BAG_FLAG_HEADINSERT 2 /** Insert at head, rather than tail */
|
||||
|
||||
|
||||
typedef struct _BAG *BAG_HANDLE;
|
||||
|
||||
extern int bag_create(BAG_HANDLE *ppb);
|
||||
extern int bag_destroy(BAG_HANDLE pb);
|
||||
|
||||
extern int bag_add_string(BAG_HANDLE pb, char *cval);
|
||||
extern int bag_add_int(BAG_HANDLE pb, int ival);
|
||||
extern int bag_add_bag(BAG_HANDLE pb, BAG_HANDLE pnew);
|
||||
|
||||
extern int bag_set_flags(BAG_HANDLE pb, unsigned int flags);
|
||||
extern int bag_get_flags(BAG_HANDLE pb, unsigned int *flags);
|
||||
|
||||
extern int bag_get_type(BAG_HANDLE pb, char *key, int *type);
|
||||
|
||||
#endif /* _BAG_H_ */
|
||||
|
16
src/config-driver.c
Normal file
16
src/config-driver.c
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(config_read(argv[1]) != CONFIG_E_SUCCESS) {
|
||||
printf("Read config!\n");
|
||||
} else {
|
||||
printf("Error reading config\n");
|
||||
}
|
||||
config_close();
|
||||
}
|
85
src/config.c
85
src/config.c
@ -32,13 +32,15 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include "bag.h"
|
||||
#include "daap.h"
|
||||
#include "err.h"
|
||||
#include "ll.h"
|
||||
#include "daapd.h"
|
||||
|
||||
/** Globals */
|
||||
int ecode;
|
||||
BAG_HANDLE config_main;
|
||||
LL_HANDLE config_main=NULL;
|
||||
|
||||
#define CONFIG_LINEBUFFER 128
|
||||
|
||||
/**
|
||||
* read a configfile into a bag
|
||||
@ -49,25 +51,94 @@ BAG_HANDLE config_main;
|
||||
int config_read(char *file) {
|
||||
FILE *fin;
|
||||
int err;
|
||||
LL_HANDLE pllnew, plltemp;
|
||||
char linebuffer[CONFIG_LINEBUFFER+1];
|
||||
char *comment, *term, *value, *delim;
|
||||
int compat_mode=1;
|
||||
|
||||
fin=fopen(file,"r");
|
||||
if(!fin) {
|
||||
ecode = errno;
|
||||
return CONFIG_E_FOPEN;
|
||||
}
|
||||
|
||||
if((err=bag_create(&config_main)) != BAG_E_SUCCESS) {
|
||||
DPRINTF(E_LOG,L_CONF,"Error creating bag: %d\n",err);
|
||||
if((err=ll_create(&pllnew)) != LL_E_SUCCESS) {
|
||||
DPRINTF(E_LOG,L_CONF,"Error creating linked list: %d\n",err);
|
||||
fclose(fin);
|
||||
return CONFIG_E_UNKNOWN;
|
||||
}
|
||||
|
||||
/* got what will be the root of the config tree, now start walking through
|
||||
* the input file, populating the tree
|
||||
*/
|
||||
while(fgets(linebuffer,CONFIG_LINEBUFFER,fin)) {
|
||||
linebuffer[CONFIG_LINEBUFFER] = '\0';
|
||||
|
||||
comment=strchr(linebuffer,'#');
|
||||
if(comment) {
|
||||
/* we should really preserve these in another tree*/
|
||||
*comment = '\0';
|
||||
}
|
||||
|
||||
while(strlen(linebuffer) && (strchr("\n\r ",linebuffer[strlen(linebuffer)-1])))
|
||||
linebuffer[strlen(linebuffer)-1] = '\0';
|
||||
|
||||
if(linebuffer[0] == '[') {
|
||||
/* section header */
|
||||
compat_mode=0;
|
||||
term=&linebuffer[1];
|
||||
value = strchr(term,']');
|
||||
if(!value) {
|
||||
ll_destroy(pllnew);
|
||||
fclose(fin);
|
||||
return CONFIG_E_BADHEADER;
|
||||
}
|
||||
*value = '\0';
|
||||
|
||||
if((err = ll_create(&plltemp)) != LL_E_SUCCESS) {
|
||||
ll_destroy(pllnew);
|
||||
fclose(fin);
|
||||
return CONFIG_E_UNKNOWN;
|
||||
}
|
||||
|
||||
ll_add_ll(pllnew,term,plltemp);
|
||||
} else {
|
||||
/* k/v pair */
|
||||
term=&linebuffer[0];
|
||||
|
||||
while((*term=='\t') || (*term==' '))
|
||||
term++;
|
||||
|
||||
value=term;
|
||||
|
||||
if(compat_mode) {
|
||||
delim="\t ";
|
||||
} else {
|
||||
delim="=";
|
||||
}
|
||||
|
||||
strsep(&value,delim);
|
||||
if((value) && (term) && (strlen(term))) {
|
||||
while(strlen(value) && (strchr("\t ",*value)))
|
||||
value++;
|
||||
|
||||
ll_add_string(pllnew,term,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fin);
|
||||
|
||||
/* Sanity check */
|
||||
ll_dump(pllnew);
|
||||
ll_destroy(pllnew);
|
||||
|
||||
return CONFIG_E_SUCCESS;
|
||||
}
|
||||
|
||||
int config_close(void) {
|
||||
if(config_main)
|
||||
ll_destroy(config_main);
|
||||
|
||||
return CONFIG_E_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -25,9 +25,10 @@
|
||||
#define CONFIG_E_SUCCESS 0
|
||||
#define CONFIG_E_FOPEN 1
|
||||
#define CONFIG_E_UNKNOWN 2
|
||||
#define CONFIG_E_BADHEADER 3
|
||||
|
||||
|
||||
extern int config_read(char *file);
|
||||
extern int config_write(WS_CONNINFO *pwsc);
|
||||
extern int config_close(void);
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
||||
|
12
src/config.mk
Normal file
12
src/config.mk
Normal file
@ -0,0 +1,12 @@
|
||||
# $Id$
|
||||
CC=gcc
|
||||
CFLAGS := $(CFLAGS) -g -DHAVE_CONFIG_H -I. -I..
|
||||
LDFLAGS := $(LDFLAGS)
|
||||
TARGET = config
|
||||
OBJECTS=config-driver.o config.o ll.o
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
$(CC) -o $(TARGET) $(LDFLAGS) $(OBJECTS)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJECTS) $(TARGET)
|
@ -31,6 +31,7 @@
|
||||
#ifndef _DAAPD_H_
|
||||
#define _DAAPD_H_
|
||||
|
||||
#include <time.h>
|
||||
#include "webserver.h"
|
||||
|
||||
/** Simple struct for holding stat info.
|
||||
|
204
src/ll.c
Normal file
204
src/ll.c
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* $Id$
|
||||
* Rock stupid char* indexed linked lists
|
||||
*
|
||||
* Copyright (C) 2006 Ron Pedde (rpedde@users.sourceforge.net)
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ll.h"
|
||||
#include "err.h"
|
||||
|
||||
|
||||
/** Internal functions */
|
||||
|
||||
int _ll_add_item(LL *pl, char *key, void *vpval, int ival, int type);
|
||||
|
||||
/**
|
||||
* create a ll
|
||||
*
|
||||
* @param ppl pointer to a LL *. Returns valid handle on LL_E_SUCCESS
|
||||
* @returns LL_E_SUCCESS on success, error code otherwise
|
||||
*/
|
||||
int ll_create(LL **ppl) {
|
||||
*ppl = (LL *)malloc(sizeof(struct _LL));
|
||||
if(!*ppl)
|
||||
return LL_E_MALLOC;
|
||||
|
||||
memset(*ppl,0x0,sizeof(struct _LL));
|
||||
return LL_E_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* destroy a ll, recusively, if neccesary
|
||||
*
|
||||
* @param pl ll to destroy
|
||||
* @returns LL_E_SUCCESS
|
||||
*/
|
||||
int ll_destroy(LL *pl) {
|
||||
LL_ITEM *current,*last;
|
||||
|
||||
last = &(pl->itemlist);
|
||||
current = pl->itemlist.next;
|
||||
|
||||
while(current) {
|
||||
switch(current->type) {
|
||||
case LL_TYPE_LL:
|
||||
ll_destroy(current->value.as_ll);
|
||||
break;
|
||||
case LL_TYPE_STRING:
|
||||
free(current->value.as_string);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
free(current->key);
|
||||
last = current;
|
||||
current = current->next;
|
||||
free(last);
|
||||
}
|
||||
|
||||
free(pl);
|
||||
|
||||
return LL_E_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* thin wrapper for _ll_add_item
|
||||
*/
|
||||
int ll_add_string(LL *pl, char *key, char *cval) {
|
||||
return _ll_add_item(pl,cval,key,0,LL_TYPE_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* thin wrapper for _ll_add_item
|
||||
*/
|
||||
int ll_add_int(LL *pl, char *key, int ival) {
|
||||
return _ll_add_item(pl,key,NULL,ival,LL_TYPE_INT);
|
||||
}
|
||||
|
||||
/**
|
||||
* thin wrapper for _ll_add_item
|
||||
*/
|
||||
int ll_add_ll(LL *pl, char *key, LL *pnew) {
|
||||
return _ll_add_item(pl,key,(void*)pnew,0,LL_TYPE_LL);
|
||||
}
|
||||
|
||||
/**
|
||||
* add an item to a ll
|
||||
*/
|
||||
int _ll_add_item(LL *pl, char *key, void* vpval, int ival, int type) {
|
||||
LL_ITEM *pli;
|
||||
|
||||
pli=(LL_ITEM *)malloc(sizeof(LL_ITEM));
|
||||
if(!pli) {
|
||||
return LL_E_MALLOC;
|
||||
}
|
||||
|
||||
pli->type = type;
|
||||
pli->key = strdup(key);
|
||||
|
||||
switch(type) {
|
||||
case LL_TYPE_INT:
|
||||
pli->value.as_int = ival;
|
||||
break;
|
||||
case LL_TYPE_LL:
|
||||
pli->value.as_ll = (LL *)vpval;
|
||||
break;
|
||||
case LL_TYPE_STRING:
|
||||
pli->value.as_string = strdup((char*)vpval);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(pl->flags & LL_FLAG_HEADINSERT) {
|
||||
pli->next = pl->itemlist.next;
|
||||
pl->itemlist.next = pli;
|
||||
} else {
|
||||
pli->next = NULL;
|
||||
pl->tailptr->next = pli;
|
||||
pl->tailptr = pli;
|
||||
}
|
||||
|
||||
return LL_E_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* internal function to get the ll item associated with
|
||||
* a specific key, using the case sensitivity specified
|
||||
* by the ll flags. This assumes that the lock is held!
|
||||
*
|
||||
* @param pl ll to fetch item from
|
||||
* @param key key name to fetch
|
||||
* @returns pointer to llitem, or null if not found
|
||||
*/
|
||||
LL_ITEM *ll_fetch_item(LL *pl, char *key) {
|
||||
LL_ITEM *current;
|
||||
|
||||
current = pl->itemlist.next;
|
||||
while(current) {
|
||||
if(pl->flags & LL_FLAG_HONORCASE) {
|
||||
if(!strcasecmp(current->key,key))
|
||||
break;
|
||||
if(!strcmp(current->key,key))
|
||||
break;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* set flags
|
||||
*
|
||||
* @param pl ll to set flags for
|
||||
* @returns LL_E_SUCCESS
|
||||
*/
|
||||
int ll_set_flags(LL *pl, unsigned int flags) {
|
||||
pl->flags = flags;
|
||||
return LL_E_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* get flags
|
||||
*
|
||||
* @param pl ll to get flags from
|
||||
* @returns LL_E_SUCCESS
|
||||
*/
|
||||
int ll_get_flags(LL *pl, unsigned int *flags) {
|
||||
*flags = pl->flags;
|
||||
return LL_E_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump a linked list
|
||||
*
|
||||
* @parm pl linked list to dump
|
||||
*/
|
||||
extern void ll_dump(LL *pl) {
|
||||
|
||||
}
|
||||
|
72
src/ll.h
Normal file
72
src/ll.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* $Id$
|
||||
* Rock stupid char* indexed linked lists
|
||||
*
|
||||
* Copyright (C) 2006 Ron Pedde (rpedde@users.sourceforge.net)
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef _LL_H_
|
||||
#define _LL_H_
|
||||
|
||||
#define LL_TYPE_INT 0
|
||||
#define LL_TYPE_STRING 1
|
||||
#define LL_TYPE_LL 2
|
||||
|
||||
|
||||
#define LL_E_SUCCESS 0
|
||||
#define LL_E_MALLOC 1
|
||||
#define LL_E_NOKEY 2
|
||||
|
||||
#define LL_FLAG_HONORCASE 1 /** Make keys case sensitive */
|
||||
#define LL_FLAG_HEADINSERT 2 /** Insert at head, rather than tail */
|
||||
|
||||
|
||||
typedef struct _LLITEM {
|
||||
int type;
|
||||
char *key;
|
||||
union {
|
||||
int as_int;
|
||||
char *as_string;
|
||||
struct _LL *as_ll;
|
||||
} value;
|
||||
struct _LLITEM *next;
|
||||
} LL_ITEM, *LL_ITEMHANDLE;
|
||||
|
||||
typedef struct _LL {
|
||||
unsigned int flags;
|
||||
struct _LLITEM *tailptr;
|
||||
struct _LLITEM itemlist;
|
||||
} LL, *LL_HANDLE;
|
||||
|
||||
|
||||
|
||||
extern int ll_create(LL **ppl);
|
||||
extern int ll_destroy(LL *pl);
|
||||
|
||||
extern int ll_add_string(LL *pl, char *key, char *cval);
|
||||
extern int ll_add_int(LL *pl, char *key, int ival);
|
||||
extern int ll_add_ll(LL *pl, char *key, LL *pnew);
|
||||
|
||||
extern int ll_set_flags(LL *pl, unsigned int flags);
|
||||
extern int ll_get_flags(LL *pl, unsigned int *flags);
|
||||
|
||||
extern LL_ITEM *ll_fetch_item(LL *pl, char *key);
|
||||
|
||||
extern void ll_dump(LL *pl);
|
||||
|
||||
#endif /* _LL_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user