diff --git a/src/bag.c b/src/bag.c index 6aaa0cc1..c9d07a86 100644 --- a/src/bag.c +++ b/src/bag.c @@ -19,6 +19,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include #include @@ -26,7 +30,7 @@ #include "bag.h" #include "err.h" -struct _BAGITEM { +typedef struct _BAGITEM { int type; char *name; union { @@ -35,21 +39,23 @@ struct _BAGITEM { struct _BAG *as_bag; } value; struct _BAGITEM *next; - struct _BAGITEM *prev; -}; +} BAG_ITEM; struct _BAG { + unsigned int flags; + struct _BAGITEM *tailptr; struct _BAGITEM itemlist; }; - /** Globals */ pthread_mutex_t bag_mutex=PTHREAD_MUTEX_INITIALIZER; -/** Forwards */ -void bag_lock(void); -void bag_unlock(void); -int bag_delete(BAG_HANDLE bp); +/** 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, @@ -57,57 +63,66 @@ int bag_delete(BAG_HANDLE bp); * I don't think performance is going to be an issue, so I'll just * use a global lock. */ -void bag_lock(void) { +void _bag_lock(void) { int err; - DPRINTF(E_SPAM,L_WS,"Entering ws_lock_unsafe\n"); - if((err=pthread_mutex_lock(&bag_mutex))) { - DRPINTF(E_FATAL,L_MISC,"Could not lock mutex: %s\n",strerror(err)); + DPRINTF(E_FATAL,L_MISC,"Could not lock mutex: %s\n",strerror(err)); } } /** * unlock the mutex */ -void bag_unlock(void) { +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 bpp pointer to a BAG_HANDLE. Returns valid handle on BAG_E_SUCCESS + * @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 *bpp) { - *bpp = (BAG_HANDLE)malloc(sizeof(struct _BAG)); - if(!*bpp) +int bag_create(BAG_HANDLE *ppb) { + *ppb = (BAG_HANDLE)malloc(sizeof(struct _BAG)); + if(!*ppb) return BAG_E_MALLOC; - memset(*bpp,0x0,sizeof(struct _BAG)); + memset(*ppb,0x0,sizeof(struct _BAG)); return BAG_E_SUCCESS; } /** * destroy a bag, recusively, if neccesary * - * @param bp bag to destroy + * @param pb bag to destroy * @returns BAG_E_SUCCESS */ -int bag_destroy(BAG_HANDLE bp) { - bag_lock(); - bag_delete(bp); - bag_unlock(); +int bag_destroy(BAG_HANDLE pb) { + _bag_lock(); + _bag_delete(pb); + _bag_unlock(); return BAG_E_SUCCESS; } /** - * do the actual recursive delete + * 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 bp) { - BAG_ITEMHANDLE current; +int _bag_delete(BAG_HANDLE pb) { + BAG_ITEM *current,*last; + + last = &(pb->itemlist); + current = pb->itemlist.next; - current = bp->itemlist.next; while(current) { switch(current->type) { case BAG_TYPE_BAG: @@ -120,22 +135,44 @@ int bag_delete(BAG_HANDLE bp) { break; } + last = current; current = current->next; - free(current->prev); + free(last); } - free(bp); + 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 bp, void* vpval, int ival, int type) { - BAG_ITEMHANDLE pbi; +int _bag_add_item(BAG_HANDLE pb, void* vpval, int ival, int type) { + BAG_ITEM *pbi; - pbi=(BAG_ITEMHANDLE)malloc(sizeof(struct _BAGITEM)); + pbi=(BAG_ITEM *)malloc(sizeof(BAG_ITEM)); if(!pbi) { return BAG_E_MALLOC; } @@ -155,16 +192,92 @@ int bag_add_item(BAG_HANDLE bp, void* vpval, int ival, int type) { break; } - bag_lock(); + _bag_lock(); - pbi->next = bp->itemlist.next; - bp->itemlist.next = pbi; - pbi->prev=pbi->next->prev; - pbi->next->prev = pbi; + 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(); + _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; +} diff --git a/src/bag.h b/src/bag.h index 740e7956..829d9307 100644 --- a/src/bag.h +++ b/src/bag.h @@ -29,14 +29,25 @@ #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; -typedef struct _BAGITEM *BAG_ITEMHANDLE; -extern int bag_create(BAG_HANDLE *bpp); -extern int bag_destroy(BAG_HANDLE bp); -extern int bag_add_item(BAG_HANDLE bp, void* vpval, int ival, int type); +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_ */ diff --git a/src/config.c b/src/config.c new file mode 100644 index 00000000..fecd1391 --- /dev/null +++ b/src/config.c @@ -0,0 +1,59 @@ +/* + * $Id$ + * Functions for reading and writing the config file + * + * Copyright (C) 2006 Ron Pedde (ron@pedde.com) + * + * 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 + */ + + +/** + * \file config.c + * + * Config file reading and writing + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + + +#include "bag.h" +#include "daap.h" + +/** Globals */ + + +/** + * read a configfile into a bag + * + * @param file file to read + * @returns TRUE if successful, FALSE otherwise + */ +int config_read(char *file) { + +} + +int config_write(WS_CONNINFO *pwsc) { + +} + +int config_close(void) { + +} + diff --git a/src/config.h b/src/config.h new file mode 100644 index 00000000..e911384c --- /dev/null +++ b/src/config.h @@ -0,0 +1,29 @@ +/* + * $Id$ + * Functions for reading and writing the config file + * + * Copyright (C) 2006 Ron Pedde (ron@pedde.com) + * + * 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 _CONFIG_H_ +#define _CONFIG_H_ + +extern int config_read(char *file); +extern int config_write(WS_CONNINFO *pwsc); +extern int config_close(void); + +#endif /* _CONFIG_H_ */