gwenhywfar  5.4.1
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 {
48  GWEN_STRINGLIST *sl;
49 
51  assert(sl);
52  sl->ignoreRefCount=1;
53  return sl;
54 }
55 
56 
57 
59 {
60  GWEN_STRINGLISTENTRY *curr, *next;
61 
62  if (sl) {
63  curr=sl->first;
64  while (curr) {
65  next=curr->next;
67  curr=next;
68  } /* while */
69  GWEN_FREE_OBJECT(sl);
70  }
71 }
72 
73 
74 
76 {
77  assert(sl);
78  sl->senseCase=i;
79 }
80 
81 
82 
84 {
85  assert(sl);
86  sl->ignoreRefCount=i;
87 }
88 
89 
90 
92 {
94 
96  assert(sl);
97  sl->refCount=1;
98  if (s) {
99  if (take)
100  sl->data=s;
101  else
102  sl->data=strdup(s);
103  }
104  return sl;
105 }
106 
107 
108 
110  const char *s,
111  int take)
112 {
113  assert(e);
114  if (e->data)
115  free((void *)(e->data));
116  if (take)
117  e->data=s;
118  else
119  e->data=strdup(s);
120 }
121 
122 
123 
125 {
126  if (sl) {
127  if (sl->data)
128  free((void *)(sl->data));
129  GWEN_FREE_OBJECT(sl);
130  }
131 }
132 
133 
134 
137 {
138  GWEN_STRINGLISTENTRY *curr;
139 
140  assert(sl);
141  assert(se);
142 
143  curr=sl->first;
144  if (!curr) {
145  sl->first=se;
146  }
147  else {
148  while (curr->next) {
149  curr=curr->next;
150  }
151  curr->next=se;
152  }
153  sl->count++;
154 }
155 
156 
157 
158 GWEN_STRINGLIST *GWEN_StringList_fromTabString(const char *s, int checkDup)
159 {
160  GWEN_STRINGLIST *sl;
161 
162  sl=GWEN_StringList_new();
163  if (s && *s) {
164  while (*s) {
165  const char *t;
166  char *tmpStr;
167 
168  t=strchr(s, '\t');
169  if (t) {
170  int len;
171 
172  len=(t-s);
173  tmpStr=(char *) malloc(len+1);
174  assert(tmpStr);
175  memmove(tmpStr, s, len);
176  tmpStr[len]=0;
177  /* add partial string, take it over */
178  GWEN_StringList_AppendString(sl, tmpStr, 1, checkDup);
179  s=t+1;
180  }
181  else {
182  /* just add the remaining string (don't take over, copy!) */
183  GWEN_StringList_AppendString(sl, s, 0, checkDup);
184  break;
185  }
186  }
187  }
188 
189  return sl;
190 }
191 
192 
193 
196 {
197  GWEN_STRINGLISTENTRY *curr;
198 
199  assert(sl);
200  assert(se);
201 
202  curr=sl->first;
203  if (curr) {
204  if (curr==se) {
205  sl->first=curr->next;
206  if (sl->count)
207  sl->count--;
208  }
209  else {
210  while (curr->next!=se) {
211  curr=curr->next;
212  }
213  if (curr) {
214  curr->next=se->next;
215  if (sl->count)
216  sl->count--;
217  }
218  }
219  }
220 }
221 
222 
223 
225 {
226  GWEN_STRINGLISTENTRY *se, *next;
227 
228  assert(sl);
229  se=sl->first;
230  sl->first=0;
231  sl->count=0;
232  while (se) {
233  next=se->next;
235  se=next;
236  } /* while */
237 }
238 
239 
240 
242  const char *s,
243  int take,
244  int checkDouble)
245 {
247 
248  if (checkDouble) {
249  se=sl->first;
250  if (sl->senseCase) {
251  while (se) {
252  if (strcmp(se->data, s)==0) {
253  if (take)
254  free((char *)s);
255  se->refCount++;
256  return 0;
257  }
258  se=se->next;
259  } /* while */
260  }
261  else {
262  while (se) {
263  if (strcasecmp(se->data, s)==0) {
264  if (take)
265  free((char *)s);
266  se->refCount++;
267  return 0;
268  }
269  se=se->next;
270  } /* while */
271  }
272  } /* if checkdouble */
273 
274  se=GWEN_StringListEntry_new(s, take);
276  return 1;
277 }
278 
279 
280 
282  const char *s,
283  int take,
284  int checkDouble)
285 {
287 
288  if (checkDouble) {
289  se=sl->first;
290  if (sl->senseCase) {
291  while (se) {
292  if (strcmp(se->data, s)==0) {
293  if (take)
294  free((char *)s);
295  se->refCount++;
296  return 0;
297  }
298  se=se->next;
299  } /* while */
300  }
301  else {
302  while (se) {
303  if (strcasecmp(se->data, s)==0) {
304  if (take)
305  free((char *)s);
306  se->refCount++;
307  return 0;
308  }
309  se=se->next;
310  } /* while */
311  }
312  } /* if checkdouble */
313  se=GWEN_StringListEntry_new(s, take);
314  se->next=sl->first;
315  sl->first=se;
316  sl->count++;
317  return 1;
318 }
319 
320 
321 
323 {
325 
326  se=sl->first;
327  if (sl->senseCase) {
328  while (se) {
329  if (strcmp(se->data, s)==0) {
330  assert(se->refCount);
331  se->refCount--;
332  if (sl->ignoreRefCount)
334  else {
335  if (se->refCount==0)
337  }
338  return 1;
339  }
340  se=se->next;
341  } /* while */
342  return 0;
343  }
344  else {
345  while (se) {
346  if (strcasecmp(se->data, s)==0) {
347  assert(se->refCount);
348  se->refCount--;
349  if (sl->ignoreRefCount)
351  else {
352  if (se->refCount==0)
354  }
355  return 1;
356  }
357  se=se->next;
358  } /* while */
359  return 0;
360  }
361 }
362 
363 
364 
366 {
368 
369  assert(sl);
370  se=sl->first;
371  if (se) {
372  assert(se->refCount);
373 
374  se->refCount--;
375  if (sl->ignoreRefCount)
377  else {
378  if (se->refCount==0)
380  }
381  }
382 }
383 
384 
385 
387 {
388  assert(sl);
389  return sl->first;
390 }
391 
392 
393 
395 {
396  assert(se);
397  return se->next;
398 }
399 
400 
401 
403 {
404  assert(se);
405  return se->data;
406 }
407 
408 
409 
411 {
412  assert(se);
413  if (se->data)
414  free((void *)(se->data));
415  if (s)
416  se->data=strdup(s);
417  else
418  se->data=NULL;
419 }
420 
421 
422 
423 unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl)
424 {
425  assert(sl);
426  return sl->count;
427 }
428 
429 
430 
432  const char *s)
433 {
435 
436  assert(sl);
437  se=sl->first;
438  if (sl->senseCase) {
439  while (se) {
440  if (strcmp(se->data, s)==0) {
441  return 1;
442  }
443  se=se->next;
444  } /* while */
445  return 0;
446  }
447  else {
448  while (se) {
449  if (strcasecmp(se->data, s)==0) {
450  return 1;
451  }
452  se=se->next;
453  } /* while */
454  return 0;
455  }
456 }
457 
458 
459 
460 int GWEN_StringList_GetStringPos(const GWEN_STRINGLIST *sl, const char *s)
461 {
463  int i;
464 
465  assert(sl);
466  se=sl->first;
467  if (sl->senseCase) {
468  i=0;
469  while (se) {
470  if (strcmp(se->data, s)==0) {
471  return i;
472  }
473  i++;
474  se=se->next;
475  } /* while */
476  return -1;
477  }
478  else {
479  i=0;
480  while (se) {
481  if (strcasecmp(se->data, s)==0) {
482  return i;
483  }
484  i++;
485  se=se->next;
486  } /* while */
487  return -1;
488  }
489 }
490 
491 
492 
494 {
496  int i;
497 
498  assert(sl);
499  se=sl->first;
500  if (sl->senseCase) {
501  i=0;
502  while (se) {
503  if (strcmp(se->data, s)==0) {
504  return se;
505  }
506  i++;
507  se=se->next;
508  } /* while */
509  return NULL;
510  }
511  else {
512  i=0;
513  while (se) {
514  if (strcasecmp(se->data, s)==0) {
515  return se;
516  }
517  i++;
518  se=se->next;
519  } /* while */
520  return NULL;
521  }
522 }
523 
524 
525 
527 {
529  GWEN_STRINGLIST *newsl;
530 
531  assert(sl);
532  newsl=GWEN_StringList_new();
533 
534  se=sl->first;
535  while (se) {
536  GWEN_STRINGLISTENTRY *newse;
537 
538  newse=GWEN_StringListEntry_new(se->data, 0);
539  GWEN_StringList_AppendEntry(newsl, newse);
540  se=se->next;
541  } /* while */
542 
543  return newsl;
544 }
545 
546 
548  void *(*func)(const char *s, void *u),
549  void *user_data)
550 {
552  const char *el;
553  void *result = 0;
554  assert(l);
555 
557  if (!it)
558  return 0;
559  while (it) {
560  el = GWEN_StringListEntry_Data(it);
561  result = func(el, user_data);
562  if (result) {
563  return result;
564  }
565  it = GWEN_StringListEntry_Next(it);
566  }
567  return 0;
568 }
569 
570 
571 
573 {
574  assert(l);
575  if (l->first==0)
576  return 0;
577  return l->first->data;
578 }
579 
580 
581 
582 static int GWEN_StringList__compar_asc_nocase(const void *a, const void *b)
583 {
584  const GWEN_STRINGLISTENTRY *const *pse1 = a, * const * pse2 = b;
585  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
586  if (se1 && se2 && se1->data && se2->data)
587  return strcmp(se1->data, se2->data);
588  else
589  return 0;
590 }
591 static int GWEN_StringList__compar_desc_nocase(const void *a, const void *b)
592 {
593  const GWEN_STRINGLISTENTRY *const *pse1 = a, * const * pse2 = b;
594  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
595  if (se1 && se2 && se1->data && se2->data)
596  return strcmp(se2->data, se1->data);
597  else
598  return 0;
599 }
600 static int GWEN_StringList__compar_asc_case(const void *a, const void *b)
601 {
602  const GWEN_STRINGLISTENTRY *const *pse1 = a, * const * pse2 = b;
603  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
604  if (se1 && se2 && se1->data && se2->data)
605  return strcasecmp(se1->data, se2->data);
606  else
607  return 0;
608 }
609 static int GWEN_StringList__compar_desc_case(const void *a, const void *b)
610 {
611  const GWEN_STRINGLISTENTRY *const *pse1 = a, * const * pse2 = b;
612  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
613  if (se1 && se2 && se1->data && se2->data)
614  return strcasecmp(se2->data, se1->data);
615  else
616  return 0;
617 }
618 
619 static int GWEN_StringList__compar_asc_int(const void *a, const void *b)
620 {
621  const GWEN_STRINGLISTENTRY *const *pse1 = a, * const * pse2 = b;
622  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
623  if (se1 && se2 && se1->data && se2->data) {
624  int i1, i2;
625 
626  i1=atoi(se1->data);
627  i2=atoi(se2->data);
628  return (i1>i2) - (i1<i2);
629  }
630  else
631  return 0;
632 }
633 
634 static int GWEN_StringList__compar_desc_int(const void *a, const void *b)
635 {
636  const GWEN_STRINGLISTENTRY *const *pse1 = a, * const * pse2 = b;
637  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
638  if (se1 && se2 && se1->data && se2->data) {
639  int i1, i2;
640 
641  i1=atoi(se1->data);
642  i2=atoi(se2->data);
643  return (i2>i1) - (i2<i1);
644  }
645  else
646  return 0;
647 }
648 
649 
650 
652  int ascending,
653  GWEN_STRINGLIST_SORT_MODE sortMode)
654 {
655  GWEN_STRINGLISTENTRY **tmpEntries;
656  GWEN_STRINGLISTENTRY *sentry;
657  GWEN_STRINGLISTENTRY **psentry;
658 
659  if (l->count<2)
660  return;
661 
662  /* sort entries into a linear pointer list */
663  tmpEntries=(GWEN_STRINGLISTENTRY **)malloc((l->count+1)*
664  sizeof(GWEN_STRINGLISTENTRY *));
665  assert(tmpEntries);
666  sentry=l->first;
667  psentry=tmpEntries;
668  while (sentry) {
669  *(psentry++)=sentry;
670  sentry=sentry->next;
671  } /* while */
672  *psentry=0;
673 
674  /* sort */
675  switch (sortMode) {
677  if (ascending)
678  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY *),
680  else
681  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY *),
683  break;
684 
686  if (ascending)
687  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY *),
689  else
690  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY *),
692  break;
693 
695  if (ascending)
696  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY *),
698  else
699  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY *),
701  break;
702 
703  default:
704  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown sortmode %d", sortMode);
705  }
706 
707  /* sort entries back into GWEN_STRINGLIST */
708  psentry=tmpEntries;
709  sentry=0;
710  while (*psentry) {
711  if (sentry)
712  sentry->next=*psentry;
713  else
714  l->first=*psentry;
715  sentry=*psentry;
716  psentry++;
717  } /* while */
718  sentry->next=NULL;
719 
720  free(tmpEntries);
721 
722 }
723 
724 
725 
726 const char *GWEN_StringList_StringAt(const GWEN_STRINGLIST *sl, int idx)
727 {
729 
730  assert(sl);
731  se=sl->first;
732  while (se) {
733  if (idx--==0)
734  return se->data;
735  se=se->next;
736  } /* while */
737  return 0;
738 }
739 
740 
741 
742 GWEN_STRINGLIST *GWEN_StringList_fromString(const char *str, const char *delimiters, int checkDouble)
743 {
744  if (str && *str) {
745  GWEN_STRINGLIST *sl;
746  const unsigned char *s;
747 
748  sl=GWEN_StringList_new();
749  s=(const unsigned char *)str;
750 
751  while (*s) {
752  /* skip blanks */
753  while (*s && *s<33)
754  s++;
755 
756  if (*s) {
757  const unsigned char *pStart;
758  int len;
759 
760  /* read word */
761  pStart=s;
762  //s++;
763  while (*s && strchr(delimiters, *s)==NULL)
764  s++;
765  len=s-pStart;
766 
767  if (len) {
768  char *toAdd;
769 
770  toAdd=(char *) malloc(len+1);
771  assert(toAdd);
772 
773  memmove(toAdd, pStart, len);
774  toAdd[len]=0;
775 
776  GWEN_StringList_AppendString(sl, toAdd, 1, checkDouble);
777  }
778  }
779 
780  if (*s==0)
781  break;
782  s++;
783  }
784 
785  if (GWEN_StringList_Count(sl)==0) {
787  return NULL;
788  }
789  return sl;
790  }
791  else
792  return NULL;
793 }
794 
795 
796 
void * GWEN_StringList_ForEach(const GWEN_STRINGLIST *l, void *(*func)(const char *s, void *u), void *user_data)
Definition: stringlist.c:547
GWEN_STRINGLIST * GWEN_StringList_fromTabString(const char *s, int checkDup)
Definition: stringlist.c:158
struct GWEN_STRINGLISTENTRYSTRUCT GWEN_STRINGLISTENTRY
Definition: stringlist.h:51
void GWEN_StringListEntry_ReplaceString(GWEN_STRINGLISTENTRY *e, const char *s, int take)
Definition: stringlist.c:109
int GWEN_StringList_GetStringPos(const GWEN_STRINGLIST *sl, const char *s)
Definition: stringlist.c:460
void GWEN_StringList_Clear(GWEN_STRINGLIST *sl)
Definition: stringlist.c:224
GWEN_STRINGLISTENTRY * GWEN_StringList_FindStringEntry(const GWEN_STRINGLIST *sl, const char *s)
Definition: stringlist.c:493
void GWEN_StringList_Sort(GWEN_STRINGLIST *l, int ascending, GWEN_STRINGLIST_SORT_MODE sortMode)
Definition: stringlist.c:651
static int GWEN_StringList__compar_asc_int(const void *a, const void *b)
Definition: stringlist.c:619
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
#define NULL
Definition: binreloc.c:300
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:281
static int GWEN_StringList__compar_asc_nocase(const void *a, const void *b)
Definition: stringlist.c:582
void GWEN_StringList_SetSenseCase(GWEN_STRINGLIST *sl, int i)
Definition: stringlist.c:75
#define GWEN_LOGDOMAIN
Definition: logger.h:35
void GWEN_StringList_RemoveEntry(GWEN_STRINGLIST *sl, GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:194
const char * GWEN_StringList_StringAt(const GWEN_STRINGLIST *sl, int idx)
Definition: stringlist.c:726
GWEN_STRINGLISTENTRY * GWEN_StringList_FirstEntry(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:386
const char * GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:402
void GWEN_StringList_free(GWEN_STRINGLIST *sl)
Definition: stringlist.c:58
static int GWEN_StringList__compar_asc_case(const void *a, const void *b)
Definition: stringlist.c:600
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:55
int GWEN_StringList_AppendString(GWEN_STRINGLIST *sl, const char *s, int take, int checkDouble)
Definition: stringlist.c:241
void GWEN_StringListEntry_free(GWEN_STRINGLISTENTRY *sl)
Definition: stringlist.c:124
static int GWEN_StringList__compar_desc_nocase(const void *a, const void *b)
Definition: stringlist.c:591
struct GWEN_STRINGLISTSTRUCT GWEN_STRINGLIST
Definition: stringlist.h:54
int GWEN_StringList_RemoveString(GWEN_STRINGLIST *sl, const char *s)
Definition: stringlist.c:322
GWEN_STRINGLIST * GWEN_StringList_fromString(const char *str, const char *delimiters, int checkDouble)
Definition: stringlist.c:742
GWEN_STRINGLISTENTRY * GWEN_StringListEntry_new(const char *s, int take)
Definition: stringlist.c:91
GWEN_STRINGLIST * GWEN_StringList_dup(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:526
unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:423
static int GWEN_StringList__compar_desc_case(const void *a, const void *b)
Definition: stringlist.c:609
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
const char * GWEN_StringList_FirstString(const GWEN_STRINGLIST *l)
Definition: stringlist.c:572
int GWEN_StringList_HasString(const GWEN_STRINGLIST *sl, const char *s)
Definition: stringlist.c:431
GWEN_STRINGLISTENTRY * GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:394
void GWEN_StringList_AppendEntry(GWEN_STRINGLIST *sl, GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:135
void GWEN_StringListEntry_SetData(GWEN_STRINGLISTENTRY *se, const char *s)
Definition: stringlist.c:410
void GWEN_StringList_RemoveFirstString(GWEN_STRINGLIST *sl)
Definition: stringlist.c:365
static int GWEN_StringList__compar_desc_int(const void *a, const void *b)
Definition: stringlist.c:634
GWEN_STRINGLIST * GWEN_StringList_new(void)
Definition: stringlist.c:46
void GWEN_StringList_SetIgnoreRefCount(GWEN_STRINGLIST *sl, int i)
Definition: stringlist.c:83