gwenhywfar  4.99.25rc9
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  const char *s)
324 {
326 
327  se=sl->first;
328  if (sl->senseCase) {
329  while (se) {
330  if (strcmp(se->data, s)==0) {
331  assert(se->refCount);
332  se->refCount--;
333  if (sl->ignoreRefCount)
335  else {
336  if (se->refCount==0)
338  }
339  return 1;
340  }
341  se=se->next;
342  } /* while */
343  return 0;
344  }
345  else {
346  while (se) {
347  if (strcasecmp(se->data, s)==0) {
348  assert(se->refCount);
349  se->refCount--;
350  if (sl->ignoreRefCount)
352  else {
353  if (se->refCount==0)
355  }
356  return 1;
357  }
358  se=se->next;
359  } /* while */
360  return 0;
361  }
362 }
363 
364 
365 
367 {
368  assert(sl);
369  return sl->first;
370 }
371 
372 
373 
375 {
376  assert(se);
377  return se->next;
378 }
379 
380 
381 
383 {
384  assert(se);
385  return se->data;
386 }
387 
388 
389 
391 {
392  assert(se);
393  if (se->data)
394  free((void *)(se->data));
395  if (s)
396  se->data=strdup(s);
397  else
398  se->data=NULL;
399 }
400 
401 
402 
403 unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl)
404 {
405  assert(sl);
406  return sl->count;
407 }
408 
409 
410 
412  const char *s)
413 {
415 
416  assert(sl);
417  se=sl->first;
418  if (sl->senseCase) {
419  while (se) {
420  if (strcmp(se->data, s)==0) {
421  return 1;
422  }
423  se=se->next;
424  } /* while */
425  return 0;
426  }
427  else {
428  while (se) {
429  if (strcasecmp(se->data, s)==0) {
430  return 1;
431  }
432  se=se->next;
433  } /* while */
434  return 0;
435  }
436 }
437 
438 
439 
440 int GWEN_StringList_GetStringPos(const GWEN_STRINGLIST *sl, const char *s)
441 {
443  int i;
444 
445  assert(sl);
446  se=sl->first;
447  if (sl->senseCase) {
448  i=0;
449  while (se) {
450  if (strcmp(se->data, s)==0) {
451  return i;
452  }
453  i++;
454  se=se->next;
455  } /* while */
456  return -1;
457  }
458  else {
459  i=0;
460  while (se) {
461  if (strcasecmp(se->data, s)==0) {
462  return i;
463  }
464  i++;
465  se=se->next;
466  } /* while */
467  return -1;
468  }
469 }
470 
471 
472 
474 {
476  int i;
477 
478  assert(sl);
479  se=sl->first;
480  if (sl->senseCase) {
481  i=0;
482  while (se) {
483  if (strcmp(se->data, s)==0) {
484  return se;
485  }
486  i++;
487  se=se->next;
488  } /* while */
489  return NULL;
490  }
491  else {
492  i=0;
493  while (se) {
494  if (strcasecmp(se->data, s)==0) {
495  return se;
496  }
497  i++;
498  se=se->next;
499  } /* while */
500  return NULL;
501  }
502 }
503 
504 
505 
507 {
509  GWEN_STRINGLIST *newsl;
510 
511  assert(sl);
512  newsl=GWEN_StringList_new();
513 
514  se=sl->first;
515  while (se) {
516  GWEN_STRINGLISTENTRY *newse;
517 
518  newse=GWEN_StringListEntry_new(se->data, 0);
519  GWEN_StringList_AppendEntry(newsl, newse);
520  se=se->next;
521  } /* while */
522 
523  return newsl;
524 }
525 
526 
528  void *(*func)(const char *s, void *u),
529  void *user_data)
530 {
532  const char *el;
533  void *result = 0;
534  assert(l);
535 
537  if (!it)
538  return 0;
539  while (it) {
540  el = GWEN_StringListEntry_Data(it);
541  result = func(el, user_data);
542  if (result) {
543  return result;
544  }
545  it = GWEN_StringListEntry_Next(it);
546  }
547  return 0;
548 }
549 
550 
551 
553 {
554  assert(l);
555  if (l->first==0)
556  return 0;
557  return l->first->data;
558 }
559 
560 
561 
562 static int GWEN_StringList__compar_asc_nocase(const void *a, const void *b)
563 {
564  const GWEN_STRINGLISTENTRY *const *pse1 = a, * const * pse2 = b;
565  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
566  if (se1 && se2 && se1->data && se2->data)
567  return strcmp(se1->data, se2->data);
568  else
569  return 0;
570 }
571 static int GWEN_StringList__compar_desc_nocase(const void *a, const void *b)
572 {
573  const GWEN_STRINGLISTENTRY *const *pse1 = a, * const * pse2 = b;
574  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
575  if (se1 && se2 && se1->data && se2->data)
576  return strcmp(se2->data, se1->data);
577  else
578  return 0;
579 }
580 static int GWEN_StringList__compar_asc_case(const void *a, const void *b)
581 {
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  return strcasecmp(se1->data, se2->data);
586  else
587  return 0;
588 }
589 static int GWEN_StringList__compar_desc_case(const void *a, const void *b)
590 {
591  const GWEN_STRINGLISTENTRY *const *pse1 = a, * const * pse2 = b;
592  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
593  if (se1 && se2 && se1->data && se2->data)
594  return strcasecmp(se2->data, se1->data);
595  else
596  return 0;
597 }
598 
599 static int GWEN_StringList__compar_asc_int(const void *a, const void *b)
600 {
601  const GWEN_STRINGLISTENTRY *const *pse1 = a, * const * pse2 = b;
602  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
603  if (se1 && se2 && se1->data && se2->data) {
604  int i1, i2;
605 
606  i1=atoi(se1->data);
607  i2=atoi(se2->data);
608  return (i1>i2) - (i1<i2);
609  }
610  else
611  return 0;
612 }
613 
614 static int GWEN_StringList__compar_desc_int(const void *a, const void *b)
615 {
616  const GWEN_STRINGLISTENTRY *const *pse1 = a, * const * pse2 = b;
617  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
618  if (se1 && se2 && se1->data && se2->data) {
619  int i1, i2;
620 
621  i1=atoi(se1->data);
622  i2=atoi(se2->data);
623  return (i2>i1) - (i2<i1);
624  }
625  else
626  return 0;
627 }
628 
629 
630 
632  int ascending,
633  GWEN_STRINGLIST_SORT_MODE sortMode)
634 {
635  GWEN_STRINGLISTENTRY **tmpEntries;
636  GWEN_STRINGLISTENTRY *sentry;
637  GWEN_STRINGLISTENTRY **psentry;
638 
639  if (l->count<2)
640  return;
641 
642  /* sort entries into a linear pointer list */
643  tmpEntries=(GWEN_STRINGLISTENTRY **)malloc((l->count+1)*
644  sizeof(GWEN_STRINGLISTENTRY *));
645  assert(tmpEntries);
646  sentry=l->first;
647  psentry=tmpEntries;
648  while (sentry) {
649  *(psentry++)=sentry;
650  sentry=sentry->next;
651  } /* while */
652  *psentry=0;
653 
654  /* sort */
655  switch (sortMode) {
657  if (ascending)
658  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY *),
660  else
661  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY *),
663  break;
664 
666  if (ascending)
667  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY *),
669  else
670  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY *),
672  break;
673 
675  if (ascending)
676  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY *),
678  else
679  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY *),
681  break;
682 
683  default:
684  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown sortmode %d", sortMode);
685  }
686 
687  /* sort entries back into GWEN_STRINGLIST */
688  psentry=tmpEntries;
689  sentry=0;
690  while (*psentry) {
691  if (sentry)
692  sentry->next=*psentry;
693  else
694  l->first=*psentry;
695  sentry=*psentry;
696  psentry++;
697  } /* while */
698  sentry->next=NULL;
699 
700  free(tmpEntries);
701 
702 }
703 
704 
705 
706 const char *GWEN_StringList_StringAt(const GWEN_STRINGLIST *sl, int idx)
707 {
709 
710  assert(sl);
711  se=sl->first;
712  while (se) {
713  if (idx--==0)
714  return se->data;
715  se=se->next;
716  } /* while */
717  return 0;
718 }
719 
720 
721 
722 GWEN_STRINGLIST *GWEN_StringList_fromString(const char *str, const char *delimiters, int checkDouble)
723 {
724  if (str && *str) {
725  GWEN_STRINGLIST *sl;
726  const unsigned char *s;
727 
728  sl=GWEN_StringList_new();
729  s=(const unsigned char *)str;
730 
731  while (*s) {
732  /* skip blanks */
733  while (*s && *s<33)
734  s++;
735 
736  if (*s) {
737  const unsigned char *pStart;
738  int len;
739 
740  /* read word */
741  pStart=s;
742  //s++;
743  while (*s && strchr(delimiters, *s)==NULL)
744  s++;
745  len=s-pStart;
746 
747  if (len) {
748  char *toAdd;
749 
750  toAdd=(char *) malloc(len+1);
751  assert(toAdd);
752 
753  memmove(toAdd, pStart, len);
754  toAdd[len]=0;
755 
756  GWEN_StringList_AppendString(sl, toAdd, 1, checkDouble);
757  }
758  }
759 
760  if (*s==0)
761  break;
762  s++;
763  }
764 
765  if (GWEN_StringList_Count(sl)==0) {
767  return NULL;
768  }
769  return sl;
770  }
771  else
772  return NULL;
773 }
774 
775 
776 
void * GWEN_StringList_ForEach(const GWEN_STRINGLIST *l, void *(*func)(const char *s, void *u), void *user_data)
Definition: stringlist.c:527
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:440
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:473
void GWEN_StringList_Sort(GWEN_STRINGLIST *l, int ascending, GWEN_STRINGLIST_SORT_MODE sortMode)
Definition: stringlist.c:631
static int GWEN_StringList__compar_asc_int(const void *a, const void *b)
Definition: stringlist.c:599
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
#define NULL
Definition: binreloc.c:297
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:562
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:706
GWEN_STRINGLISTENTRY * GWEN_StringList_FirstEntry(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:366
const char * GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:382
GWENHYWFAR_API int GWEN_StringList_RemoveString(GWEN_STRINGLIST *sl, const char *s)
Definition: stringlist.c:322
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:580
#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:571
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:722
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:506
#define GWENHYWFAR_API
Definition: gwenhywfarapi.h:67
unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:403
static int GWEN_StringList__compar_desc_case(const void *a, const void *b)
Definition: stringlist.c:589
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
const char * GWEN_StringList_FirstString(const GWEN_STRINGLIST *l)
Definition: stringlist.c:552
int GWEN_StringList_HasString(const GWEN_STRINGLIST *sl, const char *s)
Definition: stringlist.c:411
GWEN_STRINGLISTENTRY * GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:374
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:390
static int GWEN_StringList__compar_desc_int(const void *a, const void *b)
Definition: stringlist.c:614
GWEN_STRINGLIST * GWEN_StringList_new(void)
Definition: stringlist.c:46
void GWEN_StringList_SetIgnoreRefCount(GWEN_STRINGLIST *sl, int i)
Definition: stringlist.c:83