gwenhywfar
4.3.1
|
00001 /*************************************************************************** 00002 begin : Thu Apr 03 2003 00003 copyright : (C) 2003 by Martin Preuss 00004 email : martin@libchipcard.de 00005 00006 *************************************************************************** 00007 * * 00008 * This library is free software; you can redistribute it and/or * 00009 * modify it under the terms of the GNU Lesser General Public * 00010 * License as published by the Free Software Foundation; either * 00011 * version 2.1 of the License, or (at your option) any later version. * 00012 * * 00013 * This library is distributed in the hope that it will be useful, * 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00016 * Lesser General Public License for more details. * 00017 * * 00018 * You should have received a copy of the GNU Lesser General Public * 00019 * License along with this library; if not, write to the Free Software * 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * 00021 * MA 02111-1307 USA * 00022 * * 00023 ***************************************************************************/ 00024 00025 00026 #ifdef HAVE_CONFIG_H 00027 # include <config.h> 00028 #endif 00029 00030 #define DISABLE_DEBUGLOG 00031 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(void){ 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 GWEN_STRINGLIST *GWEN_StringList_fromTabString(const char *s, int checkDup) { 00151 GWEN_STRINGLIST *sl; 00152 00153 sl=GWEN_StringList_new(); 00154 if (s && *s) { 00155 while(*s) { 00156 const char *t; 00157 char *tmpStr; 00158 00159 t=strchr(s, '\t'); 00160 if (t) { 00161 int len; 00162 00163 len=(t-s); 00164 tmpStr=(char*) malloc(len+1); 00165 assert(tmpStr); 00166 memmove(tmpStr, s, len); 00167 tmpStr[len]=0; 00168 /* add partial string, take it over */ 00169 GWEN_StringList_AppendString(sl, tmpStr, 1, checkDup); 00170 s=t+1; 00171 } 00172 else { 00173 /* just add the remaining string (don't take over, copy!) */ 00174 GWEN_StringList_AppendString(sl, s, 0, checkDup); 00175 break; 00176 } 00177 } 00178 } 00179 00180 return sl; 00181 } 00182 00183 00184 00185 void GWEN_StringList_RemoveEntry(GWEN_STRINGLIST *sl, 00186 GWEN_STRINGLISTENTRY *se){ 00187 GWEN_STRINGLISTENTRY *curr; 00188 00189 assert(sl); 00190 assert(se); 00191 00192 curr=sl->first; 00193 if (curr) { 00194 if (curr==se) { 00195 sl->first=curr->next; 00196 if (sl->count) 00197 sl->count--; 00198 } 00199 else { 00200 while(curr->next!=se) { 00201 curr=curr->next; 00202 } 00203 if (curr) { 00204 curr->next=se->next; 00205 if (sl->count) 00206 sl->count--; 00207 } 00208 } 00209 } 00210 } 00211 00212 00213 00214 void GWEN_StringList_Clear(GWEN_STRINGLIST *sl){ 00215 GWEN_STRINGLISTENTRY *se, *next; 00216 00217 assert(sl); 00218 se=sl->first; 00219 sl->first=0; 00220 while (se) { 00221 next=se->next; 00222 GWEN_StringListEntry_free(se); 00223 se=next; 00224 } /* while */ 00225 } 00226 00227 00228 00229 int GWEN_StringList_AppendString(GWEN_STRINGLIST *sl, 00230 const char *s, 00231 int take, 00232 int checkDouble){ 00233 GWEN_STRINGLISTENTRY *se; 00234 00235 if (checkDouble) { 00236 se=sl->first; 00237 if (sl->senseCase) { 00238 while(se) { 00239 if (strcmp(se->data, s)==0) { 00240 if (take) 00241 free((char*)s); 00242 se->refCount++; 00243 return 0; 00244 } 00245 se=se->next; 00246 } /* while */ 00247 } 00248 else { 00249 while(se) { 00250 if (strcasecmp(se->data, s)==0) { 00251 if (take) 00252 free((char*)s); 00253 se->refCount++; 00254 return 0; 00255 } 00256 se=se->next; 00257 } /* while */ 00258 } 00259 } /* if checkdouble */ 00260 00261 se=GWEN_StringListEntry_new(s, take); 00262 GWEN_StringList_AppendEntry(sl, se); 00263 return 1; 00264 } 00265 00266 00267 00268 int GWEN_StringList_InsertString(GWEN_STRINGLIST *sl, 00269 const char *s, 00270 int take, 00271 int checkDouble){ 00272 GWEN_STRINGLISTENTRY *se; 00273 00274 if (checkDouble) { 00275 se=sl->first; 00276 if (sl->senseCase) { 00277 while(se) { 00278 if (strcmp(se->data, s)==0) { 00279 if (take) 00280 free((char*)s); 00281 se->refCount++; 00282 return 0; 00283 } 00284 se=se->next; 00285 } /* while */ 00286 } 00287 else { 00288 while(se) { 00289 if (strcasecmp(se->data, s)==0) { 00290 if (take) 00291 free((char*)s); 00292 se->refCount++; 00293 return 0; 00294 } 00295 se=se->next; 00296 } /* while */ 00297 } 00298 } /* if checkdouble */ 00299 se=GWEN_StringListEntry_new(s, take); 00300 se->next=sl->first; 00301 sl->first=se; 00302 return 1; 00303 } 00304 00305 00306 00307 GWENHYWFAR_API int GWEN_StringList_RemoveString(GWEN_STRINGLIST *sl, 00308 const char *s){ 00309 GWEN_STRINGLISTENTRY *se; 00310 00311 se=sl->first; 00312 if (sl->senseCase) { 00313 while(se) { 00314 if (strcmp(se->data, s)==0) { 00315 assert(se->refCount); 00316 se->refCount--; 00317 if (sl->ignoreRefCount) 00318 GWEN_StringList_RemoveEntry(sl, se); 00319 else { 00320 if (se->refCount==0) 00321 GWEN_StringList_RemoveEntry(sl, se); 00322 } 00323 return 1; 00324 } 00325 se=se->next; 00326 } /* while */ 00327 return 0; 00328 } 00329 else { 00330 while(se) { 00331 if (strcasecmp(se->data, s)==0) { 00332 assert(se->refCount); 00333 se->refCount--; 00334 if (sl->ignoreRefCount) 00335 GWEN_StringList_RemoveEntry(sl, se); 00336 else { 00337 assert(se->refCount); 00338 if (se->refCount==0) 00339 GWEN_StringList_RemoveEntry(sl, se); 00340 } 00341 return 1; 00342 } 00343 se=se->next; 00344 } /* while */ 00345 return 0; 00346 } 00347 } 00348 00349 00350 00351 GWEN_STRINGLISTENTRY *GWEN_StringList_FirstEntry(const GWEN_STRINGLIST *sl){ 00352 assert(sl); 00353 return sl->first; 00354 } 00355 00356 00357 00358 GWEN_STRINGLISTENTRY *GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se){ 00359 assert(se); 00360 return se->next; 00361 } 00362 00363 00364 00365 const char *GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se){ 00366 assert(se); 00367 return se->data; 00368 } 00369 00370 00371 unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl){ 00372 assert(sl); 00373 return sl->count; 00374 } 00375 00376 00377 00378 int GWEN_StringList_HasString(const GWEN_STRINGLIST *sl, 00379 const char *s){ 00380 GWEN_STRINGLISTENTRY *se; 00381 00382 assert(sl); 00383 se=sl->first; 00384 if (sl->senseCase) { 00385 while(se) { 00386 if (strcmp(se->data, s)==0) { 00387 return 1; 00388 } 00389 se=se->next; 00390 } /* while */ 00391 return 0; 00392 } 00393 else { 00394 while(se) { 00395 if (strcasecmp(se->data, s)==0) { 00396 return 1; 00397 } 00398 se=se->next; 00399 } /* while */ 00400 return 0; 00401 } 00402 } 00403 00404 00405 00406 int GWEN_StringList_GetStringPos(const GWEN_STRINGLIST *sl, const char *s){ 00407 GWEN_STRINGLISTENTRY *se; 00408 int i; 00409 00410 assert(sl); 00411 se=sl->first; 00412 if (sl->senseCase) { 00413 i=0; 00414 while(se) { 00415 if (strcmp(se->data, s)==0) { 00416 return i; 00417 } 00418 i++; 00419 se=se->next; 00420 } /* while */ 00421 return -1; 00422 } 00423 else { 00424 i=0; 00425 while(se) { 00426 if (strcasecmp(se->data, s)==0) { 00427 return i; 00428 } 00429 i++; 00430 se=se->next; 00431 } /* while */ 00432 return -1; 00433 } 00434 } 00435 00436 00437 00438 GWEN_STRINGLIST *GWEN_StringList_dup(const GWEN_STRINGLIST *sl){ 00439 GWEN_STRINGLISTENTRY *se; 00440 GWEN_STRINGLIST *newsl; 00441 00442 assert(sl); 00443 newsl=GWEN_StringList_new(); 00444 00445 se=sl->first; 00446 while(se) { 00447 GWEN_STRINGLISTENTRY *newse; 00448 00449 newse=GWEN_StringListEntry_new(se->data, 0); 00450 GWEN_StringList_AppendEntry(newsl, newse); 00451 se=se->next; 00452 } /* while */ 00453 00454 return newsl; 00455 } 00456 00457 00458 void *GWEN_StringList_ForEach(const GWEN_STRINGLIST *l, 00459 void *(*func)(const char *s, void *u), 00460 void *user_data) { 00461 GWEN_STRINGLISTENTRY *it; 00462 const char *el; 00463 void *result = 0; 00464 assert(l); 00465 00466 it = GWEN_StringList_FirstEntry(l); 00467 if (!it) 00468 return 0; 00469 while(it) { 00470 el = GWEN_StringListEntry_Data(it); 00471 result = func(el, user_data); 00472 if (result) { 00473 return result; 00474 } 00475 it = GWEN_StringListEntry_Next(it); 00476 } 00477 return 0; 00478 } 00479 00480 00481 00482 const char *GWEN_StringList_FirstString(const GWEN_STRINGLIST *l){ 00483 assert(l); 00484 if (l->first==0) 00485 return 0; 00486 return l->first->data; 00487 } 00488 00489 00490 00491 static int GWEN_StringList__compar_asc_nocase(const void *a, const void *b) { 00492 const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b; 00493 const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2; 00494 if (se1 && se2 && se1->data && se2->data) 00495 return strcmp(se1->data, se2->data); 00496 else 00497 return 0; 00498 } 00499 static int GWEN_StringList__compar_desc_nocase(const void *a, const void *b) { 00500 const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b; 00501 const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2; 00502 if (se1 && se2 && se1->data && se2->data) 00503 return strcmp(se2->data, se1->data); 00504 else 00505 return 0; 00506 } 00507 static int GWEN_StringList__compar_asc_case(const void *a, const void *b) { 00508 const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b; 00509 const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2; 00510 if (se1 && se2 && se1->data && se2->data) 00511 return strcasecmp(se1->data, se2->data); 00512 else 00513 return 0; 00514 } 00515 static int GWEN_StringList__compar_desc_case(const void *a, const void *b) { 00516 const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b; 00517 const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2; 00518 if (se1 && se2 && se1->data && se2->data) 00519 return strcasecmp(se2->data, se1->data); 00520 else 00521 return 0; 00522 } 00523 00524 static int GWEN_StringList__compar_asc_int(const void *a, const void *b) { 00525 const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b; 00526 const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2; 00527 if (se1 && se2 && se1->data && se2->data) 00528 return (atoi(se1->data)<atoi(se2->data)); 00529 else 00530 return 0; 00531 } 00532 00533 static int GWEN_StringList__compar_desc_int(const void *a, const void *b) { 00534 const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b; 00535 const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2; 00536 if (se1 && se2 && se1->data && se2->data) 00537 return (atoi(se1->data)>atoi(se2->data)); 00538 else 00539 return 0; 00540 } 00541 00542 00543 00544 void GWEN_StringList_Sort(GWEN_STRINGLIST *l, 00545 int ascending, 00546 GWEN_STRINGLIST_SORT_MODE sortMode) { 00547 GWEN_STRINGLISTENTRY **tmpEntries; 00548 GWEN_STRINGLISTENTRY *sentry; 00549 GWEN_STRINGLISTENTRY **psentry; 00550 00551 if (l->count<1) 00552 return; 00553 00554 /* sort entries into a linear pointer list */ 00555 tmpEntries=(GWEN_STRINGLISTENTRY **)malloc((l->count+1)* 00556 sizeof(GWEN_STRINGLISTENTRY*)); 00557 assert(tmpEntries); 00558 sentry=l->first; 00559 psentry=tmpEntries; 00560 while(sentry) { 00561 GWEN_STRINGLISTENTRY *nsentry; 00562 00563 *(psentry++)=sentry; 00564 nsentry=sentry->next; 00565 sentry->next=0; 00566 sentry=nsentry; 00567 } /* while */ 00568 *psentry=0; 00569 00570 /* sort */ 00571 switch(sortMode) { 00572 case GWEN_StringList_SortModeNoCase: 00573 if (ascending) 00574 qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*), 00575 GWEN_StringList__compar_desc_nocase); 00576 else 00577 qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*), 00578 GWEN_StringList__compar_asc_nocase); 00579 break; 00580 00581 case GWEN_StringList_SortModeCase: 00582 if (ascending) 00583 qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*), 00584 GWEN_StringList__compar_desc_case); 00585 else 00586 qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*), 00587 GWEN_StringList__compar_asc_case); 00588 break; 00589 00590 case GWEN_StringList_SortModeInt: 00591 if (ascending) 00592 qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*), 00593 GWEN_StringList__compar_desc_int); 00594 else 00595 qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*), 00596 GWEN_StringList__compar_asc_int); 00597 break; 00598 00599 default: 00600 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown sortmode %d", sortMode); 00601 } 00602 00603 /* sort entries back into GWEN_STRINGLIST */ 00604 psentry=tmpEntries; 00605 sentry=0; 00606 while(*psentry) { 00607 (*psentry)->next=0; 00608 if (sentry) 00609 sentry->next=*psentry; 00610 else 00611 l->first=*psentry; 00612 sentry=*psentry; 00613 psentry++; 00614 } /* while */ 00615 00616 free(tmpEntries); 00617 00618 } 00619 00620 00621 00622 const char *GWEN_StringList_StringAt(const GWEN_STRINGLIST *sl, int idx) { 00623 GWEN_STRINGLISTENTRY *se; 00624 00625 assert(sl); 00626 se=sl->first; 00627 while(se) { 00628 if (idx--==0) 00629 return se->data; 00630 se=se->next; 00631 } /* while */ 00632 return 0; 00633 } 00634 00635 00636 00637 GWEN_STRINGLIST *GWEN_StringList_fromString(const char *str, const char *delimiters, int checkDouble) { 00638 if (str && *str) { 00639 GWEN_STRINGLIST *sl; 00640 const unsigned char *s; 00641 00642 sl=GWEN_StringList_new(); 00643 s=(const unsigned char*)str; 00644 00645 while(*s) { 00646 /* skip blanks */ 00647 while(*s && *s<33) 00648 s++; 00649 00650 if (*s) { 00651 const unsigned char *pStart; 00652 int len; 00653 00654 /* read word */ 00655 pStart=s; 00656 //s++; 00657 while(*s && strchr(delimiters, *s)==NULL) 00658 s++; 00659 len=s-pStart; 00660 00661 if (len) { 00662 char *toAdd; 00663 00664 toAdd=(char*) malloc(len+1); 00665 assert(toAdd); 00666 00667 memmove(toAdd, pStart, len); 00668 toAdd[len]=0; 00669 00670 GWEN_StringList_AppendString(sl, toAdd, 1, checkDouble); 00671 } 00672 } 00673 00674 if (*s==0) 00675 break; 00676 s++; 00677 } 00678 00679 if (GWEN_StringList_Count(sl)==0) { 00680 GWEN_StringList_free(sl); 00681 return NULL; 00682 } 00683 return sl; 00684 } 00685 else 00686 return NULL; 00687 } 00688 00689 00690