stringlist.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003  -------------------
00004  cvs         : $Id$
00005  begin       : Thu Apr 03 2003
00006  copyright   : (C) 2003 by Martin Preuss
00007  email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU Lesser General Public            *
00013  *   License as published by the Free Software Foundation; either          *
00014  *   version 2.1 of the License, or (at your option) any later version.    *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00024  *   MA  02111-1307  USA                                                   *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 
00029 #ifdef HAVE_CONFIG_H
00030 # include <config.h>
00031 #endif
00032 
00033 #include <gwenhywfar/gwenhywfarapi.h>
00034 #include <gwenhywfar/misc.h>
00035 #include "stringlist_p.h"
00036 #include "debug.h"
00037 #include <stdlib.h>
00038 #include <assert.h>
00039 #include <string.h>
00040 #ifdef HAVE_STRINGS_H
00041 # include <strings.h>
00042 #endif
00043 
00044 
00045 
00046 GWEN_STRINGLIST *GWEN_StringList_new(){
00047   GWEN_STRINGLIST *sl;
00048 
00049   GWEN_NEW_OBJECT(GWEN_STRINGLIST, sl);
00050   assert(sl);
00051   sl->ignoreRefCount=1;
00052   return sl;
00053 }
00054 
00055 
00056 
00057 void GWEN_StringList_free(GWEN_STRINGLIST *sl){
00058   GWEN_STRINGLISTENTRY *curr, *next;
00059 
00060   if (sl) {
00061     curr=sl->first;
00062     while(curr) {
00063       next=curr->next;
00064       GWEN_StringListEntry_free(curr);
00065       curr=next;
00066     } /* while */
00067     GWEN_FREE_OBJECT(sl);
00068   }
00069 }
00070 
00071 
00072 
00073 void GWEN_StringList_SetSenseCase(GWEN_STRINGLIST *sl, int i) {
00074   assert(sl);
00075   sl->senseCase=i;
00076 }
00077 
00078 
00079 
00080 void GWEN_StringList_SetIgnoreRefCount(GWEN_STRINGLIST *sl, int i) {
00081   assert(sl);
00082   sl->ignoreRefCount=i;
00083 }
00084 
00085 
00086 
00087 GWEN_STRINGLISTENTRY *GWEN_StringListEntry_new(const char *s, int take){
00088   GWEN_STRINGLISTENTRY *sl;
00089 
00090   GWEN_NEW_OBJECT(GWEN_STRINGLISTENTRY, sl);
00091   assert(sl);
00092   sl->refCount=1;
00093   if (s) {
00094     if (take)
00095       sl->data=s;
00096     else
00097       sl->data=strdup(s);
00098   }
00099   return sl;
00100 }
00101 
00102 
00103 
00104 void GWEN_StringListEntry_ReplaceString(GWEN_STRINGLISTENTRY *e,
00105                                         const char *s,
00106                                         int take){
00107   assert(e);
00108   if (e->data)
00109     free((void*)(e->data));
00110   if (take)
00111     e->data=s;
00112   else
00113     e->data=strdup(s);
00114 }
00115 
00116 
00117 
00118 void GWEN_StringListEntry_free(GWEN_STRINGLISTENTRY *sl){
00119   if (sl) {
00120     if (sl->data)
00121       free((void*)(sl->data));
00122     GWEN_FREE_OBJECT(sl);
00123   }
00124 }
00125 
00126 
00127 
00128 void GWEN_StringList_AppendEntry(GWEN_STRINGLIST *sl,
00129                                  GWEN_STRINGLISTENTRY *se){
00130   GWEN_STRINGLISTENTRY *curr;
00131 
00132   assert(sl);
00133   assert(se);
00134 
00135   curr=sl->first;
00136   if (!curr) {
00137     sl->first=se;
00138   }
00139   else {
00140     while(curr->next) {
00141       curr=curr->next;
00142     }
00143     curr->next=se;
00144   }
00145   sl->count++;
00146 }
00147 
00148 
00149 
00150 void GWEN_StringList_RemoveEntry(GWEN_STRINGLIST *sl,
00151                                  GWEN_STRINGLISTENTRY *se){
00152   GWEN_STRINGLISTENTRY *curr;
00153 
00154   assert(sl);
00155   assert(se);
00156 
00157   curr=sl->first;
00158   if (curr) {
00159     if (curr==se) {
00160       sl->first=curr->next;
00161       if (sl->count)
00162         sl->count--;
00163     }
00164     else {
00165       while(curr->next!=se) {
00166         curr=curr->next;
00167       }
00168       if (curr) {
00169         curr->next=se->next;
00170         if (sl->count)
00171           sl->count--;
00172       }
00173     }
00174   }
00175 }
00176 
00177 
00178 
00179 void GWEN_StringList_Clear(GWEN_STRINGLIST *sl){
00180   GWEN_STRINGLISTENTRY *se, *next;
00181 
00182   assert(sl);
00183   se=sl->first;
00184   sl->first=0;
00185   while (se) {
00186     next=se->next;
00187     GWEN_StringListEntry_free(se);
00188     se=next;
00189   } /* while */
00190 }
00191 
00192 
00193 
00194 int GWEN_StringList_AppendString(GWEN_STRINGLIST *sl,
00195                                  const char *s,
00196                                  int take,
00197                                  int checkDouble){
00198   GWEN_STRINGLISTENTRY *se;
00199 
00200   if (checkDouble) {
00201     se=sl->first;
00202     if (sl->senseCase) {
00203       while(se) {
00204         if (strcmp(se->data, s)==0) {
00205           if (take)
00206             free((char*)s);
00207           se->refCount++;
00208           return 0;
00209         }
00210         se=se->next;
00211       } /* while */
00212     }
00213     else {
00214       while(se) {
00215         if (strcasecmp(se->data, s)==0) {
00216           if (take)
00217             free((char*)s);
00218           se->refCount++;
00219           return 0;
00220         }
00221         se=se->next;
00222       } /* while */
00223     }
00224   } /* if checkdouble */
00225 
00226   se=GWEN_StringListEntry_new(s, take);
00227   GWEN_StringList_AppendEntry(sl, se);
00228   return 1;
00229 }
00230 
00231 
00232 
00233 int GWEN_StringList_InsertString(GWEN_STRINGLIST *sl,
00234                                  const char *s,
00235                                  int take,
00236                                  int checkDouble){
00237   GWEN_STRINGLISTENTRY *se;
00238 
00239   if (checkDouble) {
00240     se=sl->first;
00241     if (sl->senseCase) {
00242       while(se) {
00243         if (strcmp(se->data, s)==0) {
00244           if (take)
00245             free((char*)s);
00246           se->refCount++;
00247           return 0;
00248         }
00249         se=se->next;
00250       } /* while */
00251     }
00252     else {
00253       while(se) {
00254         if (strcasecmp(se->data, s)==0) {
00255           if (take)
00256             free((char*)s);
00257           se->refCount++;
00258           return 0;
00259         }
00260         se=se->next;
00261       } /* while */
00262     }
00263   } /* if checkdouble */
00264   se=GWEN_StringListEntry_new(s, take);
00265   se->next=sl->first;
00266   sl->first=se;
00267   return 1;
00268 }
00269 
00270 
00271 
00272 GWENHYWFAR_API int GWEN_StringList_RemoveString(GWEN_STRINGLIST *sl,
00273                                                 const char *s){
00274   GWEN_STRINGLISTENTRY *se;
00275 
00276   se=sl->first;
00277   if (sl->senseCase) {
00278     while(se) {
00279       if (strcmp(se->data, s)==0) {
00280         assert(se->refCount);
00281         se->refCount--;
00282         if (sl->ignoreRefCount)
00283           GWEN_StringList_RemoveEntry(sl, se);
00284         else {
00285           if (se->refCount==0)
00286             GWEN_StringList_RemoveEntry(sl, se);
00287         }
00288         return 1;
00289       }
00290       se=se->next;
00291     } /* while */
00292     return 0;
00293   }
00294   else {
00295     while(se) {
00296       if (strcasecmp(se->data, s)==0) {
00297         assert(se->refCount);
00298         se->refCount--;
00299         if (sl->ignoreRefCount)
00300           GWEN_StringList_RemoveEntry(sl, se);
00301         else {
00302           assert(se->refCount);
00303           if (se->refCount==0)
00304             GWEN_StringList_RemoveEntry(sl, se);
00305         }
00306         return 1;
00307       }
00308       se=se->next;
00309     } /* while */
00310     return 0;
00311   }
00312 }
00313 
00314 
00315 
00316 GWEN_STRINGLISTENTRY *GWEN_StringList_FirstEntry(const GWEN_STRINGLIST *sl){
00317   assert(sl);
00318   return sl->first;
00319 }
00320 
00321 
00322 
00323 GWEN_STRINGLISTENTRY *GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se){
00324   assert(se);
00325   return se->next;
00326 }
00327 
00328 
00329 
00330 const char *GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se){
00331   assert(se);
00332   return se->data;
00333 }
00334 
00335 
00336 unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl){
00337   assert(sl);
00338   return sl->count;
00339 }
00340 
00341 
00342 
00343 int GWEN_StringList_HasString(const GWEN_STRINGLIST *sl,
00344                               const char *s){
00345   GWEN_STRINGLISTENTRY *se;
00346 
00347   assert(sl);
00348   se=sl->first;
00349   if (sl->senseCase) {
00350     while(se) {
00351       if (strcmp(se->data, s)==0) {
00352         return 1;
00353       }
00354       se=se->next;
00355     } /* while */
00356     return 0;
00357   }
00358   else {
00359     while(se) {
00360       if (strcasecmp(se->data, s)==0) {
00361         return 1;
00362       }
00363       se=se->next;
00364     } /* while */
00365     return 0;
00366   }
00367 }
00368 
00369 
00370 
00371 GWEN_STRINGLIST *GWEN_StringList_dup(const GWEN_STRINGLIST *sl){
00372   GWEN_STRINGLISTENTRY *se;
00373   GWEN_STRINGLIST *newsl;
00374 
00375   assert(sl);
00376   newsl=GWEN_StringList_new();
00377 
00378   se=sl->first;
00379   while(se) {
00380     GWEN_STRINGLISTENTRY *newse;
00381 
00382     newse=GWEN_StringListEntry_new(se->data, 0);
00383     GWEN_StringList_AppendEntry(newsl, newse);
00384     se=se->next;
00385   } /* while */
00386 
00387   return newsl;
00388 }
00389 
00390 
00391 void *GWEN_StringList_ForEach(const GWEN_STRINGLIST *l, 
00392                               void *(*func)(const char *s, void *u), 
00393                               void *user_data) {
00394   GWEN_STRINGLISTENTRY *it;
00395   const char *el;
00396   void *result = 0;
00397   assert(l);
00398 
00399   it = GWEN_StringList_FirstEntry(l);
00400   if (!it)
00401     return 0;
00402   while(it) {
00403     el = GWEN_StringListEntry_Data(it);
00404     result = func(el, user_data);
00405     if (result) {
00406       return result;
00407     }
00408     it = GWEN_StringListEntry_Next(it);
00409   }
00410   return 0;
00411 }
00412 
00413 
00414 
00415 const char *GWEN_StringList_FirstString(const GWEN_STRINGLIST *l){
00416   assert(l);
00417   if (l->first==0)
00418     return 0;
00419   return l->first->data;
00420 }
00421 
00422 
00423 
00424 static int GWEN_StringList__compar_asc_nocase(const void *a, const void *b) {
00425   const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
00426   const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
00427   if (se1 && se2 && se1->data && se2->data)
00428     return strcmp(se1->data, se2->data);
00429   else
00430     return 0;
00431 }
00432 static int GWEN_StringList__compar_desc_nocase(const void *a, const void *b) {
00433   const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
00434   const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
00435   if (se1 && se2 && se1->data && se2->data)
00436     return strcmp(se2->data, se1->data);
00437   else
00438     return 0;
00439 }
00440 static int GWEN_StringList__compar_asc_case(const void *a, const void *b) {
00441   const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
00442   const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
00443   if (se1 && se2 && se1->data && se2->data)
00444     return strcasecmp(se1->data, se2->data);
00445   else
00446     return 0;
00447 }
00448 static int GWEN_StringList__compar_desc_case(const void *a, const void *b) {
00449   const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
00450   const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
00451   if (se1 && se2 && se1->data && se2->data)
00452     return strcasecmp(se2->data, se1->data);
00453   else
00454     return 0;
00455 }
00456 
00457 static int GWEN_StringList__compar_asc_int(const void *a, const void *b) {
00458   const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
00459   const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
00460   if (se1 && se2 && se1->data && se2->data)
00461     return (atoi(se1->data)<atoi(se2->data));
00462   else
00463     return 0;
00464 }
00465 
00466 static int GWEN_StringList__compar_desc_int(const void *a, const void *b) {
00467   const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
00468   const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
00469   if (se1 && se2 && se1->data && se2->data)
00470     return (atoi(se1->data)>atoi(se2->data));
00471   else
00472     return 0;
00473 }
00474 
00475 
00476 
00477 void GWEN_StringList_Sort(GWEN_STRINGLIST *l,
00478                           int ascending,
00479                           GWEN_STRINGLIST_SORT_MODE sortMode) {
00480   GWEN_STRINGLISTENTRY **tmpEntries;
00481   GWEN_STRINGLISTENTRY *sentry;
00482   GWEN_STRINGLISTENTRY **psentry;
00483 
00484   if (l->count<1)
00485     return;
00486 
00487   /* sort entries into a linear pointer list */
00488   tmpEntries=(GWEN_STRINGLISTENTRY **)malloc((l->count+1)*
00489                                             sizeof(GWEN_STRINGLISTENTRY*));
00490   assert(tmpEntries);
00491   sentry=l->first;
00492   psentry=tmpEntries;
00493   while(sentry) {
00494     GWEN_STRINGLISTENTRY *nsentry;
00495 
00496     *(psentry++)=sentry;
00497     nsentry=sentry->next;
00498     sentry->next=0;
00499     sentry=nsentry;
00500   } /* while */
00501   *psentry=0;
00502 
00503   /* sort */
00504   switch(sortMode) {
00505   case GWEN_StringList_SortModeNoCase:
00506     if (ascending)
00507       qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
00508             GWEN_StringList__compar_desc_nocase);
00509     else
00510       qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
00511             GWEN_StringList__compar_asc_nocase);
00512     break;
00513 
00514   case GWEN_StringList_SortModeCase:
00515     if (ascending)
00516       qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
00517             GWEN_StringList__compar_desc_case);
00518     else
00519       qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
00520             GWEN_StringList__compar_asc_case);
00521     break;
00522 
00523   case GWEN_StringList_SortModeInt:
00524     if (ascending)
00525       qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
00526             GWEN_StringList__compar_desc_int);
00527     else
00528       qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
00529             GWEN_StringList__compar_asc_int);
00530     break;
00531 
00532   default:
00533     DBG_ERROR(GWEN_LOGDOMAIN, "Unknown sortmode %d", sortMode);
00534   }
00535 
00536   /* sort entries back into GWEN_STRINGLIST */
00537   psentry=tmpEntries;
00538   sentry=0;
00539   while(*psentry) {
00540     (*psentry)->next=0;
00541     if (sentry)
00542       sentry->next=*psentry;
00543     else
00544       l->first=*psentry;
00545     sentry=*psentry;
00546     psentry++;
00547   } /* while */
00548 
00549   free(tmpEntries);
00550 
00551 }
00552 
00553 
00554 
00555 const char *GWEN_StringList_StringAt(const GWEN_STRINGLIST *sl, int idx) {
00556   GWEN_STRINGLISTENTRY *se;
00557 
00558   assert(sl);
00559   se=sl->first;
00560   while(se) {
00561     if (idx--==0)
00562       return se->data;
00563     se=se->next;
00564   } /* while */
00565   return 0;
00566 }
00567 
00568 
00569 
00570 

Generated on Wed Sep 3 15:21:59 2008 for gwenhywfar by  doxygen 1.5.6