gwenhywfar  4.6.0beta
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 
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 
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  while (se) {
221  next=se->next;
223  se=next;
224  } /* while */
225 }
226 
227 
228 
230  const char *s,
231  int take,
232  int checkDouble){
234 
235  if (checkDouble) {
236  se=sl->first;
237  if (sl->senseCase) {
238  while(se) {
239  if (strcmp(se->data, s)==0) {
240  if (take)
241  free((char*)s);
242  se->refCount++;
243  return 0;
244  }
245  se=se->next;
246  } /* while */
247  }
248  else {
249  while(se) {
250  if (strcasecmp(se->data, s)==0) {
251  if (take)
252  free((char*)s);
253  se->refCount++;
254  return 0;
255  }
256  se=se->next;
257  } /* while */
258  }
259  } /* if checkdouble */
260 
261  se=GWEN_StringListEntry_new(s, take);
263  return 1;
264 }
265 
266 
267 
269  const char *s,
270  int take,
271  int checkDouble){
273 
274  if (checkDouble) {
275  se=sl->first;
276  if (sl->senseCase) {
277  while(se) {
278  if (strcmp(se->data, s)==0) {
279  if (take)
280  free((char*)s);
281  se->refCount++;
282  return 0;
283  }
284  se=se->next;
285  } /* while */
286  }
287  else {
288  while(se) {
289  if (strcasecmp(se->data, s)==0) {
290  if (take)
291  free((char*)s);
292  se->refCount++;
293  return 0;
294  }
295  se=se->next;
296  } /* while */
297  }
298  } /* if checkdouble */
299  se=GWEN_StringListEntry_new(s, take);
300  se->next=sl->first;
301  sl->first=se;
302  return 1;
303 }
304 
305 
306 
308  const char *s){
310 
311  se=sl->first;
312  if (sl->senseCase) {
313  while(se) {
314  if (strcmp(se->data, s)==0) {
315  assert(se->refCount);
316  se->refCount--;
317  if (sl->ignoreRefCount)
319  else {
320  if (se->refCount==0)
322  }
323  return 1;
324  }
325  se=se->next;
326  } /* while */
327  return 0;
328  }
329  else {
330  while(se) {
331  if (strcasecmp(se->data, s)==0) {
332  assert(se->refCount);
333  se->refCount--;
334  if (sl->ignoreRefCount)
336  else {
337  assert(se->refCount);
338  if (se->refCount==0)
340  }
341  return 1;
342  }
343  se=se->next;
344  } /* while */
345  return 0;
346  }
347 }
348 
349 
350 
352  assert(sl);
353  return sl->first;
354 }
355 
356 
357 
359  assert(se);
360  return se->next;
361 }
362 
363 
364 
366  assert(se);
367  return se->data;
368 }
369 
370 
371 unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl){
372  assert(sl);
373  return sl->count;
374 }
375 
376 
377 
379  const char *s){
381 
382  assert(sl);
383  se=sl->first;
384  if (sl->senseCase) {
385  while(se) {
386  if (strcmp(se->data, s)==0) {
387  return 1;
388  }
389  se=se->next;
390  } /* while */
391  return 0;
392  }
393  else {
394  while(se) {
395  if (strcasecmp(se->data, s)==0) {
396  return 1;
397  }
398  se=se->next;
399  } /* while */
400  return 0;
401  }
402 }
403 
404 
405 
406 int GWEN_StringList_GetStringPos(const GWEN_STRINGLIST *sl, const char *s){
408  int i;
409 
410  assert(sl);
411  se=sl->first;
412  if (sl->senseCase) {
413  i=0;
414  while(se) {
415  if (strcmp(se->data, s)==0) {
416  return i;
417  }
418  i++;
419  se=se->next;
420  } /* while */
421  return -1;
422  }
423  else {
424  i=0;
425  while(se) {
426  if (strcasecmp(se->data, s)==0) {
427  return i;
428  }
429  i++;
430  se=se->next;
431  } /* while */
432  return -1;
433  }
434 }
435 
436 
437 
440  GWEN_STRINGLIST *newsl;
441 
442  assert(sl);
443  newsl=GWEN_StringList_new();
444 
445  se=sl->first;
446  while(se) {
447  GWEN_STRINGLISTENTRY *newse;
448 
449  newse=GWEN_StringListEntry_new(se->data, 0);
450  GWEN_StringList_AppendEntry(newsl, newse);
451  se=se->next;
452  } /* while */
453 
454  return newsl;
455 }
456 
457 
459  void *(*func)(const char *s, void *u),
460  void *user_data) {
462  const char *el;
463  void *result = 0;
464  assert(l);
465 
467  if (!it)
468  return 0;
469  while(it) {
470  el = GWEN_StringListEntry_Data(it);
471  result = func(el, user_data);
472  if (result) {
473  return result;
474  }
475  it = GWEN_StringListEntry_Next(it);
476  }
477  return 0;
478 }
479 
480 
481 
483  assert(l);
484  if (l->first==0)
485  return 0;
486  return l->first->data;
487 }
488 
489 
490 
491 static int GWEN_StringList__compar_asc_nocase(const void *a, const void *b) {
492  const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
493  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
494  if (se1 && se2 && se1->data && se2->data)
495  return strcmp(se1->data, se2->data);
496  else
497  return 0;
498 }
499 static int GWEN_StringList__compar_desc_nocase(const void *a, const void *b) {
500  const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
501  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
502  if (se1 && se2 && se1->data && se2->data)
503  return strcmp(se2->data, se1->data);
504  else
505  return 0;
506 }
507 static int GWEN_StringList__compar_asc_case(const void *a, const void *b) {
508  const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
509  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
510  if (se1 && se2 && se1->data && se2->data)
511  return strcasecmp(se1->data, se2->data);
512  else
513  return 0;
514 }
515 static int GWEN_StringList__compar_desc_case(const void *a, const void *b) {
516  const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
517  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
518  if (se1 && se2 && se1->data && se2->data)
519  return strcasecmp(se2->data, se1->data);
520  else
521  return 0;
522 }
523 
524 static int GWEN_StringList__compar_asc_int(const void *a, const void *b) {
525  const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
526  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
527  if (se1 && se2 && se1->data && se2->data)
528  return (atoi(se1->data)<atoi(se2->data));
529  else
530  return 0;
531 }
532 
533 static int GWEN_StringList__compar_desc_int(const void *a, const void *b) {
534  const GWEN_STRINGLISTENTRY * const * pse1 = a, * const * pse2 = b;
535  const GWEN_STRINGLISTENTRY *se1 = *pse1, *se2 = *pse2;
536  if (se1 && se2 && se1->data && se2->data)
537  return (atoi(se1->data)>atoi(se2->data));
538  else
539  return 0;
540 }
541 
542 
543 
545  int ascending,
546  GWEN_STRINGLIST_SORT_MODE sortMode) {
547  GWEN_STRINGLISTENTRY **tmpEntries;
548  GWEN_STRINGLISTENTRY *sentry;
549  GWEN_STRINGLISTENTRY **psentry;
550 
551  if (l->count<1)
552  return;
553 
554  /* sort entries into a linear pointer list */
555  tmpEntries=(GWEN_STRINGLISTENTRY **)malloc((l->count+1)*
556  sizeof(GWEN_STRINGLISTENTRY*));
557  assert(tmpEntries);
558  sentry=l->first;
559  psentry=tmpEntries;
560  while(sentry) {
561  GWEN_STRINGLISTENTRY *nsentry;
562 
563  *(psentry++)=sentry;
564  nsentry=sentry->next;
565  sentry->next=0;
566  sentry=nsentry;
567  } /* while */
568  *psentry=0;
569 
570  /* sort */
571  switch(sortMode) {
573  if (ascending)
574  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
576  else
577  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
579  break;
580 
582  if (ascending)
583  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
585  else
586  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
588  break;
589 
591  if (ascending)
592  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
594  else
595  qsort(tmpEntries, l->count, sizeof(GWEN_STRINGLISTENTRY*),
597  break;
598 
599  default:
600  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown sortmode %d", sortMode);
601  }
602 
603  /* sort entries back into GWEN_STRINGLIST */
604  psentry=tmpEntries;
605  sentry=0;
606  while(*psentry) {
607  (*psentry)->next=0;
608  if (sentry)
609  sentry->next=*psentry;
610  else
611  l->first=*psentry;
612  sentry=*psentry;
613  psentry++;
614  } /* while */
615 
616  free(tmpEntries);
617 
618 }
619 
620 
621 
622 const char *GWEN_StringList_StringAt(const GWEN_STRINGLIST *sl, int idx) {
624 
625  assert(sl);
626  se=sl->first;
627  while(se) {
628  if (idx--==0)
629  return se->data;
630  se=se->next;
631  } /* while */
632  return 0;
633 }
634 
635 
636 
637 GWEN_STRINGLIST *GWEN_StringList_fromString(const char *str, const char *delimiters, int checkDouble) {
638  if (str && *str) {
639  GWEN_STRINGLIST *sl;
640  const unsigned char *s;
641 
642  sl=GWEN_StringList_new();
643  s=(const unsigned char*)str;
644 
645  while(*s) {
646  /* skip blanks */
647  while(*s && *s<33)
648  s++;
649 
650  if (*s) {
651  const unsigned char *pStart;
652  int len;
653 
654  /* read word */
655  pStart=s;
656  //s++;
657  while(*s && strchr(delimiters, *s)==NULL)
658  s++;
659  len=s-pStart;
660 
661  if (len) {
662  char *toAdd;
663 
664  toAdd=(char*) malloc(len+1);
665  assert(toAdd);
666 
667  memmove(toAdd, pStart, len);
668  toAdd[len]=0;
669 
670  GWEN_StringList_AppendString(sl, toAdd, 1, checkDouble);
671  }
672  }
673 
674  if (*s==0)
675  break;
676  s++;
677  }
678 
679  if (GWEN_StringList_Count(sl)==0) {
681  return NULL;
682  }
683  return sl;
684  }
685  else
686  return NULL;
687 }
688 
689 
690