gwenhywfar  4.99.8beta
stringlist.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Thu Apr 03 2003
3  copyright : (C) 2003 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU Lesser General Public *
10  * License as published by the Free Software Foundation; either *
11  * version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  * *
23  ***************************************************************************/
24 
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 #define DISABLE_DEBUGLOG
31 
32 
33 #include <gwenhywfar/gwenhywfarapi.h>
34 #include <gwenhywfar/misc.h>
35 #include "stringlist_p.h"
36 #include "debug.h"
37 #include <stdlib.h>
38 #include <assert.h>
39 #include <string.h>
40 #ifdef HAVE_STRINGS_H
41 # include <strings.h>
42 #endif
43 
44 
45 
47  GWEN_STRINGLIST *sl;
48 
50  assert(sl);
51  sl->ignoreRefCount=1;
52  return sl;
53 }
54 
55 
56 
58  GWEN_STRINGLISTENTRY *curr, *next;
59 
60  if (sl) {
61  curr=sl->first;
62  while(curr) {
63  next=curr->next;
65  curr=next;
66  } /* while */
67  GWEN_FREE_OBJECT(sl);
68  }
69 }
70 
71 
72 
74  assert(sl);
75  sl->senseCase=i;
76 }
77 
78 
79 
81  assert(sl);
82  sl->ignoreRefCount=i;
83 }
84 
85 
86 
89 
91  assert(sl);
92  sl->refCount=1;
93  if (s) {
94  if (take)
95  sl->data=s;
96  else
97  sl->data=strdup(s);
98  }
99  return sl;
100 }
101 
102 
103 
105  const char *s,
106  int take) {
107  assert(e);
108  if (e->data)
109  free((void*)(e->data));
110  if (take)
111  e->data=s;
112  else
113  e->data=strdup(s);
114 }
115 
116 
117 
119  if (sl) {
120  if (sl->data)
121  free((void*)(sl->data));
122  GWEN_FREE_OBJECT(sl);
123  }
124 }
125 
126 
127 
129  GWEN_STRINGLISTENTRY *se) {
130  GWEN_STRINGLISTENTRY *curr;
131 
132  assert(sl);
133  assert(se);
134 
135  curr=sl->first;
136  if (!curr) {
137  sl->first=se;
138  }
139  else {
140  while(curr->next) {
141  curr=curr->next;
142  }
143  curr->next=se;
144  }
145  sl->count++;
146 }
147 
148 
149 
150 GWEN_STRINGLIST *GWEN_StringList_fromTabString(const char *s, int checkDup) {
151  GWEN_STRINGLIST *sl;
152 
153  sl=GWEN_StringList_new();
154  if (s && *s) {
155  while(*s) {
156  const char *t;
157  char *tmpStr;
158 
159  t=strchr(s, '\t');
160  if (t) {
161  int len;
162 
163  len=(t-s);
164  tmpStr=(char*) malloc(len+1);
165  assert(tmpStr);
166  memmove(tmpStr, s, len);
167  tmpStr[len]=0;
168  /* add partial string, take it over */
169  GWEN_StringList_AppendString(sl, tmpStr, 1, checkDup);
170  s=t+1;
171  }
172  else {
173  /* just add the remaining string (don't take over, copy!) */
174  GWEN_StringList_AppendString(sl, s, 0, checkDup);
175  break;
176  }
177  }
178  }
179 
180  return sl;
181 }
182 
183 
184 
186  GWEN_STRINGLISTENTRY *se) {
187  GWEN_STRINGLISTENTRY *curr;
188 
189  assert(sl);
190  assert(se);
191 
192  curr=sl->first;
193  if (curr) {
194  if (curr==se) {
195  sl->first=curr->next;
196  if (sl->count)
197  sl->count--;
198  }
199  else {
200  while(curr->next!=se) {
201  curr=curr->next;
202  }
203  if (curr) {
204  curr->next=se->next;
205  if (sl->count)
206  sl->count--;
207  }
208  }
209  }
210 }
211 
212 
213 
215  GWEN_STRINGLISTENTRY *se, *next;
216 
217  assert(sl);
218  se=sl->first;
219  sl->first=0;
220  sl->count=0;
221  while (se) {
222  next=se->next;
224  se=next;
225  } /* while */
226 }
227 
228 
229 
231  const char *s,
232  int take,
233  int checkDouble) {
235 
236  if (checkDouble) {
237  se=sl->first;
238  if (sl->senseCase) {
239  while(se) {
240  if (strcmp(se->data, s)==0) {
241  if (take)
242  free((char*)s);
243  se->refCount++;
244  return 0;
245  }
246  se=se->next;
247  } /* while */
248  }
249  else {
250  while(se) {
251  if (strcasecmp(se->data, s)==0) {
252  if (take)
253  free((char*)s);
254  se->refCount++;
255  return 0;
256  }
257  se=se->next;
258  } /* while */
259  }
260  } /* if checkdouble */
261 
262  se=GWEN_StringListEntry_new(s, take);
264  return 1;
265 }
266 
267 
268 
270  const char *s,
271  int take,
272  int checkDouble) {
274 
275  if (checkDouble) {
276  se=sl->first;
277  if (sl->senseCase) {
278  while(se) {
279  if (strcmp(se->data, s)==0) {
280  if (take)
281  free((char*)s);
282  se->refCount++;
283  return 0;
284  }
285  se=se->next;
286  } /* while */
287  }
288  else {
289  while(se) {
290  if (strcasecmp(se->data, s)==0) {
291  if (take)
292  free((char*)s);
293  se->refCount++;
294  return 0;
295  }
296  se=se->next;
297  } /* while */
298  }
299  } /* if checkdouble */
300  se=GWEN_StringListEntry_new(s, take);
301  se->next=sl->first;
302  sl->first=se;
303  sl->count++;
304  return 1;
305 }
306 
307 
308 
310  const char *s) {
312 
313  se=sl->first;
314  if (sl->senseCase) {
315  while(se) {
316  if (strcmp(se->data, s)==0) {
317  assert(se->refCount);
318  se->refCount--;
319  if (sl->ignoreRefCount)
321  else {
322  if (se->refCount==0)
324  }
325  return 1;
326  }
327  se=se->next;
328  } /* while */
329  return 0;
330  }
331  else {
332  while(se) {
333  if (strcasecmp(se->data, s)==0) {
334  assert(se->refCount);
335  se->refCount--;
336  if (sl->ignoreRefCount)
338  else {
339  if (se->refCount==0)
341  }
342  return 1;
343  }
344  se=se->next;
345  } /* while */
346  return 0;
347  }
348 }
349 
350 
351 
353  assert(sl);
354  return sl->first;
355 }
356 
357 
358 
360  assert(se);
361  return se->next;
362 }
363 
364 
365 
367  assert(se);
368  return se->data;
369 }
370 
371 
372 
374  assert(se);
375  if (se->data) free((void*)(se->data));
376  if (s) se->data=strdup(s);
377  else se->data=NULL;
378 }
379 
380 
381 
382 unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl) {
383  assert(sl);
384  return sl->count;
385 }
386 
387 
388 
390  const char *s) {
392 
393  assert(sl);
394  se=sl->first;
395  if (sl->senseCase) {
396  while(se) {
397  if (strcmp(se->data, s)==0) {
398  return 1;
399  }
400  se=se->next;
401  } /* while */
402  return 0;
403  }
404  else {
405  while(se) {
406  if (strcasecmp(se->data, s)==0) {
407  return 1;
408  }
409  se=se->next;
410  } /* while */
411  return 0;
412  }
413 }
414 
415 
416 
417 int GWEN_StringList_GetStringPos(const GWEN_STRINGLIST *sl, const char *s) {
419  int i;
420 
421  assert(sl);
422  se=sl->first;
423  if (sl->senseCase) {
424  i=0;
425  while(se) {
426  if (strcmp(se->data, s)==0) {
427  return i;
428  }
429  i++;
430  se=se->next;
431  } /* while */
432  return -1;
433  }
434  else {
435  i=0;
436  while(se) {
437  if (strcasecmp(se->data, s)==0) {
438  return i;
439  }
440  i++;
441  se=se->next;
442  } /* while */
443  return -1;
444  }
445 }
446 
447 
448 
451  int i;
452 
453  assert(sl);
454  se=sl->first;
455  if (sl->senseCase) {
456  i=0;
457  while(se) {
458  if (strcmp(se->data, s)==0) {
459  return se;
460  }
461  i++;
462  se=se->next;
463  } /* while */
464  return NULL;
465  }
466  else {
467  i=0;
468  while(se) {
469  if (strcasecmp(se->data, s)==0) {
470  return se;
471  }
472  i++;
473  se=se->next;
474  } /* while */
475  return NULL;
476  }
477 }
478 
479 
480 
483  GWEN_STRINGLIST *newsl;
484 
485  assert(sl);
486  newsl=GWEN_StringList_new();
487 
488  se=sl->first;
489  while(se) {
490  GWEN_STRINGLISTENTRY *newse;
491 
492  newse=GWEN_StringListEntry_new(se->data, 0);
493  GWEN_StringList_AppendEntry(newsl, newse);
494  se=se->next;
495  } /* while */
496 
497  return newsl;
498 }
499 
500 
502  void *(*func)(const char *s, void *u),
503  void *user_data) {
505  const char *el;
506  void *result = 0;
507  assert(l);
508 
510  if (!it)
511  return 0;
512  while(it) {
513  el = GWEN_StringListEntry_Data(it);
514  result = func(el, user_data);
515  if (result) {
516  return result;
517  }
518  it = GWEN_StringListEntry_Next(it);
519  }
520  return 0;
521 }
522 
523 
524 
526  assert(l);
527  if (l->first==0)
528  return 0;
529  return l->first->data;
530 }
531 
532 
533 
534 static int GWEN_StringList__compar_asc_nocase(const void *a, const void *b) {
535  const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
536  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
537  if (se1 && se2 && se1->data && se2->data)
538  return strcmp(se1->data, se2->data);
539  else
540  return 0;
541 }
542 static int GWEN_StringList__compar_desc_nocase(const void *a, const void *b) {
543  const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
544  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
545  if (se1 && se2 && se1->data && se2->data)
546  return strcmp(se2->data, se1->data);
547  else
548  return 0;
549 }
550 static int GWEN_StringList__compar_asc_case(const void *a, const void *b) {
551  const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
552  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
553  if (se1 && se2 && se1->data && se2->data)
554  return strcasecmp(se1->data, se2->data);
555  else
556  return 0;
557 }
558 static int GWEN_StringList__compar_desc_case(const void *a, const void *b) {
559  const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
560  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
561  if (se1 && se2 && se1->data && se2->data)
562  return strcasecmp(se2->data, se1->data);
563  else
564  return 0;
565 }
566 
567 static int GWEN_StringList__compar_asc_int(const void *a, const void *b) {
568  const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
569  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
570  if (se1 && se2 && se1->data && se2->data) {
571  int i1, i2;
572 
573  i1=atoi(se1->data);
574  i2=atoi(se2->data);
575  return (i1>i2) - (i1<i2);
576  }
577  else
578  return 0;
579 }
580 
581 static int GWEN_StringList__compar_desc_int(const void *a, const void *b) {
582  const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
583  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
584  if (se1 && se2 && se1->data && se2->data) {
585  int i1, i2;
586 
587  i1=atoi(se1->data);
588  i2=atoi(se2->data);
589  return (i2>i1) - (i2<i1);
590  }
591  else
592  return 0;
593 }
594 
595 
596 
598  int ascending,
599  GWEN_STRINGLIST_SORT_MODE sortMode) {
600  GWEN_STRINGLISTENTRY **tmpEntries;
601  GWEN_STRINGLISTENTRY *sentry;
602  GWEN_STRINGLISTENTRY **psentry;
603 
604  if (l->count<2)
605  return;
606 
607  /* sort entries into a linear pointer list */
608  tmpEntries=(GWEN_STRINGLISTENTRY **)malloc((l->count+1)*
609  sizeof(GWEN_STRINGLISTENTRY*));
610  assert(tmpEntries);
611  sentry=l->first;
612  psentry=tmpEntries;
613  while(sentry) {
614  *(psentry++)=sentry;
615  sentry=sentry->next;
616  } /* while */
617  *psentry=0;
618 
619  /* sort */
620  switch(sortMode) {
622  if (ascending)
623  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
625  else
626  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
628  break;
629 
631  if (ascending)
632  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
634  else
635  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
637  break;
638 
640  if (ascending)
641  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
643  else
644  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
646  break;
647 
648  default:
649  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown sortmode %d", sortMode);
650  }
651 
652  /* sort entries back into GWEN_STRINGLIST */
653  psentry=tmpEntries;
654  sentry=0;
655  while(*psentry) {
656  if (sentry)
657  sentry->next=*psentry;
658  else
659  l->first=*psentry;
660  sentry=*psentry;
661  psentry++;
662  } /* while */
663  sentry->next=NULL;
664 
665  free(tmpEntries);
666 
667 }
668 
669 
670 
671 const char *GWEN_StringList_StringAt(const GWEN_STRINGLIST *sl, int idx) {
673 
674  assert(sl);
675  se=sl->first;
676  while(se) {
677  if (idx--==0)
678  return se->data;
679  se=se->next;
680  } /* while */
681  return 0;
682 }
683 
684 
685 
686 GWEN_STRINGLIST *GWEN_StringList_fromString(const char *str, const char *delimiters, int checkDouble) {
687  if (str && *str) {
688  GWEN_STRINGLIST *sl;
689  const unsigned char *s;
690 
691  sl=GWEN_StringList_new();
692  s=(const unsigned char*)str;
693 
694  while(*s) {
695  /* skip blanks */
696  while(*s && *s<33)
697  s++;
698 
699  if (*s) {
700  const unsigned char *pStart;
701  int len;
702 
703  /* read word */
704  pStart=s;
705  //s++;
706  while(*s && strchr(delimiters, *s)==NULL)
707  s++;
708  len=s-pStart;
709 
710  if (len) {
711  char *toAdd;
712 
713  toAdd=(char*) malloc(len+1);
714  assert(toAdd);
715 
716  memmove(toAdd, pStart, len);
717  toAdd[len]=0;
718 
719  GWEN_StringList_AppendString(sl, toAdd, 1, checkDouble);
720  }
721  }
722 
723  if (*s==0)
724  break;
725  s++;
726  }
727 
728  if (GWEN_StringList_Count(sl)==0) {
730  return NULL;
731  }
732  return sl;
733  }
734  else
735  return NULL;
736 }
737 
738 
739 
void * GWEN_StringList_ForEach(const GWEN_STRINGLIST *l, void *(*func)(const char *s, void *u), void *user_data)
Definition: stringlist.c:501
GWEN_STRINGLIST * GWEN_StringList_fromTabString(const char *s, int checkDup)
Definition: stringlist.c:150
struct GWEN_STRINGLISTENTRYSTRUCT GWEN_STRINGLISTENTRY
Definition: stringlist.h:51
void GWEN_StringListEntry_ReplaceString(GWEN_STRINGLISTENTRY *e, const char *s, int take)
Definition: stringlist.c:104
int GWEN_StringList_GetStringPos(const GWEN_STRINGLIST *sl, const char *s)
Definition: stringlist.c:417
void GWEN_StringList_Clear(GWEN_STRINGLIST *sl)
Definition: stringlist.c:214
GWEN_STRINGLISTENTRY * GWEN_StringList_FindStringEntry(const GWEN_STRINGLIST *sl, const char *s)
Definition: stringlist.c:449
void GWEN_StringList_Sort(GWEN_STRINGLIST *l, int ascending, GWEN_STRINGLIST_SORT_MODE sortMode)
Definition: stringlist.c:597
static int GWEN_StringList__compar_asc_int(const void *a, const void *b)
Definition: stringlist.c:567
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:92
#define NULL
Definition: binreloc.c:290
GWEN_STRINGLIST_SORT_MODE
Definition: stringlist.h:39
int GWEN_StringList_InsertString(GWEN_STRINGLIST *sl, const char *s, int take, int checkDouble)
Definition: stringlist.c:269
static int GWEN_StringList__compar_asc_nocase(const void *a, const void *b)
Definition: stringlist.c:534
void GWEN_StringList_SetSenseCase(GWEN_STRINGLIST *sl, int i)
Definition: stringlist.c:73
#define GWEN_LOGDOMAIN
Definition: logger.h:35
void GWEN_StringList_RemoveEntry(GWEN_STRINGLIST *sl, GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:185
const char * GWEN_StringList_StringAt(const GWEN_STRINGLIST *sl, int idx)
Definition: stringlist.c:671
GWEN_STRINGLISTENTRY * GWEN_StringList_FirstEntry(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:352
const char * GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:366
GWENHYWFAR_API int GWEN_StringList_RemoveString(GWEN_STRINGLIST *sl, const char *s)
Definition: stringlist.c:309
void GWEN_StringList_free(GWEN_STRINGLIST *sl)
Definition: stringlist.c:57
static int GWEN_StringList__compar_asc_case(const void *a, const void *b)
Definition: stringlist.c:550
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:86
int GWEN_StringList_AppendString(GWEN_STRINGLIST *sl, const char *s, int take, int checkDouble)
Definition: stringlist.c:230
void GWEN_StringListEntry_free(GWEN_STRINGLISTENTRY *sl)
Definition: stringlist.c:118
static int GWEN_StringList__compar_desc_nocase(const void *a, const void *b)
Definition: stringlist.c:542
struct GWEN_STRINGLISTSTRUCT GWEN_STRINGLIST
Definition: stringlist.h:54
GWEN_STRINGLIST * GWEN_StringList_fromString(const char *str, const char *delimiters, int checkDouble)
Definition: stringlist.c:686
GWEN_STRINGLISTENTRY * GWEN_StringListEntry_new(const char *s, int take)
Definition: stringlist.c:87
GWEN_STRINGLIST * GWEN_StringList_dup(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:481
#define GWENHYWFAR_API
Definition: gwenhywfarapi.h:67
unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:382
static int GWEN_StringList__compar_desc_case(const void *a, const void *b)
Definition: stringlist.c:558
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
const char * GWEN_StringList_FirstString(const GWEN_STRINGLIST *l)
Definition: stringlist.c:525
int GWEN_StringList_HasString(const GWEN_STRINGLIST *sl, const char *s)
Definition: stringlist.c:389
GWEN_STRINGLISTENTRY * GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:359
void GWEN_StringList_AppendEntry(GWEN_STRINGLIST *sl, GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:128
void GWEN_StringListEntry_SetData(GWEN_STRINGLISTENTRY *se, const char *s)
Definition: stringlist.c:373
static int GWEN_StringList__compar_desc_int(const void *a, const void *b)
Definition: stringlist.c:581
GWEN_STRINGLIST * GWEN_StringList_new(void)
Definition: stringlist.c:46
void GWEN_StringList_SetIgnoreRefCount(GWEN_STRINGLIST *sl, int i)
Definition: stringlist.c:80